// ================================================================================================================================
//
//	Conversion of color coordinates
//	from RGB (red, green, blue)
//	to   HSB (hue, saturation, brightness) and vice versa.
//
//	Source:	http://www.cs.rit.edu/~ncs/color/t_convert.html
//
//	Converted to JavaScript by Henk Reints, January 2003
//
//	r, g, b	in [0..1]	(red, green, blue)
//	h	in [0..360>	(hue)
//	s	in [0..1]	(saturation)
//	b	in [0..1]	(brightness)
//
//	{s,h} are polar coordinates where h is the angle, so if s = 0 the value of h is irrelevant;
//	it can be any value without affecting the result; h = 0 will be returned in that case.
//
//	function RGBtoHSB (rgb)		accepts Array with r,g,b as input and returns Array with h,s,b
//	function HSBtoRGB (hsb)		accepts Array with h,s,b as input and returns Array with r,g,b
//
//	-------------------------------------------------------------------------------------------------------------------
//	the functions above are the actual conversion routines, the functions below handle different color representations:
//	-------------------------------------------------------------------------------------------------------------------
//
//	function RGB256toHSB (rgb)	is same as RGBtoHSB but accepts rgb values in [0..255]
//	function HSBtoRGB256 (hsb)	is same as HSBtoRGB but returns integer rgb values in [0..255]
//
//	function HTMLtoRGB256 (hex)	returns an RGB256 Array derived from an HTML RGB color code in #RRGGBB hex format
//	function RGB256toHTML (rgb)	returns an HTML RGB color code in #RRGGBB hex format derived from an RGB256 Array
//
//	function HTMLtoHSB (hex)	returns an HSB Array derived from an HTML RGB color code in #RRGGBB hex format
//	function HSBtoHTML (hsb)	returns an HTML RGB color code in #RRGGBB hex format derived from an HSB Array
//
// ================================================================================================================================

function RGBtoHSB (rgb)
{	var r = rgb[0], g = rgb[1], b = rgb[2], m = Math.min(r,g,b), M = Math.max(r,g,b), d = M-m
	return [(((d==0 ? 0 : r==M ? (g-b)/d : g==M ? 2+(b-r)/d : 4+(r-g)/d)+6)%6)*60, (M==0 ? 0 : d/M), M]
}

function HSBtoRGB (hsb)
{	var h = hsb[0]/60, s = hsb[1], v = hsb[2]
	var i = Math.floor(h), f = h-i, p = v*(1-s), q = v*(1-s*f), t = v*(1-s*(1-f))
	return [[v,t,p],[q,v,p],[p,v,t],[p,q,v],[t,p,v],[v,p,q]][i]
}

function RGB256toHSB	(rgb)	{return RGBtoHSB( [rgb[0]/255, rgb[1]/255, rgb[2]/255] ) }

function HSBtoRGB256	(hsb)	{var rgb = HSBtoRGB(hsb); return [Math.round(rgb[0]*255), Math.round(rgb[1]*255), Math.round(rgb[2]*255) ] }

function HTMLtoRGB256	(hex)	{return [parseInt(hex.substr(1,2),16), parseInt(hex.substr(3,2),16), parseInt(hex.substr(5,2),16) ] }

function RGB256toHTML	(rgb)	{return "#" +	[ ("0"+rgb[0].toString(16)).slice(-2)
						, ("0"+rgb[1].toString(16)).slice(-2)
						, ("0"+rgb[2].toString(16)).slice(-2)
						].join("").toUpperCase() }

function HTMLtoHSB	(hex)	{return RGB256toHSB (HTMLtoRGB256 (hex) ) }

function HSBtoHTML	(hsb)	{return RGB256toHTML (HSBtoRGB256 (hsb) ) }

// ================================================================================================================================
//	now define some arrays holding all HTML color names and their color codes:
// ================================================================================================================================

