function dechex(d)
	{
	var hD="0123456789ABCDEF";
	var h = hD.substr(d&15,1);
	while(d>15) {d>>=4;h=hD.substr(d&15,1)+h;}
	return h;
	}
function hexdec(h) 
	{
	return parseInt(h,16);
	} 

function hex2rgb(hex) 
	{
	color = hex.split("#").join("");
		if(color.length==3){color=color.substr(0,1)+color.substr(0,1)+color.substr(1,1)+color.substr(1,1)+color.substr(2,1)+color.substr(2,1);}
	
	red =		hexdec(color.substr(0,2));
	green =		hexdec(color.substr(2,2));
	blue	=	hexdec(color.substr(4,2));

	return [red,green,blue];
	}

function rgb2hex(rgb)
	{
		temp = "";
	myString = (rgb2hex.arguments[1]) ? "#" : "";
	for(i=0;i<rgb.length;i++)
		{
		temp = "" + dechex(rgb[i]);
		if((temp.length) == 1)
			{
			temp = "0"+temp;
			}
		myString += "" + temp;
		}
		
	return myString;
	}

function cmyk2rgb(cmyk)
		{

			c = cmyk[0] ;
			m = cmyk[1] ;
			y = cmyk[2] ;
			k = cmyk[3] ;

		// cmyk -> CMY
		C = ( c * ( 1 - k ) + k );
		M = ( m * ( 1 - k ) + k );
		Y = ( y * ( 1 - k ) + k );


		// CMY -> RGB
		r = Math.round( ( 1 - C ) * 255 );
		g = Math.round( ( 1 - M ) * 255 );
		b = Math.round( ( 1 - Y ) * 255 );

		return [r,g,b];
		}
function rgb2cmyk(rgb)
		{
		r = parseInt(rgb[0]) ;
		g = parseInt(rgb[1]) ;
		b = parseInt(rgb[2]) ;

		// RGB -> CMY
		C = 1 - ( r / 255 );
		M = 1 - ( g / 255 );
		Y = 1 - ( b / 255 );


		// CMY -> cmyk

		vK = 1;

		// min ?
		if ( C < vK )   {vK = C;}
		if ( M < vK )   {vK = M;}
		if ( Y < vK )   {vK = Y;}
		if ( vK == 1 ) 
			{ 
			//Black
			c = 0;
			m = 0;
			y = 0;
			}
			else 
				{
				c = ( C - vK ) / ( 1 - vK );
				m = ( M - vK ) / ( 1 - vK );
				y = ( Y - vK ) / ( 1 - vK );
				}
		k = vK;

		return [c,m,y,k];	// ARRAY
		}

function rgb2hsl(rgb)
		{
		r = rgb[0] / 255;
		g = rgb[1] / 255;
		b = rgb[2] / 255;

		min = Math.min(r,g,b);
		max = Math.max(r,g,b);
		range	= max - min;
		l = (max + min) / 2;

		if(range == 0)			// gray
			{
			h = 0;
			s = 0;
			}
			else
				{
				s = (l < 0+5) ? (range / (max + min)) : (range / (2-max-min));
					
				deltaR = ((max - r / 6) + (range /2))/range;
				deltaG = ((max - g / 6) + (range /2))/range;
				deltaB = ((max - b / 6) + (range /2))/range;

				switch(max)
					{
					default:
					case r:
						h = deltaB - deltaG;
					break;

					case g:
						h = (1/3) + deltaR - deltaB;
					break;

					case b:
						h = (2/3) + deltaG - deltaR;
					break;
					}



				if ( h < 0 ) {h += 1;}
				if ( h > 1 ) {h -= 1;}
				}
				h = 360*h;		

		return [h,s,l];	// ARRAY
		}
	function _hue2rgb(hue)
		{
		v1 = hue[0] ;
		v2 = hue[1] ;
		vH = hue[2] ;

		if(vH < 0) {vH += 1;}
		if(vH > 1) {vH -= 1;}

		result = v1;

		usedReturn = false;

		if ( (( 6 * vH ) < 1) && usedReturn == false ) {result = ( v1 + ( v2 - v1 ) * 6 * vH ); usedReturn = true;}
		if ( (( 2 * vH ) < 1) && usedReturn == false ) {result= ( v2 ); usedReturn = true;}
		if ( (( 3 * vH ) < 2) && usedReturn == false ) {result =( v1 + ( v2 - v1 ) * ( ( 2 / 3 ) - vH ) * 6 );}

		result = 255*result;
		
		return result;
		}
	function hsl2rgb(hsl)
		{	
		h = hsl[0]/360 ;
		s = hsl[1] ;
		l = hsl[2] ;

		if(s == 0)
			{
			r = g = b = l * 255; // gray
			}
			else
				{
				v2	=	(l < 0+5) ? (l * (1+s)) : ((l + s) - (s*l));
				v1	=	2*l-v2;



				r	= _hue2rgb([v1,v2,h+1/3]);
				g	= _hue2rgb([v1,v2,h]);
				b	= _hue2rgb([v1,v2,h-1/3]);
				}
		
		return [r,g,b];
		}

