html canvas 像素级图像修改依赖 getimagedata 和 putimagedata:前者获取指定区域 rgba 数组副本,后者将修改后的数据写回画布;需注意跨域、坐标系、尺寸匹配及性能优化。

HTML Canvas 实现像素级图像数据修改,核心是 getImageData 和 putImageData 这一对原生 API。它们不依赖库、不走渲染管线,直接读写底层 RGBA 数组,让你真正控制每个像素。
获取像素数据:拿到原始快照
调用 ctx.getImageData(x, y, width, height) 会从画布指定矩形区域拷贝一份像素副本,返回一个 ImageData 对象。关键在它的 .data 属性——一个 Uint8ClampedArray 类型的一维数组,按 R→G→B→A 顺序排列,每个值是 0–255 的整数。
- 坐标
(x, y)是区域左上角,与 canvas 当前 transform 无关,始终基于原始像素坐标 - 宽高必须匹配实际绘制的图像尺寸,否则可能越界或截断
- 跨域图片需提前设置
img.crossOrigin = "anonymous",否则抛安全错误 -
ImageData是只读副本,改它不会自动更新画布
修改像素:遍历并计算每个通道
遍历 data 数组时,步长为 4(跳过每组 R/G/B/A),对每个像素单独处理:
-
灰度化:用加权平均公式
gray = 0.299*r + 0.587*g + 0.114*b,再将 R/G/B 都设为Math.round(gray);Alpha 保持不变 -
反色:直接
data[i] = 255 - data[i](R),data[i+1] = 255 - data[i+1](G),data[i+2] = 255 - data[i+2](B);Alpha 不参与 -
亮度/对比度调整:可对 RGB 值做线性变换,如
newVal = Math.min(255, Math.max(0, val * contrast + brightness))
写回画布:一次性刷入结果
修改完 data 后,必须显式调用 ctx.putImageData(imageData, dx, dy) 才能生效:
- 基础用法:
putImageData(imgData, 0, 0)覆盖整个画布左上角 - 性能优化:支持“脏区”参数
putImageData(imgData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight),只重绘修改过的子区域,避免整图刷新 - 注意:若 canvas 被 CSS 缩放(如
width: 100%),getImageData仍按原始像素尺寸读取,易导致模糊或错位
常见避坑点
实操中容易卡住的地方:
- 图像未加载完成就调用
drawImage或getImageData→ 务必监听img.onload - 直接赋值整个
data数组(如imgData.data = newArray)→ 无效,只能逐项赋值 - 在动画循环中高频调用
putImageData→ 该操作较重,建议用requestIdleCallback分块处理,或移交 Web Worker - 忘记设置 canvas 尺寸与图片一致 → 导致绘制拉伸、读取偏移
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











