/* --------------------------------------------------------------------------------
   Farbwahl

   Autor: Dietmar Rabich
   Datei: farbwahl.js

   Copyright (c) Dietmar Rabich, Duelmen.
   Alle Rechte vorbehalten.

   Diese Datei stammt von http://skripte.rabich.de/.

   Das Entfernen oder Veraendern dieser Informationen ist
   ohne ausdrueckliche Zustimmung des Autors nicht gestattet.

   Aenderungen:
   5.10.2003  Erstellung
-------------------------------------------------------------------------------- */

var	hexziffern	= new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F");

// Dezimalzahl in Hex umwandeln
function dezhex(x)
{
	var	dwert	= parseInt(x);
	if(isNaN(dwert))
	{
		alert("Dezimalzahlen bestehen nur aus den Ziffern 0 bis 9!");
		return x;
	}

	var	wert	= "";

	while(dwert > 0)
	{
		zf	= dwert % 16;
		wert	= hexziffern[zf] + wert;
		dwert	-= zf;
		dwert	/= 16;
	}

	return wert;
}

// Zweistellige Hexzahl
function doublehex(x)
{
	var	tmp	= "00" + dezhex(x);
	tmp	= tmp.substring(tmp.length - 2, tmp.length);
	return tmp;
}

// Limitierung des Werts
function limit(w, mi, ma)
{
	if(w > ma)
		return ma;
	if(w < mi)
		return mi;
	return w;
}

// Maximum aller uebergebenen Werte
function max()
{
	if(arguments.length <= 0)
		return null;
	var	m	= arguments[0];
	var	i;
	for(i = 1; i < arguments.length; i++)
		if(arguments[i] > m)
			m	= arguments[i];
	return m;
}

// Minimum aller uebergebenen Werte
function min()
{
	if(arguments.length <= 0)
		return null;
	var	m	= arguments[0];
	var	i;
	for(i = 1; i < arguments.length; i++)
		if(arguments[i] < m)
			m	= arguments[i];
	return m;
}

// Formularwerte RGB in Objekte uebertragen
function getRGB(form)
{
	this.r	= parseInt(form.R.value);
	this.g	= parseInt(form.G.value);
	this.b	= parseInt(form.B.value);
	if(isNaN(this.r))
		this.r	= 0;
	if(isNaN(this.g))
		this.g	= 0;
	if(isNaN(this.b))
		this.b	= 0;
	this.r = limit(this.r, 0, 255);
	this.g = limit(this.g, 0, 255);
	this.b = limit(this.b, 0, 255);

	return this;
}

// Formularwerte HSB in Objekte uebertragen
function getHSB(form)
{
	this.h	= parseInt(form.H.value);
	this.s	= parseInt(form.S.value);
	this.b	= parseInt(form.V.value);
	if(isNaN(this.h))
		this.h	= 0;
	if(isNaN(this.s))
		this.s	= 0;
	if(isNaN(this.b))
		this.b	= 0;
	this.h = limit(this.h, 0, 359);
	this.s = limit(this.s, 0, 100);
	this.b = limit(this.b, 0, 100);

	return this;
}

// Formularwerte RGB setzen
function setRGB(form, rgb)
{
	form.R.value	= rgb.r;
	form.G.value	= rgb.g;
	form.B.value	= rgb.b;
}

// Formularwerte HSB setzen
function setHSB(form, hsb)
{
	form.H.value	= hsb.h;
	form.S.value	= hsb.s;
	form.V.value	= hsb.b;
}

// HSB aus RGB berechnen (als Objekt)
function makeHSB(rgb)
{
	var	ma	= max(rgb.r, rgb.g, rgb.b);
	var	mi	= min(rgb.r, rgb.g, rgb.b);
	var	delta	= ma - mi;

	if(delta == 0)
		this.h	= 0;
	else
	{
		if(rgb.r == ma)
			this.h	= (rgb.g - rgb.b) / delta;
		else if(rgb.g == ma)
			this.h	= 2 + (rgb.b - rgb.r) / delta;
		else if(rgb.b == ma)
			this.h	= 4 + (rgb.r - rgb.g) / delta;

		this.h	*= 60;
		this.h	= (this.h < 0) ? (this.h + 360) : this.h;
		this.h	= limit(Math.round(this.h), 0, 359);
	}
	this.b	= limit(Math.round(100 * ma / 255), 0, 100);
	this.s	= limit(Math.round((ma == 0) ? 0 : (100 * delta / ma)), 0, 100);
}