// next list obtained from http://msdn.microsoft.com/workshop/author/dhtml/reference/colors/colors.asp
colorDefinitions =
[["#F0F8FF","aliceblue"]	,["#FAEBD7","antiquewhite"]	,["#00FFFF","aqua"]			,["#7FFFD4","aquamarine"]
,["#F0FFFF","azure"]		,["#F5F5DC","beige"]		,["#FFE4C4","bisque"]			,["#000000","black"]
,["#FFEBCD","blanchedalmond"]	,["#0000FF","blue"]		,["#8A2BE2","blueviolet"]		,["#A52A2A","brown"]
,["#DEB887","burlywood"]	,["#5F9EA0","cadetblue"]	,["#7FFF00","chartreuse"]		,["#D2691E","chocolate"]
,["#FF7F50","coral"]		,["#6495ED","cornflowerblue"]	,["#FFF8DC","cornsilk"]			,["#DC143C","crimson"]
,["#00FFFF","cyan"]		,["#00008B","darkblue"]		,["#008B8B","darkcyan"]			,["#B8860B","darkgoldenrod"]
,["#A9A9A9","darkgray"]		,["#006400","darkgreen"]	,["#BDB76B","darkkhaki"]		,["#8B008B","darkmagenta"]
,["#556B2F","darkolivegreen"]	,["#FF8C00","darkorange"]	,["#9932CC","darkorchid"]		,["#8B0000","darkred"]
,["#E9967A","darksalmon"]	,["#8FBC8B","darkseagreen"]	,["#483D8B","darkslateblue"]		,["#2F4F4F","darkslategray"]
,["#00CED1","darkturquoise"]	,["#9400D3","darkviolet"]	,["#FF1493","deeppink"]			,["#00BFFF","deepskyblue"]
,["#696969","dimgray"]		,["#1E90FF","dodgerblue"]	,["#B22222","firebrick"]		,["#FFFAF0","floralwhite"]
,["#228B22","forestgreen"]	,["#FF00FF","fuchsia"]		,["#DCDCDC","gainsboro"]		,["#F8F8FF","ghostwhite"]
,["#FFD700","gold"]		,["#DAA520","goldenrod"]	,["#808080","gray"]			,["#008000","green"]
,["#ADFF2F","greenyellow"]	,["#F0FFF0","honeydew"]		,["#FF69B4","hotpink"]			,["#CD5C5C","indianred"]
,["#4B0082","indigo"]		,["#FFFFF0","ivory"]		,["#F0E68C","khaki"]			,["#E6E6FA","lavender"]
,["#FFF0F5","lavenderblush"]	,["#7CFC00","lawngreen"]	,["#FFFACD","lemonchiffon"]		,["#ADD8E6","lightblue"]
,["#F08080","lightcoral"]	,["#E0FFFF","lightcyan"]	,["#FAFAD2","lightgoldenrodyellow"]	,["#90EE90","lightgreen"]
,["#D3D3D3","lightgrey"]	,["#FFB6C1","lightpink"]	,["#FFA07A","lightsalmon"]		,["#20B2AA","lightseagreen"]
,["#87CEFA","lightskyblue"]	,["#778899","lightslategray"]	,["#B0C4DE","lightsteelblue"]		,["#FFFFE0","lightyellow"]
,["#00FF00","lime"]		,["#32CD32","limegreen"]	,["#FAF0E6","linen"]			,["#FF00FF","magenta"]
,["#800000","maroon"]		,["#66CDAA","mediumaquamarine"]	,["#0000CD","mediumblue"]		,["#BA55D3","mediumorchid"]
,["#9370DB","mediumpurple"]	,["#3CB371","mediumseagreen"]	,["#7B68EE","mediumslateblue"]		,["#00FA9A","mediumspringgreen"]
,["#48D1CC","mediumturquoise"]	,["#C71585","mediumvioletred"]	,["#191970","midnightblue"]		,["#F5FFFA","mintcream"]
,["#FFE4E1","mistyrose"]	,["#FFE4B5","moccasin"]		,["#FFDEAD","navajowhite"]		,["#000080","navy"]
,["#FDF5E6","oldlace"]		,["#808000","olive"]		,["#6B8E23","olivedrab"]		,["#FFA500","orange"]
,["#FF4500","orangered"]	,["#DA70D6","orchid"]		,["#EEE8AA","palegoldenrod"]		,["#98FB98","palegreen"]
,["#AFEEEE","paleturquoise"]	,["#DB7093","palevioletred"]	,["#FFEFD5","papayawhip"]		,["#FFDAB9","peachpuff"]
,["#CD853F","peru"]		,["#FFC0CB","pink"]		,["#DDA0DD","plum"]			,["#B0E0E6","powderblue"]
,["#800080","purple"]		,["#FF0000","red"]		,["#BC8F8F","rosybrown"]		,["#4169E1","royalblue"]
,["#8B4513","saddlebrown"]	,["#FA8072","salmon"]		,["#F4A460","sandybrown"]		,["#2E8B57","seagreen"]
,["#FFF5EE","seashell"]		,["#A0522D","sienna"]		,["#C0C0C0","silver"]			,["#87CEEB","skyblue"]
,["#6A5ACD","slateblue"]	,["#708090","slategray"]	,["#FFFAFA","snow"]			,["#00FF7F","springgreen"]
,["#4682B4","steelblue"]	,["#D2B48C","tan"]		,["#008080","teal"]			,["#D8BFD8","thistle"]
,["#FF6347","tomato"]		,["#40E0D0","turquoise"]	,["#EE82EE","violet"]			,["#F5DEB3","wheat"]
,["#FFFFFF","white"]		,["#F5F5F5","whitesmoke"]	,["#FFFF00","yellow"]			,["#9ACD32","yellowgreen"]
]
colorNames	= []	// each element will get [name,          HTML-RGB-index, HSB-index], will be sorted by name
colorHTML	= []	// each element will get [HTML-RGB code, name-index      HSB-index], will be sorted by HTML-RGB code
colorHSB	= []	// each element will get [H, S, B,       name-index,     RGB-index], different sort possibilities, see below
maxColorNameLength = 0
for (i = 0; i < colorDefinitions.length; i++)
{	colorNames[i] = [colorDefinitions[i][1] ,i ,i]
	colorHTML[i]  = [colorDefinitions[i][0]]
	colorHSB[i]   = HTMLtoHSB(colorHTML[i][0])
	maxColorNameLength = Math.max (colorDefinitions[i][1].length, maxColorNameLength)
}
delete colorDefinitions
colorNames.sort()
for (i = 0; i < colorNames.length; i++)
{	colorHTML[colorNames[i][1]][1] = i
	colorHSB [colorNames[i][2]][3] = i
}
colorHTML.sort()
for (i = 0; i < colorHTML.length; i++)
{	colorNames[colorHTML[i][1]][1] = i
}

