BitmapData类介绍

注:文中的Bitmap data和BMD均为同一意思BitmapData ,BMD为其缩写

------------------------------------------------------------------------------------------------------------


今天介绍另外一个比较常用和中高级难度的类:BitmapData


用好这个类,可以说是半支脚踏入了Flash
高手 的大门···(主要是不是太多的人精通这个··呵呵··)我也可以趁这篇文章的机会好好巩固+学习···

好,长话短说··马上进入正题:



一,概括:


Bitmapdata继承Object对象,实现IBitmapDrawable接口,这个接口有什么用,你可以理解为Drawable,能被画。官方介 绍是:IBitmapDrawable 接口由可作为 BitmapData 类draw()方法的source参数传递的对象来实现。 这些对象的类型为 BitmapData 或 DisplayObject。 其实就是能被“画”,这点我在一会的公共方法中会详细介绍。


个人理解来说,BitmapData主要提供的是对图像的“像素级”的操作,如果你想切实感受一下,有个挺好的办法,打开FLASH IDE(其实就是Flash),然后CTRL+R导入一张图片,然后再按CTRL+B打散,这时得到的图片状态就有点BitmapData的味道了··· 而其他用FLASH矢量
工具 画出来的都可以理解为BitmapData的一种···

刚刚说只是想大家对BitmapData有模糊的了解,下面再深一步说,BitmapData的名字可以拆开来看,就是Bitmap+Data,翻译成中文就是:位图
数据 ,所以它可以看作数据储存的一种,而不是真正的显示对象,要想看到BitmapData,我们需要把Bitmapdata赋到一个Bitmap对象中,然后addChild(Bitmap),那么就能看到具体的画面了···

那么BitmapData的像素级操作作用在哪呢?比较大家喜欢津津乐道的就是粒子
效果 ,作为一个需要大量计算的应用 来 说,1像素长宽的粒子无疑是能存在的最小的粒子;另外一个是作为数据传输,大家如果想实现上传图片或者下载图片的效果,基本的理念就是将 Bitmapdata使用JPEGEncoder编码成二进制数据,把二进制发送给服务器端;第三种是滤镜视觉特效,例如一些水波划动特效;第四种是视频 摄像头的视频检测;当然还有很多有趣的玩法,例如通过Bitmapdata压缩数据之类的,这些可以等大家熟悉了再慢慢研究···

二,公共
属性

BitmapData的公共属性很少,只有4种,而且都属于Read-Only(只读),只读的意思就是“只能读”(好废话),所以我们可以取出BitmapData的属性来做运算,但是却不能赋值给它们,跟只读区别的就是Read-Write(读写)。


有时
程序 有莫名其妙的问题,可以查看帮助文档,是不是因为你尝试对只读属性进行了赋值导致的。

1,height


就是Bitmapdata存储像素数据的高度


2,width


同理,就是Bitmapdata存储数据的宽度,这里扯多一句,一般保存长宽的都是Number属性,因为长宽可能存在小数点,而有些其他的属性可能是int的,把带有小数点的值赋值给int的属性的话,会自动把小数点后面的数值去掉,造成一些莫名其妙的错误,所以写
代码 的时候要多注意看代码提示里的属性说明。

3,transparent


是一个Boolen值,表示此Bitmapdata是否支持透明像素,一般的颜色分为16位颜色0xRRGGBB和32位颜色0xAARRGGBB。其中 0x是16进制数字的意思,后面的每两位都代表着0~F,16个范围,所以每个颜色通道都有16*16=256位的数值,其中32位颜色就是多了一个 AA(透明度)通道。


4,rect


返回BiamapData所占的矩形对象(Rectangle),你可以暂时理解为一个对象,这个对象储存了x,y,width,height等数值。

三,公共方法

BitmapData一共有32个公共方法,当然一部分是成对出现的get/set方法,让我们来一一介绍。


1,构造方法


BitmapData(width:int, height:int, transparent:Boolean = true, fillColor:uint = 0xFFFFFFFF)


