Canvas的像素操作:getImageData() 方法

Canvas 2D API 的 CanvasRenderingContext2D.getImageData() 返回一个 ImageData 对象,用于描述 canvas 指定区域的隐含像素数据。

语法

getImageData(sx, sy, sw, sh, settings)

参数

sx

要提取 ImageData 的矩形左上角的 x 轴坐标。

sy

要提取 ImageData 的矩形左上角的 y 轴坐标。

sw

要提取 ImageData 的矩形的宽度。正值向右延伸,负值向左延伸。

sh

要提取 ImageData 的矩形的高度。正值向下延伸,负值向上延伸。

settings 可选

一个具有以下属性的对象:

  • colorSpace:指定图像数据的颜色空间。可以设置为 "srgb" 表示 sRGB 色彩空间,或 "display-p3" 表示 display-p3 色彩空间。

 像素操作

ImageData对象中存储着 canvas 对象真实的像素数据,它包含以下几个只读属性:

  • width

图片宽度,单位是像素

  • height

图片高度,单位是像素

  • data

Uint8ClampedArray类型的一维数组,包含着 RGBA 格式的整型数据,范围在 0 至 255 之间(包括 255)。

data 属性返回一个 ,它可以被使用作为查看初始像素数据。每个像素用 4 个 1bytes 值 (按照红,绿,蓝和透明值的顺序; 这就是"RGBA"格式) 来代表。每个颜色值部份用 0 至 255 来代表。每个部份被分配到一个在数组内连续的索引,左上角像素的红色部份在数组的索引 0 位置。像素从左到右被处理,然后往下,遍历整个数组。

Uint8ClampedArray包含 height × width × 4 字节数据,索引值从 0 到 (height× width × 4)-1

 获取canvas中某个点位的RGBA值

// 要读取图片中位于第 50 行,第 200 列的像素的R/G/B/A 值
imageData.data[50 * (imageData.width * 4) + 200 * 4 + 0];  // R
imageData.data[50 * (imageData.width * 4) + 200 * 4 + 1];  // G
imageData.data[50 * (imageData.width * 4) + 200 * 4 + 2];  // B
imageData.data[50 * (imageData.width * 4) + 200 * 4 + 3];  // A

getImageData()方法的应用

  • 获取图片中点位的颜色值

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <style>
        .container {
            display: flex;
            height: 40px;
            width: 300px;
        }

        #color {
            height: 40px;
            width: 40px;
        }

        #text {
            padding-left: 10px;
            line-height: 40px;
        }
    </style>
    <canvas id="canvas"></canvas>
    <div class="container">
        <div id="color"></div>
        <div id="text"></div>
    </div>
    <script>
        var img = new Image();
        img.src = 'https://img.zbt.com/e/steam/item/730/QUstNDcgfCBBc2lpbW92IChNaW5pbWFsIFdlYXIp.png';
        img.crossOrigin = 'Anonymous';
        var canvas = document.getElementById('canvas');
        var color = document.getElementById('color');
        var text = document.getElementById('text');
        var ctx = canvas.getContext('2d');

        img.onload = function () {
            // 在canvas上画图片
            canvas.width = img.width;
            canvas.height = img.height;
            ctx.drawImage(img, 0, 0, img.width, img.height);
            canvas.addEventListener('mousemove', pick);
        };

        function pick(event) {
            // 获取鼠标坐标
            var x = event.layerX;
            var y = event.layerY;

            // 获取图片像素信息
            var pixel = ctx.getImageData(x, y, 1, 1);
            var data = pixel.data;

            console.log(x, y, pixel, data);

            // 获取rgba值
            var rgba = 'rgba(' + data[0] + ',' + data[1] + ',' + data[2] + ',' + (data[3] / 255) + ')';

            // 设置小正方形的背景颜色
            color.style.background = rgba;

            // 把拼接的字符串设置为元素的文本内容
            text.textContent = rgba;
        }
      
    </script>
</body>

</html>
  • 透明图片描边

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>outline</title>
</head>

<body>
    <style>
        canvas {
            position: absolute;
            top: 0;
            left: 0;
            z-index: 1;
        }

        img {
            position: absolute;
            top: 0;
            left: 0;
            z-index: 9999;
        }
    </style>
    <canvas id="can"></canvas>
    <script>

        // 某点位的RGBA值
        const pointXA = function (Val) {
            const { distance, data, x, y, width, isExist } = Val,
                Index = y * (width * 4) + (x + distance) * 4,
                A = data[Index + 3];
            return isExist ? A === 0 : A !== 0;
        }
        const pointYA = function (Val) {
            const { distance, data, x, y, width, height, isExist } = Val,
                Index = (y + distance) * (width * 4) + (x + 1) * 4,
                A = data[Index + 3];
            if (y > 30 && y < height - 30) {
                return isExist ? A === 0 : A !== 0;
            } else {
                return false;
            }
        }
        function isEdgePixel(data, x, y, width, height, direction = 'x') {
            // y 为 行 x 为 列
            let index = y * (width * 4) + x * 4, fun = null;
            if (direction === 'x') {
                fun = pointXA;
            } else {
                fun = pointYA;
            }
            const val = { data, x, y, width, height },
                currentA = fun({ ...val, isExist: true, distance: 0 }),
                distance2A = fun({ ...val, isExist: true, distance: 2 });
            distanceopposite2YA = fun({ ...val, isExist: true, distance: -2 }),
                distance4YA = fun({ ...val, isExist: false, distance: 4 }),
                distanceopposite4YA = fun({ ...val, isExist: false, distance: -4 }),
                isEdge = currentA && distance2A && distanceopposite2YA && (distance4YA || distanceopposite4YA);
            return isEdge;
        }

        (function createdCanvas() {
            const canvas = document.querySelector("#can"); // 创建canvas标签
            const ctx = canvas.getContext("2d"); // 获取2D渲染上下文
            const img = new Image(); // 创建新的图片对象
            img.crossOrigin = "Anonymous"
            img.src = "https://img.zbt.com/e/steam/item/730/QUstNDcgfCBBc2lpbW92IChNaW5pbWFsIFdlYXIp.png"
            let edgeXPoints = [], edgeYPoints = [];
            img.onload = () => {
                // 图片加载完成后执行的操作
                canvas.width = img.width; // 设置canvas宽度
                canvas.height = img.height; // 设置canvas高度
                // 绘制图片
                ctx.drawImage(img, 0, 0, img.width, img.height);
                // 获取像素数据
                const imageData = ctx.getImageData(
                    0,
                    0,
                    canvas.width,
                    canvas.height
                );
                const data = imageData.data;
                // 遍历像素数据
                for (let y = 0; y < canvas.height; y++) {
                    for (let x = 0; x < canvas.width; x++) {
                        const index = (y * canvas.width + x) * 4;
                        // 根据像素颜色判断是否为边缘像素(这里只是一个简单的示例,你可能需要更复杂的算法来检测边缘)
                        if (isEdgePixel(data, x, y, canvas.width, canvas.height, 'x')) {
                            // 如果是边缘像素,记录坐标
                            edgeXPoints.push({ x, y });
                        }
                        if (isEdgePixel(data, x, y, canvas.width, canvas.height, 'y')) {
                            // 如果是边缘像素,记录坐标
                            edgeYPoints.push({ x, y });
                        }
                    }
                }

                // 描边
                ctx.beginPath();
                [...edgeXPoints, ...edgeYPoints].forEach((point, index) => {
                    let x = point.x, y = point.y;
                    ctx.fillStyle = "gold";
                    ctx.fillRect(x, y, 1, 1);
                });
            };
        })();
    </script>
</body>

</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值