switch	(0)	// select HSB sort order
{
	case 11:
		HSBsortOrder = "S+B,S,H"
		colorHSB.sort(function(A,B){var e=A[1]+A[2]-B[1]-B[2];if(e==0)e=A[1]-B[1];if(e==0)e=A[0]-B[0];return e})
		break
	case 10:
		HSBsortOrder = "S+B,B,H"
		colorHSB.sort(function(A,B){var e=A[1]+A[2]-B[1]-B[2];if(e==0)e=A[2]-B[2];if(e==0)e=A[0]-B[0];return e})
		break
	case 9:
		HSBsortOrder = "S+B,H,S"
		colorHSB.sort(function(A,B){var e=A[1]+A[2]-B[1]-B[2];if(e==0)e=A[0]-B[0];if(e==0)e=A[1]-B[1];return e})
		break
	case 8:
		HSBsortOrder = "S+B,H,B"
		colorHSB.sort(function(A,B){var e=A[1]+A[2]-B[1]-B[2];if(e==0)e=A[0]-B[0];if(e==0)e=A[2]-B[2];return e})
		break
	case 7:
		HSBsortOrder = "H,S+B,S"
		colorHSB.sort(function(A,B){var e=A[0]-B[0];if(e==0)e=A[1]+A[2]-B[1]-B[2];if(e==0)e=A[1]-B[1];return e})
		break
	case 6:
		HSBsortOrder = "H,S+B,B"
		colorHSB.sort(function(A,B){var e=A[0]-B[0];if(e==0)e=A[1]+A[2]-B[1]-B[2];if(e==0)e=A[2]-B[2];return e})
		break
	case 5:
		HSBsortOrder = "B,S,H"
		colorHSB.sort(function(A,B){var e=A[2]-B[2];if(e==0)e=A[1]-B[1];if(e==0)e=A[0]-B[0];return e})
		break
	case 4:
		HSBsortOrder = "B,H,S"
		colorHSB.sort(function(A,B){var e=A[2]-B[2];if(e==0)e=A[0]-B[0];if(e==0)e=A[1]-B[1];return e})
		break
	case 3:
		HSBsortOrder = "S,B,H"
		colorHSB.sort(function(A,B){var e=A[1]-B[1];if(e==0)e=A[2]-B[2];if(e==0)e=A[0]-B[0];return e})
		break
	case 2:
		HSBsortOrder = "S,H,B"
		colorHSB.sort(function(A,B){var e=A[1]-B[1];if(e==0)e=A[0]-B[0];if(e==0)e=A[2]-B[2];return e})
		break
	case 1:
		HSBsortOrder = "H,B,S"
		colorHSB.sort(function(A,B){var e=A[0]-B[0];if(e==0)e=A[2]-B[2];if(e==0)e=A[1]-B[1];return e})
		break
	default:
		HSBsortOrder = "H,S,B"
		colorHSB.sort(function(A,B){var e=A[0]-B[0];if(e==0)e=A[1]-B[1];if(e==0)e=A[2]-B[2];return e})
		break
}
// function for comparing two Arrays containing Numbers, element by element:
// function compareNumberArrays(A,B){for(var e=0,i=0;e==0&&i<A.length&&i<B.length;i++)e=A[i]-B[i];return e!=0?e:A.length-B.length})}
// can be used for sorting Arrays of which each element itself is an Array of Numbers: [Array Object].sort(compareNumberArrays)

