ZetCode

JavaScript Canvas getImageData 教程

最后修改于 2025 年 4 月 3 日

在本篇文章中,我们将探讨 JavaScript 中的 Canvas getImageData 方法。此方法对于画布内容的像素级操作至关重要。掌握 getImageData 对于图像处理和视觉效果至关重要。

基本定义

getImageData 方法返回一个 ImageData 对象,该对象表示画布特定区域的像素数据。这些数据包括所选区域中每个像素的 RGBA 值。该方法接受四个参数。

参数是左上角的 x、y 坐标,以及要捕获的矩形的宽度和高度。返回的 ImageData 对象包含宽度、高度和一个像素数据的 Uint8ClampedArray。

基本 getImageData 用法

此示例演示了如何从画布检索像素数据。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Basic getImageData</title>
</head>
<body>

<canvas id="myCanvas" width="300" height="200"></canvas>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    // Draw a red rectangle
    ctx.fillStyle = 'red';
    ctx.fillRect(50, 50, 100, 100);
    
    // Get pixel data
    const imageData = ctx.getImageData(50, 50, 100, 100);
    console.log(imageData);
</script>

</body>
</html>

在这个基本示例中,我们创建一个画布并绘制一个红色矩形。然后,我们使用 getImageData 捕获该矩形的像素数据。

imageData 对象包含 width、height 和 data 属性。data 属性是一个类型化数组,包含区域中每个像素的 RGBA 值。

读取像素颜色

此示例展示了如何从画布读取特定像素的颜色。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Reading Pixel Colors</title>
</head>
<body>

<canvas id="myCanvas" width="300" height="200"></canvas>
<p id="output"></p>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    const output = document.getElementById('output');
    
    // Draw a gradient
    const gradient = ctx.createLinearGradient(0, 0, 300, 0);
    gradient.addColorStop(0, 'red');
    gradient.addColorStop(1, 'blue');
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, 300, 200);
    
    // Get pixel at position (150, 100)
    const pixelData = ctx.getImageData(150, 100, 1, 1).data;
    output.textContent = `RGBA: ${pixelData[0]}, ${pixelData[1]}, ${pixelData[2]}, ${pixelData[3]}`;
</script>

</body>
</html>

此示例创建了一个从红色到蓝色的渐变,并显示位置 (150,100) 像素的 RGBA 值。像素数据存储在 Uint8ClampedArray 中。

每个像素由四个连续的数组元素 (R,G,B,A) 表示。颜色值的范围为 0 到 255,透明度 (alpha) 的范围也为 0 到 255。

创建灰度滤镜

此示例演示了如何使用 getImageData 创建灰度滤镜。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Grayscale Filter</title>
</head>
<body>

<canvas id="myCanvas" width="300" height="200"></canvas>
<button onclick="applyGrayscale()">Apply Grayscale</button>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    // Draw a colorful rectangle
    ctx.fillStyle = 'red';
    ctx.fillRect(0, 0, 100, 200);
    ctx.fillStyle = 'green';
    ctx.fillRect(100, 0, 100, 200);
    ctx.fillStyle = 'blue';
    ctx.fillRect(200, 0, 100, 200);
    
    function applyGrayscale() {
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const data = imageData.data;
        
        for (let i = 0; i < data.length; i += 4) {
            const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
            data[i] = avg;     // R
            data[i + 1] = avg;  // G
            data[i + 2] = avg;  // B
        }
        
        ctx.putImageData(imageData, 0, 0);
    }
</script>

</body>
</html>

此示例创建了一个具有三个彩色矩形的画布。单击按钮时,applyGrayscale 函数会将图像转换为灰度。

该函数获取所有像素数据,计算每个像素 RGB 值的平均值,并将所有三个颜色通道设置为该平均值。然后将修改后的数据放回画布上。

创建颜色反转滤镜

此示例展示了如何使用 getImageData 创建颜色反转效果。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Color Inversion</title>
</head>
<body>

