当前位置: 首页 > 文档资料 > HTML5 Canvas 实战 >

3.12 创建像素化的图像聚焦

优质
小牛编辑
127浏览
2023-12-01

你正在寻找一种新颖的聚焦图像方法?像素化图像聚焦怎么样?本节,我们将探讨图像像素化的艺术,我们的做法是,遍历一个算法,该算法像素化一副图像,并使像素化的程度越来越小,直到图像完全被聚焦。

图像聚焦
图3-10 图像聚焦

警告:由于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),再把图像被恢复到初始状态。