html5如何实现图片渐变映射_html5渐变映射处理法【代码】

10次阅读

图片渐变映射是将图像像素亮度或Alpha通道值映射为渐变色,需用canvas手动读取像素、计算灰度、插值渐变色并重绘,核心步骤包括drawImage、getImageData、灰度加权计算、归一化插值及putImageData。

html5如何实现图片渐变映射_html5渐变映射处理法【代码】

什么是图片渐变映射,不是 css 渐变背景

很多人搜“图片渐变映射”,其实是想把一张图片的**像素亮度或 Alpha 通道**,映射成某种线性/径向渐变颜色(比如:暗部变蓝、亮部变黄),而不是给图片加个渐变遮罩层。html5 原生不提供“图像 → 渐变色”这种映射函数,必须靠 canvasRenderingContext2D 手动读取像素、计算映射、重绘

getImageData + putImageData 实现灰度→渐变映射

核心思路:把原图转为灰度值(0–255),再用这个值查表或插值到一个预设渐变色数组中。注意不能直接对 img 元素操作,必须绘制到 后处理。

  • 图片需同源(否则 getImageDataSecurityError
  • 先调用 ctx.drawImage(img, 0, 0) 将图片画入 canvas
  • ctx.getImageData(0, 0, width, height) 获取像素数组(Uint8ClampedArray,每 4 个元素一组:R/G/B/A)
  • 遍历每个像素,算灰度:gray = 0.299*r + 0.587*g + 0.114*b(YUV 加权)
  • gray 归一化为 t = gray / 255,再插值到你的渐变色断点(例如 [[0,0,255], [255,255,0]] 表示蓝→黄)
  • 写回 data 数组,并用 ctx.putImageData() 刷新画面
const canvas = document.getElementById('c'); const ctx = canvas.getContext('2d'); const img = new Image(); img.onload = () => {   canvas.width = img.width; canvas.height = img.height;   ctx.drawImage(img, 0, 0);   const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);   const data = imageData.data;   const gradientColors = [[0,0,255], [255,255,0]]; // 蓝→黄    for (let i = 0; i < data.length; i += 4) {     const r = data[i], g = data[i+1], b = data[i+2];     const gray = 0.299*r + 0.587*g + 0.114*b;     const t = Math.min(1, Math.max(0, gray / 255));     const [r0,g0,b0] = gradientColors[0];     const [r1,g1,b1] = gradientColors[1];     data[i]   = r0 + t*(r1-r0);     data[i+1] = g0 + t*(g1-g0);     data[i+2] = b0 + t*(b1-b0);   }   ctx.putImageData(imageData, 0, 0); }; img.src = 'photo.jpg';

createRadialGradientcreateLinearGradient 不适用此场景

这两个 Canvas API 是用来**绘制渐变形状**的(比如画一个渐变圆),它们生成的是 CanvasGradient 对象,无法反向作用于已有图像像素。强行用 ctx.fillStyle = gradfillRect 只会盖住原图,不是“映射”。真要结合使用,得自己做逐像素采样:用坐标 (x,y) 算出该点在渐变中的归一化位置 t,再查色——但这已经脱离“图片映射”本意,变成自定义着色器逻辑了。

性能与兼容性要注意这些点

大图(如 2000×3000)做全量像素遍历会卡顿,尤其低端设备。实际项目中建议:

立即学习前端免费学习笔记(深入)”;

  • requestIdleCallback 分块处理,避免阻塞线程
  • 对高清图先缩放到 50% 再处理(canvas.width/height 设小些),视觉损失小但性能提升明显
  • IE 完全不支持 getImageData跨域图片;safaridata: 协议图片有限制
  • 若需实时响应(如拖拽调节映射曲线),考虑用 webglWebGLRenderingContext)替代 Canvas 2D,但复杂度陡增

真正难的不是写几行代码,而是决定灰度怎么转色——加 gamma 校正?用 Lab 色彩空间?是否保留原始色相?这些没标准答案,得看设计目标。

text=ZqhQzanResources