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;
}