构造方法有4个参数,其中两个必填,就是长宽,这两个值的输入保持“用多少填多少”的原则,因为Bitmapdata也是一种形式的内存开销,所以能省就 省。第三个是transparent,就是是否允许透明像素,原则同上,如果能确定不用的话,最好关掉,默认为允许,第四个为填充颜 色,bitmapdata既然是data,那肯定要有初始数据的存在,一开始是一些纯色的填充,默认为白色。


2,应用滤镜


applyFilter(sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point, filter:BitmapFilter):void


这个函数很有意思,在我的印象里,bitmapdata.applyFilter就是直接对bitmapdata进行一次滤镜算法,然后把其中的像素进行从新赋值,那为什么会有这么四个参数呢。


我印象中的处理过程是:BMD--->滤镜算法--->得到的新BMD


而实际上确是:


Step1:


sourceBitmapData--->(sourceRect滤镜的作用矩形区域)--->filter(滤镜)--->新的BMD(长宽为作用矩形区域sourceRect的长宽)


Step2:


原来的BitmapData--->在destPoint的x,y位置上--->画上新的BMD


这样一来,除了可以实现对自己实施滤镜,还有了更多的可操作性。


3,复制


clone():BitmapData


这个与之前介绍的复杂类型一样,这里就不多说了,详情可参考之前的Matrix的clone方法介绍部分。


4,变色


colorTransform(rect:Rectangle, colorTransform:ColorTransform):void


这个有点头疼,牵扯到ColorTransform类,也是一个大家比较陌生的类,那么这个hold一hold,大家先知道这个函数作用就是将某一rect的区域按colorTransform的定义进行变色。


5,与其他BitmapData进行像素值的"比较",其实就是求差异(或者叫各像素相减得的差)


compare(otherBitmapData:BitmapData):Object


首先这两个BMD的比较分为几种情况:


(1)如果宽度不相同,函数返回-3。


(2)如果高度不相同,函数返回-4;


(3)如果宽高都不相同,先算宽,即函数返回-3;


(4)如果两个BMD完全相同,函数返回0;


(5)如果两个BMD长宽相同,颜色不同,则返回一个新的Bitmapdata对象,新BMD对象特征如下:


bmd1.compare(bmd2);


新BMD的每一点像素值为bmd1减bmd2所得,由于有Alpha存在,当RRGGBB不相同时,忽略Alpha的比较,新值为0xFF(RRGGBB差);当RRGGBB相同时,则返回Alpha的差,新值则为0xZZ(Alpha差)XXXXX(RGB值)。


总的来说就是先比较颜色,颜色不同的情况下就不考虑透明度。颜色相同就看透明度的差异。不修改原对象,只返回一个新的BitmapData对象。具体玩法还不明,呵呵。


6,复制通道


copyChannel(sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point, sourceChannel:uint, destChannel:uint):void


这个就是对某一区域内所有像素的颜色通道的替换。sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point这三个参数分别对应作用BMD,作用区域,和生成图在原BMD的位置。sourceChannel:uint, destChannel:uint这两个参数就是分别对应用哪个通道的值,去替换哪个通道。具体的通道保存在BitmapDataChannel类中。


注意,这类替换过程并不影响sourceBitmapData的像素信息,他只是将计算的结果重新赋值到原BMD的对应位置上。


7,复制像素


copyPixels(sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point, alphaBitmapData:BitmapData = null, alphaPoint:Point = null, mergeAlpha:Boolean = false):void


sourceBitmapData, sourceRect, destPoint老三样,就不说了,说说其他三个参数。


alphaBitmapData和alphaPoint貌似是在Copy时有关Alpha通道的Map映射,作为Alpah通道值传入,而mergeAlpha则为是否复制Alpha通道的开关。


后面三个参数其实也不是太确定用法···不过平常的使用前面的就可以了,在涉及到Alpha通道的复制时可以再深入研究。这个函数可以用作截图,当然另外的一个draw方法也可以。


8,释放内存


dispose():void


