我试图将透明度应用于从<br />
检索到的某些ImageData
。简单吧?只需为每四个数据点设置一个合适的值......只是,它似乎只适用于没有预先存在的alpa值的像素。
canvas
(由于同源策略,它有点难以复制,但这里是使用png jsfiddle徽标的小提琴:http://jsfiddle.net/97c0eetr/)
为什么这种不透明度算法不适用于jsfiddle徽标(以及我在http://localhost上测试的其他透明png?)
编辑:FF42 Ubuntu,如果它有所作为。
答案 0 :(得分:2)
你遇到了big endian / little endian问题:在今天的大多数计算机/设备上,字节序都是小端,这意味着对于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;
}
在这里更新了小提琴: http://jsfiddle.net/97c0eetr/5/
最好的100%解决方案当然是根据浏览器的endinannes选择两个不透明度功能。但是通过投注小端,您可以覆盖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;
}
编辑:为什么背景不是红色? - &GT;&GT;使用putImageData
时,您使用原始1像素进行1像素复制方法。所以一切都会被替换,例如,globalCompositeOperation
或任何设置。因此红色背景只是被新数据覆盖。
解决方案是在临时画布上putImageData
- 将使用正确的不透明度编写 - 然后在目标画布上以drawImage
编写,以便在绘制时考虑不透明度。
由于您已经有两幅画布,因此更改非常简单,请参阅此处更新的小提琴: http://jsfiddle.net/97c0eetr/4/