Canvas支持直接处理图片中的像素,通过对图片像素进行各种类型的处理,能够实现不同的图片效果,本文的示例图片来自参考文献1,图片像素处理方法参照的参考文献2-7。
Canvas主要通过两种方式获取图片像素集合:
- getImageData;该方法获取Canvas中指定位置的图片像素集合,函数返回的是canvasPixelArray对象,该对象中的data属性保存的是像素集合的一维数组,通过处理该数组实现像素处理;
- createImageData:该方法在canvas中创建一个图片区域,然后返回该区域的像素集合;
像素处理完成后,通过调用canvas的putImageData图片像素集合内容显示在指定的地方。
下面通过实现几种像素处理方式来展示图片处理效果,更详细的说明可以看参考文献2-7。
颜色反转
颜色反转效果原理是用255减去每个像素中的r、g、b值。示例代码如下所示:
var cnv = document.getElementById("canvas");
var cxt=cnv.getContext("2d");
var cnvInverse = document.getElementById("inverse");
var cxtInverse=cnvInverse.getContext("2d");
var image=new Image();
image.src= "image/Gundam.jpeg";
image.onload= function( )
{
cxt.drawImage(image,0,0,cnv.clientWidth,cnv.clientHeight);
var imgData=cxt.getImageData(0,0,cnv.clientWidth,cnv.clientHeight);
var data=imgData.data;
for(var i=0;i<data.length;i+=4)
{
data[i+0]=255-data[i+0];
data[i+1]=255-data[i+1];
data[i+2]=255-data[i+2];
}
cxtInverse.putImageData(imgData,0,0);
}
但是真正执行代码时,显示的图片效果是下面这样的,处理后的图片没有显示出来。
打开火狐浏览器提供的调试器界面,发现代码报如下的操作不安全的错误。
错误原因好像是由于跨域访问造成的,看的不是太明白(还是个网页编程新手)。根据参考文献3的解决办法,关闭了如下图所示的火狐浏览器的设置。
在刷新网页,即可看到颜色反转的效果,如下图所示。
黑白效果
就是将彩色图片转换为灰度图,参考文献中提供了三种做法:平均值、加权、最大值。
平均值做法是将每个像素的r、g、b值都设置为他们三个和的平均值,示例代码及效果图如下所示
for(var i=0;i<data.length;i+=4)
{
var average=(data[i+0]+data[i+1]+data[i+2])/3;
data[i+0]=255-average;
data[i+1]=255-average;
data[i+2]=255-average;
}
加权做法是将每个像素的r、g、b值都设置为他们三个的加权和,权重系统可以调节,本文是参照的参考文献2中的权重,加权代码及示意图如下所示
var average=data[i+0]*0.3+data[i+1]*0.6+data[i+2]*0.1;
最大值做法是将每个像素的r、g、b值都设置为他们三个中的最大值,代码及示意图如下所示:
var average=Math.max(Math.max(data[i+0],data[i+1]),data[i+2]);
亮度效果
主要是指将每个像素的r、g、b值加上相同的值,可以是正值,也可以是负值。示例代码如下:
for(var i=0;i<data.length;i+=4)
{
var a=-50;
data[i+0]+=a;
data[i+1]+=a;
data[i+2]+=a;
}
统一加正值的效果如下:
统一加负值的效果如下:
复古效果
复古效果是对每个像素中的r、g、b值都进行加权平均处理,加权参数可以调节,本文参考的是参考文献2中的代码,其示例代码及效果如下所示:
for(var i=0;i<data.length;i+=4)
{
var r=data[i+0];
var g=data[i+1];
var b=data[i+2];
data[i+0]=r*0.39+g*0.76+b*0.18;
data[i+1]=r*0.35+g*0.68+b*0.16;
data[i+2]=r*0.27+g*0.53+b*0.13;
}
单色蒙版
主要指将每个像素的r、g、b平均值赋予某个通道,其它两个通道值赋0。示例代码以红绿蓝单色蒙版效果如下所示:
for(var i=0;i<data.length;i+=4)
{
var r=data[i+0];
var g=data[i+1];
var b=data[i+2];
var average=(r+g+b)/3;
data[i+0]=average;
data[i+1]=0;
data[i+2]=0;
}
透明处理
主要是调整每个像素中的透明度,示例代码及图片如下所示:
for(var i=0;i<data.length;i+=4)
{
data[i+3]=data[i+3]*0.3;
}
浮雕效果
主要是操作当前像素与邻近像素的r、g、b值,本文根据参考文献中的C#代码改成的JavaScript代码。示例代码及图片如下所示:
for(var i=0;i<data.length-4;i+=4)
{
var r1=data[i+0];
var g1=data[i+1];
var b1=data[i+2];
var r2=data[i+4];
var g2=data[i+5];
var b2=data[i+6];
var r = Math.abs(g1 - g2 + 128);
var g = Math.abs(g1 - g2 + 128);
var b = Math.abs(b1 - b2 + 128);
if (r > 255)
r = 255;
if (r < 0)
r = 0;
if (g > 255)
g = 255;
if (g < 0)
g = 0;
if (b > 255)
b = 255;
if (b < 0)
b = 0;
data[i+0]=r;
data[i+1]=g;
data[i+2]=b;
}
图片像素的处理方式有很多,本文主要跟基于参考文献演示了其中比较简单的几种效果,有兴趣的朋友可以再去实验更复杂的效果。网上应该也有很多成熟的JavaScript图片操作库可以直接使用。
原文地址:
[1]图片地址:https://m.sohu.com/a/239776224_666417
[2]从0到1 HTML5 Canvas动画开发
[3]https://blog.csdn.net/mochong/article/details/84055015?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&dist_request_id=1328575.184.16146071539985545&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control
[4]https://www.cnblogs.com/jameslong/p/3805993.html
[5]https://blog.csdn.net/chdjj/article/details/19568857
[6]https://www.cnblogs.com/mq0036/p/4026057.html
[7]https://blog.csdn.net/weixin_34319817/article/details/94711204