这个主要作用是释放掉分配给BitmapData的内存,并将宽高设置为0,此后的所有对BitmapData的操作都将不生效。


9,draw方法,显示对象BitmapData化


draw(source:IBitmapDrawable, matrix:Matrix = null, colorTransform:ColorTransform = null, blendMode:String = null, clipRect:Rectangle = null, smoothing:Boolean = false):void


这里的六个参数,除了第一个是必选外,其余的都是可选:


source:要被“画”的对象。


matrix:一个变型矩阵,作用于BitmapData。


colorTransform:一个颜色变换,作用于BitmapData。


blendMode:图层叠加模式。具体的模式可以在BlendMode 类中找到。将BitmapData与source进行图层叠加。


clipRect:定义了draw source的区域。


smoothing:定义是否进行图像平滑。只对source是BitmapData时起作用。


这个绝对是BitmapData的重头戏,非常常用的方法。画一切可以“画”的对象,就是文章开头提到的实现了IBitmapDrawable接口的对象都可被“画”。BitmapData和DisplayObject都实现了这个接口。


这样做的好处是可以在显示对象不需要被使用的时候Draw一个假的放在舞台上,或者有很多元件在舞台上运动的时候,统一把结果Draw在一张BitmapData上,节省CPU的开销,实现用内存换取CPU性能。


注意,如果跨域没有安全文件的话,draw方法是无法draw到内容的,不过这种情况在一般的内容里不会出现。


10,填充矩形

fillRect(rect:Rectangle, color:uint):void


这个应该很好理解,就是输入一个矩形对象,然后用对应的颜色填充这块矩形对象的区域就OK了。


11,颜料桶填充


floodFill(x:int, y:int, color:uint):void


这个也是另外的一种填充,模拟的是我们平常在IDE里进行的颜料桶填充方式(选中颜色,选中填充的点,就会将所有附近相同颜色的像素一起填充)。对应的x,y就是点的坐标,color自然就是颜色啦。


12,计算滤镜作用区域


generateFilterRect(sourceRect:Rectangle, filter:BitmapFilter):Rectangle


因为滤镜的作用区域不一定总等于输入的作用区域,所以这个函数是用来计算滤镜的实际作用区域的,输入的是一个矩形区域sourceRect和需要作用的滤镜filter,返回的是实际滤镜会影响到的矩形。


13,获取颜色区域


getColorBoundsRect(mask:uint, color:uint, findColor:Boolean = true):Rectangle


这个在做摄像头应用的常用来检测颜色的区域。返回的是由所有符合条件的像素组成的最大矩形。


color:就是要查找的颜色


findColor:为true时,是查找与color相同的颜色;为false则是查找与color不相同的颜色。


mask:是一个与输入color的掩码操作,作用是例如我只想进行某个通道的颜色比对时,可以不必管其他通道的的具体值。具体的运算方法是& (按位 AND),即逻辑与或非中的“与”操作,具体的结果是1&1=1,1&0=0&1=0&0=0,是二进制下的运算。


至于怎么比对?其实0xF = 二进制下的1111,类似的转化而已。


14,取得某点颜色(16位版)


getPixel(x:int, y:int):uint


很简单,就是取得x,y点的颜色(不包含Alpha通道)。


15,取得某点颜色,(32位版)


getPixel32(x:int, y:int):uint


同上,不过这次包含了Alpha通道


16,取得区域的像素二进制信息


getPixels(rect:Rectangle):ByteArray


这个函数是将一片区域rect内的所有图形信息,打包成一个二进制数组类ByteArray,作用是可以在头像上传时上传用户选择的部分。二进制数组类ByteArray也是一个高级的类,以后会有介绍。


17,获取区域内的像素矢量数组Vector


getVector(rect:Rectangle):Vector.<uint>


Vector这种数据结构是FP10以后新加的,那么这个方法对应的也只能在FP10或以上版本里使用。学过Java的同学可能很熟悉,其实Vector 是一种固定数据类型的数组。即这个数组里的所有内容都必须是某种数据类型的。这样做的好处是因为事先规定好了数组的类型,那么在使用时不用花时间去判断弱 类型,大大提高了运行效率,其他的使用方法大概跟Array一样。


