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