第六章 像素缓冲和其它一些效果

我们到目前所做的事情都是基于图片或者形状,当然这已经是较高的水平了。不过,Canvas同样给了你操作像素的能力,你可以获取到Canvas中的每一个像素或某一小块的像素,通过像素变换,我们可以实现很多有趣的效果。

生成纹理

加入我们想要生成西洋跳棋的纹理(大小为300*200),代码如下:

//create a new 300 x 300 pixel buffer 
var data = c.createImageData(300,200); 

//loop over every pixel 
for(var x=0; x<data.width; x++) { 
    for(var y=0; y<data.height; y++) { 

        var val = 0; 
        var horz = (Math.floor(x/4) % 2 == 0); //loop every 4 pixels 
        var vert = (Math.floor(y/4) % 2 == 0); // loop every 4 pixels 
        if( (horz && !vert) || (!horz && vert)) { 
            val = 255; 
        } else { 
            val = 0; 
        } 
        // 连续的四个值分别代表rgba的值
        var index = (y*data.width+x)*4;  //calculate index 
        data.data[index] = val;   // red 
        data.data[index+1] = val; // green 
        data.data[index+2] = val; // blue 
        data.data[index+3] = 255; // force alpha to 100% 
    } 
} 
//set the data back 
c.putImageData(data,0,0);

代码相当简单,我们创建了一个缓冲器,依据x和y的坐标,循环为像素点设置颜色,然后把缓冲图形绘制在Canvas上。你可能已经注意到虽然我们绘制的是2维的图像,但是我们的缓冲图形是一维的,我们需要自己计算像素坐标的索引。

此处学习了createImageData()putImageData()两个函数。

Canvas 数据是一个非常长的一维数组,其每一个像素组件都有一个整数值,每个像素都由红绿蓝及alpha构成,并以此顺序排列,因此,如果要给一个像素的红色组件赋值,需要使用以下公式(y * width + x) * 4,举例来说,对想像素位置为8,10的像素点,如果位图的宽度为20,那么他的红色点坐标为(10*20 + 8) * 4.而一旦你找到的某像素的红点,你就可以很简单的通过增加索引值找到其他颜色设置的索引值。上述代码的效果如下: 黑白像素图

给图片添加噪点

我们给上述图片添加一些噪点让它显得更加真实,方法也很简单,随机给一些像素设置其它颜色即可。

if(val == 0) { 
    val = Math.random()*100; 
} else { 
    val = 255-Math.random()*100; 
}

图片颜色反转

上面我们描述了使用图片缓冲生成图片的方法,我们同样可以修改已经存在的Canvas的数据。这意味着Photoshop提供了那些滤镜很多是可以通过Canvas来实现的。比如说反转一张图片,反转用到的是一个简单的方程,一副rgba格式的图片,其没一个值都在0~255之间,反转就是把对应的值改为255减去原来的值。比如说如下原图 原图 使用以下代码进行调整

var img = new Image(); 
img.onload = function() { 
    //draw the image to the canvas 
    c.drawImage(img,0,0); 
    //get the canvas data 
    var data = c.getImageData(0,0,canvas.width,canvas.height); 
    //invert each pixel 
    for(n=0; n<data.width*data.height; n++) { 
        var index = n*4;  
        data.data[index]   = 255-data.data[index]; 
        data.data[index+1] = 255-data.data[index+1]; 
        data.data[index+2] = 255-data.data[index+2]; 
        //don't touch the alpha 
    } 

    //set the data back 
    c.putImageData(data,0,0); 
} 
img.src = "baby_original.png";

在这里我们只是让rgb的反转,没有去设置alpha,得到的效果如下: 反转效果图

去色

我们再来举一个例子,代码其实和上面的代码类似,只是换用了另外一个方程,这次我们把彩色的图片转换为了黑白图片。

for(n=0; n<data.width*data.height; n++) { 
    var index = n*4;  
    var r = data.data[index]; 
    var g = data.data[index+1]; 
    var b = data.data[index+2]; 
    var v = r*0.21+g*0.71+b*0.07; // weighted average 
    data.data[index]   = v; 
    data.data[index+1] = v; 
    data.data[index+2] = v; 
    //don't touch the alpha 
}

请注意,我们这里并非统一取了灰色,我们为了让眼睛和其它的一些敏感部位更加突出,着重的强调了绿色,效果图如下: 黑白效果图 通过像素缓存绘制和操作像素,你可以达到很多有意思的效果,唯一的限制在于操作的速度,处理二进制的数据并非JavaScript的强项,但是随着浏览器越来越快,网页能做的事情确实是越来越多的,如果你对这方面感兴趣,下文中我还会介绍一些库帮助你实现这些效果。

混合模式

Canvas同样支持混合模式,这和你在Photoshop中看到的一些模式是一样的,每一次你绘制一个形状,它会和原先存在于改点的像素对比,最终得到最后的结果。一般来说我们会使用SrcOver的方法,意味着源像素会被绘制在目标像素之上,这意味着如果当前像素为部分透明,混合后像素的透明度为二者的均值。SrcOver只是众多混合方式中的一种,当绘制叠加的圆圈的时候,我们也可以用lighter模式,这种模式会把两个像素叠加在一起,且混合的最大值为白色。

c.globalCompositeOperation = "lighter"; //set the blend mode 
c.fillStyle = "#ff6699";  //fill with a pink 

//randomly draw 50 circles 
for(var i=0; i<50; i++) { 
    c.beginPath(); 
    c.arc( 
        Math.random()*400, // random x 
        Math.random()*400, // random y 
        40,                // radius 
        0,Math.PI*2);      // full circle 
    c.closePath(); 
    c.fill(); 
}

lighter

阴影效果

类似CSS,Canvas同样支持阴影,你可以为阴影设置颜色,偏移,模糊半径来实现不同的效果,下面这个效果让绿色的文字具有白色的边缘光。

c.fillStyle = "black"; 
c.fillRect(0,0,canvas.width,canvas.height); 

c.shadowColor = "white"; 
c.shadowOffsetX = 0; 
c.shadowOffsetY = 0; 
c.shadowBlur = 30; 

c.font = 'bold 80pt Arial'; 
c.fillStyle = "#55cc55"; 
c.fillText("ALIEN",30,200);

阴影效果

results matching ""

    No results matching ""