有没有办法停止画布数据的Alpha通道的预乘,或者解决方法?
我想生成一个图像(在这种情况下,一些随机的rgba值)并将画布另存为图像。
在第二步中,我想使用imageData将原始图像与生成的图像进行比较,但是由于生成的图像中我的rgba像素的alpha通道的预乘,因此无法正常工作。
The example
function drawImage(ctx) {
var img = ctx.createImageData(canvas.width,canvas.height);
for (var i=img.data.length;i-=4;) {
img.data[i] = Math.floor(Math.random() * 255);
img.data[i+1] = Math.floor(Math.random() * 255);
img.data[i+2] = Math.floor(Math.random() * 255);
img.data[i+3] = Math.floor(Math.random() * 255);
}
ctx.putImageData(img, 0, 0);
// our image data we just set
console.log(img.data);
// the image data we just placed onto the canvas
console.log(ctx.getImageData(0,0,canvas.width, canvas.height).data);
}
在控制台中,您将找到两个console.log输出。第一个在预乘之前,第二个在预乘之后。这两个输出是不同的,有些值相差3或更多。仅当涉及部分透明性时(alpha设置为255以外的任何值),才会发生这种情况。
有没有办法获得相同的输出?关于这个问题有什么想法吗?任何想法如何创建类似的解决方法来解决此问题?
先感谢您!
最佳答案
Bleh,就画布规范而言,这是一个公认的问题。它指出:
由于在预乘alpha颜色值之间进行转换的有损特性,刚使用putImageData()设置的像素可能会以不同的值返回到等效的getImageData()。
所以这:
var can = document.createElement('canvas');
var ctx = can.getContext('2d');
can.width = 1;
can.height = 1;
var img = ctx.createImageData(1, 1);
img.data[0] = 40;
img.data[1] = 90;
img.data[2] = 200;
var ALPHAVALUE = 5;
img.data[3] = ALPHAVALUE;
console.log(img.data);
ctx.putImageData(img, 0, 0);
console.log(ctx.getImageData(0, 0, 1, 1).data);
输出:
[40, 90, 200, 5]
[51, 102, 204, 5]
在所有浏览器中。
因此,这是有损操作,除非他们更改规范以提供不使用预乘法的选项,否则没有解决方法。 WHATWG邮件列表中早在2008年就对此进行了讨论,他们认为规范不能要求“往返” /放置/获取图像数据的身份。
如果需要“保存”图像数据,则不能使用putImageData保存并保持相同的保真度。通过将全Alpha数据绘制到临时画布并使用较小的
globalAlpha
重新绘制到主画布的解决方法也不起作用。所以你很不走运。抱歉。
直到今天(2014年5月12日),这仍然在WHATWG列表中进行讨论:http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2014-May/296792.html