💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] 在 Canvas 中,可以通过`getImageData()`和`putImageData()`配合使用来对图片进行像素操作,所谓像素操作,即黑白效果、复古效果、亮度效果等常用图片处理方式。 ## getImageData() `getImageData()`方法用于获取一张图片的像素数据。 语法: ```js var imgData = cxt.getImageData(x, y, width, height) var data = imgData.data ``` 说明: x、y 表示所选图片区域的坐标,width、height 表示所选图片区域的宽度和高度。 该方法返回一个对象,这个对象有一个 data 属性保存了这一张图片像素数据的数组,数组取值如 [r1, g1, b1, a1, r2, g2, b2, a2]。即,在 imgData.data 这个数组中每四个数存储着 1 个像素的 rgba 颜色纸,这四个数分别是该像素的红(r)、绿(g)、蓝(b)、透明度(a)。另外,imgData.data.length 表示图片像素总量。 ## putImageData() `putImageData()`方法用于输出一张图片的像素数据。 语法: ```js cxt.putImageData(image, x, y) ``` 说明: image 表示重新绘制的图形,也就是使用 getImageData() 方法获取的 canvasPixelArray 对象。x、y 表示重新绘制图形左上角的横坐标、纵坐标。 ## 像素操作示例 ### 反转效果 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>canvas</title> </head> <body> <canvas id="canvas" width="1024" height="700" style="border: 1px solid gray; display: block; margin: 0 auto"></canvas> <script> window.onload = function(){ let cnv = document.getElementById('canvas') let cxt = cnv.getContext('2d') let image = new Image() image.src= "./image.jpg" // 500 x 281 image.onload = function () { cxt.drawImage(image, 10, 10) let imageData = cxt.getImageData(10, 10, 500, 281) let data = imageData.data console.log(data) // 遍历每个像素 for (let i = 0; i < data.length; i += 4) { // 反转效果即 RGB 颜色值取反 data[i + 0] = 255 - data[i + 0] data[i + 1] = 255 - data[i + 1] data[i + 2] = 255 - data[i + 2] } // 在指定位置输出图片 cxt.putImageData(imageData, 10, 300) } } </script> </body> </html> ``` 需要注意的是,getImageData() 需要以服务器形式启动才能使用(跨域限制),以文件形式打开会有以下错误: ![](https://img.kancloud.cn/17/34/173498c38f65f93db7203ac00e5113af_658x111.png) 原因可以参考:[https://www.cnblogs.com/jdksummer/articles/2565998.html](https://www.cnblogs.com/jdksummer/articles/2565998.html) 如果你使用 VSCode 编辑器,安装 live server 插件后即可以服务器形式启动文件: ![](https://img.kancloud.cn/8e/d5/8ed5fe298b4d2a321de5e6d641a725c1_475x391.png =300x) 上面的代码效果如下: ![](https://img.kancloud.cn/5a/35/5a356f011baabbab2a7682a06f607c31_1327x789.png) ### 黑白效果 黑白效果,也叫灰度图,其实现算法如下:首先取红、绿、蓝三个通道的平均值,然后 data[i + 0]、data[i + 1]、data[i + 2] 全部保存为这个平均值即可。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>canvas</title> </head> <body> <canvas id="canvas" width="1024" height="700" style="border: 1px solid gray; display: block; margin: 0 auto"></canvas> <script> window.onload = function(){ let cnv = document.getElementById('canvas') let cxt = cnv.getContext('2d') let image = new Image() image.src= "./image.jpg" // 500 x 281 image.onload = function () { cxt.drawImage(image, 10, 10) let imageData = cxt.getImageData(10, 10, 500, 281) let data = imageData.data // 遍历每个像素 for (let i = 0; i < data.length; i += 4) { let average = (data[i + 0] + data[i + 1] + data[i + 2]) / 3 data[i + 0] = average data[i + 1] = average data[i + 2] = average } cxt.putImageData(imageData, 10, 300) } } </script> </body> </html> ``` ![](https://img.kancloud.cn/31/5f/315f4b89882a5797f46fe10d8e37ca57_1322x790.png) 也可以使用加权平均值来调整黑白效果: ```js let grayscale = data[i] * 0.3 + data[i + 1] * 0.6 + data[i + 2] * 0.1 data[i + 0] = grayscale // 红 data[i + 1] = grayscale // 绿 data[i + 2] = grayscale // 蓝 ``` ![](https://img.kancloud.cn/92/b9/92b9056e90cc3f708c51197b5f3ea99d_1350x748.png) ### 亮度效果 亮度效果是指让图片变得更亮或者更暗,实现算法很简单:将红、绿、蓝三个通道值,分别同时加上一个正值或负值即可。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>canvas</title> </head> <body> <canvas id="canvas" width="1024" height="700" style="border: 1px solid gray; display: block; margin: 0 auto"></canvas> <script> window.onload = function(){ let cnv = document.getElementById('canvas') let cxt = cnv.getContext('2d') let image = new Image() image.src= "./image2.jpg" // 240 x 163 image.onload = function () { cxt.drawImage(image, 10, 10) let imageData = cxt.getImageData(10, 10, 240, 160) let data = imageData.data console.log(data) // 遍历每个像素 for (let i = 0; i < data.length; i += 4) { // 亮度效果,三原色同时加上或减去一个值 let a = 100 data[i + 0] += a data[i + 1] += a data[i + 2] += a } // 在指定位置输出图片 cxt.putImageData(imageData, 10, 220) } } </script> </body> </html> ``` ![](https://img.kancloud.cn/a0/3d/a03db98207545fa6405b668a708beb53_472x493.png =300x) ### 复古效果 复古效果(sepia),是指使得图片有一种古旧效果。实现算法:将红、绿、蓝三个通道,分别取这三个值的某种加权平均值。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>canvas</title> </head> <body> <canvas id="canvas" width="1024" height="700" style="border: 1px solid gray; display: block; margin: 0 auto"></canvas> <script> window.onload = function(){ let cnv = document.getElementById('canvas') let cxt = cnv.getContext('2d') let image = new Image() image.src= "./image.jpg" // 500 x 281 image.onload = function () { cxt.drawImage(image, 10, 10) let imageData = cxt.getImageData(10, 10, 500, 281) let data = imageData.data console.log(data) // 遍历每个像素 for (let i = 0; i < data.length; i += 4) { let r = data[i + 0] let g = data[i + 1] let 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 // 值随便取,有一定大小规律即可 } // 在指定位置输出图片 cxt.putImageData(imageData, 10, 300) } } </script> </body> </html> ``` ![](https://img.kancloud.cn/7c/83/7c83b3595058a12d17a7a0f73be18860_1327x750.png) ### 红色蒙版 红色蒙版即让图片呈现一种偏红的效果,实现算法:将红通道赋值为红、绿、蓝这三个的平均值,并且将绿通道、蓝通道都赋值为 0。 ```js // 遍历每个像素 for (let i = 0; i < data.length; i += 4) { let r = data[i + 0] let g = data[i + 1] let b = data[i + 2] let average = (r + g + b) / 3 data[i + 0] = average data[i + 1] = 0 data[i + 2] = 0 } ``` ![](https://img.kancloud.cn/7f/44/7f448de6316ae2896985069710a42a58_1313x767.png) ### 透明处理 语法: ```js let n = 0.5 for (let i = 0; i < data.length; i += 4) { data[i + 3] = data[i + 3] * n // n 的取值范围为 0.0 ~ 1.0 } ``` ![](https://img.kancloud.cn/63/e3/63e3387d5ff36dda4a5811d2cd583d0d_1354x746.png) ## createImageData() 方法