/*
 * Javascript Image Effects - Core Functions
 * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com
 * This software is free to use for non-commercial purposes. For anything else, please contact the author.
 */

var jsImageFX = {

	effects : {}, 

	doEffects : function(oImg, oCanvasImg, strFilter) 
	{
		var bHasCanvas = false;
		var bHasCanvasImageData = false;
		var bIsIE = !!(window.attachEvent && !window.opera);  // ew..

		var oCanvas = document.createElement("canvas");
		if (oCanvas.getContext) {
			bHasCanvas = true;
			var oCtx = oCanvas.getContext("2d");
			if (oCtx.getImageData) {
				bHasCanvasImageData = true;
			}
		}

		var iWidth = parseInt(oImg.offsetWidth);
		var iHeight = parseInt(oImg.offsetHeight);

		var strFilterName = strFilter;
		var oOptions = {};

		var oArgs = {};
		if (strFilter.indexOf("(") > -1) {
			strFilterName = strFilter.substr(0, strFilter.indexOf("("));
			var aArg = strFilter.match(/\((.*?)\)/);
			if (aArg[1]) {
				aArg = aArg[1].split(";");
				for (var a=0;a<aArg.length;a++) {
					aThisArg = aArg[a].split("=");
					if (aThisArg.length == 2)
						oArgs[aThisArg[0]] = aThisArg[1];
				}
			}
		}

		if (typeof jsImageFX.effects[strFilterName] != "function") {
			return false;
		}

		if (bHasCanvas) {
			oCanvas.width = iWidth;
			oCanvas.height = iHeight;
			oCanvas.style.width = iWidth;
			oCanvas.style.height = iHeight;
	
			oCtx.drawImage(oCanvasImg, 0, 0, iWidth, iHeight);
		}

		var oImage = {
			image : oImg,
			canvas : oCanvas,
			width : iWidth,
			height : iHeight,
			client : {
				hasCanvas : bHasCanvas,
				hasCanvasImageData : bHasCanvasImageData,
				isIE : bIsIE
			},
			useData : true
		}

		var bRes = jsImageFX.effects[strFilterName](oImage, oArgs);

		if (bHasCanvas) {
			if (oImage.useData) {
				if (bHasCanvasImageData) {
					oCanvas.getContext("2d").putImageData(oImage.canvasData, 0, 0);
					// Opera doesn't seem to update the canvas until we draw something on it, lets draw a 0x0 rectangle.
					oCanvas.getContext("2d").fillRect(0,0,0,0);
				}
			}
			
			// copy properties and stuff from the source image
			oCanvas.title = oImg.title;
			oCanvas.alt  = oImg.alt;
			oCanvas.imgsrc = oImg.src;
			oCanvas.className = oImg.className;
			oCanvas.cssText = oImg.cssText;
			oCanvas.id = oImg.id;

			oImg.parentNode.replaceChild(oCanvas, oImg);
		}
	},

	// load the image file
	doImage : function(oImg, strFilter)
	{
		var oCanvasImg = new Image();
		oCanvasImg.src = oImg.src;
		if (oCanvasImg.complete) {
			jsImageFX.doEffects(oImg, oCanvasImg, strFilter);
		} else {
			oCanvasImg.onload = function() {
				jsImageFX.doEffects(oImg, oCanvasImg, strFilter)
			}
		}
	},

	processImages : function() 
	{
		var aImg = document.getElementsByTagName("img");
		var aImages = [];
		for (var i=0;i<aImg.length;i++) {
			aImages[i] = aImg[i];
		}

		for (var i=0;i<aImages.length;i++) {
			if (aImages[i].getAttribute("imagefx")) {
				jsImageFX.doImage(aImages[i], aImages[i].getAttribute("imagefx"));
			}
		}
	}

}


if (window.addEventListener) { 
	window.addEventListener("load", jsImageFX.processImages, false); 
} else if (window.attachEvent) { 
	window.attachEvent("onload", jsImageFX.processImages); 
}

