如何应用alpha图层蒙版,使一些图像透明使用画布

how to apply alpha layer mask to make some of the image transparent using canvas

本文关键字:图像 透明 何应用 应用 图层 alpha      更新时间:2023-09-26

有人能帮我解决这个问题吗?我想应用alpha图层蒙版,使一些图像使用画布透明。

谢谢你。

var redImageData = redCanvas.getContext("2d").getImageData(0, 0, 200, 200); //overlay
    var ImageData = imageCanvas.getContext("2d").getImageData(0, 0, 200, 200);
var px = redImageData.data;
var px2 = ImageData.data;
for(var i = 0; i < px.length; i += 4) {
     if(px[i + 0] == 0 && px[i + 1] == 0 && px[i+2] == 0){
         px[i + 3] = 0;
     } else {
         px[i + 0] = px2[i + 0];
         px[i + 1] = px2[i + 1];
         px[i + 2] = px2[i + 2];
         px[i + 3] = px2[i + 3];
     }
}
ctx.imageSmoothingEnabled = true;
ctx.putImageData(redImageData, 0, 0);

alpha mask over https://i.stack.imgur.com/zCzOf.png

链接的图像实际上不是alpha蒙版,而是哑光图像。不同之处在于,哑光图像表示作为alpha通道,但将其显示为RGB(或灰度)组件。它实际上没有α通道。哑光图像在视频合成软件中很常见,但在网络上不太有用。

Canvas或它使用的Porter-Duff方法不直接支持哑光图像,因此它们必须首先转换为实际的alpha通道。要做到这一点,你必须迭代每个像素,并移动一个组件值(从红色,绿色或蓝色-无关紧要)到alpha通道。

完成后,你可以使用画布对象,现在有适当的alpha通道与复合操作,只使用alpha信息(混合模式是另一个章节)。

更好的方法当然是提供带有适当alpha通道的PNG图像。但在任何情况下,为了显示也可以处理哑光图像,尽管效率不高,我们可以这样做:

将哑光图像转换为alpha通道

第一步:此代码部分展示了如何有效地将哑光图像转换为alpha通道的前置步骤。生成的颜色对于主合成步骤并不重要,因为它只会使用alpha通道,正如已经提到的。

在尝试使用图像之前,通过使用图像的onload回调或在加载完所有内容后运行脚本,确保图像已正确加载。

这段代码将使用像素的完整32位值(为了效率)简单地将一个组件(在本例中为蓝色)移动到alpha通道中,这使得图像看起来是青色的,但是您可以看到橙色背景显示出适当的alpha(大部分代码是处理加载和设置)。

window.onload = function() {
  // at this stage the image has loaded:
  var img = document.getElementById("img");
  var canvas = document.getElementById("c");
  var ctx = canvas.getContext("2d");
  // - setup canvas to match image
  canvas.width = img.naturalWidth;
  canvas.height = img.naturalHeight;
  // - draw image
  ctx.drawImage(img, 0, 0);
  // CONV. STEP: move a component channel to alpha-channel
  var idata = ctx.getImageData(0, 0, canvas.width, canvas.height);
  var data32 = new Uint32Array(idata.data.buffer);
  var i = 0, len = data32.length;
  
  while(i < len) {
    data32[i] = data32[i++] << 8; // shift blue channel into alpha (little-endian)
  }
  
  // update canvas
  ctx.putImageData(idata, 0, 0);      
};
body {background: #f72; font-size:44px; color:rgba(0,0,0,0.5)}
<img id="img" crossorigin="anonymous" src="https://i.imgur.com/QRGYuWg.png"> ► 
<canvas id="c"></canvas>

<标题>合成h1> 二部分则是关于使用新的alpha通道进行合成。

在这种情况下,哑光图像的黑色变成完全透明,而白色变成完全不透明。你可以在转换步骤中扭转这一点,但只要你知道哑光图像的外观,它就不会真正哑光。

我们使用合成模式source-in来替换内部内容。这将根据alpha值替换内容,同时保持alpha通道不变。

首先使用相同的模式处理内部部分,允许我们在绘制框架之前对内容做额外的事情(考虑小背景,阴影等)。

作为最后一步,我们填充透明区域,框架本身,通过使用合成模式destination-over,取代更透明的区域与内容绘制到画布(概念上它绘制"后面";现有内容)。

下面的代码使用了简单的彩色框-只需将它们替换为您想要绘制的任何内容。

window.onload = function() {
  var img = document.getElementById("img");
  var canvas = document.getElementById("c");
  var ctx = canvas.getContext("2d");
  canvas.width = img.naturalWidth;
  canvas.height = img.naturalHeight;
  ctx.drawImage(img, 0, 0);
  var idata = ctx.getImageData(0, 0, canvas.width, canvas.height);
  var data32 = new Uint32Array(idata.data.buffer);
  var i = 0, len = data32.length;
  while(i < len) data32[i] = data32[i++] << 8;
  ctx.putImageData(idata, 0, 0);
  
  // COMP. STEPS: use the mask with composite operation. Since our frame
  // is black (= transparent as alpha) we can use the following mode:
  ctx.globalCompositeOperation = "source-in";
  
  // draw something, here a blue box, replace with whatever you want
  ctx.fillStyle = "blue";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  
  // to fill the frame area, still transparent, use this mode:
  ctx.globalCompositeOperation = "destination-over";
  ctx.fillStyle = "yellow";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
};
body {background: #f72; font-size:44px; color:rgba(0,0,0,0.5)}
<img id="img" crossorigin="anonymous" src="https://i.imgur.com/QRGYuWg.png"> ► 
<canvas id="c"></canvas>