html - 以灰度保存 Canvas

标签 html canvas save html5-canvas grayscale

我想知道是否可以在 HTML5 中使用彩色 Canvas ,然后在单击保存按钮时将其保存为黑白(灰度)PNG。我已经设法将 Canvas 保存为 PNG,太棒了!但我想添加灰度功能,而不必自己用 Illustrator 等程序更改它。 顺便说一句, Canvas 上有移动的粒子。 (虽然我不确定这是否有任何影响)

谢谢~!

function download(){
    var dt = c.toDataURL('image/png');
    this.href = dt; 
}; 
downloadlink.addEventListener('click', download, false); 

最佳答案

可以通过从 Canvas 中提取 RGB 数据并计算它们的亮度值来实现。

不过,有几个先决条件需要满足,例如 CORS(在这种情况下这似乎不是问题,因为您已经可以保存图像)以及是否希望在保存后保留原始数据您可以将 Canvas 上的当前图像复制到临时图像,或者保留需要提取的像素数据的备份。

RGB 到亮度

根据REC 709(或BT.709)公式,将RGB数据转换为亮度值(灰色)的公式如下:

luma = Red x 0.2126 + Green x 0.7152 + Blue x 0.0722

或者,您可以改用 REC 601 (BT.601) 公式(这在标清视频素材中更为常见):

luma = Red x 0.299 + Green x 0.587 + Blue x 0.114

要使用它,只需遍历所有像素,使用这些公式之一获取亮度值,并将目标中的所有 channel 替换为生成的亮度值。

临时数据

对于临时数据,我们可以执行以下任一操作(单击保存按钮时):

临时 Canvas

  • 创建临时 Canvas
  • 设置大小等于源 Canvas
  • 使用 drawImage() 在源 Canvas 中绘制
  • 使用 getImageData() 提取目标 Canvas 的像素数据
  • 迭代像素,使用公式转换,放回数据
  • 保存图片然后丢弃临时 Canvas

图像数据备份

  • 使用 getImageData() 提取图像数据 - 这将作为我们的备份
  • 使用 createImageData() 创建相同大小的新 ImageData
  • 迭代备份中的像素,但将结果以亮度形式放入创建的 ImageData
  • 将创建的ImageData放回去,保存出图片
  • 放回备份数据

是否需要后一步实际上取决于您如何更新 Canvas 。如果您正在为循环制作动画,则可能不需要放回备份(或保留一个),如果一切都得到更新,但如果是这样并且您看到灰色闪烁或某些区域留下灰色,则需要此步骤。

使用ImageData方法的例子

var ctx = c.getContext("2d"), img = new Image;
img.onload = setup;  img.crossOrigin = "";
img.src = "//i.imgur.com/OrYVGI8.jpg";

function setup() {
  c.width = this.naturalWidth;  c.height = this.naturalHeight;
  ctx.drawImage(this, 0, 0);    btn.disabled = false
}

// Main code for demo
btn.onclick = function() {
  
  var idataSrc = ctx.getImageData(0, 0, c.width, c.height), // original
      idataTrg = ctx.createImageData(c.width, c.height),    // empty data
      dataSrc = idataSrc.data,                              // reference the data itself
      dataTrg = idataTrg.data,
      len = dataSrc.length, i = 0, luma;
  
  // convert by iterating over each pixel each representing RGBA
  for(; i < len; i += 4) {
    // calculate luma, here using Rec 709
    luma = dataSrc[i] * 0.2126 + dataSrc[i+1] * 0.7152 + dataSrc[i+2] * 0.0722;

    // update target's RGB using the same luma value for all channels
    dataTrg[i] = dataTrg[i+1] = dataTrg[i+2] = luma;
    dataTrg[i+3] = dataSrc[i+3];                            // copy alpha
  }
  
  // put back luma data so we can save it as image
  ctx.putImageData(idataTrg, 0, 0);
  demo.src = c.toDataURL();                                 // set demo result's src url
  
  // restore backup data
  ctx.putImageData(idataSrc, 0, 0);
};
<button disabled id=btn>SAVE TO GREY</button> (click then scroll down to see result)<br>
<canvas id=c></canvas><br><img id=demo>

关于html - 以灰度保存 Canvas ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37159358/

相关文章:

javascript - 尝试使用显示/隐藏慢慢淡入/淡出一段

javascript - Bootstrap : Creating Multiple Popovers with Button click

canvas - 增加 Chart.js Scale Padding/Margin

javascript - 如果点击链接出现404错误,如何重定向网页?

javascript - 如何在 JavaScript 中使用条件语句包含多种颜色样式

javascript - 在 Canvas 背景图像上插入绘制的形状

javascript - HTML5 Canvas 形状从圆形到三 Angular 形

vba - 将当前电子邮件中的附件保存到派生文件夹中。

javascript - 将图表图像保存在特定位置 GWT

c - 在程序中运行程序