// RGB aus HSB berechnen (als Objekt)
function makeRGB(hsb)
{
	var	h	= hsb.h / 360;
	var	s	= hsb.s / 100;
	var	b	= hsb.b / 100;

	if(s == 0)
	{
		this.r	= b;
		this.g	= b;
		this.b	= b;
	}
	else
	{
		h	= (h == 1) ? 0 : (6 * h)
		var	p	= b * (1 - s)
		var	f	= h - Math.floor(h);
		var	q	= p + (b - p) * (h - Math.floor(h));
		var	t	= b - (b - p) * (h - Math.floor(h));

		if(h < 1)
		{
			this.r	= b;
			this.g	= q;
			this.b	= p;
		}
		else if(h < 2)
		{
			this.r	= t;
			this.g	= b;
			this.b	= p;
		}
		else if(h < 3)
		{
			this.r	= p;
			this.g	= b;
			this.b	= q;
		}
		else if(h < 4)
		{
			this.r	= p;
			this.g	= t;
			this.b	= b;
		}
		else if(h < 5)
		{
			this.r	= q;
			this.g	= p;
			this.b	= b;
		}
		else
		{
			this.r	= b;
			this.g	= p;
			this.b	= t;
		}
	}

   	this.r = limit(Math.round(this.r * 255), 0, 255);
   	this.g = limit(Math.round(this.g * 255), 0, 255);
   	this.b = limit(Math.round(this.b * 255), 0, 255);
}

// Eingabepruefung
function pruefung(form)
{
	var	rgb	= new getRGB(form);
	var	hsb	= new getHSB(form);

	setRGB(form, rgb);
	setHSB(form, hsb);

	return true;
}

// Setzt einen Wert
function setze(id, rgb)
{
	document.getElementById(id).style.backgroundColor	= "rgb(" + rgb.r + "," + rgb.g + "," + rgb.b + ")";
	document.getElementById(id + "_text").innerHTML	="#" + doublehex(rgb.r) +
					doublehex(rgb.g) +
					doublehex(rgb.b);
}

// Setzt HSB/H-Wert
function setzeHsbFs(hsb, chg, id)
{
	var	hsb_temp	= new Object();
	hsb_temp.h	= (hsb.h + chg + 360) % 360;
	hsb_temp.s	= hsb.s;
	hsb_temp.b	= hsb.b;

	var	rgb	= new makeRGB(hsb_temp);
	setze(id, rgb);
}

// Setzt HSB/S-Wert
function setzeHsbS(hsb, chg, id)
{
	var	hsb_temp	= new Object();
	hsb_temp.h	= hsb.h;
	hsb_temp.s	= limit(hsb.s + chg, 0, 100);
	hsb_temp.b	= hsb.b;

	var	rgb	= new makeRGB(hsb_temp);
	setze(id, rgb);
}

// Setzt HSB/B-Wert
function setzeHsbB(hsb, chg, id)
{
	var	hsb_temp	= new Object();
	hsb_temp.h	= hsb.h;
	hsb_temp.s	= hsb.s;
	hsb_temp.b	= limit(hsb.b + chg, 0, 100);

	var	rgb	= new makeRGB(hsb_temp);
	setze(id, rgb);
}

// Setzt RGB/R-Wert
function setzeRgbR(rgb, chg, id)
{
	var	rgb_temp	= new Object();
	rgb_temp.r	= limit(rgb.r + chg, 0, 255);
	rgb_temp.g	= rgb.g;
	rgb_temp.b	= rgb.b;

	setze(id, rgb_temp);
}

// Setzt RGB/G-Wert
function setzeRgbG(rgb, chg, id)
{
	var	rgb_temp	= new Object();
	rgb_temp.r	= rgb.r;
	rgb_temp.g	= limit(rgb.g + chg, 0, 255);
	rgb_temp.b	= rgb.b;

	setze(id, rgb_temp);
}

// Setzt RGB/B-Wert
function setzeRgbB(rgb, chg, id)
{
	var	rgb_temp	= new Object();
	rgb_temp.r	= rgb.r;
	rgb_temp.g	= rgb.g;
	rgb_temp.b	= limit(rgb.b + chg, 0, 255);

	setze(id, rgb_temp);
}

// Setzt RGB/RG-Wert
function setzeRgbRG(rgb, chg, id)
{
	var	rgb_temp	= new Object();
	rgb_temp.r	= limit(rgb.r + chg, 0, 255);
	rgb_temp.g	= limit(rgb.g + chg, 0, 255);
	rgb_temp.b	= rgb.b;

	setze(id, rgb_temp);
}

