在实际的工作中,有时候会有一些需求,让你做一些图片的滤镜效果,比如将图片变成黑白,调整图片亮度等。本文手把手教你如何实现五种滤镜效果
,核心代码总共不到 70 行。
笔者所在的公司就有一个需求需要用到图片处理的知识,大概场景我来描述一下:
用户可以手动上传印章,并且支持给印章设置不同的显示效果,这里的效果具体指的是“线条的清晰程度”,如下图所示:
这里我们使用 Canvas 来实现。如果你对 Canvas 不熟悉,建议看下之前我写的一篇文章100 * 100 Canvas 占用内存多大,花上几分钟看完,基本上够看懂这篇文章了。
准备工作
首先我们先将图片绘制到 Canvas 画布上,为了简单起见,图片大小固定为 300 x 300。
1 | <canvas id="canvas" width="300px" height="300px"></canvas> |
(html)
1 | //获取canvas元素 |
(js)
效果是这样的:
操作像素
熟悉 Canvas 的应该知道上面的 this.imgData 实际上就是ImageData类的实例,其中 imgData.data 是一个 Uint8ClampedArray, 其描述了一个一维数组,包含以 RGBA 顺序的数据,数据使用 0 至 255(包含)的整数表示。 简单来说,就是图片像素信息,每四位表示一个像素单元
。其中每四位的信息分别是 RGBA。即第一个 Bit 标记 R,第二个 Bit 表示 G,第三个 Bit 表示 B,第四个 Bit 表示 A,第五个 Bit 又是 R…,依次类推。
接下来,我们就要操作 imgData,来实现滤镜的效果。简单起见,我这里对超过 200 的值进行了一次提高亮度
的操作。实际上这个值是 200,还是别的数字,需要我们化身”调参工程师”,不断实验才行。 并且粗暴地对 RGB 执行同样的逻辑是不合理的。更为合理的做法是对 RGB 的阀值分别进行度量,由于比较麻烦,我这里没有实现。但是如果你对效果要求比较高,那么最好可以分开度量。
1 | const data = this.imgData.data; |
如上,我们对图片的像素进行了处理,以达到我们的目的,这样从用户感官上来看,显示效果发生了变化,大概效果如图:
(清晰版)
(模糊版)
如果你愿意的话,你也可以将处理好的图片进行导出,也很简单,直接调用 Canvas 实例的
toDataURL
方法即可,图片保存的格式也可以在这个方法中进行指定。
日常开发中,我们还可能碰到很多其他的滤镜效果。下面介绍几个比较现常见的效果。 如果你正好用到了不妨作为参考。如果遇到了新的滤镜效果, 不妨在文末向我留言,看到后会及时回答,提前感谢你的参与。
下面介绍其他四种滤镜效果。这里只贴出核心代码,完整代码可以访问我的 Github Repo 进行查看。如果你嫌下载到本地麻烦,也可以在这里在线安装并访问,打开这个链接,分别执行yarn
和yarn start
即可。
以下效果均以下图为原图制作:
如何实现黑白效果
1 | for (let i = 0; i < data.length; i += 4) { |
如何实现反色效果
1 | for (let i = 0; i < data.length; i += 4) { |
如何给图片增加噪音
1 | const random = ((Math.random() * 70) >>> 0) - 35; |
如何提高图片亮度
1 | const brightness = +e.target.value; |
总结
本文通过不到 70 行代码实现了五种滤镜效果
,对于其他滤镜效果也可以参考这种方式来实现。还不赶紧拿上小姐姐的照片来秀一手么?