ndfweb.cn

BitmapData類介紹


2021-08-21 22:07:56 (4012)



今天介紹另外一個比較常用和中高級難度的類: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的一個基礎介紹,具體的應用可以上網看到很多,而且這個類的玩法也很多。隻有掌握紮實了基礎知識,才能看懂學習別人精彩的算法。


本文版权:http://www.ndfweb.cn/news-898.html
  NDF俱乐部
  国际域名注册
  建站咨询
简体中文 NDF网站建设淘宝店 | ICO图标在线生成 | 外贸网站建设 | 联系我们
©2007-2024 NDF Corporation 鲁ICP备08005967号 Sitemap - RSSRSS订阅