我正在尝试使用HTML5 canvas创建图像编辑工具。输入图像是带有Alpha通道的png。有没有一种有效的方法可以将alpha值设置为255并恢复RGB颜色?
类似于下面的代码,但是没有巨大的像素循环。我尝试使用混合,但似乎一旦alpha值为0,就无法恢复RGB。
var imageData = context.getImageData(0, 0, 512, 512);
var data = imageData.data;
for(var i = 0, n = data.length; i < n; i += 4) {
data[i + 3] = 255;
}
...
答案 0 :(得分:0)
虽然png格式确实是store the "non-premutlipied" alpha,但是另一方面,CanvasRenderingContext2D总是使用pre-multiply alpha。
因此,CanvasRenderingContext2D无法完成您需要的工作。
实际上,由于Alpha在写入时会被预乘,因此如果您在上下文中写入#AABBCC00
(透明)像素,则绘制的实际上是#00000000
。
另外,由于binary floating points work的方式,即使使用非零的alpha值,也无法确保在不同的浏览器/设备中具有相同的输出:
// demonstrates alpha premultiplying at writing on a canvas 2d context
//
// 4 pixels are authored with the same RGB channels values but with different alpha values
// If no pre-multiplying was done, all these would output the same RGB channels values at getting
var ctx = document.createElement('canvas').getContext('2d'),
img = ctx.createImageData(4,1),
// we use an Uint32Array to write every pixel in a single op
arr = new Uint32Array(img.data.buffer);
// AARRGGBB in little endian
arr[0] = 0x00AABBCC; // transparent (alpha 0)
arr[1] = 0x01AABBCC; // almost-transparent (alpha 1/255)
arr[2] = 0x7FAABBCC; // semi-transparent (alpha 0.5/1)
arr[3] = 0xFFAABBCC; // opaque
// write it to our context
ctx.putImageData(img, 0,0);
// grab it directly
var result = ctx.getImageData(0,0,4,1).data;
console.log('transparent', result.slice(0,4));
// outputs [0, 0, 0, 0]
console.log('almost-transparent', result.slice(4,8));
// outputs something like [255, 255, 255, 1]
console.log('semi-transparent', result.slice(8,12));
// outputs something around [204, 187, 170, 127]
// on my FF it is [204, 188, 170, 127]
// on my chrome it is [205, 187, 171, 127]
console.log('opaque', result.slice(12,16));
// outputs [204, 187, 171, 125]
如您所见,只有完全不透明的像素会保留其初始RGB通道的值。
因此,要执行所需的操作,您将必须实际解析png文件,并手动提取IDAT块中包含的数据。
为此,您需要将其作为ArrayBuffer加载并在these specs之后进行解析。
但是在开始编写解析器之前,您必须考虑100%的用户实际使用无损软件来保留RGB通道值的可能性(不同于画布)。
答案 1 :(得分:0)
为此,我的解决方案是使用2个画布,一个用于rgb,另一个用于alpha。我将rgb画布的alpha设置为255。因此,当我们擦除/取消擦除时,它仅在alpha画布中发生。我使用“目标输入”将rgb画布与alpha画布混合在一起进行显示。