gpt4 book ai didi

javascript - HTML5 Canvas 透明度与 png 的怪异

转载 作者:行者123 更新时间:2023-12-02 15:19:17 25 4
gpt4 key购买 nike

我正在尝试对从 canvas 检索的一些 ImageData 应用透明度。很简单,对吧?只需为每四个数据点设置一个适当的值...仅,它似乎只适用于没有预先存在的 alpa 值的像素。

//create 2 canvases
var canvas = document.createElement("canvas");
document.body.appendChild(canvas);
var ctx = canvas.getContext("2d");
canvas.id = "tempCanvas";
var canvas2 = document.createElement("canvas");
document.body.appendChild(canvas2);
var ctx2 = canvas2.getContext("2d");
canvas2.id = "tempCanvas2";

//draw the png in the first canvas
var testimg = document.getElementById("testimg");
ctx.drawImage(testimg, 0, 0, 200, 200);

//helper function to opacity to the pixels
opacity = function(pixels, value){
var d = pixels.data;
for(var i=0;i<d.length;i+=4){
d[i+3] = value*255; //scale by 255
if(d[i+3] > 255) d[i+3] = 255; //clamp
}
return pixels;
}

//make the first canvas' image data opaque
var data = ctx.getImageData(0,0,200,200);
data = opacity(data, 0.5);
//draw to second canvas
ctx2.fillStyle="#900";
ctx2.fillRect(0,0,200,200);

//should get a jsfiddle logo overlayed on red background
//instead, get yucky grey background
ctx2.putImageData(data, 0, 0);

(由于同源策略,重现有点困难,但这里有一个使用 png jsfiddle Logo 的 fiddle : http://jsfiddle.net/97c0eetr/ )

为什么这种不透明度算法不适用于 jsfiddle Logo (以及我在 http://localhost 上测试的其他透明 png)?

编辑:FF42 Ubuntu,如果有影响的话。

最佳答案

您遇到了大端/小端问题:在当今的大多数计算机/设备上,端序是小端,这意味着对于 32 位值,字节顺序是 3-2-1-0。

因此,不透明度,即第 4 个字节(索引 3)将在 pixelIndex * 4 + 0 处找到。 ... == pixelIndex * 4 .

只需在代码中将不透明度函数更改为:

opacity = function(pixels, value){
var d = pixels.data;
for(var i=0;i<d.length;i+=4){
d[i] = value*255; //scale by 255
if(d[i] > 255) d[i] = 255; //clamp
}
return pixels;
}

这里更新了 fiddle : http://jsfiddle.net/97c0eetr/5/

最好的 100% 解决方案当然是有两个不透明度函数,您可以根据浏览器的结尾来选择。但通过押注于小端,您可以覆盖大约 99% 的设备。

如果您想了解字节顺序,我曾经做了一个小要点来了解它,请在这里找到它: https://gist.github.com/TooTallNate/4750953

代码如下:

function endianness () {
var b = new ArrayBuffer(4);
var a = new Uint32Array(b);
var c = new Uint8Array(b);
a[0] = 0xdeadbeef;
if (c[0] == 0xef) return 'LE';
if (c[0] == 0xde) return 'BE';
throw new Error('unknown endianness');
}

顺便说一下,你的函数可以简化为

opacity = function(pixels, value){
value = Math.floor(value * 255);
if (value>255) value = 255;
var d = pixels.data;
for(var i=0;i<d.length;i+=4){
d[i] = value;
}
return pixels;
}
<小时/>

编辑:那么为什么背景不是红色的? -->> 使用 putImageData 时,您正在使用原始 1 像素进行 1 像素复制方法。所以一切都会被替换,无论如何,例如 globalCompositeOperation或任何设置。所以红色背景刚刚被新数据覆盖。

解决方案是putImageData在临时 Canvas 上 - 将以正确的不透明度写入 -,然后写入 drawImage它在您的目标 Canvas 上,以便在绘制时考虑不透明度。

由于您已经有两个 Canvas ,因此更改很容易,请在此处查看更新的 fiddle : http://jsfiddle.net/97c0eetr/4/

关于javascript - HTML5 Canvas 透明度与 png 的怪异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34205157/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com