注:文中的Bitmapdata和BMD均為同一意思BitmapData,BMD為其縮寫
一,概括:
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
?
返回一個新的 BitmapData 對象,它是對原始實例的克隆,包含與原始實例所含位圖完全相同的副本。
4,變色
colorTransform(rect:Rectangle, colorTransform:ColorTransform):void
對位圖數據進行顏色變化
?
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
?
為沒有拉伸、旋轉或色彩效果的圖像之間的像素處理提供一個快速例程。 此方法在目標 BitmapData 對象的目標點將源圖像的矩形區域復制為同樣大小的矩形區域。
?
如果包括 alphaBitmap 參數和 alphaPoint 參數,則可以將另一個圖像用作源圖像的 Alpha 源。 如果源圖像具有 Alpha 數據,則這兩組 Alpha 數據都用于將源圖像中的像素組合到目標圖像中。 alphaPoint 參數是 Alpha 圖像中與源矩形左上角對應的點。 源圖像和 Alpha 圖像交叉區域之外的任何像素都不會被復制到目標圖像。
?
mergeAlpha 屬性控制在將透明圖像復制到另一透明圖像時是否使用 Alpha 通道。 若要復制含有 Alpha 通道數據的像素,請將 mergeAlpha 屬性設置為 true。 默認情況下,mergeAlpha 屬性為 false。
?
參數? sourceBitmapData:BitmapData — 要從中復制像素的輸入位圖圖像。 源圖像可以是另一個 BitmapData 實例,也可以指當前 BitmapData 實例。?
?
?sourceRect:Rectangle — 定義要用作輸入的源圖像區域的矩形。?
?
?destPoint:Point — 目標點,它表示將在其中放置新像素的矩形區域的左上角。?
?
?alphaBitmapData:BitmapData (default = null) — 第二個 Alpha BitmapData 對象源。?
?
?alphaPoint:Point (default = null) — Alpha BitmapData 對象源中與 sourceRect 參數的左上角對應的點。?
?
?mergeAlpha:Boolean (default = false) — 若要使用 Alpha 通道,請將該值設置為 true。 若要復制不含 Alpha 通道的像素,請將該值設置為 false。
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,作用是可以在頭像上傳時上傳用戶選擇的部分。
?
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
?
注意到這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在攝像頭檢測中有很重要的應用,
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。
?
總結: 如果你看完后還有不明白的,那就在看一遍,如果你對某個方法不夠理解或想看看用此方法的例子你可以直接看幫助文檔。