那么这个函数其实没有太多的难点,就是返回一个Vector,里面包含的都是每一个像素的颜色信息而已。


18,获取区域内通道信息矢量数组Vector


histogram(hRect:Rectangle = null):Vector.<Vector>


这个也是FP10的新API,具体作用跟getVector很像,只是将getVector的结果继续拆分了而已。


返回的Vector里面有4个Vector,4个Vector里面装的是4个通道(Alpha,Red Green,Blue)的值0~255。再巩固一下Vector是有类型的数组,所以返回的是Vector.<Vector>,而4个 Vector则是Vector.<Number>。


19,不规则碰撞检测(高级碰撞检测)

hitTest(firstPoint:Point, firstAlphaThreshold:uint, secondObject:Object, secondBitmapDataPoint:Point = null, secondAlphaThreshold:uint = 1):Boolean


详细的介绍可以参考《ActionScript Animation》,中文译名好像就Flash高级动画教程还是啥的,封面是个长颈鹿的··这本书挺出名的···


这里转一些介绍(其实配合上调用函数的对象,是6个参数)高手介绍的比我清楚得多:


注意到这5个参数被分成了两组:一个和另一个。每组都需要一个点来确定位图的左上角起点。


接着每组都还有一个透明阈值。之前提到过,支持透明的位图对象,每个像素的透明度取值范围在0(完全透明)到255(完全不透明)。参数透明阈值即指定, 透明度在多少的时候就算碰撞。


最后还剩一个参数,另一个对象。注意它的类型是Object。允许传递的可以是一个点(Point),一个矩形(Rectangle)或者另一个位图对象 (BitmapData)。如果传一个点或者一个矩形,那么后面的两个参数可以忽略。


到此,测试都是围绕着Bitmap对象。而大多情况下的MovieClip,Sprite和Shape对象是没法用hitTest的。有个办法就是暗中准 备一些BitmapData,不把它们加入到显示列表。当要对两个显示对象进行碰撞检测时,先把它们分别绘制到一个准备好的位图对象中,然后如法炮制。要 知道,这不是唯一的办法,却是个不错的办法。


20,锁定变化


lock():void


因为对像素的操作涉及很多中间步骤,如果每操作一次都更新一次,那么如此大的计算量会把CPU拖垮的,这个函数的作用就是把BMD锁住,只保存更新步骤,而不更新实际像素。在做粒子效果时如果没有这一步绝对卡死人。


21,图像合并


merge(sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point, redMultiplier:uint, greenMultiplier:uint, blueMultiplier:uint, alphaMultiplier:uint):void


头三个参数又是老三样,不多说。


后面的4个参数分别是AARRGGBB通道Multiplier


计算方法为新值=Source通道*Multiplier;


22,生成噪点


noise(randomSeed:int, low:uint = 0, high:uint = 255, channelOptions:uint = 7, grayScale:Boolean = false):void


生成一堆杂乱无章的图像填充BMD,意义何在??一般是做贴图的MAP映射吧···创造出凹凸不平的效果,一般很少人会直接用吧···


randomSeed:随机的一个种子,就是从这个数字生成一大堆噪点图


low,high各通道在0~255区间取的最低和最高值


channelOptions:uint (default =7) — 一个数字,可以是四个颜色通道值的任意组合。 您可以使用逻辑 OR 运算符(|)来组合通道值。 (谁看的懂谁告诉我···我是不知道他想怎样了)


grayScale:这个如果设为true,则生成像素的RGB值将相等,即生成“灰度图”。如果是false则是为有色彩的。


23,调色板


paletteMap(sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point, redArray:Array = null, greenArray:Array = null, blueArray:Array = null, alphaArray:Array = null):void


这个API在摄像头检测中有很重要的应用,回想刚刚的getColorBoundsRect(不用回想了,如果你能看一次就记住才有鬼了,还是拖上去看看 吧),:D,检测一个0xRRGGBB的颜色?见鬼!256x256x256=16777216种颜色,才定义其中一种??除非是我自己填的,不然找啥 啊~~


