关于BitmapData.getPixel32()的Alpha通道问题

昨天,YBoy在腾讯微博发了一个问题,是关于BitmapData.getPixel32()?题目是《BitmapData.getPixel32() 返回值不准确,为什么?》

问题描述:当alpha 通道为 0xFF,我们用getPixel32()获取得到的某个值就是正确值,但若alpha 通道不为 0xFF时,我们会发现,这个值用getPixel32()获取会出现失真的情况,就算我们已经是setPixel32()一个固定点的颜色,情况也还是这样,为什么会返回的RGB会失真?

备注:BitmapData.getPixel32() 方法可以获得某像素点的 ARGB 颜色值,它包含 Alpha 通道数据和 RGB 数据。

测试数据:
①RGB值相同而Alpha值不同的情况:
[cc lang="actionscript"]var bmd:BitmapData = new BitmapData(100, 100, true, 0);
bmd.setPixel32(0, 0, 0×01536435); // 把坐标为(0, 0)的点设置颜色值 0×01536435
trace(bmd.getPixel32(0, 0).toString(16)); // 输出 1000000 ,明显有偏差

var bmd3:BitmapData = new BitmapData(100, 100, true, 0);
bmd3.setPixel32(0, 0, 0×21536435); // 把坐标为(0, 0)的点设置颜色值 0×21536435
trace(bmd3.getPixel32(0, 0).toString(16)); // 输出 21556436 ,明显有偏差

var bmd6:BitmapData = new BitmapData(100, 100, true, 0);
bmd6.setPixel32(0, 0, 0×51536435); // 把坐标为(0, 0)的点设置颜色值 0×51536435
trace(bmd6.getPixel32(0, 0).toString(16)); // 输出 51526535 ,明显有偏差

var bmd9:BitmapData = new BitmapData(100, 100, true, 0);
bmd9.setPixel32(0, 0, 0×81536435); // 把坐标为(0, 0)的点设置颜色值 0×81536435
trace(bmd9.getPixel32(0, 0).toString(16)); // 输出 81536535 ,明显有偏差

var bmd10:BitmapData = new BitmapData(100, 100, true, 0);
bmd10.setPixel32(0, 0, 0×98536435); // 把坐标为(0, 0)的点设置颜色值 0×98536435
trace(bmd10.getPixel32(0, 0).toString(16)); // 输出 98526536 ,明显有偏差[/cc]

②Alpha值相同而RGB值不同的情况:
[cc lang="actionscript"]var bmd11:BitmapData = new BitmapData(100, 100, true, 0);
bmd11.setPixel32(0, 0, 0×83536435); // 把坐标为(0, 0)的点设置颜色值 0×83536435
trace(bmd11.getPixel32(0, 0).toString(16)); // 输出 83546335 ,明显有偏差

var bmd21:BitmapData = new BitmapData(100, 100, true, 0);
bmd21.setPixel32(0, 0, 0xf3536435); // 把坐标为(0, 0)的点设置颜色值 0×f3536435
trace(bmd21.getPixel32(0, 0).toString(16)); // 输出 f3536335 ,明显有偏差

var bmd31:BitmapData = new BitmapData(100, 100, true, 0);
bmd31.setPixel32(0, 0, 0×43536435); // 把坐标为(0, 0)的点设置颜色值 0×43536435
trace(bmd31.getPixel32(0, 0).toString(16)); // 输出 43546335 ,明显有偏差[/cc]

③特殊情况,Alpha为FF和00:
[cc lang="actionscript"] var fullbmd:BitmapData = new BitmapData(100, 100, true, 0);
fullbmd.setPixel32(0, 0, 0xff536435); // 把坐标为(0, 0)的点设置颜色值 0×ff536435
trace(fullbmd.getPixel32(0, 0).toString(16)); // 输出 ff536435,没有偏差

var emptybmd:BitmapData = new BitmapData(100, 100, true, 0);
emptybmd.setPixel32(0, 0, 0×00536435); // 把坐标为(0, 0)的点设置颜色值 0×00536435
trace(emptybmd.getPixel32(0, 0).toString(16)); // 输出 0[/cc]

结论:三种不同情况的测试,除了Alpha值为FF的情况,RGB返回的结果都存在失真,并且,但Alpha值为00时,我们还看到RGB返回的值竟然为0;

寻找问题的解决方案:
解答①,颜色值被压缩,相邻值颜色甚为接近,当取值时,FP会出现判断失误?



