Javascript 如何使用canvas imageData停止alpha预乘?
是否有方法停止画布数据的alpha通道的预乘法,或解决方法 我想生成一个图像(在本例中是一些随机的rgba值)并将画布另存为图像 在第二步中,我希望使用imageData将原始图像与生成的图像进行比较,但是由于生成的图像中我的rgba像素的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
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