以灰度保存画布

时间:2016-05-11 10:06:56

标签: html5 canvas save html5-canvas grayscale

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

感谢〜!

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

3 个答案:

答案 0 :(得分:7)

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

有一些必需品需要满足,比如CORS(在这种情况下似乎不是问题,因为你已经可以保存图像),如果你想在保存后保留原始数据您可以将画布上的当前图像复制到临时图像,也可以保留需要提取的像素数据的备份。

RGB到Luma

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

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

另外,您可以使用REC 601(BT.601)公式(这在SD视频素材中更常见):

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

要使用此功能,只需遍历所有像素,使用其中一个公式获取亮度值,并将目标中的所有通道替换为生成的亮度值。

临时数据

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

临时画布

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

ImageData备份

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

如果需要后一步,实际上取决于您如何更新画布。如果你动画循环,可能不需要放回备份(或保留一个),如果一切都得到更新,但如果是这样,你看到灰色闪光或某些区域变灰,那么就需要这一步。 / p>

使用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);
};
&#13;
<button disabled id=btn>SAVE TO GREY</button> (click then scroll down to see result)<br>
<canvas id=c></canvas><br><img id=demo>
&#13;
&#13;
&#13;

答案 1 :(得分:4)

或者你可以在用白色填充的画布上绘制图像之前使用app:customVisibility="@{viewModel.isVisible}" ,而不是有趣但结果相同(:

答案 2 :(得分:0)

我建议像这样计算亮度:

var luma = (11 * obj.data[i] + 16 * obj.data[i + 1] +  5 * obj.data[i + 2]) >> 5;