canvas 像素操作
在 canvas 中可以使用 context.drawImage(image,dx,dy) 方法将图片绘制在 canvas 上。将图片绘制上去后,还可以使用 context.getImageData(sx, sy, sw, sh) 方法获取 canvas 区域隐含的像素数据,该方法返回一个 ImageData 对象,里面包含的是 canvas 像素信息。
getImageData 函数
这个函数有四个参数,都是必选的。context.getImageData(sx, sy, sw, sh) ,其中:
- sx:将要被提取的图像数据矩形区域的左上角 x 坐标;
- sy:将要被提取的图像数据矩形区域的左上角 y 坐标;
- sw:将要被提取的图像数据矩形区域的宽度;
- sy:将要被提取的图像数据矩形区域的高度;
const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");
let image = new Image(canvas.height);
image.src = "图片路劲.jpg";
// image onload后再获得像素,不然有可能获得不了
image.onload = function(){
ctx.drawImage(image,0,0);
let imageData = ctx.getImageData(0,0,canvas.width,canvas.height);
console.log(imageData);
/*
imageData键值说明:
colorSpace: string -- 图片色彩转换标准
data: Array -- 我们想要获得的区域内的像素信息
height: number -- canvas高度
width: number -- canvas宽度
ps:imageData.data 中的像素数据是一个一维正整数数组(Uint8ClampedArray 类型的数组,即:无符号整型),一个像素信息包含 RGB 三原色信息和透明度。data 数组数据每四个为一组,分别表示 RGB 通道和透明度。这四种值取值都在 0-255 之间。
*/
}
putImageData() 函数
该方法可以将 imageData 对象绘制到 canvas 上。我们可以用 getImageData 将获取到的 imageData 数据处理后再使用 putImageData 方法重新绘制到 canvas 中。 参数: ctx.putImageData(imagedata, dx, dy); 或:ctx.putImageData(imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight);
- imagedata:getImageData返回的imageData数据
- dx:源图像数据在目标画布中的 x 轴方向的偏移量;
- dy:源图像数据在目标画布中的 y 轴方向的偏移量;
- dirtyX 可选:在源图像数据中,矩形区域左上角的位置。默认是整个图像数据的左上角(x 坐标)。
- dirtyY 可选::在源图像数据中,矩形区域左上角的位置。默认是整个图像数据的左上角(y 坐标)。
- dirtyWidth 可选:在源图像数据中,矩形区域的宽度。默认是图像数据的宽度。
- dirtyHeight 可选:在源图像数据中,矩形区域的高度。默认是图像数据的高度。
简单的 canvas 的像素操作
在 CSS 颜色值里,可以使用六位十六进制法表示颜色值,比如:#000000 表示纯黑色,还可以使用 rgb 通道表示法表示一个颜色,格式:rgb(red,green,blue) 当值是 rgb(255,255,255) 是就是纯白色,rgb(255,0,0) 表示红色。rgb 通道的取值在 0-255 之间。在 CSS 当中,还定义了 rgba 颜色值,多出来的 a 表示透明度,只不过取值在 0-1 之间,0 表示透明度为 100%(而在 canvas 的像素中,透明度同样是 0-255 之间)。
通过上面getImageData 和putImageData我们就可以随意操作像素数据了。 这里简单用代码给出几个例子
<img src="http://localhost:3000/img.jpg" height="300" width="300" />
<canvas id="canvas" height="150" width="150" style="width:300px;height: 300px;"></canvas>
<script>
const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");
let image = new Image(canvas.height);
image.src = "http://localhost:3000/img.jpg";
image.onload = function () {
ctx.drawImage(image, 0, 0);
let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
let data = imageData.data;
let newData = imageData
//到这一步 我们已经获取到区域内的像素数组data了
//接下来我们只需要遍历之后对每一个像素进行独立操作就可以了
for (let i = 0; i < data.length; i += 4) {
let r = newData.data[i], g = newData.data[i + 1], b = newData.data[i + 2]
//这里注意一下 一个像素信息包含 RGB 三原色信息和透明度
//所以这里data数组是每四个数组元素代表一个像素
//修改透明度(乘的这个值越高 透明度越低 取值范围 0-1 浮点型)
//newData.data[i + 3] = 255*0.5
// 修改明度(乘的这个值越高 明度越高 取值范围0-1 浮点型)
// newData.data[i] = r * 0.5
// newData.data[i + 1] = g * 0.5
// newData.data[i + 2] = b * 0.5
//反色
// newData.data[i] = 255 - r
// newData.data[i + 1] = 255 - g
//newData.data[i + 2] = 255 - b
//灰度
// newData.data[i] = (r + g + b) / 3
// newData.data[i + 1] = (r + g + b) / 3
// newData.data[i + 2] = (r + g + b) / 3
//毛玻璃
// const rand = Math.floor(Math.random() * 10) % 10
// newData.data[i] = newData.data[i + (rand * 4) * (newData.width + 1)]
// newData.data[i + 1] = newData.data[i + 1 + (rand * 4) * (newData.width + 1)]
// newData.data[i + 2] = newData.data[i + 2 + (rand * 4) * (newData.width + 1)]
//模糊滤镜:每一个点的颜色等于周围8个点颜色的平均值
// newData.data[i] = (newData.data[i - canvas.width * 4 - 4] + newData.data[i - canvas.width * 4] + newData.data[i - canvas.width * 4 + 4] + newData.data[i - 4] + newData.data[i + 4] + newData.data[i + 4] + newData.data[i + canvas.width * 4 - 4] + newData.data[i + canvas.width * 4] + newData.data[i + canvas.width * 4 + 4]) / 8
// newData.data[i + 1] = (newData.data[i + 1 - canvas.width * 4 - 4] + newData.data[i + 1 - canvas.width * 4] + newData.data[i + 1 - canvas.width * 4 + 4] + newData.data[i + 1 - 4] + newData.data[i + 1 + 4] + newData.data[i + 1 + 4] + newData.data[i + 1 + canvas.width * 4 - 4] + newData.data[i + 1 + canvas.width * 4] + newData.data[i + 1 + canvas.width * 4 + 4]) / 8
// newData.data[i + 2] = (newData.data[i + 2 - canvas.width * 4 - 4] + newData.data[i + 2 - canvas.width * 4] + newData.data[i + 2 - canvas.width * 4 + 4] + newData.data[i + 2 - 4] + newData.data[i + 2 + 4] + newData.data[i + 2 + 4] + newData.data[i + 2 + canvas.width * 4 - 4] + newData.data[i + 2 + canvas.width * 4] + newData.data[i + 2 + canvas.width * 4 + 4]) / 8
}
ctx.putImageData(newData, 0, 0);
}
</script>
运行结果
透明度:
明度:
灰度:
反色:
模糊滤镜:
只开启R通道:
只开启G通道:
只开启B通道:
毛玻璃:
浮雕:
最后
本文到此结束,希望对你有帮助 :)
如果还有什么疑问或者建议,可以多多交流,不才文笔有限,才疏学浅,文中若有不正之处,万望告知,及时更正。