algorytm.org

Implementacja w JavaScript



Baza Wiedzy
wersja offline serwisu przeznaczona na urządzenia z systemem Android
Darowizny
darowiznaWspomóż rozwój serwisu
Nagłówki RSS
Artykuły
Implementacje
Komentarze
Forum
Bookmarki






Sonda
Implementacji w jakim języku programowania poszukujesz?

Tilt-Shift - efekt makiety - Implementacja w JavaScript
Ocena użytkownikóww: *****  / 0
SłabyŚwietny
Nadesłany przez Tomasz Lubiński, 06 czerwca 2012 16:30
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.
Pobierz pełne rozwiązanie.

Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.

tilt-shift/tilt_shift.js:
//Tilt Shift
//(c) 2012 by Tomasz Lubinski
//www.algorytm.org

/* Data	of the image */
var imageData;

/* Generate array for Gaussian blur with given sigma factor and not greater than given width */
function gaussian_array(factor, width)
{
	var result = new Array();
	for (var i=0; i<width; i++)
	{
		value = (1/(Math.sqrt(2*Math.PI)*factor))*Math.exp(-(i*i)/(2*factor*factor));
		if (value < 0.003)
		{
			break;	
		}
		result.push(value);
	}
	return result;
}

/* Tilt Shift effect */
function tilt_shift(inFocusCenter)
{
	var canvas = document.getElementById("canvas");
	var ctx	= canvas.getContext("2d");

	// read	the width and height of	the canvas
	var width = canvas.width;
	var height = canvas.height;

	var inFocusHeight = document.params.param_height.value;
	var outFocusStartTop = Math.max(Math.floor(inFocusCenter - inFocusHeight/2), 0);
	var outFocusStartDown = Math.min(Math.floor(inFocusCenter + inFocusHeight/2), height);
	var outFocusHeight = inFocusCenter>height/2?outFocusStartTop:(height-outFocusStartDown);
	var outFocusBlur = document.params.param_blur.value - 0.1;

	var newImageData = ctx.createImageData(width, height);
	var newImageDataData = newImageData.data;
	var imageDataData = imageData.data;
		
	// copy in-focus part
	for (var i=outFocusStartTop; i<outFocusStartDown; i++)
	{
		for (var j=0; j<width; j++)
		{
			index = (i*width+j)*4;
			newImageDataData[index+0] = imageDataData[index+0];
			newImageDataData[index+1] = imageDataData[index+1];
			newImageDataData[index+2] = imageDataData[index+2];
			newImageDataData[index+3] = imageDataData[index+3];
		}
	}

	// perform Tilt Shift - blur horizontal (above in-focus)
	for (var i=0; i<outFocusStartTop; i++)
	{
		factor = (outFocusStartTop-i)/outFocusHeight;
		var blurArray = gaussian_array(factor*outFocusBlur+0.1, width);
		var sum = blurArray[0];		
		for (var k=1; k<blurArray.length; k++)
		{
			sum += 2*blurArray[k];
		}
		for (var j=0; j<width; j++)
		{
			index = (i*width+j)*4;
			var r = imageDataData[index+0]*blurArray[0];
			var g = imageDataData[index+1]*blurArray[0];
			var b = imageDataData[index+2]*blurArray[0];
			for (var k=1; k<blurArray.length; k++)
			{
				if (j+k >= width) 
				{
					index = (i*width+width-(j+k+1-width))*4;
				}
				else
				{
					index = (i*width+j+k)*4;
				}
				r += imageDataData[index+0]*blurArray[k];
				g += imageDataData[index+1]*blurArray[k];
				b += imageDataData[index+2]*blurArray[k];
				if (j < k) 
				{
					index =(i*width+(k-j))*4;
				}
				else
				{
					index = (i*width+j-k)*4;
				}
				r += imageDataData[index+0]*blurArray[k];
				g += imageDataData[index+1]*blurArray[k];
				b += imageDataData[index+2]*blurArray[k];
			}
			index = (i*width+j)*4;
			newImageDataData[index+0] = r/sum;
			newImageDataData[index+1] = g/sum;
			newImageDataData[index+2] = b/sum;
			newImageDataData[index+3] = 255;
		}
	}
	
	// perform Tilt Shift - blur horizontal (below in-focus)
	for (var i=outFocusStartDown; i<height; i++)
	{
		factor = (i-outFocusStartDown)/outFocusHeight;
		var blurArray = gaussian_array(factor*outFocusBlur+0.1, width);
		var sum = blurArray[0];		
		for (var k=1; k<blurArray.length; k++)
		{
			sum += 2*blurArray[k];
		}		
		for (var j=0; j<width; j++)
		{
			index = (i*width+j)*4;
			var r = imageDataData[index+0]*blurArray[0];
			var g = imageDataData[index+1]*blurArray[0];
			var b = imageDataData[index+2]*blurArray[0];
			for (var k=1; k<blurArray.length; k++)
			{
				if (j+k >= width) 
				{
					index = (i*width+width-(j+k+1-width))*4;
				}
				else
				{
					index = (i*width+j+k)*4;
				}
				r += imageDataData[index+0]*blurArray[k];
				g += imageDataData[index+1]*blurArray[k];
				b += imageDataData[index+2]*blurArray[k];
				if (j < k) 
				{
					index =(i*width+(k-j))*4;
				}
				else
				{
					index = (i*width+j-k)*4;
				}
				r += imageDataData[index+0]*blurArray[k];
				g += imageDataData[index+1]*blurArray[k];
				b += imageDataData[index+2]*blurArray[k];
			}
			index = (i*width+j)*4;
			newImageDataData[index+0] = r/sum;
			newImageDataData[index+1] = g/sum;
			newImageDataData[index+2] = b/sum;
			newImageDataData[index+3] = 255;
		}
	}

	// perform Tilt Shift - blur vertical (above in-focus)
	for (var i=0; i<outFocusStartTop; i++)
	{
		factor = (outFocusStartTop-i)/outFocusHeight;
		var blurArray = gaussian_array(factor*outFocusBlur+0.1, height);
		var sum = blurArray[0];		
		for (var k=1; k<blurArray.length; k++)
		{
			sum += 2*blurArray[k];
		}		
		for (var j=0; j<width; j++)
		{
			index = (i*width+j)*4;
			var r = newImageDataData[index+0]*blurArray[0];
			var g = newImageDataData[index+1]*blurArray[0];
			var b = newImageDataData[index+2]*blurArray[0];
			for (var k=1; k<blurArray.length; k++)
			{
				if (i+k >= height) 
				{
					index = ((height-(i+k+1-height))*width+j)*4;
				}
				else
				{
					index = ((i+k)*width+j)*4;
				}
				r += newImageDataData[index+0]*blurArray[k];
				g += newImageDataData[index+1]*blurArray[k];
				b += newImageDataData[index+2]*blurArray[k];
				if (i < k) 
				{
					index =((k-i)*width+j)*4;
				}
				else
				{
					index = ((i-k)*width+j)*4;
				}
				r += newImageDataData[index+0]*blurArray[k];
				g += newImageDataData[index+1]*blurArray[k];
				b += newImageDataData[index+2]*blurArray[k];	
		
			}
			index = (i*width+j)*4;
			newImageDataData[index+0] = r/sum;
			newImageDataData[index+1] = g/sum;
			newImageDataData[index+2] = b/sum;
			newImageDataData[index+3] = 255;
		}
	}
	
	// perform Tilt Shift - blur vertical (below in-focus)
	for (var i=outFocusStartDown; i<height;	i++)
	{
		factor = (i-outFocusStartDown)/outFocusHeight;
		var blurArray = gaussian_array(factor*outFocusBlur+0.1, height);
		var sum = blurArray[0];		
		for (var k=1; k<blurArray.length; k++)
		{
			sum += 2*blurArray[k];
		}		
		for (var j=0; j<width; j++)
		{
			index = (i*width+j)*4;
			var r = newImageDataData[index+0]*blurArray[0];
			var g = newImageDataData[index+1]*blurArray[0];
			var b = newImageDataData[index+2]*blurArray[0];
			for (var k=1; k<blurArray.length; k++)
			{
				if (i+k >= height) 
				{
					index = ((height-(i+k+1-height))*width+j)*4;
				}
				else
				{
					index = ((i+k)*width+j)*4;
				}
				r += newImageDataData[index+0]*blurArray[k];
				g += newImageDataData[index+1]*blurArray[k];
				b += newImageDataData[index+2]*blurArray[k];
				if (i < k) 
				{
					index =((k-i)*width+j)*4;
				}
				else
				{
					index = ((i-k)*width+j)*4;
				}
				r += newImageDataData[index+0]*blurArray[k];
				g += newImageDataData[index+1]*blurArray[k];
				b += newImageDataData[index+2]*blurArray[k];	
			}
			index = (i*width+j)*4;
			newImageDataData[index+0] = r/sum;
			newImageDataData[index+1] = g/sum;
			newImageDataData[index+2] = b/sum;
			newImageDataData[index+3] = 255;
		}
	}	
	
	// copy	the image data back onto the canvas
	ctx.putImageData(newImageData, 0, 0);
}