// Setzt RGB/RB-Wert
function setzeRgbRB(rgb, chg, id)
{
	var	rgb_temp	= new Object();
	rgb_temp.r	= limit(rgb.r + chg, 0, 255);
	rgb_temp.g	= rgb.g;
	rgb_temp.b	= limit(rgb.b + chg, 0, 255);

	setze(id, rgb_temp);
}

// Setzt RGB/GB-Wert
function setzeRgbGB(rgb, chg, id)
{
	var	rgb_temp	= new Object();
	rgb_temp.r	= rgb.r;
	rgb_temp.g	= limit(rgb.g + chg, 0, 255);
	rgb_temp.b	= limit(rgb.b + chg, 0, 255);

	setze(id, rgb_temp);
}

// Setzt beliebigen HSB-Wert
function setzeHsb(h, s, b, id)
{
	var	hsb_temp	= new Object();
	hsb_temp.h	= limit(h, 0, 359);
	hsb_temp.s	= limit(s, 0, 100);
	hsb_temp.b	= limit(b, 0, 100);

	var	rgb	= new makeRGB(hsb_temp);
	setze(id, rgb);
}

// Berechnet diverse Farbvarianten
function varianten(rgb, hsb)
{
	// Variation der Farbschattierung
	setzeHsbFs(hsb, -40, "hsb_hmm")
	setzeHsbFs(hsb, -20, "hsb_hm")
	setzeHsbFs(hsb, 0, "hsb_h")
	setzeHsbFs(hsb, 20, "hsb_hp")
	setzeHsbFs(hsb, 40, "hsb_hpp")

	// Variation der Saettigung
   	setzeHsbS(hsb, -30, "hsb_smm")
	setzeHsbS(hsb, -15, "hsb_sm")
	setzeHsbS(hsb, 0, "hsb_s")
	setzeHsbS(hsb, 15, "hsb_sp")
	setzeHsbS(hsb, 30, "hsb_spp")

	// Variation der Helligkeit
	setzeHsbB(hsb, -30, "hsb_bmm")
	setzeHsbB(hsb, -15, "hsb_bm")
	setzeHsbB(hsb, 0, "hsb_b")
	setzeHsbB(hsb, 15, "hsb_bp")
	setzeHsbB(hsb, 30, "hsb_bpp")

	// Variation des Rot-Werts
	setzeRgbR(rgb, -102, "rgb_rmm")
	setzeRgbR(rgb, -51, "rgb_rm")
	setzeRgbR(rgb, 0, "rgb_r")
	setzeRgbR(rgb, 51, "rgb_rp")
	setzeRgbR(rgb, 102, "rgb_rpp")

	// Variation des Gruen-Werts
	setzeRgbG(rgb, -102, "rgb_gmm")
	setzeRgbG(rgb, -51, "rgb_gm")
	setzeRgbG(rgb, 0, "rgb_g")
	setzeRgbG(rgb, 51, "rgb_gp")
	setzeRgbG(rgb, 102, "rgb_gpp")

	// Variation des Blau-Werts
	setzeRgbB(rgb, -102, "rgb_bmm")
	setzeRgbB(rgb, -51, "rgb_bm")
	setzeRgbB(rgb, 0, "rgb_b")
	setzeRgbB(rgb, 51, "rgb_bp")
	setzeRgbB(rgb, 102, "rgb_bpp")

	// Variation des Gelb-Werts
	setzeRgbRG(rgb, -102, "rgb_rgmm")
	setzeRgbRG(rgb, -51, "rgb_rgm")
	setzeRgbRG(rgb, 0, "rgb_rg")
	setzeRgbRG(rgb, 51, "rgb_rgp")
	setzeRgbRG(rgb, 102, "rgb_rgpp")

	// Variation des Magenta-Werts
	setzeRgbRB(rgb, -102, "rgb_rbmm")
	setzeRgbRB(rgb, -51, "rgb_rbm")
	setzeRgbRB(rgb, 0, "rgb_rb")
	setzeRgbRB(rgb, 51, "rgb_rbp")
	setzeRgbRB(rgb, 102, "rgb_rbpp")

	// Variation des Tuerkis-Werts
	setzeRgbGB(rgb, -102, "rgb_gbmm")
	setzeRgbGB(rgb, -51, "rgb_gbm")
	setzeRgbGB(rgb, 0, "rgb_gb")
	setzeRgbGB(rgb, 51, "rgb_gbp")
	setzeRgbGB(rgb, 102, "rgb_gbpp")

	// Freie Variation
	var	ns	= (hsb.s > 50) ? -40 : 40;
	var	nb	= (hsb.b > 70) ? -30 : 30;

   	setzeHsb(hsb.h, hsb.s, hsb.b + nb, "var1");

	var	h	= hsb.h;
	var	s	= hsb.s;
	var	b	= hsb.b;

	if(h < 30)
	{
		h	+= 20;
	}
	else if(h < 60)
	{
		h	+= 150;
		s	-= -30;
		b	-= -20;
	}
	else if(h < 180)
	{
		h	-= 40;
	}
	else if(h < 220)
	{
		h	-= 160;
	}
	else if(h < 300)
	{
		s	-= 60;
	}
	else
	{
		h	+= 20;
		h	%= 360;
		s	+= ns;
	}
   	setzeHsb(h, s, b, "var2");

	h	= hsb.h;
	s	= hsb.s;
	b	= hsb.b;

	if(h < 30)
	{
		h	+= 20;
		b	+= nb;
	}
	else if(h < 60)
	{
		h	+= 150;
		s	-= 70;
		b	+= 20;
	}
	else if(h < 180)
	{
		h	-= 40;
		b	+= nb;
	}
	else if(h < 220)
	{
		h	-= 170;
		b	+= nb;
	}
	else if(h < 300)
	{
		s	-= 60;
		b	+= nb;
	}
	else
	{
		h	+= 20;
		h	%= 360;
		s	+= ns;
		b	+= nb;
	}
   	setzeHsb(h, s, b, "var3");

   	setzeHsb(hsb.h, hsb.s, 100 - hsb.b, "var4");
   	setzeHsb(0, 0, hsb.b, "var5");
}

