教你如何成为图片找茬高手

事情是这样的,前几天闲来无事,手机上下载了个图片找茬游戏,本以为是小孩子玩玩的很简单,没想到开头几关就把我难住了,有些细节真是藏的很深呀,不仔细看真的找不到。于是乎我想,肉眼很难辨别的东西是不是可以通过代码帮我快速找到?前端有 canvas 可以用来处理图像,查了下 API 也可以读取像素点,感觉可行,说干就干!

canvas 读取像素点

我们知道,canvas 是可以拷贝图像的,通过 ctx.drawImage,我们可以方便的将图片绘制在 canvas 里面,下面是例子

tsx 复制代码
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");
  const image = new Image();
  image.src = 'xxx';
  image.onload = ()=> {
   canvas.width = image.width;
   canvas.height = image.height;
   ctx.drawImage(image, 0, 0);
  }

但应该没多少童鞋知道,canvas 其实也可以读取像素点,通过 ctx.getImageData 我们可以方便的读取当前绘制图片的像素点数组。

tsx 复制代码
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;

然后我们会得到如下数组

tsx 复制代码
  // [255,254,255,255,...]

这里每4个值一组就代表了一个像素点,聪明的童鞋已经看出来了,没错,这4个值分别对应了 RGBA,如下图所示 我们可以通过对比每一个像素点,来实现图片的差异化对比。

绘制差异化像素点

既然能读取,我们能不能修改里面的像素点呢?答案是可以的,通过ctx.putImageData,我们可以方便的对现有图像的像素进行随意改造,比较常用的就是 滤镜,通过不同的滤镜算法,我们可以在网页上实现类似美图秀秀的功能,当然在我们这个需求里,也可以用来标记差异化的像素点。具体流程如下:

  1. 绘制需要对比的两张图片到 canvas
  2. 获取原图的像素点数组作为对照
  3. 遍历对比图的像素点,将和原图不同的部分用蓝色重新赋值
  4. 通过ctx.putImageData,重新生成新的图像信息
  5. 最后通过 canvastoDataURL api 生成 base64 图像

简单写了个 demo,效果类似这样

我们可以很快发现,diff 图 里蓝色明显的地方即为差异点

源代码我放在 github 上了,有兴趣的童鞋自取~ 👉 image-diff-demo

抛砖引玉

经过这个小 demo 的实战,深入理解了 ctx.getImageDatactx.putImageData 的用法,虽然原理差不多是这样子,但是还是有很多可以优化的地方,比如对比原图发现,很多没改动的地方也染上了一些蓝色,这个原因是因为两张图的相同部分的像素点也是不一致的,受限于图片压缩问题,很多颜色也是会有些许出入,虽然肉眼看不出来,但实际上从像素角度出发是不一样的,大家也可以想想怎么优化 diff 算法 可以让误差尽量减小😁

总结

image-diff 也不是新东西了,市面上也有不少成熟的产品了,开源社区耳熟能详的就是大名鼎鼎的 argos-ci,还有开源产品,比如 Resemble.js,都是比较好的 image-diff 库,大家可以按需使用,当然也可以自研,原理其实并不难。希望本篇文章对大家有帮助~

相关推荐
sunbyte1 分钟前
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | ThemeClock(主题时钟)
前端·javascript·css·vue.js·前端框架·tailwindcss
小飞悟9 分钟前
🎯 什么是模块化?CommonJS 和 ES6 Modules 到底有什么区别?小白也能看懂
前端·javascript·设计
浏览器API调用工程师_Taylor10 分钟前
AOP魔法:一招实现登录弹窗的全局拦截与动态处理
前端·javascript·vue.js
FogLetter11 分钟前
初识图片懒加载:让网页像"懒人"一样聪明加载
前端·javascript
微客鸟窝12 分钟前
一文搞懂NVM管理Node.js:从安装到实战全攻略
前端
归于尽13 分钟前
Cookie、Session、JWT 的前世今生
前端
程序员辉哥14 分钟前
学会在Cursor中使用Rules生成代码后可以躺平了吗?
前端·后端
请你吃div19 分钟前
JavaScript 实用函数大全(超实用)
前端·javascript·面试
一个水瓶座程序猿.20 分钟前
Vue3 中使用 Vueuse
前端·javascript·vue.js
夏梦春蝉21 分钟前
ES6从入门到精通:Symbol与迭代器
前端·javascript·es6