
/** Functions for colorizing some or all of the images on a page
@licstart  The following is the entire license notice for the 
JavaScript code in this page.
Copyright (C) 2009 Adrian

The JavaScript code in this page is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version.  The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.

As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.
@licend  The above is the entire license notice
for the JavaScript code in this page.
**/


//this code borrows concepts from a variety of sources
//it requires html5 support and a pretty fast js interpreter

//http://en.wikipedia.org/wiki/Rec._709
var luminosityRed = .2126;
var luminosityGreen = .7152;
var luminosityBlue = .0722;

function colorizeAllImages(allSame) {
	var hsl = randomHSL();
	var canvases = document.getElementsByTagName("canvas");
	for(var i = 0; i<canvases.length; i++) {
		if(!allSame) hsl = randomHSL();
		colorizeImage(canvases[i], hsl);
	}
	
	var images = document.getElementsByTagName("img");
	while(images.length>0) {
		if(!allSame) hsl = randomHSL();
		colorizeImage(images[0], hsl);
	}
}

function setupOutputContext(input) {
	if(input.savedInput == null) {
		//first time
		var output = document.createElement("canvas");
		input.parentNode.replaceChild(output,input);
		//save off the input
		output.savedInput = input;
	}
	else {
		var output = input;
		input = input.savedInput;
	}

	var outputContext = output.getContext("2d");

	output.height = input.height;
	output.width = input.width;
	
	outputContext.drawImage(input, 0, 0, output.width, output.height);

	return outputContext;
}


function colorizeImage(input, hsl) {
	
	var outputContext = setupOutputContext(input);


	var imageData = outputContext.getImageData(0, 0, input.width, input.height);
	var data = imageData.data;
		
	var saturationBig=hsl.saturation*255;
	
	var hueRed = normalizeHue(hsl.hue+2);
	var hueGreen = normalizeHue(hsl.hue);
	var hueBlue = normalizeHue(hsl.hue-2);

	for(i=0;i<data.length;i+=4) {
		//var d = data[i]+data[i+1]+data[i+2];
		//var max = Math.max(Math.max(data[i],data[i+1]),data[i+2]);
		//var min = Math.min(Math.min(data[i],data[i+1]),data[i+2]);
		

		var luminosity = luminosityRed * data[i] + luminosityGreen * data[i+1] + luminosityBlue * data[i+2];//45
		
		if(hsl.lightness > 0) {//9
			luminosity *= 1 - hsl.lightness;
			luminosity -= hsl.lightness * 255;
		}
		else {
			luminosity *= hsl.lightness + 1;
		}
		luminosity=Math.min(Math.max(luminosity,0),255);
		
		var q = luminosity>.5*255 ? luminosity + saturationBig - luminosity*hsl.saturation : luminosity * (hsl.saturation+1);//14
		var p = 2 * luminosity - q;//10
		//70 (174)
		/*
		data[i]=normalize(hueRed,q,p);
		data[i+1]=normalize(hueGreen,q,p);
		data[i+2]=normalize(hueBlue,q,p);
		*/
		//47 (151)
		//unwrapped (for speed) from normalize below
		data[i] = hueRed < 1 ? p+(q-p)*hueRed : hueRed < 3 ? q : hueRed < 4 ? p+(q-p)*(4-hueRed) : p;
		data[i+1] = hueGreen < 1 ? p+(q-p)*hueGreen : hueGreen < 3 ? q : hueGreen < 4 ? p+(q-p)*(4-hueGreen) : p;
		data[i+2] = hueBlue < 1 ? p+(q-p)*hueBlue : hueBlue < 3 ? q : hueBlue < 4 ? p+(q-p)*(4-hueBlue) : p;
	}
	outputContext.putImageData(imageData, 0, 0);
}

function randomHSL() {
	return {
		hue: Math.random()*6,
		saturation: Math.random()*.4,
		lightness: Math.random()*.2-.1
	};
}

function normalizeHue(hue) {
	return hue > 6 ? hue-6 : hue < 0 ? hue+6 : hue;
}
/*
//code to this function is unwrapped (for speed) above.
function normalize(hue, q, p) {
	if(hue < 1) return p+(q-p)*hue;
	if(hue < 3) return q;
	if(hue < 4) return p+(q-p)*(4-hue);
	return p;
}
*/


