从 JavaScript returns 中的图像中读取半透明像素的意外结果
Reading pixeldata from images in JavaScript returns unexpected results for semi transparent pixels
我正在从 JavaScript 中的 png 文件中读取 RGBA 数据。为此,我在 canvas 上绘制图像并使用 .getImageData
。数据与我的预期不同:
测试图片:
https://raw.githubusercontent.com/FlorianLudwig/imghash/master/test/transparent.png
JS中第三个像素的RGBA是:[9, 0, 0, 54]
(在chrome和firefox中测试过)但应该是[12, 0, 0, 54]
(至少是gimp和python枕头索赔)。
我的猜测可能是错误的
drawImage
进行一些合成(将 ctx.globalCompositeOperation
设置为 copy
没有任何区别)
- 图像加载时进行了一些颜色管理
示例代码
- http://codepen.io/anon/pen/EaemZw
- Select测试图片
- 检查控制台输出
你的猜测 #2 是正确的。
规范赋予浏览器对传入图像进行 Alpha 和 Gamma 调整的自由。
1) 合成
随着时间的推移,应用的绘制操作越多,出现的舍入误差就越多。但是,对于初始抽签,这无关紧要。
copy
模式不会像您发现的那样影响它。这只是忽略了现有的背景数据。 source-over 确实使用了背景的 alpha 值,但是因为有 none 最初它会产生相同的效果。
不过,这样做的主要问题是,由于需要在内部转换的预乘 alpha 值,alpha 和舍入误差存在一般性问题。
2) 颜色管理
浏览器确实支持各种级别的颜色管理。这包括 PNG 文件中的以下数据:
- sRGB 块说明 PNG 如何符合 sRGB 标准(相对、绝对等)
- iCCP 块包含一个 ICC 配置文件,包括伽玛,如果浏览器支持 ICC 以及这个版本的 ICC(典型版本是版本 2 和 4)。
- 如果未找到 sRGB 或 iCCP 配置文件,它将查找包含代表伽马的数字的 gAMA 块。
应用这些数据时,它会改变原始位图。 Gamma 不会影响最低值或最高值,但中间范围会有明显的变化。由于颜色管理和转换错误 (1.).
,仍然更改的值将被更改
例如,即使文件没有 gamma 块(或 "file gamma"),您的测试文件就是这种情况,或者它的值为 1,仍然会应用显示 gamma (IE 除外)。对于 windows 这将是 2.2 而对于 Mac 通常是 1.8.
这发生在返回图像以用于代码 canvas 之前。
或者我建议看一下我为此类场景创建的 pngtoy(它是 free/MIT),以使开发人员能够从 PNG 中获取未更改的原始位图(请参阅 notes/status,因为它目前仍处于 alpha 阶段)。我在下面提供了一个代码示例,它也读取了第三个像素,如预期的那样为红色通道提供 12。
使用 pngtoy 测试
这将显示未更改的原始位图值。
var out = document.querySelector("output"),
png = new PngToy();
png.fetch("https://i.imgur.com/oX1kom7.png").then(
function() {png.decode().then(show)}
);
function show(bmp) {
var data = bmp.bitmap;
out.innerHTML += data[8] + "," + data[9] + "," + data[10] + "," + data[11];
}
<script src="https://rawgit.com/epistemex/pngtoy/master/tests/Promise.js"></script>
<script src="https://rawgit.com/epistemex/pngtoy/master/pngtoy.min.js"></script>
<output>Loading external scripts (pngtoy.min.js + Promise polyfill for IE...)<br></output>
我正在从 JavaScript 中的 png 文件中读取 RGBA 数据。为此,我在 canvas 上绘制图像并使用 .getImageData
。数据与我的预期不同:
测试图片: https://raw.githubusercontent.com/FlorianLudwig/imghash/master/test/transparent.png
JS中第三个像素的RGBA是:[9, 0, 0, 54]
(在chrome和firefox中测试过)但应该是[12, 0, 0, 54]
(至少是gimp和python枕头索赔)。
我的猜测可能是错误的
drawImage
进行一些合成(将ctx.globalCompositeOperation
设置为copy
没有任何区别)- 图像加载时进行了一些颜色管理
示例代码
- http://codepen.io/anon/pen/EaemZw
- Select测试图片
- 检查控制台输出
你的猜测 #2 是正确的。
规范赋予浏览器对传入图像进行 Alpha 和 Gamma 调整的自由。
1) 合成
随着时间的推移,应用的绘制操作越多,出现的舍入误差就越多。但是,对于初始抽签,这无关紧要。
copy
模式不会像您发现的那样影响它。这只是忽略了现有的背景数据。 source-over 确实使用了背景的 alpha 值,但是因为有 none 最初它会产生相同的效果。
不过,这样做的主要问题是,由于需要在内部转换的预乘 alpha 值,alpha 和舍入误差存在一般性问题。
2) 颜色管理
浏览器确实支持各种级别的颜色管理。这包括 PNG 文件中的以下数据:
- sRGB 块说明 PNG 如何符合 sRGB 标准(相对、绝对等)
- iCCP 块包含一个 ICC 配置文件,包括伽玛,如果浏览器支持 ICC 以及这个版本的 ICC(典型版本是版本 2 和 4)。
- 如果未找到 sRGB 或 iCCP 配置文件,它将查找包含代表伽马的数字的 gAMA 块。
应用这些数据时,它会改变原始位图。 Gamma 不会影响最低值或最高值,但中间范围会有明显的变化。由于颜色管理和转换错误 (1.).
,仍然更改的值将被更改例如,即使文件没有 gamma 块(或 "file gamma"),您的测试文件就是这种情况,或者它的值为 1,仍然会应用显示 gamma (IE 除外)。对于 windows 这将是 2.2 而对于 Mac 通常是 1.8.
这发生在返回图像以用于代码 canvas 之前。
或者我建议看一下我为此类场景创建的 pngtoy(它是 free/MIT),以使开发人员能够从 PNG 中获取未更改的原始位图(请参阅 notes/status,因为它目前仍处于 alpha 阶段)。我在下面提供了一个代码示例,它也读取了第三个像素,如预期的那样为红色通道提供 12。
使用 pngtoy 测试
这将显示未更改的原始位图值。
var out = document.querySelector("output"),
png = new PngToy();
png.fetch("https://i.imgur.com/oX1kom7.png").then(
function() {png.decode().then(show)}
);
function show(bmp) {
var data = bmp.bitmap;
out.innerHTML += data[8] + "," + data[9] + "," + data[10] + "," + data[11];
}
<script src="https://rawgit.com/epistemex/pngtoy/master/tests/Promise.js"></script>
<script src="https://rawgit.com/epistemex/pngtoy/master/pngtoy.min.js"></script>
<output>Loading external scripts (pngtoy.min.js + Promise polyfill for IE...)<br></output>