使用canvas给图片增加滤镜

时间:2024-05-21 08:47:37

类似操作像素的博主还写过一篇文章:原生JavaScript + Canvas实现图片局部放大器

1. 效果图

使用canvas给图片增加滤镜

2. 实现原理

滤镜效果主要使用的均为canvas的getImageData以及putImageData
(以上两个api详细介绍可以点击蓝色链接,跳转到MDN查看)

操纵getImageData函数返回的ImageData图片的像素信息来给图片增加滤镜效果。

2.1 负片滤镜

负片滤镜会从255之中减去每个像素的红,绿,蓝分量值,再将差值设置回去,这样就反转了颜色

2.2 黑白滤镜

黑白滤镜会计算出每个像素红、绿、蓝分量值的平均值,然后将三个分量值都设置成为这个值,就把图片从彩色变为黑白

2.3 浮雕滤镜

浮雕滤镜需要当前像素右方以及下一行对应的像素值,例如

          data[i] = 255 / 2 // 平均值
            + 2 * data[i] // 当前像素值 * 2
            - data[i + 4] // 下一个像素当前分量值
            - data[i + width * 4] // 下一行像素当前分量值,width为实际图片宽度

2.4 高斯模糊滤镜

高斯模糊滤镜是根据高斯曲线调节像素色值,它能够把某一点周围的像素色值按高斯曲线统计起来,采用数学上加权平均的计算方法得到这条曲线的色值,最后能够留下人物的轮廓,即曲线. 更加具体的解释请移步到 阮一峰的高斯模糊算法.

3. 代码

由于操作大图片的像素点较多,因此实现时使用H5的web worker来处理图片信息

代码地址: https://github.com/TheKiteRunners/-JavaScript-Canvas-/tree/master
此仓库的滤镜.html对应本章代码

注意该代码要放到服务器中运行,否则会触发canvas的安全问题:

基于安全考量,canvas规范允许绘制不属于自己的(也就是其他域中的)图像,然而你不能通过canvas API保存或修改其他域中的图像
canvas安全机制如下:
每个canvas都有一个名为origin-clean的标志位,它的初始值为true,如果使用drawImage绘制了一幅其他域中的图像,那么origin-clean的值就会被设置为false。与此类似,如果用drawImage将一个origin-clean标志位false的canvas绘制到当前的canvas中,那么它的origin-clean标志也会被设置为false。
就其本身而言,将canvas的origin-clean设置为false,并不会立刻导致诸如抛出异常这样的反应来,不过如果在origin-clean标志位false的canvas上调用toDataURL或getImageData方法,那么此时浏览器就会抛出SECURITY_ERR异常

因此最简单的方法可以npm一个全局的http-server静态服务器即可运行该代码。

1. npm install http-server -g
2. 项目路径下打开控制台输入:http-server -p 8081
3. 打开浏览器输入地址即可

参考链接: David Geary著 HTML5 Canvas核心技术 202-208页