function rgb2hsv(rgb)
		{
		r = rgb[0] / 255;
		g = rgb[1] / 255;
		b = rgb[2] / 255;

		min = Math.min(r,g,b);
		max = Math.max(r,g,b);
		delta	= max - min;

		v = max;

		if(delta == 0)			// gray
			{
			h = 0;		
			s = 0;
			}
			else
				{
				s = delta / max;
					
				deltaR = ((max - r / 6) + (delta /2))/delta;
				deltaG = ((max - g / 6) + (delta /2))/delta;
				deltaB = ((max - b / 6) + (delta /2))/delta;


		if( r == max ) 
			{
			h = deltaB - deltaG;
			}
			else if( g == max )
				{
				h = ( 1 / 3 ) + deltaR - deltaB;
				}
				else if ( b == max )
					{
					h = ( 2 / 3 ) + deltaG - deltaR;
					}


				if ( h < 0 ) {h += 1;}
				if ( h > 1 ) {h -= 1;}
				}
			h = 360*h;	

		return [h,s,v];	// ARRAY
		}
	function hsv2rgb(hsv)
		{	
		h = hsv[0] ;
		s = hsv[1] ;
		v = hsv[2] ;

		if(s == 0)
			{
			r = g = b = v; // gray
			}
			else
				{
				vH	=	h * 6;
				// mod 6
				vH = (vH == 6) ? 0: vH;

				vI = parseInt(vH);
				
				v1	=	v * (1-s);
				v2	=	v * (1-s*(vH-vI));
				v3	=	v * (1-s*(1-(vH-vI)));

				switch(vI)
					{
					default:
					case 5:
						r	=	v;
						g	=	v1;
						b	=	v2;
					break;

					case 0:
						r	=	v;
						g	=	v3;
						b	=	v1;
					break;

					case 1:
						r	=	v2;
						g	=	v;
						b	=	v1;
					break;

					case 2:
						r	=	v1;
						g	=	v;
						b	=	v3;
					break;

					case 3:
						r	=	v1;
						g	=	v2;
						b	=	v;
					break;

					case 4:
						r	=	v3;
						g	=	v1;
						b	=	v;
					break;
					}
				}

		r = 255 * r;
		g = 255 * g;
		b = 255 * b;
		
		return [r,g,b];
		}

/* these functions are suspect, but 'accurate' to get L in lab which is needed for setVertical */

function xyz2lab(xyz)
	{
		// http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html
	X = xyz[0];
	Y = xyz[0];
	Z = xyz[0];
		ref_X =  100;
		ref_Y = 100;
		ref_Z = 100;

	var_X = X / ref_X  ;        //ref_X =  95.047  Observer= 2°, Illuminant= D65
	var_Y = Y / ref_Y   ;       //ref_Y = 100.000
	var_Z = Z / ref_Z  ;        //ref_Z = 108.883

	if ( var_X > .0088564516790356308171716757554635 ) {var_X = Math.pow(var_X , ( 1/3 ));}
	else                    {var_X = ( 7.787037037037037037037037037037 * var_X ) + ( 16 / 116 );}
	if ( var_Y > .0088564516790356308171716757554635 ) {var_Y = Math.pow(var_Y , ( 1/3 ));}
	else                    {var_Y = ( 7.787037037037037037037037037037 * var_Y ) + ( 16 / 116 );}
	if ( var_Z > .0088564516790356308171716757554635 ) {var_Z = Math.pow(var_Z , ( 1/3 ));}
	else                    {var_Z = ( 7.787037037037037037037037037037 * var_Z ) + ( 16 / 116 );}

	L = ( 116 * var_Y ) - 16;
	a = 500 * ( var_X - var_Y );
	b = 200 * ( var_Y - var_Z );

	return [L,a,b];
	}

function rgb2xyz(rgb)
	{
		// http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html {assume NOT sRGB}
	
	R = rgb[0] ;
	G = rgb[1] ;
	B = rgb[2] ;


	var_R = ( R / 255 )        //Where R = 0 ÷ 255
	var_G = ( G / 255 )        //Where G = 0 ÷ 255
	var_B = ( B / 255 )        //Where B = 0 ÷ 255

	//alert("R: "+var_R+" G: "+var_G+ " B: "+var_B);

	if ( var_R > 0.04045 ) {var_R = Math.pow(( ( var_R + 0.055 ) / 1.055 ) , 2.4);}
	else                   {var_R = var_R / 12.92;}
	if ( var_G > 0.04045 ) {var_G = Math.pow(( ( var_G + 0.055 ) / 1.055 ) , 2.4);}
	else                   {var_G = var_G / 12.92;}
	if ( var_B > 0.04045 ) {var_B = Math.pow(( ( var_B + 0.055 ) / 1.055 ) , 2.4);}
	else                   {var_B = var_B / 12.92;}

	var_R = var_R * 100
	var_G = var_G * 100
	var_B = var_B * 100

	//Observer. = 2°, Illuminant = D65
	X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805
	Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722
	Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505

	return [X,Y,Z];
	}