for (i = 0; i < colorHSB.length; i++)
{	colorNames[colorHSB[i][3]][2] = i			// adjust HSB index in corresponding colorNames element
	colorHSB[i][4] = 1 * colorNames[colorHSB[i][3]][1]	// add RGB index to colorHSB element
	colorHTML[colorHSB[i][4]][2] = i			// add HSB index to corresponding colorHTML element
}
// ======================================================================
// now the color Arrays are ready for use,
// below is code for displaying the color Arrays as plain text or as HTML
// ======================================================================
function fmt(a,w,d)	// format a number, w = no. of positions before decimal point, d = no. of decimals
{	var W = (arguments.length > 1 ? w : 0)
	var D = (arguments.length > 2 ? d : 0)
	var A = Math.round (a * eval ("1E" + D) )
	if (D < 0) {D = -D; A = Math.round (A * eval ("1E" + D) ); D = 0}
	var N = W + D
	var X = "" + A
	while (X.length < D+1) {X = "0" + X}
	while (X.length < N  ) {X = " " + X}
	if (D > 0) X = X.slice(0, -D) + "." + X.slice(-D)
	return X	
}
function pad(x,w,q)	// pad a String to given lengt, optionally enclose it in quotes
{	var Q = (q ? '"' : ''), W = w + 2 * Q.length, X = Q + x + Q
	while (X.length < W) {X += " "}
	return X
}
function listColorArrays()
{
	function write ()
	{	for (var x = "", i = 0; i < arguments.length; i++) x += arguments[i];
		WScript.StdOut.Write (x)
	}
	var E = 0
	for (i = 0; i < colorNames.length; i++)
	{
		write (fmt(i,3) + ":  [")
		write (pad (colorNames[i][0], maxColorNameLength, 1) + "," )
		write (fmt (colorNames[i][1], 3                    ) + "," )
		write (fmt (colorNames[i][2], 3                    ) )
		write ("]  [")
		write (pad (colorHTML [i][0], 0                 , 1) + "," )
		write (fmt (colorHTML [i][1], 3                    ) + "," )
		write (fmt (colorHTML [i][2], 3                    ) )
		write ("]  [")
		write (fmt (colorHSB  [i][0]      , 3, 1           ) + "," )
		write (fmt (colorHSB  [i][1] * 100, 3, 1           ) + "," )
		write (fmt (colorHSB  [i][2] * 100, 3, 1           ) + "," )
		write (fmt (colorHSB  [i][3]      , 3              ) + "," )
		write (fmt (colorHSB  [i][4]      , 3              ) + "]" )

		var X = HSBtoHTML ( [fmt(colorHSB[i][0],3,1), 0.01*fmt(colorHSB[i][1]*100,3,1), 0.01*fmt(colorHSB[i][2]*100,3,1) ] )
		T = colorHTML[colorHSB[i][4]][0]
		write (X == T ? "" :  " " + X + " != " + T)
		if (X != T) E++

		write ("\n")
	}
	if (E > 0) write ("\n" + E + " HSB errors\n");
}
function showColors (wide)
{
	var HTML = ""
	function write ()
	{	for (var x = "", i = 0; i < arguments.length; i++) x += arguments[i];
		HTML += x
	}
	function txtCol(i) // i = HSB index
	{	var h = colorHSB[i][0]
		var s = colorHSB[i][1]
		var b = colorHSB[i][2]
		var x = (colorHSB[i][2] < 0.7 ? "white" : "black")	// dark background => white text, light background => black text
		if (h >= 240 && h < 290 && s > 0.5) x = "white"		// >50% saturated blue-ish background => white text
		return x
	}

	write	(('<table align=center width=600 cellspacing=0><tr><td><p style="font:10pt Arial" align=justify>'

		+'The HTML color names and corresponding RGB values have been copied from the '
		+'<nobr><a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/colors/colors.asp">Color Table</a></nobr> '
		+'at '
		+'<nobr><a href="http://msdn.microsoft.com/library/">Microsoft\'s MSDN Library.</a></nobr>'

		+'<p style="font:10pt Arial" align=justify>'
		+'The [H,S,B] = Hue, Saturation, and Brightness values are computed using the algorithm found at '
		+ '<nobr><a href="http://www.cs.rit.edu/~ncs/color/t_convert.html">Color Conversion Algorithms</a></nobr> by '
		+'<nobr><a href="http://www.cs.rit.edu/~ncs/color/t_convert.html">Nan C. Schaller</a>.</nobr> '
		+'See also her page '
		+ '<nobr><a href="http://www.cs.rit.edu/~ncs/color/">Introduction to Color</a></nobr> for more about colors, including some nice java applets. '
		+'Hue ranges from 0 to 360 (degrees). Saturation and brightness both range from 0 to 1, on this page they are given as percentages from 0 to 100.'

		+'<p style="font:10pt Arial" align=center>'
		+'<a href="index.htm">Henk-Reints.nl</a>'

		+'</td></tr></table><p>'
		+(wide	? '\\<table border=1 cellspacing=0 cellpadding=5  bgcolor=white style="font:  8pt Courier New">'
			: '\\<table border=1 cellspacing=0 cellpadding=20 bgcolor=white style="font: 10pt Courier New">'
		 )
		).replace(/\s/g,"``")
		)


	var TR1 = "\\<TR><TD>", TR0 = "\\</TD></TR>", TD0 = "\\</TD><TD>"

	write	( TR1	+ "<b>"	+ pad("Ordered by HTML Color Name"	,32)	+ "</b>"
		+ TD0	+ "<b>"	+ pad("Ordered by HTML Color Code (RGB)",32)	+ "</b>"
		+ TD0	+ "<b>"	+ pad("Ordered by " + HSBsortOrder	,32)	+ "</b>"
		+ TR0)

	var D = 3, E = 0
	for (i = 0, j = colorNames.length; i < colorNames.length; i++)
	{
		window.status = "" + j--
		var X = HSBtoHTML ( [colorHSB[i][0], colorHSB[i][1], colorHSB[i][2] ] )

		var TD1 = ( "\\<TR><TD bgcolor=" + colorNames[i][0] + " style='color:" + txtCol(colorNames[i][2] ) + "'>").replace(/\s/g,"``")
		var TD2 = ("\\</TD><TD bgcolor=" + colorHTML [i][0] + " style='color:" + txtCol(colorHTML [i][2] ) + "'>").replace(/\s/g,"``")
		var TD3 = ("\\</TD><TD bgcolor=" + X                + " style='color:" + txtCol(i                ) + "'>").replace(/\s/g,"``")

		write (TD1 + (wide ? "" : "col: ") )
		write (pad (colorNames[i][0], maxColorNameLength)		+ (wide ? " "  : "<br>rgb: " ) )
		write (colorHTML[colorNames[i][1]][0]				+ (wide ? " [" : "<br>hsb: [") )
		var k = colorNames[i][2]
		write (fmt (colorHSB[k][0]      , 3, 1)				+ ",")
		write (fmt (colorHSB[k][1] * 100, 3, 1)				+ ",")
		write (fmt (colorHSB[k][2] * 100, 3, 1)				+ "]")

		write (TD2 + (wide ? "" : "col: ") )
		write (pad (colorNames[colorHTML[i][1]][0], maxColorNameLength)	+ (wide ? " "  : "<br>rgb: " ) )
		write (pad (colorHTML[i][0], 0)					+ (wide ? " [" : "<br>hsb: [") )
		var k = colorHTML[i][2]
		write (fmt (colorHSB[k][0]      , 3, 1)				+ ",")
		write (fmt (colorHSB[k][1] * 100, 3, 1)				+ ",")
		write (fmt (colorHSB[k][2] * 100, 3, 1)				+ "]")

		write (TD3 + (wide ? "" : "col: ") )
		write (pad (colorNames[colorHSB[i][3]][0], maxColorNameLength)	+ (wide ? " "  : "<br>rgb: " ) )
		write (colorHTML[colorHSB[i][4]][0]				+ (wide ? " [" : "<br>hsb: [") )
		write (fmt (colorHSB[i][0]      , 3, 1)				+ ",")
		write (fmt (colorHSB[i][1] * 100, 3, 1)				+ ",")
		write (fmt (colorHSB[i][2] * 100, 3, 1)				+ "]")

		write (TR0)
	}
	write ("\n</table>\n")

	HTML = HTML.replace(/\n/g,"\\").replace(/\s/g,"&nbsp;").replace(/``/g," ").replace(/\\/g,"\n")
//	HTML = HTML.replace(/\n/g,"<br>\n").replace(/</g,"&lt;")

	window.status = ""
	return HTML
}
function showPalette()
{
	function row (s,b)
	{	window.status = "" + [fmt(s,1,2), fmt(b,1,2) ]
		var HTML = "<tr>"
		for (var h = 0; h < 360; h += 2)
		{	HTML += "<td width=2 height=2 bgcolor=" + HSBtoHTML ( [(h-45+360)%360,s,b] ) + "></td>"
		}
		HTML += "</tr>"
		return HTML
	}
	var HTML = ["<table border=0 cellspacing=0 cellpadding=0>"]
	for (var s = 0, b = 1; s <  1; s += 0.02) HTML.push (row (s,b) );
	for (var s = 1, b = 1; b >= 0; b -= 0.02) HTML.push (row (s,b) );
	HTML.push ("</table>")
	window.status = ""
	return HTML.join("")
}
function outputHTML ()
{
	var HTML = ''
	HTML += '<html><head><title>' + document.title + '</title></head>'
	HTML += '<body bgcolor=lightgrey link=blue vlink=blue alink=red style="font: 12pt Arial;"><center>\n'
	HTML += '<b><u>' + document.title + '</u></b><p>\n'
	HTML += showColors(1) + '\n'
//	HTML += '<p>\n'
//	HTML += showPalette() + '\n'
	HTML += '</center></body></html>\n'
	document.write (HTML)
}

try		{listColorArrays() }					//  will fail if not running in cscript
catch (e)	{document.clear(); setTimeout ("outputHTML()", 1) }	// in which case html is assumed

// ================================================================================================================================
// [end of file] -- Copyright (c) 2003 Henk-Reints.nl

