AS3覚え書き5 :画像

Actionscriptで画像を扱うにはBitmapクラスやBitmapDataクラスを利用します。

BitmapDataクラス

Bitmap画像の各画素データを記憶するクラスです。

プロパティ
  • width:int
  • height:int

幅と高さ

メソッド

画素値の取得

  • getPixel(x:int, y:int):uint
  • getPixel32(x:int, y:int):uint
  • getPixels(rect:Rectangle):ByteArray

画素値の書き込み

  • setPixel(x:int, y:int, color:uint):void
  • setPixel32(x:int, y:int, color:uint):void
  • setPixels(rect:Rectangle, inputByteArray:ByteArray):void

32が付いているメソッドはα値付きの値ARGBを扱います。
〜Pixelsというメソッドではバイト配列を介して画素値を扱うことができます。

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

表示オブジェクトをこのビットマップに描画します。

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

ノイズ画像を生成します。
その他にも、copyやmergeなどのメソッドが用意されています。

Bitmapクラス

BitmapクラスはメンバとしてBitmapDataを持っている表示オブジェクトです。実際に画像を表示させるにはこのBitmapクラスを作成して表示リストに追加します。

プロパティ
  • bitmapData : BitmapData

画素値を記録したBitmapDataです。

  • smoothing : Boolean

拡大縮小などの際にスムージングを行うかどうかを設定します。
メソッドはコンストラクタ以外ありません。

Bitmap&BitmapDataクラスによる画像表示

画像表示例です。setpixel関数で全体の色を塗りつぶしてから、Bitmapデータを生成して表示させています。BitmapDataオブジェクトをコンストラクタの引数として渡して、表示するBitmapオブジェクトを作ることができます。

package  
{
	import flash.display.Sprite;
	public class BitmapTest extends Sprite
	{
		import flash.display.Bitmap;
		import flash.display.BitmapData;
		public function BitmapTest() 
		{
			var bmpdata:BitmapData= new BitmapData(200,100);
			
			for (var j:int = 0; j< bmpdata.height; j++) {
				for (var i:int = 0;i< bmpdata.width; i++ ) {
					bmpdata.setPixel(i, j, 0xFFCCFF);
				}
			}
			var bitmap:Bitmap = new Bitmap(bmpdata);
			addChild( bitmap);
		}
	}
}

表示オブジェクトをBitmapに変換する

BitmapDataクラスのdrawメソッドの引数にSpriteやMovieClipなどのDisplayObjectを渡すと、表示オブジェクトをビットマップに変換することができます。例えば、Spriteに円を描画して、ビットマップに変換したあと、赤成分だけ消して描画するような処理は下のようなコードになります。

import flash.display.Sprite;
public class BitmapTest extends Sprite
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;		
	public function BitmapTest() 
	{
		//Spriteに絵を描く
		var dispObj:Sprite = new Sprite();
		dispObj.graphics.beginFill(0xCCAACC);
		dispObj.graphics.drawCircle(20, 20, 20);
		dispObj.graphics.endFill();

		//BitmapDataを生成する
		var bmpdata:BitmapData= new BitmapData(200,100);
		bmpdata.draw(dispObj);//SpriteをBitmapDataに変換する
			
		//BitmapDataの加工
		for (var j:int = 0; j< bmpdata.height; j++) {
			for (var i:int = 0;i< bmpdata.width; i++ ) {
				var col: uint = bmpdata.getPixel(i, j);
				var red : int = (col >> 16) & 0x0000FF;
				var green : int = (col >> 8) & 0x0000FF;
				var blue : int = (col >> 0) & 0x0000FF;
				red = 0;
				bmpdata.setPixel(i, j, (red << 16) + (green << 8) + blue );
			}
		}
		//表示用Bitmapの作成		
		var bitmap:Bitmap = new Bitmap(bmpdata);
		addChild( bitmap );
	}
}

外部の画像を読み込む

Loaderクラス

外部のSWF,JPG,PNGなどの画像を読み込む表示オブジェクトはLoaderとして提供されています。外部の画像を読み込むには、まずこのLoaderクラスで画像データを読み込み、DisplayObjectとして描画します。

URLRequestクラス

画像のURLを取得するにはURLRequestクラスを利用します。

BitmapData・Bitmapクラス

次にBitmapDataクラスのdrawメソッドでこのLoaderをビットマップに変換します。最後に作成したBitmapDataを持つBitmapクラスを作成して画面に表示させます。

LoaderInfoクラスとEvent.COMPLETE

ここで注意するべき点は、画像のロード完了まで待たなければならないということです。画像のサイズが未確定の状態でビットマップを生成することはできません。ロード完了時にCOMPLETEイベントが送出されるので、onCompleteLoadingというイベントハンドラ内でBitmapDataを生成、描画しています。COMPLETEイベントを扱うことができるのはLoaderInfoクラスです。LoaderクラスはLoaderInfoクラスをcontentLoaderInfoプロパティとして所有しています。

