链接的图像是不是一个真正的阿尔法掩模但磨砂图像。不同之处在于,无光泽图像代表将作为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>
来源
2016-11-16 21:40:14
K3N
改变您的图像,使得白色部分是透明的,然后使用['globalCompositeOperation'](https://developer.mozilla.org/en-US/docs/Web/API/ CanvasRenderingContext2D/globalCompositeOperation)来执行合成。 – Kaiido