/* mouse handler */
function mouseHandler(e)
{
	// get center of the in-focus point
	if (e.button == 0)
	{
		if (e.offsetX || e.offsetX == 0)
		{
			tilt_shift(e.offsetY);
		}
		else
		{
			tilt_shift(e.layerY);
		}
	}
	else
	{
		return;
	}
}

/* touch handler for devices with touch screen */
function touchHandler(event)
{
	tilt_shift(touches[0].clientY);
}

/* load	image pointed by param_file to canvas */
function loadImage(imgSrc)
{
	var canvas = document.getElementById("canvas");
	var ctx	= canvas.getContext("2d");

	// add file:// if user specified local path
	if (imgSrc.indexOf("//") == -1 && imgSrc.indexOf(".") != 0)
	{
		imgSrc = "file:///" + imgSrc;
	}

	//support for mobile devices with touch screen
	if ("ontouchstart" in document.documentElement)
	{
		canvas.ontouchstart = touchHandler;
		canvas.ontouchmove = touchHandler;
		canvas.ontouchend = touchHandler;
	}
	//support for devices with mouse
	canvas.onmousedown = mouseHandler;

	// load	file into canvas
	var img	= new Image();
	img.onload = function(){
		var width = img.width;
		var height = img.height;
		canvas.width = width;
		canvas.height =	height;
		ctx.drawImage(img,0,0);
		// replace transparent with white
		try
		{
			imageData = ctx.getImageData(0,	0, width, height);
		} catch(e)
		{
			netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
			imageData = ctx.getImageData(0,	0, width, height);
		}
		for (var i=0; i<height;	i++)
		{
			for (var j=0; j<width; j++)
			{
				index =	(i*width+j)*4;
				if (imageData.data[index+3] == 0)
				{
					imageData.data[index+3]	= 255;
					imageData.data[index+0]	= 255;
					imageData.data[index+1]	= 255;
					imageData.data[index+2]	= 255;
				}
			}
		}
	}
	img.src	= imgSrc;
}
Dodaj komentarz