Javascript 画布:遮罩图像并保留其alpha通道?
以下是我想做的:Javascript 画布:遮罩图像并保留其alpha通道?,javascript,html,canvas,html5-canvas,Javascript,Html,Canvas,Html5 Canvas,以下是我想做的: 获取图像A和图像B。图像B是黑白掩模图像 将图像A的alpha通道替换为图像B的红色通道 在画布上绘制图像C 在图像C的顶部绘制图像A 在第4步之前,一切似乎都正常。图像C根本不可见,而图像A应该是透明的,则为白色 cx.putImageData(imageA, 0, 0); var resultData = cx.getImageData(0, 0, view.width, view.height); for (var h=0; h<resultData.data.l
cx.putImageData(imageA, 0, 0);
var resultData = cx.getImageData(0, 0, view.width, view.height);
for (var h=0; h<resultData.data.length; h+=4) {
resultData.data[h+3] = imageB.data[h];
}
cx.putImageData(imageC, 0, 0);
cx.putImageData(resultData, 0, 0);
cx.putImageData(imageA,0,0);
var resultData=cx.getImageData(0,0,view.width,view.height);
对于(var h=0;h,因为在步骤4中,您使用的是完全替代像素的putImageData
。您希望在图像C的顶部绘制图像A,因此您不能这样做。相反,您需要使用drawImage()
我们也要这样做:
cx.putImageData(imageC, 0, 0); // step 3
// create a new canvas and new context,
// call that new context ctx2 and canvas can2:
var can2 = document.createElement('canvas');
// set can2's width and height, get the context etc...
ctx2.putImageData(resultData, 0, 0);
cx.drawImage(can2, 0, 0); // step 4 using drawImage instead of putting image data
Simon是对的:putImageData
方法不注意合成;它只复制像素值。为了得到合成,我们需要使用绘图操作
我们需要用像素数据处理通道(将红色变成alpha),将更改后的像素数据放入图像,然后使用合成操作获得所需的遮罩
//copy from one channel to another
var assignChannel = function(imageData, channelTo, channelFrom) {
if(channelTo < 0 || channelTo > 3 || channelFrom < 0 || channelFrom > 3) {
throw new Error("bad channel number");
}
if(channelTo == channelFrom)
return;
var px = imageData.data;
for(var i = 0; i < px.length; i += 4) {
px[i + channelTo] = px[i + channelFrom];
}
};
/**============================================================================
* this function uses 3 or 4 canvases for clarity / pedagogical reasons:
* redCanvas has our mask image;
* maskCanvas will be used to store the alpha channel conversion of redCanvas' image;
* imageCanvas contains the image to be masked;
* ctx is the context of the canvas to which the masked image will be drawn.
============================================================================**/
var drawOnTopOfRed = function(redCanvas, maskCanvas, imageCanvas, ctx) {
var redImageData = redCanvas.getContext("2d").getImageData(0, 0, w, h);
//assign the alpha channel
assignChannel(redImageData, 3, 0);
//write the mask image
maskCanvas.getContext("2d").putImageData(redImageData, 0, 0);
ctx.save();
//draw the mask
ctx.globalCompositeOperation = "copy";
ctx.drawImage(maskCanvas, 0, 0);
//draw the image to be masked, but only where both it
//and the mask are opaque; see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#compositing for details.
ctx.globalCompositeOperation = "source-in";
ctx.drawImage(imageCanvas, 0, 0);
ctx.restore();
};
//从一个频道复制到另一个频道
var assignChannel=函数(imageData、channelTo、channelFrom){
if(channelTo<0 | | channelTo>3 | | channelFrom<0 | | channelFrom>3){
抛出新错误(“坏通道号”);
}
if(channelTo==channelFrom)
返回;
var px=imageData.data;
对于(变量i=0;i
一个涂鸦的例子:
哇,我不知道可以将画布对象作为参数传递给drawImage()。这是可行的,但由于某些原因,drawImage()比putImageData()慢得多,而且因为我需要每隔20-40毫秒绘制一次图像,所以这不是一个完美的解决方案。我做了一些实验,并用两个画布解决了这个问题。putImageData()完全替换像素值,但当我在第一个画布下放置另一个画布时,我可以看到它是透明的。无论如何,感谢您的时间,欣赏它!这很奇怪。使用imageData
几乎总是比使用drawImage
慢得多。这里可能还有其他原因-我可以看到您的完整c吗颂歌?