JayChen

V1

2022/07/13阅读:38主题:红绯

canvas像素操作

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, 00);
        let imageData = ctx.getImageData(00, 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, 00);
    }
</script>

运行结果

透明度: 明度: 灰度: 反色: 模糊滤镜: 只开启R通道: 只开启G通道: 只开启B通道: 毛玻璃: 浮雕:

最后

本文到此结束,希望对你有帮助 :)

如果还有什么疑问或者建议,可以多多交流,不才文笔有限,才疏学浅,文中若有不正之处,万望告知,及时更正。

分类:

前端

标签:

JavaScript

作者介绍

JayChen
V1