New*_*bie 14 javascript canvas rgba html5-canvas
有没有办法阻止画布数据的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);
}
Run Code Online (Sandbox Code Playgroud)
在控制台中,您将找到两个console.log输出.第一个在预乘之前,第二个在预乘之后.这两个输出是不同的,一些值偏离3或更多.这仅在涉及部分透明度时发生(将alpha设置为255以外的任何值).
有没有办法获得相同的输出?关于这个问题的任何想法?任何想法如何创建像这个问题的解决方法?
先感谢您!
Sim*_*ris 16
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);
Run Code Online (Sandbox Code Playgroud)
输出:
[40, 90, 200, 5]
[51, 102, 204, 5]
Run Code Online (Sandbox Code Playgroud)
在所有浏览器中.
所以这是一个有损操作,除非他们更改规范以提供不使用预乘的选项,否则没有解决方法.早在2008年WHATWG邮件列表中就讨论过这个问题,他们认为投放/获取图像数据的"往返"/身份并不是规范愿意要求的承诺.
如果需要"保存"图像数据,则无法使用putImageData保存图像数据并保持相同的保真度.通过将完整的alpha数据绘制到临时画布并使用较小的重绘到主画布的解决方法globalAlpha
也不起作用.
所以你运气不好.抱歉.
到今天(2014年5月12日),仍然会在WHATWG列表中讨论这个问题:http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2014-May/296792.html
我找到了一种方法来读取使用WebGL的2.这是有关我的问题的图像的精确字节值这里。看看下面的代码,它将结果getImageData
与预期输出和 WebGL 的输出进行比较:
let image = new Image();
image.addEventListener('load', function () {
let canvas = document.createElement('canvas');
let ctx = canvas.getContext("2d");
canvas.width = this.width;
canvas.height = this.height;
ctx.drawImage(this, 0, 0);
let data = ctx.getImageData(0, 0, this.width, this.height).data;
document.getElementById('imageData').innerHTML = data;
});
image.addEventListener('load', function () {
let canvas = document.createElement('canvas');
let gl = canvas.getContext("webgl2");
gl.activeTexture(gl.TEXTURE0);
let texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
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_BYTE, this);
gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
let data = new Uint8Array(this.width * this.height * 4);
gl.readPixels(0, 0, this.width, this.height, gl.RGBA, gl.UNSIGNED_BYTE, data);
document.getElementById('webGl').innerHTML = data;
});
image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4nGPg2T3JDgADyAGYmiSbAQAAAABJRU5ErkJggg==";
Run Code Online (Sandbox Code Playgroud)
<pre>Expected: 12,187,146,62<br>
ImageData: <span id="imageData"></span><br>
WebGL: <span id="webGl"></span><br></pre>
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2466 次 |
最近记录: |