paletteMap函数的作用就是重新映射各个通道的范围,例如你可以把Red通道的颜色区间从原来的256种红映射成16种红,大大提高了你的检测成功率。


头三个参数还是老三样(我发现这句都成我口头禅了,哈)。不多说。


后面4个参数其实是一类的,四个通道AARRGGBB。


那么我们应该输入什么进这些数组呢·?答案是256长度的内容,对应各个通道的256个值,但是这个值是我们来定义的。


这里注意的是,由于最后的颜色是四个通道相加出来的,所以redArray的值应该是0x00000000~0x00FF0000,要将具体的值移位到正 确的位置上。这里介绍两个大家平常很少用的二进制位操作符<<和>>,作用就是将二进制数全部向左或者向右移一位。


只要按你想要的把4个数组的映射保存好,作为参数传入就可以了。


24,柏林噪声函数

perlinNoise(baseX:Number, baseY:Number, numOctaves:uint, randomSeed:int, stitch:Boolean, fractalNoise:Boolean, channelOptions:uint = 7, grayScale:Boolean = false, offsets:Array = null):void


上网查了一下··这个柏林噪声函数好像是蛮出名的一个函数···同样是产生噪点,从视觉效果来说,柏林函数的效果更漂亮,蒙胧很多(很像PS里的云彩滤镜),而noise的话就很想电视机的杂点。


说说这里的九个参数:


baseX,baseY:帮助里说的是X和Y轴上的频率,可以理解为噪声的区域的长和宽···注意,这里的长和宽不是总的长宽,总的长宽由bitmapdata的长宽决定,这里说的噪声区域的长宽说的是单个噪声区域的长宽,总的图像由很多个这样的噪声区域组成


numOctaves:uint — 要组合以创建此杂点的 octave 函数或各个杂点函数的数目。 octave 的数目越多,创建的图像越细腻。 octave 的数目越多,需要的处理时间也会越长。 (专业术语我也看不太懂··好像是用来控制生成杂点函数octave的数量的 )


randomSeed:随机种子,通过这个生成不同的分布


stitch:中文意思是缝合,当设为true时将对不同的噪声区域进行无缝拼合。但是老实说,我设了一下false,也没看出什么区别嘛………


fractalNoise:另外一个参数,这个蛮明显的,设为true时图像将显得有种烟雾的效果,渐变比较连续。而为false时,则显得有些锐利,帮助说可以用来制作火焰和海浪效果··这个,怎么做呢???


channelOptions:跟之前的noise一样,都是把几个通道的数值进行与或非之类的操作吧···


grayScale:与之前的noise一样,设为true将生成灰度图。


offsets:一个数组,长度对应之前设置的numOctaves,定义了每个点的x,y偏移量。


25,像素溶解(听名字不懂,看解释吧)


pixelDissolve(sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point, randomSeed:int = 0, numPixels:int = 0, fillColor:uint = 0):int


这个函数很迷糊,但是很有意思。如果你打开帮助看看他的例子就会发现了。动画效果还是蛮Cool的(其实Cool在哪??汗··可能只有我们程序员觉得Cool吧··)


总的来说就是每次随机取几个点,然后填充过去,然后再取几个点,继续填充,一直到完全填充完成为止。因此需要不停的调用。


解释解释参数和返回值,还有两种情况的运作方式。


6个参数,头3个还是老三样(又来了,汗),那我们从第四个开始说起吧


randomSeed:产生随机数的随机种子


numPixels:每次变化的像素数目


fillColor:要填充的颜色


返回的是后续调用需要用的新的随机种子,这个可用可不用了


这个函数分两种情况,当sourceBitmapData就是原BMD时,用fillColor定义的颜色进行填充,不考虑destPoint的偏移。当sourceBitmapData不是原BMD时,用sourceBitmapData对原BMD进行填充。


26,滚动Bitmapdata


