位圖(Bitmaps)
與濾鏡相同,可以用整本書來介紹 Bitmap 和 BitmapData 類,看起來也不錯,但是這并不是本書的目的。我們將通過一些簡單的例子,用來指出 AS 2 與 AS 3 中位圖處理的變化。
在 AS 2 中,通過調(diào)用 BitmapData()函數(shù),新建一個 BitmapData 對象使用如下參數(shù):
new BitmapData (width:Number, height:Number, transparent:Boolean, fillColor:Number)
你也許猜到了, BitmapData 類同樣也是嵌入在一個包中,完整的使用名稱如下 flash.display.BitmapData。所以需要導(dǎo)入包,對于 width 和 height 參數(shù)則非常顯而易見, transparent 參數(shù)表示創(chuàng)建的圖像是否包涵一個 alpha 通道,選擇 true 或 false ,fillColor 是創(chuàng)建圖像的初始顏色,如果 transparent 為 true 的話,那么位圖就用 32 位色表示,0xAARRGGBB,如果為 false 的話,就可以使用 24 位安全色表示。
在創(chuàng)建 BitmapData 對象時,也許很想能看到它的樣子。在 AS 2 中,使用 attachBitmap 命令在影片剪輯中添加一個位圖。大家也許會想,現(xiàn)在是否可以使用 addChild 在顯示對象中添加一個位圖,但事實上并沒有這么簡單。問題在于 addChild 只對繼承自 DisplayObject 類的對象起作用,如 Sprite 影片,影片剪輯和文本框。然而,如果我們研究一下類的結(jié)構(gòu),就會發(fā)現(xiàn) BitmapData ,沒有繼承自 DisplayObject,所有不能直接添加對象。這就是為什么要有 Bitmap 類的原因, Bitmap 類幾乎始終都有一個函數(shù)作為 BitmapData 實例的容器,可以這樣創(chuàng)建:
var myBitmapData:BitmapData = new BitmapData(100, 100, false, 0xff0000); var myBitmap:Bitmap = new Bitmap(myBitmapData);
現(xiàn)在就可以將對象加入到顯示列表了:
addChild(myBitmap);
使其可見后,Bitmap 實例也可以改變位置,進(jìn)行縮放,增加濾鏡等等。 測試這個例子,只需要在第二章給出的類框架的 init 方法加入這三行就可以了,不要忘記導(dǎo)入 flash.display.Bitmap 和 flash.display.BitmapData,運行后就會看到一個紅色的正方形。乍看上去,與使用繪圖 API 所畫的圖形沒什么不同,但是要知道這并不是矢量圖繪制法:填充一個紅色的正方形。這是張位圖圖像,在位圖中每一個像素都要分別指定而且是可變的。事實上,每一個像素值都可以使用 getPixel,getPixel32 和 setPixel,setPixel32 進(jìn)行讀取和設(shè)置。兩個版本的不同之處在于 getPixel 和 setPixel 使用24位色彩值忽略了 alpha 通道,而 “32”版的則使用32位色彩值其中包括了透明度信息。讓我們來做個例子,制作一個簡單的噴漆工具,就像所有位圖噴漆程序一樣。 這里是文檔類,SprayPaint.as:
package { import flash.display.Sprite; import flash.display.Bitmap; import flash.display.BitmapData; import flash.events.MouseEvent; import flash.events.Event; import flash.filters.BlurFilter; public class SprayPaint extends Sprite { private var canvas:BitmapData; private var color:uint; private var size:Number = 50; private var density:Number = 50; public function SprayPaint() { init(); } private function init():void { canvas = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0x00000000); var bmp:Bitmap = new Bitmap(canvas); addChild(bmp); stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); } private function onMouseDown(event:MouseEvent):void { color = Math.random() * 0xffffff + 0xff000000; addEventListener(Event.ENTER_FRAME, onEnterFrame); } private function onMouseUp(event:MouseEvent):void { removeEventListener(Event.ENTER_FRAME, onEnterFrame); } private function onEnterFrame(event:Event):void { for (var i:int = 0; i < density; i++) { var angle:Number = Math.random() * Math.PI * 2; var radius:Number = Math.random() * size; var xpos:Number = mouseX + Math.cos(angle) * radius; var ypos:Number = mouseY + Math.sin(angle) * radius; canvas.setPixel32(xpos, ypos, color); } } } }
這也許是目前為止最復(fù)雜的代碼,但除了 BitmapData 的內(nèi)容外,其它的知識前面都講過,只不過又使用了一遍而已。一步步來看,首先,創(chuàng)建了一些類變量,包括 canvas 變量,用于存放 BitmapData 的實例。創(chuàng)建的實例尺寸等于舞臺的尺寸,并使用透明的背景色。然后使用 canvas 創(chuàng)建一個位圖,并加入到顯示列表。 鼠標(biāo)事件處理函數(shù)中選擇了一個隨機的顏色,并且?guī)в刑砑雍蛣h除 enterFrame 事件處理函數(shù)的功能。我們來回憶一下三角學(xué),首先,從 0 到 Math.PI * 2 中計算出一個隨機的角度,不要忘記使用弧度制表示,相當(dāng)于隨機的360度。然后,計算出一個隨機的半徑后,再使用三角函數(shù)將半徑和角度轉(zhuǎn)換為 x,y 值。最后使用 setPixel32 以鼠標(biāo)位置加上隨機的 x,y 值的像素點設(shè)置為噴漆色,每一次開始噴漆時隨機決定顏色。在這個例子中有一個 for 循環(huán),每一幀都會進(jìn)行循環(huán),每次循環(huán)多少次由 density 的值決定。 color 的值為24位的色彩值,然后加上 0xFF000000,為的是設(shè)置 alpha 通道為完全不透明,如果沒有加上這個值,那么所有的顏色就都為透明的。如果用 0xFFFFFFFF 乘以 Math.random(),那么顏色的透明度是隨機的,也許是你想要的,但不是我想要的。通過改變 density 和 size 的值再測試一下,看看會有些什么不同的效果。大家也許已經(jīng)想到如何讓用戶來控制改變這些參數(shù)了。
剛剛看到這個程序時,你也許會想,“真是小題大作,完全可以用繪圖 API 或通過加載小影片剪輯并改變顏色來實現(xiàn)”。是的,完成可以這么做,但是如果使用繪圖 API 繪出成千上萬的獨立圖像后,會發(fā)習(xí)畫得越多,速度越慢。畫過幾百個圖形后,慢下來的速度會變得非常明顯,這個程序也就費掉了,使用加載影片剪輯的方式也是如此。但是,使用位圖就完全不同了,我們可以使用這個程序噴上一天,都不影響程序的速度或效率。 如果想看到更酷的效果,就把下面一行代碼加在位圖對象 bmp 的后面:
bmp.filters = [new BlurFilter(2, 2, 3)];
在位圖中使用模糊濾鏡比在矢量圖中使用效果更加明顯。當(dāng)然,設(shè)置像素是 BitmapData 對象能做的最簡單的操作之一。除了獲取和設(shè)置像素,BitmapData 對象還有其它二十多種方法,這些方法可用來復(fù)制像素,設(shè)置閾值,分解,合并,滾動,等等。我個人最喜歡的一個是 perlinenoise 方法,該函數(shù)允許我們創(chuàng)建一個隨機的有組織的圖案。對于制造煙,云和水波紋效果都非常有用。有興趣的話大家可以試驗一下。
讀取和嵌入資源
最后一個重點話題是獲取外部資源的概念,如在影片中加載位圖或外部 SWF 文件。有兩種方法,一種是在動畫播放時將資源讀入,這就是我們所熟知的讀取(loading)。另一種方法是在 SWF 編譯時嵌入(embed)資源。
讀取資源
創(chuàng)建一個 Loader 對象來讀取一個資源,這是flash.display.Loader 類的一個實例。 loader 是個顯示對象,意味著可以使用 addChild() 方法將它加入到顯示列表中,就像 sprite 和 bitmap 一樣。然后告訴這個 loader 去讀取一個外部 SWF 或外部位圖,如 JPEG,PNG,等等。
在 AS 2 中,當(dāng)處理外部文件路徑或 URL 時,只需要使用一個簡單的字符串表示路徑。 在 AS 3 中,則需要創(chuàng)建一個 flash.net.URLLoader 實例,傳入表示路徑的字符串,并且還需要一個額外的步驟,雖然有些煩人,但是我們還是要習(xí)慣這種用法。 這里是一個在運行時讀取外部資源的例子(文檔類 LoadAsset.as):
package { import flash.display.Sprite; import flash.display.Loader; import flash.net.URLRequest; public class LoadAsset extends Sprite { public function LoadAsset() { init(); } private function init():void { var loader:Loader = new Loader(); addChild(loader); loader.load(new URLRequest("picture.jpg")); } } }
嵌入資源
雖然在有些情況下,在運行時讀取資源很合適,但是在有些情況下有一些外部圖形只想加載到 SWF 自里面。這時,如果使用 Flash IDE,可以簡單地導(dǎo)入這個對象到庫中并設(shè)置為“為 ActionScript 導(dǎo)出”。但在使用 Flex Builder 2 或 Flex 2 SDK 命令編譯器時,沒有庫,那么如何在 SWF 中加載外部資源呢?
答案是使用[Embed]元數(shù)據(jù)(metadata)標(biāo)簽嵌入資源,元數(shù)據(jù)標(biāo)簽是指加到 ActionScript 文件中的非正式 ActionScript 語句。另外,它們指示編譯器在編譯過程中去做某種事情,[Embed]標(biāo)簽告訴編譯器在最終的 SWF 文件中加載一個特殊的外部資源,資源可以是位圖或外部 SWF 文件。告訴編譯器要嵌入的資源所在的 source 路徑的屬性,如下:
[Embed(source="picture.jpg")]
在元數(shù)據(jù)語句的后面,直接聲明一個 Class 類型的變量,如下:
[Embed(source="picture.jpg")] private var Image:Class;
現(xiàn)在可以使用這個變量創(chuàng)建一個新的資源實例,如下:
var img:Bitmap = new Image();
注意創(chuàng)建的這個對象是 Bitmap 類型的。如果嵌入一個外部 SWF 文件,創(chuàng)建的這個對象應(yīng)該是 Sprite 類型的,如下:
[Embed(source="animation.swf")] private var Anim:Class; var anim:Sprite = new Anim();
這里是一個在 SWF 中嵌入外部 JPEG 的例子:
package { import flash.display.Sprite; import flash.display.Bitmap; public class EmbedAsset extends Sprite { [Embed(source="picture.jpg")]; private var Image:Class; public function EmbedAsset() { init(); } private function init():void { var img:Bitmap = new Image(); addChild(img); } } }
如果我們使用 Flash IDE ,只要將對象導(dǎo)入到庫中并“為 ActionScript 導(dǎo)出”給出一個類名就可以了。不需要使用 [Embed] 元數(shù)據(jù)標(biāo)簽及類變量,事實上,F(xiàn)lash IDE 編譯器甚至不支持 [Embed] 元數(shù)據(jù)標(biāo)簽。這里只作一個簡單的介紹,因為在本書后面的內(nèi)容中不會用到這個技術(shù),但是很顯然這是個非常有用的方法。
本章重要公式
在本章中我們又收集了很多有價值的工具,大多都與顏色有關(guān)。
轉(zhuǎn)換為十進(jìn)制: trace(hexValue);
十進(jìn)制轉(zhuǎn)換為十六進(jìn)制: trace(decimalValue.toString(16));
顏色合成: color24 = red << 16 | green << 8 | blue; color32 = alpha << 24 | red << 16 | green << 8 | blue;
顏色提取: red = color24 >> 16; green = color24 >> 8 & 0xFF; blue = color24 & 0xFF; alpha = color32 >> 24; red = color32 >> 16 & 0xFF; green = color32 >> 8 & 0xFF; blue = color232 & 0xFF;
過控制點的曲線: // xt, yt is the point you want to draw through // x0, y0 and x2, y2 are the end points of the curve x1 = xt * 2 – (x0 + x2) / 2; y1 = yt * 2 – (y0 + y2) / 2; moveTo(x0, y0); curveTo(x1, y1, x2, y2);
本文鏈接:http://www.95time.cn/tech/multimedia/2008/5795.asp
出處:藍(lán)色理想
責(zé)任編輯:bluehearts
上一頁 渲染技術(shù) [8] 下一頁
◎進(jìn)入論壇RIA設(shè)計與應(yīng)用版塊參加討論
|