3.12 创建像素化的图像聚焦
你正在寻找一种新颖的聚焦图像方法?像素化图像聚焦怎么样?本节,我们将探讨图像像素化的艺术,我们的做法是,遍历一个算法,该算法像素化一副图像,并使像素化的程度越来越小,直到图像完全被聚焦。
警告:由于getImageData()方法的安全限制,本节的例子必须在Web服务器上运行。
绘制步骤
按照以下步骤,创建一个像素化函数,该函数慢慢聚焦一幅图像:
1. 定义focusImage()函数,该函数根据pixilation变量的值,对图像进行去像素化处理:
function focusImage(canvas, context, imageObj, pixelation) {
var sourceWidth = imageObj.width;
var sourceHeight = imageObj.height;
var sourceX = canvas.width / 2 - sourceWidth / 2;
var sourceY = canvas.height / 2 - sourceHeight / 2;
var destX = sourceX;
var destY = sourceY;
var imageData = context.getImageData(sourceX, sourceY, sourceWidth, sourceHeight);
var data = imageData.data;
for (var y = 0; y < sourceHeight; y += pixelation) {
for (var x = 0; x < sourceWidth; x += pixelation) {
// 获取样本像素的颜色分量
var red = data[((sourceWidth * y) + x) * 4];
var green = data[((sourceWidth * y) + x) * 4 + 1];
var blue = data[((sourceWidth * y) + x) * 4 + 2];
// 覆盖样本像素右下侧的矩形区域,该矩形区域的宽度和高等于pixelation的数量
for (var n = 0; n < pixelation; n++) {
for (var m = 0; m < pixelation; m++) {
if (x + m < sourceWidth) {
data[((sourceWidth * (y + n)) + (x + m)) * 4] = red;
data[((sourceWidth * (y + n)) + (x + m)) * 4 + 1] = green;
data[((sourceWidth * (y + n)) + (x + m)) * 4 + 2] = blue;
}
}
}
}
}
//覆盖源图像
context.putImageData(imageData, destX, destY);
}
2. 定义画布上下文、fps值(由它来决定图像聚焦的快慢)、与fps对应的时间间隔、初始的像素化的数量:
window.onload = function(){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var fps = 20; // frames / second
var timeInterval = 1000 / fps; // milliseconds
// 定义pixelation的初始值,该值越大,图像越模糊,当pixelation = 1时,图像完全被聚焦
var pixelation = 40;
3. 新建一个image对象,把onload属性设置为一个函数,该函数创建一个循环,该循环定时调用focusImage()函数,并在每次调用时减少pixelation的值,直到图像被聚焦,然后在onload定义的外面,设置image对象的源地址:
var imageObj = new Image();
imageObj.onload = function() {
var sourceWidth = imageObj.width;
var sourceHeight = imageObj.height;
var destX = canvas.width / 2 - sourceWidth / 2;
var destY = canvas.height / 2 - sourceHeight / 2;
var intervalId = setInterval(function() {
context.drawImage(imageObj, destX, destY);
if (pixelation < 1) {
clearInterval(intervalId);
}
else {
focusImage(canvas, context, imageObj, pixelation--);
}
}, timeInterval);
};
imageObj.src = "jet_300x214.jpg";
};
4. 在HTML文档的body部分嵌入canvas标签:
<canvas id="myCanvas" width="600" height="250" style="border:1px solid black;">
</canvas>
工作原理
在跳入像素化算法之前,让我们先给像素化下个定义。图像的像素化发生在当人眼可以分辨组成图像的每一个像素的时候。老派电子游戏的画面及被放大的小图像是像素化很好的例子。用外行的话来说,如果我们把像素化定义为组成图像的每一个像素都可见的条件,这仅仅意味着像素本身相当大。事实上,像素越大,图像就变得越模糊。我们可以利用这个观察,来创建像素化算法。
要创建一个图像像素化算法,我们可以抽取图像的颜色样本,并在该像素的位置绘制一个硕大的像素。由于像素需要是一个正方形,我们可以把像素的尺寸构造为1 x 1(像素的标准尺寸), 2 x 2, 3 x 3, 4 x 4等等。像素越大,图像看上去就越模糊。
目前为止,我们只是简单地遍历data属性中的每一个像素,并使用简单算法来改变它们,并没有太多关注哪些像素被更新。然而,在本节的例子中,我们需要基于x,y坐标查看指定区域,来检查这些样本像素。我们根据x,y坐标,使用下面公式取出每一个像素的RGBA分量:
var red = data[((sourceWidth * y) + x) * 4];
var green = data[((sourceWidth * y) + x) * 4 + 1];
var blue = data[((sourceWidth * y) + x) * 4 + 2];
有了这些公式,我们就可以调用setInterval()函数,随着时间的推移,渲染一系列被像素化的图像,并且被像素化的部分逐次减少,直到pixilation的值等于0(即被像素化的区域为0),再把图像被恢复到初始状态。