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 方法都采用并返回未经过相乘的值。内部像素表示形式在其作为值返回之前从经过预乘的形式转换为未经过相乘的形式。在设置操作过程中,设置原始图像像素之前,像素值是经过预乘的

相关文章推荐

Bimap getPixels方法研究

Android bitmap getPixels有俩个方法,这个俩个方法都是获取图片的pixel的。 1、getPixel(int x, int y) 2、getPixels(int[] pixel...
  • hnulwt
  • hnulwt
  • 2014年12月10日 18:42
  • 2893

Android中Bitmap类getPixel方法获取的像素值为负

最近在做Android上的图像处理,在Android上直接对像素操作,居然出现了意想不到的事情。Bitmap类getPixel方法获取的像素值全部是负的,本来应该是黑色的,也就是0的,全部变成了-16...

Android Bitmap 加载与像素操作

1. Bitmap像素读写操作 2. 加载超大Bitmap对象的缩小版本并显示 3. 演示Bitmap上的像素操作...

关于Bitmap像素颜色的判断

android.graphics.Bitmap.Config是一个枚举类型,里面定义了位图的四种格式。通过名称可以大概判处出颜色的存储方式: ALPHA_8:由一个字节表示的图像,是一种8位的位...

Flex中ByteArray与BitmapData互相转换实现图片的二进制保存与复原

view plaincopy to clipboardprint? class="javascript" name="code">package com.kyit.lg..util   { ...

去噪:用于验证码图片识别的类续(C#代码)

1、如何设前景/背景的分界值    UnCodebase类中有一个GetPicValidByValue( int dgGrayValue) 函数,可以得到前景的有效区域,常有人问我前景/背景的分界值d...

Flex中的CSS: (4)内部样式和内联样式最终被编译的AS源文件不相同

看例子。 这些区别有助于我们归纳编译器对不同形式CSS的编译规则。 内部样式: ...
  • tiangej
  • tiangej
  • 2012年06月14日 23:39
  • 843

Bitmap序列化(将BitmapData保存为原生Binary/ByteArray),AS3保存图像的方法

当应用程序需要将位图图像保存到本地或发送到服务端时, 通常的方法是在发送数据前将图像通过PNG或JPEG编码。如果只是想保存位图图像,只要序列化BitmapData即可,将图像转换为JPEG/PNG是...

AS3语言:BitmapData类介绍

注:文中的Bitmapdata和BMD均为同一意思BitmapData,BMD为其缩写 一,概括: Bitmapdata继承Object对象,实现IBitmapDrawable接口,这个接口有什么...
  • carzyer
  • carzyer
  • 2011年12月28日 09:16
  • 3374

随机字符串算法:13位随机字符串,两两不相同,至少1个大写字母,至少包含这5个字符之3“$@%*#”

高效算法实现:生成13位随机字符串,字符两两不相同,至少1个大写字母,至少包含这5个字符之3“$@%*#”...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:AS3 的BitmapData的setPixel与getPixel时,值不相同。
举报原因:
原因补充:

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