Javascript 如何使用canvas imageData停止alpha预乘?

Javascript 如何使用canvas imageData停止alpha预乘?,javascript,canvas,html5-canvas,rgba,Javascript,Canvas,Html5 Canvas,Rgba,是否有方法停止画布数据的alpha通道的预乘法,或解决方法 我想生成一个图像(在本例中是一些随机的rgba值)并将画布另存为图像 在第二步中,我希望使用imageData将原始图像与生成的图像进行比较,但是由于生成的图像中我的rgba像素的alpha通道的预乘法,这将不起作用 function drawImage(ctx) { var img = ctx.createImageData(canvas.width,canvas.height); for (var i=i

是否有方法停止画布数据的alpha通道的预乘法,或解决方法

我想生成一个图像(在本例中是一些随机的rgba值)并将画布另存为图像

在第二步中,我希望使用imageData将原始图像与生成的图像进行比较,但是由于生成的图像中我的rgba像素的alpha通道的预乘法,这将不起作用

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以外的任何值)

有没有办法获得相同的输出?对这个问题有什么想法吗?有什么办法可以解决这个问题吗


提前谢谢你

哎呀,就画布规范而言,这是一个公认的问题。它注意到:

由于在预乘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]
在所有浏览器中

所以这是一个有损操作,除非他们修改规范,提供不使用预乘的选项,否则没有解决办法。早在2008年WHATWG邮件列表中就讨论过这一点,他们认为put/get图像数据的“往返/标识”并不是规范愿意要求的承诺

如果需要“保存”图像数据,则无法使用putImageData保存图像数据并保持相同的保真度。解决方法是将完整的alpha数据绘制到临时画布上,然后使用较小的
globalAlpha
重新绘制到主画布上,这也行不通

所以你运气不好。对不起



时至今日(2014年5月12日),WHATWG列表上仍在讨论这一点:

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]
在所有浏览器中

所以这是一个有损操作,除非他们修改规范,提供不使用预乘的选项,否则没有解决办法。早在2008年WHATWG邮件列表中就讨论过这一点,他们认为put/get图像数据的“往返/标识”并不是规范愿意要求的承诺

如果需要“保存”图像数据,则无法使用putImageData保存图像数据并保持相同的保真度。解决方法是将完整的alpha数据绘制到临时画布上,然后使用较小的
globalAlpha
重新绘制到主画布上,这也行不通

所以你运气不好。对不起



直到今天(2014年5月12日),WHATWG的名单上仍在讨论这一点:

这仍然是一个令人沮丧的问题


我想如果你在webgl的纹理中使用它,你可以把它作为一个统一的字节数组来传递


我想如果你在webgl的纹理中使用它,你可以把它作为一个统一的字节数组来传递

我找到了一种使用webgl 2读取图像的精确字节值的方法。这与我的问题有关。请看下面的代码,它将
getImageData
的结果与预期输出和WebGL的输出进行比较:

let image=new image();
image.addEventListener('load',函数(){
让canvas=document.createElement('canvas');
设ctx=canvas.getContext(“2d”);
canvas.width=this.width;
canvas.height=this.height;
ctx.drawImage(this,0,0);
让data=ctx.getImageData(0,0,this.width,this.height);
document.getElementById('imageData')。innerHTML=data;
});
image.addEventListener('load',函数(){
让canvas=document.createElement('canvas');
设gl=canvas.getContext(“webgl2”);
gl.activeTexture(gl.TEXTURE0);
让纹理=gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D,纹理);
const framebuffer=gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER,FRAMEBUFFER);
gl.framebufferTexture2D(gl.FRAMEBUFFER,gl.COLOR_ATTACHMENT0,gl.TEXTURE_2D,TEXTURE,0);
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_字节,this);
总图绘制缓冲区([gl.COLOR_ATTACHMENT0]);
让数据=新的UINT8数组(this.width*this.height*4);
gl.readPixels(0,0,this.width,this.height,gl.RGBA,gl.UNSIGNED_字节,数据);
document.getElementById('webGl')。innerHTML=数据;
});
image.src=“数据:image/png;base64,ivborw0kggoaaaansuhueugaaaaaabcayaaaaffcsjaaaaduleqvr4ngpg2t3jdgadymyisbaqaaabjru5erkjggg=”
预计:12187146,62
图像数据:

WebGL:
我找到了一种使用WebGL 2读取图像准确字节值的方法。这与我的问题有关。请看下面的代码,它将
getImageData
的结果与预期输出和WebGL的输出进行比较:

let image=new image();
image.addEventListener('load',函数(){
让canvas=document.createElement('canvas');
设ctx=canvas.getContext(“2d”);
canvas.width=this.width;
canvas.height=this.height;
ctx.drawImage(this,0,0);
让data=ctx.getImageData(0,0,this.width,this.height);
document.getElementById('imageData')。innerHTML=data;
});
image.addEventListener('load',函数(){
让canvas=document.createElement('canvas');
设gl=canvas.getContext(“webgl2”);
gl.activeTexture(gl.TEXTURE0);
让纹理=gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D,纹理);
常量帧缓冲区=gl.createFramebuffe