import flash.display.Sprite;
public class BitmapTest extends Sprite
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;		
	import flash.display.Loader;
	import flash.net.URLRequest;
	import flash.events.Event;

	private var myLoader:Loader = new Loader();
	public function BitmapTest() 
	{
		//画像のURLまたはパスを取得
		var myUrlRequest:URLRequest = new URLRequest("test.jpg");
		//画像を読み込む
		myLoader.load(myUrlRequest);
		//画像ロード完了時のイベントリスナーを追加
		myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteLoading);
	}
	private function onCompleteLoading(eventObject:Event):void {
		//Loaderと同じサイズのBitmapDataを作成する
		var bmpdata:BitmapData = new BitmapData(myLoader.width, myLoader.height);
		//Loader→BitmapDataに変換する
		bmpdata.draw(myLoader);
		//表示用Bitmapを生成
		var bmp : Bitmap = new Bitmap( bmpdata );
		addChild( bmp );//表示
	}
}

画素値を配列として扱う

Actionscriptではbyte配列用のクラスとしてByteArrayクラスが用意されています。
BitmapDataからByteArrayへ変換するには、BitmapDataのgetPixelsメソッドを利用します。引数には、抽出する矩形領域を指定して、画素データを配列として格納するByteArrayオブジェクトが戻り値となります。

	//bmpdataはBitmapData
	var bytes:ByteArray = new ByteArray();
	bytes = bmpdata.getPixels(bmpdata.rect);

逆にByteArrayからBitmapDataに戻すには、setPixelsに上書きする矩形領域と、書き込みたいByteArrayを引数にして呼び出します。
ByteArrayには現在指し示す位置offsetが定められており、positionメソッドでその値にアクセスできます。
getPixelsで値を書き込んだByteArrayオブジェクトはpositionが終端になっているため、一旦元に戻してからsetPixelに変換しないと範囲外へのアクセスとなってエラーになります。

	bytes.position = 0;
	bmpdata.setPixels(bmpdata.rect, bytes);

getPixelで配列に変換するとARGBやRGB形式などで値が格納されます。例えばARGB形式の場合、(i,j)画素を扱う場合は次のようなindexにアクセスするとよいでしょう。

	bytes[j * width * 4 + i * 4 + 0] = alpha;
	bytes[j * width * 4 + i * 4 + 1] = red;
	bytes[j * width * 4 + i * 4 + 2] = green;
	bytes[j * width * 4 + i * 4 + 3] = blue;

外部から画像を読み込んでbitmapDataに変換し、さらに配列に変換して画像処理を行うためのサンプルです。

import flash.display.Sprite;
public class BitmapTest extends Sprite
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;		
	import flash.display.Loader;
	import flash.net.URLRequest;
	import flash.events.Event;
	import flash.utils.ByteArray;
	private var myLoader:Loader = new Loader();
	public function BitmapTest() 
	{
			//画像のURLまたはパスを取得
		var myUrlRequest:URLRequest = new URLRequest("test.jpg");
			//画像を読み込む
		myLoader.load(myUrlRequest);
			myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteLoading);

	}
	private function onCompleteLoading(eventObject:Event):void {

		//Loaderと同じサイズのBitmapDataを作成する
		var bmpdata:BitmapData = new BitmapData(myLoader.width, myLoader.height);
		//Loader→BitmapDataに変換する
		bmpdata.draw(myLoader);

		var bytes:ByteArray = new ByteArray();
		var width:int = bmpdata.width;
		var height:int = bmpdata.height;
		//Bitmapdata→ByteArrayに変換する
		bytes = bmpdata.getPixels(bmpdata.rect);

		//ここから画像処理
		var alpha:Number;
		var red:Number;
		var green:Number;
		var blue:Number;
		for (var j:int = 0; j< height; j++) {
			for (var i:int = 0; i < width; i++ ) {
				alpha = bytes[j * width * 4 + i * 4 + 0];
				red= bytes[j * width * 4 + i * 4 + 1];
				green= bytes[j * width * 4 + i * 4 + 2];
				blue = bytes[j * width * 4 + i * 4 + 3];
				red = 0;//赤だけ消去
				bytes[j * width * 4 + i * 4 + 0] = alpha;
				bytes[j * width * 4 + i * 4 + 1] = red;
				bytes[j * width * 4 + i * 4 + 2] = green;
				bytes[j * width * 4 + i * 4 + 3] = blue;
			}
		}
		//ここまで画像処理
		bytes.position = 0;
		//ByteArray→Bitmapdataに変換する
		bmpdata.setPixels(bmpdata.rect, bytes);
		var bmp : Bitmap = new Bitmap( bmpdata );
		addChild( bmp );
	}
}