// Cubehelix color scheme for Max/MSP/Jitter
// By Théophile Clet
// https://tflcl.xyz
//
// Based on Dave Green's work:
// http://www.mrao.cam.ac.uk/~dag/CUBEHELIX/cubetry.html
//
// Original publication: Green, D. A., 2011, `A colour scheme for the display of astronomical intensity images', Bulletin of the Astronomical Society of India, 39, 289. (2011BASI...39..289G at ADS.)
// http://astron-soc.in/bulletin/11June/289392011.pdf )
//
// Original js code taken straight from the online example implementation:
// http://www.mrao.cam.ac.uk/~dag/CUBEHELIX/cubetry.html
autowatch = 1 ;
inlets = 1 ;
outlets = 4 ;
var RGBOUTLET = 0 ;
var HSLOUTLET = 1 ;
var LISTOUTLET = 2
var DUMPOUTLET = 3 ;
setinletassist ( 0 , "List as input: {makeCubehelixRGB, start[float], rots[float], sign[-1,1], hue[float], gamma[float], levels(int), flip([0,1]}" )
setoutletassist ( 0 , "To jit.matrix: always outputs the color palette as a ARGB 4-plane matrix" ) ;
setoutletassist ( 1 , "To jit.matrix: if 'hslenable 1' outputs the color palette as a AHSL 4-plane matrix" ) ;
setoutletassist ( 2 , "If 'listmode 1' outputs all colors in list format as RGB or HSL." ) ;
setoutletassist ( 3 , "Bangs when generation is done." ) ;
var hslmode = false ;
var listmode = false ;
function hslenable ( s ) {
hslmode = s ;
}
function listenable ( s ) {
listmode = s ;
}
function makeCubehelix ( start , rots , hue , gamma , levels , flip ) {
//dumpOut(start, rots, hue, gamma, levels, flip);
outlet ( RGBOUTLET , "dim" , levels , 1 ) ;
if ( hslmode ) {
outlet ( HSLOUTLET , "dim" , levels , 1 ) ;
}
for ( var i = 0 ; i < levels ; i ++ ) {
var fract = CubeHelixFract ( i , levels , flip ) ;
var color = CubeHelixRGB ( fract , start , rots , hue , gamma ) ;
if ( flip == 1 ) { fract = 1.0 - fract ; }
outlet ( RGBOUTLET , "setcell" , i , 0 , "val" , 1. , color ) ;
if ( hslmode ) {
color = rgb2hsl ( color [ 0 ] , color [ 1 ] , color [ 2 ] ) ;
outlet ( HSLOUTLET , "setcell" , i , 0 , "val" , 1. , color ) ;
}
if ( listmode ) { outlet ( LISTOUTLET , i , color ) ; }
}
outlet ( RGBOUTLET , "bang" ) ;
if ( hslmode ) { outlet ( HSLOUTLET , "bang" ) ; }
if ( listmode ) { outlet ( LISTOUTLET , "bang" ) ; }
outlet ( DUMPOUTLET , "bang" ) ;
}
function dumpOut ( start , rots , hue , gamma , levels , flip ) {
outlet ( DUMPOUTLET , "start" , start ) ;
outlet ( DUMPOUTLET , "rots" , rots ) ;
outlet ( DUMPOUTLET , "hue" , hue ) ;
outlet ( DUMPOUTLET , "gamma" , gamma ) ;
outlet ( DUMPOUTLET , "levels" , levels ) ;
outlet ( DUMPOUTLET , "flip" , flip ) ;
}
function rgb2hsl ( r , g , b ) {
var max = Math . max ( r , g , b ) , min = Math . min ( r , g , b ) ;
var h , s , l = ( max + min ) / 2 ;
if ( max == min ) {
h = s = 0 ; // achromatic
} else {
var d = max - min ;
s = l > 0.5 ? d / ( 2 - max - min ) : d / ( max + min ) ;
switch ( max ) {
case r : h = ( g - b ) / d + ( g < b ? 6 : 0 ) ; break ;
case g : h = ( b - r ) / d + 2 ; break ;
case b : h = ( r - g ) / d + 4 ; break ;
}
h /= 6 ;
}
return [ h , s , l ] ;
}
// ----------------------------------------------------------------------------
// 2017 May 30: make consistent with Fortran
// 2021 mai 12: a bit of calculation optimization (I think) - Théophile Clet
// ----------------------------------------------------------------------------
function CubeHelixRGB ( fract , start , rots , hue , gamma ) {
var angle = 2 * Math . PI * ( start / 3.0 + 1 + rots * fract ) ;
var fract = Math . pow ( fract , gamma ) ;
var amp = hue * fract * ( 1 - fract ) / 2.0 ;
var r = fract + amp * ( - 0.14861 * Math . cos ( angle ) + 1.78277 * Math . sin ( angle ) ) ;
r = Math . max ( Math . min ( r , 1.0 ) , 0.0 ) ;
var g = fract + amp * ( - 0.29227 * Math . cos ( angle ) - 0.90649 * Math . sin ( angle ) ) ;
g = Math . max ( Math . min ( g , 1.0 ) , 0.0 ) ;
var b = fract + amp * ( + 1.97294 * Math . cos ( angle ) ) ;
b = Math . max ( Math . min ( b , 1.0 ) , 0.0 ) ;
return [ r , g , b ] ;
}
// ----------------------------------------------------------------------------
function CubeHelixFract ( i , n , flip ) {
var fraction = i / ( n - 1 ) ;
if ( flip == 1 ) {
fraction = 1 - fraction ;
}
return fraction ;
}