// Berechnung der Farbwerte
function berechnen(form, basis_rgb)
{
	if(!pruefung(form))
		return;

	var	rgb;
	var	hsb;

	// Fuer direkte Farbeingabe ein klein wenig schummeln
	if(basis_rgb == null)
	{
		var	farbe	= form.RGBFarbwert.value;
		rgb	= new Object();
		if(farbe.length <= 1)
		{
			rgb.r	= 255;
			rgb.g	= 255;
			rgb.b	= 255;
			basis_rgb	= true;
		}
		else
		{
			if(farbe.substr(0, 1) != "#")
				farbe	= "#" + farbe;
			farbe	+= "FFFFFF";
			rgb.r	= parseInt(farbe.substr(1, 2), 16);
			rgb.g	= parseInt(farbe.substr(3, 2), 16);
			rgb.b	= parseInt(farbe.substr(5, 2), 16);
			if(isNaN(rgb.r))
				rgb.r	= 255;
			if(isNaN(rgb.g))
				rgb.g	= 255;
			if(isNaN(rgb.b))
				rgb.b	= 255;
			basis_rgb	= true;
		}
		setRGB(form, rgb);
	}

	if(basis_rgb)
	{
		rgb	= new getRGB(form);
		hsb	= new makeHSB(rgb);
		setHSB(form, hsb);
	}
	else
	{
		hsb	= new getHSB(form);
		rgb	= new makeRGB(hsb);
		setRGB(form, rgb);
	}

	form.RGBFarbwert.value	= "#" + doublehex(rgb.r) +
					doublehex(rgb.g) +
					doublehex(rgb.b);
	document.getElementById("Anzeige").style.backgroundColor	= form.RGBFarbwert.value;

	varianten(rgb, hsb);
}

// Naheliegende Idealfarbe
function ideal(form)
{
	function iround(val)
	{
		var	r	= val % 51;
		var	n	= (val - r) / 51;
		return ((r <= 25) ? n : (n+ 1)) * 51;
	}

	if(!pruefung(form))
		return;

	form.R.value	= iround(parseInt(form.R.value));
	form.G.value	= iround(parseInt(form.G.value));
	form.B.value	= iround(parseInt(form.B.value));

	berechnen(form, true);
}

// Feld addieren
function add(form, feld, inc)
{
	var	twert	= parseInt(form[feld].value);
	if(isNaN(twert))
	{
		alert("Bei dem Wert handelt es sich nicht um eine Zahl!");
		return;
	}
	twert	+= inc;
	if(twert > 255)
		twert	= 255;

	form[feld].value	= twert;

	berechnen(form, true);
}

// Feld subtrahieren
function sub(form, feld, dec)
{
	var	twert	= parseInt(form[feld].value);
	if(isNaN(twert))
	{
		alert("Bei dem Wert handelt es sich nicht um eine Zahl!");
		return;
	}
	twert	-= dec;
	if(twert < 0)
		twert	= 0;

	form[feld].value	= twert;

	berechnen(form, true);
}

// EOF