<canvas id="myCanvas" width="300" height="200"></canvas>
<button onclick="invertColors()">Invert Colors</button>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    // Draw an image or shape
    ctx.fillStyle = 'yellow';
    ctx.fillRect(0, 0, 300, 200);
    ctx.fillStyle = 'purple';
    ctx.beginPath();
    ctx.arc(150, 100, 80, 0, Math.PI * 2);
    ctx.fill();
    
    function invertColors() {
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const data = imageData.data;
        
        for (let i = 0; i < data.length; i += 4) {
            data[i] = 255 - data[i];      // R
            data[i + 1] = 255 - data[i + 1]; // G
            data[i + 2] = 255 - data[i + 2]; // B
        }
        
        ctx.putImageData(imageData, 0, 0);
    }
</script>

</body>
</html>

此示例创建了一个带有黄色背景和紫色圆形的画布。invertColors 函数通过从 255 中减去每个颜色通道来反转颜色。

在反转的图像中,红色变为青色,绿色变为品红色,蓝色变为黄色。在此操作中,alpha 通道保持不变。

边缘检测算法

这个高级示例演示了一个简单的边缘检测算法。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Edge Detection</title>
</head>
<body>

<canvas id="sourceCanvas" width="300" height="200"></canvas>
<canvas id="edgeCanvas" width="300" height="200"></canvas>
<button onclick="detectEdges()">Detect Edges</button>

<script>
    const sourceCanvas = document.getElementById('sourceCanvas');
    const edgeCanvas = document.getElementById('edgeCanvas');
    const sourceCtx = sourceCanvas.getContext('2d');
    const edgeCtx = edgeCanvas.getContext('2d');
    
    // Draw a sample image on source canvas
    sourceCtx.fillStyle = 'white';
    sourceCtx.fillRect(0, 0, 300, 200);
    sourceCtx.fillStyle = 'black';
    sourceCtx.beginPath();
    sourceCtx.arc(150, 100, 50, 0, Math.PI * 2);
    sourceCtx.fill();
    
    function detectEdges() {
        const imageData = sourceCtx.getImageData(0, 0, sourceCanvas.width, sourceCanvas.height);
        const data = imageData.data;
        const width = imageData.width;
        const height = imageData.height;
        
        // Create a new ImageData for edges
        const edgeData = edgeCtx.createImageData(width, height);
        
        // Simple edge detection (difference with right and bottom pixels)
        for (let y = 0; y < height - 1; y++) {
            for (let x = 0; x < width - 1; x++) {
                const i = (y * width + x) * 4;
                const right = ((y * width) + (x + 1)) * 4;
                const bottom = ((y + 1) * width + x) * 4;
                
                // Calculate differences
                const diffR = Math.abs(data[i] - data[right]) + Math.abs(data[i] - data[bottom]);
                const diffG = Math.abs(data[i + 1] - data[right + 1]) + Math.abs(data[i + 1] - data[bottom + 1]);
                const diffB = Math.abs(data[i + 2] - data[right + 2]) + Math.abs(data[i + 2] - data[bottom + 2]);
                
                const edgeValue = (diffR + diffG + diffB) / 3;
                const edgeIndex = (y * width + x) * 4;
                
                edgeData.data[edgeIndex] = edgeValue;
                edgeData.data[edgeIndex + 1] = edgeValue;
                edgeData.data[edgeIndex + 2] = edgeValue;
                edgeData.data[edgeIndex + 3] = 255;
            }
        }
        
        edgeCtx.putImageData(edgeData, 0, 0);
    }
</script>

</body>
</html>

此示例实现了一个基本的边缘检测算法。它将每个像素与其右侧和底部的邻居进行比较,以检测颜色差异。

该算法计算所有颜色通道的平均差值。较大的差异表示边缘,这些边缘以灰度值的形式绘制在第二个画布上。这展示了高级像素操作。

来源

MDN getImageData 文档

在本篇文章中,我们探索了使用 getImageData 操作画布像素的各种技术。这些方法对于在 Web 应用程序中进行图像处理和创建视觉效果至关重要。

作者

我的名字是 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直撰写编程文章。至今,我已撰写了 1400 多篇文章和 8 本电子书。我在教授编程方面拥有十多年的经验。

列出 所有 JS Canvas 教程