scroll(x:int, y:int):void


对BMD水平和垂直移动,这个很好理解。


注意!!滚动的只是原来定义的Bitmapdata,对于由于X,Y移出区域的Bitmapdata的位置,将按边缘像素进行填充。但是新填充的区域,不会参与同一次的X,Y滚动。


即scroll(40,40)和scroll(40,0);scroll(0,40)得到的结果不同。


27,设置某点颜色(16位)


setPixel(x:int, y:int, color:uint):void


像素级的操作来了(其实之前也有的··),这个函数可以单独设置BMD某个点的颜色,三个参数分别是x,y,颜色。对应位置和颜色,很好理解吧,不多说了。


28,设置某点颜色(32位)


setPixel32(x:int, y:int, color:uint):void


跟上面的setPixel非常类似,只是设置的颜色是32位(包含Alpha通道)而已。


29,二进制数组(ByteArray)填充


setPixels(rect:Rectangle, inputByteArray:ByteArray):void


这个函数跟setPixel的区别在于多了一个“s”,这个s嘛,在英语里就是复数的意思,所以此函数的作用是同时设置多个像素。其中一个作用可以是在接 收到服务器传来的图像的二进制数据并将其转化为BitmapData数据。当然这个目前就无法做DEMO了,但是我们可以用自带的API自娱自乐一把。还 记得set的好兄弟get吗?我们之前就介绍过setPixels函数,这两个可以配套使用。


输入的参数:


rect:输入数据填充的区域。至于是从左到右还是从右到左还是从上往下还是从下往上,我也不太清楚。其实我还是清楚一点的,应该是从左往右,从上往下填 (做了实验的),如果有错请高手指出。注:如果二进制数值不足以填充矩型区域,会引发错误。所以记得用try,catch包好。


inputByteArray:输入的二进制数组。


30,Vector数组填充

setVector(rect:Rectangle, inputVector:Vector.<uint>):void


跟ByteArray填充差不多,不过这次用的是Vector数组。测试也可以用set的好搭档:getVector。


注:Vector是FP10的新数据结构,使用要用FlashPlayer10或以上版本。



31,颜色阈值函数(比较函数)


threshold(sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point, operation:String, threshold:uint, color:uint = 0, mask:uint = 0xFFFFFFFF, copySource:Boolean = false):uint


这个也是个功能很强大的函数,在摄像头应用中会用到,用来简化颜色。


作用概括来说,就是设定比较的条件,对符合条件的像素颜色,统统设置为一个新的值。


有8个参数,头3个老三样(我又来了),让我们来说后五个:


operation:比较条件,“<”、“<=”、“>”、“>=”、“==”“!=”


threshold:这个单词大家不是很熟,是阙值,就是我们要用来进行比较的颜色值。


color:比较结果为true之后,像素颜色设置的新值。


mask:掩码。可以把你不想比较的通道屏蔽掉。


copySource:当sourceBitmapData不等于原BMD的时候有用。设置为true时,当比较失败时仍将sourceBitmapData的数据Copy过去原BMD。而false时就不Copy。


返回值是已改变像素的数目,也可以用来做判断结果,有多少像素达到了某某要求。



32,解锁


unlock(changeRect:Rectangle = null):void


配合之前的lock()来用,目的是为了在多次操作过程中停止更新,节省CPU效率。附带了一个参数changeRect,是可以设定解锁的区域,可以只将变化了的区域解锁,这样就不用更新整张BMD,进一步节省了CPU。



总结:


Bitmapdata的API很多,而且也有很多的自己也不熟悉,断断续续的写了三天多,之间又有其他事情做。所以可能有些名词没有深入解释,只是一笔带过;或者语言风格的不统一;可能还有些地方自己也没弄明白讲的也不太好,缺陷还有很多。以后还需要继续努力。


这次也是对Bitmapdata的一个基础介绍,具体的应用可以上网看到很多,而且这个类的玩法也很多。只有掌握扎实了基础知识,才能看懂学习别人精彩的算法。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值