2016-11-16 46 views
2

有人可以帮我解决这个问题吗? 我想应用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遮罩过于https://i.stack.imgur.com/zCzOf.png

+1

改变您的图像,使得白色部分是透明的,然后使用['globalCompositeOperation'](https://developer.mozilla.org/en-US/docs/Web/API/ CanvasRenderingContext2D/globalCompositeOperation)来执行合成。 – Kaiido

回答

1

链接的图像是不是一个真正的阿尔法掩模但磨砂图像。不同之处在于,无光泽图像代表作为alpha通道,但将其显示为RGB(或灰度)组件。它实际上并没有alpha通道。无光泽图像在视频合成软件中很常见,但在网络上不太实用。

画布或其使用的Porter-Duff方法不直接支持亚光图像,因此必须先将其转换为实际的Alpha通道。要做到这一点,你必须迭代每个像素,并将其中一个分量值(从红色,绿色或蓝色 - 无所谓)放入alpha通道。

完成后,您可以使用现在具有合适alpha通道的画布对象以及仅使用alpha信息的混合操作(混合模式是不同的章节)。

更好的方法当然是提供图像作为PNG与适当的alpha通道。但在任何情况下,以显示它有可能也采用磨砂图像工作,但效率不高,我们可以做到以下几点:

转换无光泽的图案为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>

复化

然后,第二部分成为如何使用新的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>