HTML5 Canvas透明度与pngs的怪异

时间:2015-12-10 15:00:36

标签: javascript html5 canvas transparency

我试图将透明度应用于从<br />检索到的某些ImageData。简单吧?只需为每四个数据点设置一个合适的值......只是,它似乎只适用于没有预先存在的alpa值的像素。

canvas

(由于同源策略,它有点难以复制,但这里是使用png jsfiddle徽标的小提琴:http://jsfiddle.net/97c0eetr/

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

编辑:FF42 Ubuntu,如果它有所作为。

1 个答案:

答案 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/