javascript 为什么 HTML Canvas getImageData() 不返回刚设置的完全相同的值?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4309364/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does HTML Canvas getImageData() not return the exact same values that were just set?
提问by Phrogz
When writing pixels to an HTML Canvas context using putImageDataI find that the pixel values are not exactly the same when I fetch them again. I have put up a sample test pageshowing the problem. Boiled down, the problem is:
使用将像素写入 HTML Canvas 上下文时,putImageData我发现再次获取像素值时像素值并不完全相同。我已经提供了一个显示问题的示例测试页面。归结起来,问题是:
var id = someContext.getImageData(0,0,1,1);
id.data[0]=id.data[3]=64; // 25% red, 25% alpha
id.data[1]=id.data[2]=0; // No blue or green
someContext.putImageData(id,0,0);
var newData = someContext.getImageData(0,0,1,1);
console.log( newData.data[0] );
On Chrome v8, the red value comes back as 63; on Firefox v3.6, Safari v5, and IE9 the red value comes back as 67(all on Windows). On OS X, Chrome v7, Safari v5, and Firefox v3.6 also come back as 67. None of them come back as the 64value originally set!
在 Chrome v8 上,红色值返回为63; 在 Firefox v3.6、Safari v5 和 IE9 上,红色值恢复为67(所有在 Windows 上)。在 OS X 上,Chrome v7、Safari v5 和 Firefox v3.6 也以67. 它们都没有按照64最初设置的值返回!
Using setTimeoutto delay between setting and re-fetching makes no difference. Changing the background of the page makes no difference. Using save()and restore()on the context (per this unlikely article) makes no difference.
使用setTimeout设定和重新取之间的延迟没什么区别。更改页面背景没有任何区别。在上下文中使用save()和restore()(根据这篇不太可能的文章)没有区别。
采纳答案by olliej
ImageData is defined in HTML5 as being unpremultiplied, but most canvas implementations use a premultiplied backing buffer to speed up compositing, etc. This means that when data is written and then read from the backing buffer it can change.
ImageData 在 HTML5 中被定义为未预乘,但大多数画布实现使用预乘后备缓冲区来加速合成等。这意味着当数据被写入然后从后备缓冲区读取时,它可以改变。
I would assume that Chrome v8 picked up a buggy version of the [un]premultiplying code from webkit.org (It has been broken before, although i don't recall any recent occurances, and that doesn't explain the windows only variance)
我会假设 Chrome v8 从 webkit.org 获取了 [un] 预乘代码的错误版本(它之前已经被破坏了,虽然我不记得最近发生的任何事情,这并不能解释仅 Windows 的差异)
[edit: it could be worth checking a webkit nightly on windows? as the imagedata implementation doesn't have anything platform specific it's shared between all webkit browsers and could simply be broken in MSVC based builds]
[编辑:是否值得每晚在 Windows 上检查一个 webkit?由于 imagedata 实现没有任何特定于平台的内容,因此它在所有 webkit 浏览器之间共享,并且可能会在基于 MSVC 的构建中被破坏]
回答by Tower
HTML5 specification encourages browser vendors to use something that is called Premultiplied Alpha. In essence this means that pixels are stored in 32-bit integers where each channel contains a 8-bit color value. For performance reasons, the Premultiplied Alpha is used by browsers. What it means is that it premultiplies color values based on the alpha value.
HTML5 规范鼓励浏览器供应商使用称为Premultiplied Alpha. 本质上,这意味着像素以 32 位整数存储,其中每个通道包含一个 8 位颜色值。出于性能原因,浏览器使用预乘 Alpha。这意味着它根据 alpha 值预乘颜色值。
Here's an example. You have a color such that the values for RGB are 128, 64, 67. Now, for the sake of higher performance, the color values will be premultiplied by the alpha value. So, in case the alpha value is 16, all the color values will get multiplied by 16/256(= 0.0625). In this case, the resulting values for RGB become 8, 4, 4.1875(rounded to 4because pixel color values are not floats).
这是一个例子。您有一种颜色,使得 RGB 的值为128、64、67。现在,为了获得更高的性能,颜色值将与 alpha 值相乘。因此,如果 alpha 值为16,则所有颜色值都将乘以16/256(= 0.0625)。在这种情况下,RGB 的结果值变为8, 4, 4.1875(四舍五入,4因为像素颜色值不是浮点数)。
The problem shows up when you do exactly what you are doing here; setting color data with a specific alpha value and then pulling back the actual color values. The previous Blue color of 4.1875that got rounded to 4will become 64instead of 67when you call getImageData().
当您完全按照此处的操作进行操作时,问题就会出现;使用特定的 alpha 值设置颜色数据,然后拉回实际的颜色值。以前的蓝颜色4.1875是得到了四舍五入到4将成为64代替67,当你打电话getImageData()。
That is why you are seeing all this and it will never change unless the underlying implementation in a browser engine changes to use a color system that does not suffer from this.
这就是为什么您会看到所有这些并且它永远不会改变,除非浏览器引擎中的底层实现更改为使用不受此影响的颜色系统。
回答by Niet the Dark Absol
Looks like a rounding issue to me...
对我来说似乎是一个四舍五入的问题......
64/255 = 0.2509... (rounded down to give 0.25)
0.25 * 255 = 63.75 (rounded down to give 63)
== OR ==
64/255 = 0.2509... (rounded up to give 0.26)
0.26 * 255 = 66.3 (rounded up to give 67)
Remember that 255 is the maximum value, not 256 ;)
请记住,255 是最大值,而不是 256 ;)
EDIT: Of course, this wouldn't explain why the alpha channel is behaving...
编辑:当然,这不能解释为什么 alpha 通道的行为......

