AS3 的BitmapData的setPixel与getPixel时,值不相同。

转载 2012年03月23日 10:05:39

原文:http://riaoo.com/?p=1651

        事情发展的起因是这样的: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 明显有偏差

原始的 ARGB 数据 0×44536435(十六进制):

  • Alpha = 0×44;(透明通道)
  • Red_原始 = 0×53;(红通道)
  • Green_原始 = 0×64;(绿通道)
  • Blue_原始 = 0×35;(蓝通道)

还原的 ARGB 数据 0×44526534 (十六进制):

  • Alpha = 0×44;
  • Red_还原 = 0×52
  • Green_还原 = 0×65
  • Blue_还原 = 0×34

可以看得出,只有 Alpha 通道是准确的(始终不变),其余通道都有偏差。这是因为 还原的 ARGB 数据 是从 经过相乘后的 ARGB 数据 中还原过来的:

相乘过程

原始的 ARGB 数据(0×44536435)在被 BitmapData 存储前都经过相乘,就是 RGB 跟 Alpha 通道相乘(把 Alpha 值转为一个百分比进行计算,这个百分比等于:Alpha/0xFF):

  • Alpha = 0×44;
  • Red_相乘 = Red * ( Alpha / 0xFF ) = 0×53 * ( 0×44 / 0xFF ) = 0×16
  • Green_相乘 = Green * ( Alpha / 0xFF ) = 0×64 * ( 0×44 / 0xFF ) = 0x1A
  • Blue_相乘 = Blue * ( Alpha / 0xFF ) = 0×35 * ( 0×44 / 0xFF ) = 0x0E

还原过程

还原过程就相乘过程的逆过程,就是把 RGB 除以 Alpha 通道(同样地,把 Alpha 值转为一个百分比进行计算,这个百分比等于:Alpha/0xFF):

  • Alpha = 0×44;
  • Red_还原 = Red_相乘 / ( Alpha / 0xFF ) = 0×16 / ( 0×44 / 0xFF ) = 0×52
  • Green_还原 = Green_相乘 / ( Alpha / 0xFF ) = 0x1A / ( 0×44 / 0xFF ) = 0×61
  • Blue_还原 = Blue_相乘 / ( Alpha / 0xFF ) = 0x0E / ( 0×44 / 0xFF ) = 0×34

整个流程原始数据 -> 相乘数据 -> 还原数据。分别对比 实验数据 和 理论分析数据 

实验数据:

  • 实际上,调用 getPixel32() 方法后得到:0×44526534

理论分析数据:

  • 按理论分析,调用 getPixel32() 方法后应用得到:0×44526134

分析到现在,还是很郁闷。理论值跟实际值不同(其中红色文字的 Blue 通道不同)。按道理,让 getPixel32() 返回值产生偏差的原因就是以上所述,但,经过痛苦的分析后却又发现 让 getPixel32() 返回值产生偏差的原因不完全是以上所述

总结:

        一切都是 Adobe Flash Player 的错,而不完全是 Adobe 的错。总之在开发过程中,一定要牢记:别指望 BitmapData 能准确存储每点像素的原始颜色值。最后奉上官方语言参考上的解说:

BitmapData 对象中的所有像素都作为预乘颜色值进行存储。预乘图像像素具有已经与 Alpha 数据相乘的红色、绿色和蓝色通道值。例如,如果 Alpha 值为 0,则 RGB 通道的值也为 0,与它们未经过相乘的值无关。这种丢失数据的情况可能会在执行操作时导致一些问题。所有 BitmapData 方法都采用并返回未经过相乘的值。内部像素表示形式在其作为值返回之前从经过预乘的形式转换为未经过相乘的形式。在设置操作过程中,设置原始图像像素之前,像素值是经过预乘的

SetPixel用法

SetPixel  函数功能:该函数将指定坐标处的像素设为指定的颜色。  函数原型:COLORREF SetPixel(HDC hdc, int X, int Y, COLORREF crColor)...
  • zhouqian88423
  • zhouqian88423
  • 2009年12月06日 11:54
  • 2153

as3 操作图片,获取,设置实际像素,扣除透明区域

private var a:Loader = new Loader(); private function test():void { a.load(new URLRequest("as...
  • arvin0
  • arvin0
  • 2016年07月13日 11:49
  • 1760

as3 抠图、选取透明区域

Bitmap:位图对象,对所有加载的外部图片均可以转换成位图对象再加载显示BitmapData:对位图的所有像素的信息以数据的形式保存在BitmapData对象中,其中构造方法第三个参数transpa...
  • xiaoniba1024
  • xiaoniba1024
  • 2011年06月23日 11:59
  • 3327

AS3 水波效果

原文:http://bbs.9ria.com/thread-12480-1-3.html 2008年的贴子,感觉是非常不错的。 代码: package { import flash.displ...
  • linjf520
  • linjf520
  • 2012年05月04日 15:51
  • 1382

解决 C# GetPixel 和 SetPixel 效率问题

在对Bitmap图片操作的时候,有时需要用到获取或设置像素颜色方法:GetPixel 和 SetPixel, 如果直接对这两个方法进行操作的话速度很慢,这里我们可以通过把数据提取出来操作,然后操...
  • yangyikun0428
  • yangyikun0428
  • 2016年12月21日 00:00
  • 1905

强大的bitmapData.draw()

draw()方法 public function draw(source:IBitmapDrawable, matrix:Matrix = null, colorTransform:ColorTran...
  • xiang08
  • xiang08
  • 2009年08月04日 14:12
  • 12563

as3中bitmapData中draw方法重新理解

as3中bitmapData中draw方法重新理解
  • u013406800
  • u013406800
  • 2015年07月07日 21:07
  • 2948

C#调用GDI函数SetPixel

System.IntPtr hDC = gObject.GetHdc();             Color color = Color.PaleVioletRed;             f...
  • xuyongbeijing2008
  • xuyongbeijing2008
  • 2013年12月17日 14:11
  • 1873

[AS3]BitmapBytes类-实现BitmapData与ByteArray(Base64)之间互转功能

转载:http://www.klstudio.com/post/145.html[AS3]BitmapBytes类-实现BitmapData与ByteArray(Base64)之间互转功能【组件版本】...
  • yc1404
  • yc1404
  • 2013年01月31日 14:20
  • 1486

ByteArray和BitMap的相互转换,以及扣图

package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display....
  • a7719665
  • a7719665
  • 2010年06月21日 09:57
  • 7630
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:AS3 的BitmapData的setPixel与getPixel时,值不相同。
举报原因:
原因补充:

(最多只允许输入30个字)