/*
 * Javascript Image Effects - Invert filter
 * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com
 * This software is free to use for non-commercial purposes. For anything else, please contact the author.
 */

jsImageFX.effects.invert = function(oImage)
{
	if (oImage.client.hasCanvas && oImage.client.hasCanvasImageData) {

		var oCtx = oImage.canvas.getContext("2d");
		var oDataSrc = oCtx.getImageData(0, 0, oImage.width, oImage.height);
		var oDataDst = oCtx.getImageData(0, 0, oImage.width, oImage.height);
		var aDataSrc = oDataSrc.data;
		var aDataDst = oDataDst.data;
		oImage.canvasData = oDataDst;

		var h = oImage.height;
		var w = oImage.width;
		var y = h;
		do {
			var iOffsetY = (y-1)*w*4;
			var x = w;
			do {
				var iOffset = iOffsetY + (x-1)*4;
				aDataDst[iOffset] = 255 - aDataSrc[iOffset];
				aDataDst[iOffset+1] = 255 - aDataSrc[iOffset+1];
				aDataDst[iOffset+2] = 255 - aDataSrc[iOffset+2];
				aDataDst[iOffset+3] = aDataSrc[iOffset+3];
	
			} while (--x);
		} while (--y);
		return true;

	} else if (oImage.client.isIE) {
		oImage.image.style.filter += " invert";
		return true;
	}
}/*
 * Javascript Image Effects - Desaturation filter
 * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com
 * This software is free to use for non-commercial purposes. For anything else, please contact the author.
 */

jsImageFX.effects.desaturate = function(oImage)
{
	if (oImage.client.hasCanvas && oImage.client.hasCanvasImageData) {

		var oCtx = oImage.canvas.getContext("2d");
		var oDataSrc = oCtx.getImageData(0, 0, oImage.width, oImage.height);
		var oDataDst = oCtx.getImageData(0, 0, oImage.width, oImage.height);
		var aDataSrc = oDataSrc.data;
		var aDataDst = oDataDst.data;
		oImage.canvasData = oDataDst;

		var h = oImage.height;
		var w = oImage.width;
		var y = h;
		do {
			var iOffsetY = (y-1)*w*4;
			var x = w;
			do {
				var iOffset = iOffsetY + (x-1)*4;
				var iBrightness = Math.round(aDataSrc[iOffset]*0.3 + aDataSrc[iOffset+1]*0.59 + aDataSrc[iOffset+2]*0.11);

				aDataDst[iOffset] = iBrightness;
				aDataDst[iOffset+1] = iBrightness;
				aDataDst[iOffset+2] = iBrightness;
				aDataDst[iOffset+3] = aDataSrc[iOffset+3];
	
			} while (--x);
		} while (--y);
		return true;

	} else if (oImage.client.isIE) {
		oImage.image.style.filter += " gray";
		return true;
	}
}