进行验证:
[cc lang="actionscript"] var bmd10:BitmapData = new BitmapData(100, 100, true, 0);
bmd10.setPixel32(0, 0, 0×98536435); // 把坐标为(0, 0)的点设置颜色值 0×98536435
trace(bmd10.getPixel32(0, 0).toString(16)); // 输出 98526536 ,明显有偏差
var bmd110:BitmapData = new BitmapData(100, 100, true, 0);
bmd110.setPixel32(0, 0, 0×98536435); // 把坐标为(0, 0)的点设置颜色值 0×98536435
trace(bmd110.getPixel32(0, 0).toString(16)); // 输出 98526536 ,明显有偏差[/cc]
这个结论是假的!同时getPixel32时,我们发现取得的值是一样的。

解答②,这是一个Bug?而且还是长年累月积累下来并没有解决的Bug?
只要我们Google一下“getpixel as3 inaccurate”(请Google in US),你就会发现一大堆这问题,但貌似解答的方法甚为少,貌似这是Alpha通道引发的一个Bug,一直悬而未决….
参考地址: 点击
官方那边还没有给出一个回应?貌似这个问题更多是出现在PNG格式的图像的getPixel上,在这个上,我们可以理解为图像不同颜色压缩机制存异,导致出现偏差,但如果在我们刚才的测试中,我们就算在Bitmap上setPixel了,也未能获取正确值。

可见,这是Alpha的问题,估计是官方为了适应不用格式的图像文件(PNG、JPG)的颜色压缩方法,从而致使,这个Alpha返回了不准确值。

4月19日晚补充一下:
早上Y.Boy提出在 getPixel32 时,其实是还原ARGB数据。确实,这个想法可以解释Alpha为00值时RGB返回值为0,但我们若Alpha值为非FF和非00时,这个判断就失效了。期待Adobe能尽快修复这个Bug吧…

引用Y.Boy总结一句:“别指望 BitmapData 能准确存储每点像素的原始颜色值.”

原创文章,转载请注明: 转载自Norris's Landscape

本文链接地址: 关于BitmapData.getPixel32()的Alpha通道问题

2010-04-19   文章标签:  | 当前有 4 个评论 »

4 Responses to “关于BitmapData.getPixel32()的Alpha通道问题”

  1.  Y.Boy wrote:

    我想,是因为 BitmapData 中的像素数据并非采用 未经相乘 的ARGB数据来存储的。在 getPixel32 时,其实是还原ARGB数据。

    四月 19th, 2010 at 9:50 上午
  2.  Norris wrote:

    你的这个设想,我今天早上出门时也想了想,后来拿笔去算了算,没对上,估计这个问题得在Adobe平台技术峰会上询问一下FP的架构师Lee Thomason了…

    四月 19th, 2010 at 9:25 下午
  3.  解析BitmapData.getPixel32()返回值因何不准确 « 业界交流 wrote:

    [...] 网友Norris很热心,他把他的观点写得井井有条:http://www.norris2u4.com/?p=370 。在继续往后阅读前,先看看我的总结,造成 getPixel32() [...]

    四月 21st, 2010 at 10:39 上午
  4.  详细分析为什么BitmapData.getPixel32()返回值不准确 | ADSpark汇聚人,汇聚经验 wrote:

    [...] Y.Boy 2010年04月19日,星期一         事情发展的起因是这样的:BitmapData.getPixel32()返回值不准确,为什么? 网友Norris很热心,他把他的观点写得井井有条:http://www.norris2u4.com/?p=370 。在继续往后阅读前,先看看我的总结,造成 getPixel32() 返回值存在偏差的根本原因是:BitmapData 存储的像素数据并不是各通道(ARGB)的原始数据,而是 RGB 跟 Alpha 通道相乘后的数据。在调用 BitmapData.getPixel32() 方法时,Flash Player 虽然返回的是未经相乘的 ARGB 数据,但这个数据是还原后的 ARGB ,而不是原始 ARGB 。以下例子说明了这一点: var bmd:BitmapData = new BitmapData(100, 100, true, 0); bmd.setPixel32(0, 0, 0×44536435); // 把坐标为(0, 0)的点设置颜色值 0×44536435 trace(bmd.getPixel32(0, 0).toString(16)); // 输出 44526534 ,明显有偏差 [...]

    四月 23rd, 2010 at 12:56 下午

留下评论