jsImageFX.effects.emboss = function(oImage, oOptions)
{
	if (oImage.client.hasCanvas && oImage.client.hasCanvasImageData) {

		var oCtx = oImage.canvas.getContext("2d");
		var oDataSrc = oCtx.getImageData(0, 0, oImage.width, oImage.height);
		var oDataDst = oCtx.getImageData(0, 0, oImage.width, oImage.height);
		var aDataSrc = oDataSrc.data;
		var aDataDst = oDataDst.data;
		oImage.canvasData = oDataDst;


		if (!oOptions) oOptions = {};
		oOptions.strength = parseFloat(oOptions.strength) > 0 ? parseFloat(oOptions.strength) : 1;
		oOptions.grayLevel = 180;

		var h = oImage.height;
		var w = oImage.width;

		var y = h;
		do {
			var iOffsetY = (y-1)*w*4;

			var iOffsetYPrev = (y-2)*w*4;

			if (y == 1) {
				iOffsetYPrev = iOffsetY;
			}	

			var x = w;
			do {
				if (x < w && y < h) {

					var iOffset = iOffsetY + (x-1)*4;
					var iOffsetPrev = iOffsetYPrev + (x-1)*4;

					if (x == 1) {
						iOffsetPrev = iOffset;
					}

					var iR = 0;
					var iG = 0;
					var iB = 0;

					iDeltaR = aDataSrc[iOffset] - aDataSrc[iOffsetPrev-4];
					iDeltaG = aDataSrc[iOffset+1] - aDataSrc[iOffsetPrev-3];
					iDeltaB = aDataSrc[iOffset+2] - aDataSrc[iOffsetPrev-2];

					var iDif = iDeltaR;
					if (Math.abs(iDeltaG) > Math.abs(iDif)) {
						iDif = iDeltaG;
					}
					if (Math.abs(iDeltaB) > Math.abs(iDif)) {
						iDif = iDeltaB;
					}

					var iGray = oOptions.grayLevel - iDif;
					if (iGray < 0) iGray = 0;
					if (iGray > 255) iGray = 255;

					aDataDst[iOffset] = iGray;
					aDataDst[iOffset+1] = iGray;
					aDataDst[iOffset+2] = iGray;
					aDataDst[iOffset+3] = aDataSrc[iOffset+3];
				}

			} while (--x);
		} while (--y);
		return true;
	} else if (oImage.client.isIE) {
		oImage.image.style.filter += " progid:DXImageTransform.Microsoft.emboss()";
		return true;
	}
}

jsImageFX.effects.lighten = function(oImage, oArgs)
{
	var fAmount = 0;

	if (oArgs) {
		if (typeof oArgs.amount != "undefined")
			fAmount = parseFloat(oArgs.amount);
	}

	if (oImage.client.hasCanvas && oImage.client.hasCanvasImageData) {
		var oCtx = oImage.canvas.getContext("2d");
		var oDataSrc = oCtx.getImageData(0, 0, oImage.width, oImage.height);
		var oDataDst = oCtx.getImageData(0, 0, oImage.width, oImage.height);
		var aDataSrc = oDataSrc.data;
		var aDataDst = oDataDst.data;
		oImage.canvasData = oDataDst;

		var h = oImage.height;
		var w = oImage.width;
		var y = h;
		do {
			var iOffsetY = (y-1)*w*4;
			var x = w;
			do {
				var iOffset = iOffsetY + (x-1)*4;
	
				var iR = aDataSrc[iOffset];
				var iG = aDataSrc[iOffset+1];
				var iB = aDataSrc[iOffset+2];

				if (fAmount < 0 ||true) {
					iR = iR + iR*fAmount;
					iG = iG + iG*fAmount;
					iB = iB + iB*fAmount;
				} else if (fAmount > 0) {
					iR = iR + (255-iR)*fAmount;
					iG = iG + (255-iG)*fAmount;
					iB = iB + (255-iB)*fAmount;
				}

				if (iR < 0 ) iR = 0;
				if (iG < 0 ) iG = 0;
				if (iB < 0 ) iB = 0;
				if (iR > 255 ) iR = 255;
				if (iG > 255 ) iG = 255;
				if (iB > 255 ) iB = 255;

				aDataDst[iOffset] = iR;
				aDataDst[iOffset+1] = iG;
				aDataDst[iOffset+2] = iB;
				aDataDst[iOffset+3] = aDataSrc[iOffset+3];
	
			} while (--x);
		} while (--y);
		return true;

	} else if (oImage.client.isIE) {
		if (fAmount < 0) {
			oImage.image.style.filter += " light()";
			oImage.image.filters[oImage.image.filters.length-1].addAmbient(
				255,255,255,
				100 * -fAmount
			);
		} else if (fAmount > 0) {
			oImage.image.style.filter += " light()";
			oImage.image.filters[oImage.image.filters.length-1].addAmbient(
				255,255,255,
				100
			);
			oImage.image.filters[oImage.image.filters.length-1].addAmbient(
				255,255,255,
				100 * fAmount
			);
		}
		return true;
	}
}