POPSブログ

LoaderとBitmapDataに関すること

71

  Category:  as32012/04/01 pops 

最初の第一歩は画像の表示である、Loaderを使用することになるが、初めての場合難解である。色々な表示例をまとめてみた。


LoaderとBitmapDataに関すること


AS3でも何でも、最初の第一歩は画像の表示である、Loaderを使用することになるが、初めての場合難解である。
理解するもしないも、一つの定形文として覚えたほうが良い。(Loader、Listener、BitmapData、をセットで無理やり覚えこむ)、表示できれば、おのずと後で何となく理解できる。要するに処理の順序(決まり)があるからそれに従わなければならない。


私の場合、注意していること

  • 画像を表示する場合、BitmapData変換しておいて使用する事を原則としています。
  • LoaderをaddChildでかさねれば簡単ですが時と場合により使いわける。
  • 場合によりBitmapをaddChildする場合もある。
  • BitmapDataの保存は配列のpushの使い方を工夫する。

画像を表示する場合、BitmapData変換しておいて使用するのがベスト

画像を表示する方法については、Loaderの使い方などにより、色々な方法があり、どの方法が良いのか中々判らない。

1. 簡単な方法である、Loader、Bitmapを直接addChildする場合は、どうしても複数画像が重なり、重くなりがちであるから状況次第で使いわける。画像加工は難しい。
2. 面倒でも、BitmapDataに変換しておいて使用するのがベストである。画像に何らかの処理をするにもBitmapDataに対して行われることが多い。自由度が高くなる。
3. 1つのSpriteで、グラフィックにその都度BitmapDataを流し込む処理は面倒だが、重ねないので時間経過で重くならない。コードをかくのが面倒。
4. BitmapDataを保存するときは、配列のpushの使い方を工夫するのがいい。LOADエラーの場合に、エラー対象画像を除外できる。


簡単なLoaderとBitmapData化とその表示例


//init
private function init():void {
	//画像読み込みLoader、Listenerを定義
	var image_name:String = "/main/images/testImage101.jpg";
	var loader:Loader = new Loader();
	loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
	loader.load( new URLRequest(image_name), new LoaderContext(true) );
}
// Show-Image
private function onComplete(e:Event):void {
	//onComplete(e:Event)を参照BitmapDataを取り出す
	var cliploader:Loader = e.currentTarget.loader;
	var bd:BitmapData = new BitmapData(cliploader.width, cliploader.height, false);
	//BitmapData化、BitmapDataのベースにcliploader情報を入れる
	bd.draw(cliploader);
	//Spriteを用意してgraphicsに流し込む、画像表示
	var imageBox:Sprite = new Sprite();
	imageBox.graphics.beginBitmapFill(bd, null, false, false);
	imageBox.graphics.drawRect(0, 0, cliploader.width, cliploader.height);
	imageBox.graphics.endFill();
	//addChild表示
	addChild(imageBox);
}


上の例では新たにcliploaderに代入しているが、直接なら
var bd:BitmapData = new BitmapData(e.currentTarget.loader.width, e.currentTarget.loader.height, false);
でも良いことになる

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

直接ステージにLoaderをaddChildして表示させる、上の例では

addChild(cliploader);
で、画像を表示できるが、単に表示出来ると言うだけであり、加工などは出来ないから
一番簡単かもしれないが、通常に使えるものでは無い

============================================================================================

新たなLoaderであるcliploaderからBitmapを取り出す場合
var bitmap:Bitmap = Bitmap(cliploader.content) as Bitmap;
//bitmapは直接大きさを修正できる
bitmap.width = 64;
bitmap.height = 48;

Bitmapの良い点は直接表示できることだ、但し回転などは出来ない色々制約はある
addChild(bitmap);

そのため、SpriteにBitmapをaddChildして使用すれば、多少は色々出来るようになる
Bitmapは、直接ステージに表示出来るが、常識的には余り無い、やはり何かの中にいれる

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

新たなLoaderを作らず、直接TargetからBitmapを取り出す場合
(e:Event)はloaderのイベントであるからloaderをふくんで居る、だから

var bitmap:Bitmap = Bitmap(e.currentTarget.loader.content) as Bitmap;
これでも可能だ

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

取り出したBitmapからBitmapDataを取り出す
var bd:BitmapData = new BitmapData(幅, 高さ, false);
//BitmapData化、BitmapDataのベースにBitmap情報を入れる
bd.draw(bitmap);

----------------------------------------------
bd.draw();出来るのは
Loaderオブジェクト、Bitmapオブジェクト、TextFieldオブジェクト、がある


色々な方法があるものだ

結果的に画像を表示させるには、表示させる容器である、Spriteを作り

  • SpriteにグラフィックでBitmapDataを流し込む
  • SpriteにBitmapでaddChildする

後々の加工、書き換えなどの操作を行うには、2つの方法しか無い。面倒でもBitmapData化などが必要です。


スライドショー表示などで画像を順次、addChildすれば簡単そうだが結局は重なり、表示処理は重くなる。画像の枚数などを考慮しながら設計しなければならない。このことに気づいたのは極最近だ、よってほとんど全てBitmapDataに変換してから使用している。面倒でも1度コードを作れば、使いまわしが出来る。


layerについて

前々から、重なり順を考慮して、layerごとに管理してきたが、layerはいくら増やしても良いことになっていた。つまりは重なり順をが管理していたと思う。
AS3になってlayerに関することは調べても何もでてこない。重なり順はわかるがそれをコードで管理は難しい。
よって、私の場合は、Spriteでlayerを作り(仮想layer)、それで管理しながら制作している。単に判り易いからであるが他にそのようなことをしている人は居ないみたいだ。


画像を表示のサンプル

FlashTest173c.swf


FLASH表示テスト 専用のSWF FlashTest173c.swf 465x465


注意、FlashTest173c.swf は「BaserCMS」で使用する専用です。画像は /main/images/xxxx.jpg


画像表示と処理の例をまとめて表示してみた

サンプル表示のことは下記コードの説明を読んで頂きたい。BINARY画像をBINARY形式で読み出すことは余り無いと思う。
LoaderとBitmapDataの関係などがわかるし、コピーすれば、一部変数の書き換えはしなければならないが、色々応用できる。


AS3

as FlashTest173c.as

FlashDevelopで制作しました。中には使用していない変数もあります。画像URLなどは環境に合わせてください。


//LoaderとBitmapDataに関すること
//FlashTest173c

package
{

	import flash.display.*;
	import flash.events.*;
	import flash.net.*;
	import flash.geom.*;
	import flash.system.*;
	import flash.utils.*;
	import flash.text.*;
	import flash.filters.ColorMatrixFilter;
	import flash.filters.BlurFilter;
	
	[SWF(width="465", height="465", frameRate="30", backgroundColor="0x000000")]

	public class FlashTest173c extends Sprite
	{

		//layer
		private var layer1:Sprite;
		private var layer2:Sprite;
		private var layer3:Sprite;
		private var layer4:Sprite;
		private var layer5:Sprite;
		private var layer6:Sprite;
		private var layer7:Sprite;
		private var layer8:Sprite;
		//text
		private var tf:TextField;
		//画像名保存配列
		private var photos:Array = [];
		//保存用BitmapData容器
		private var backImage_bd:BitmapData;
		//保存用オブジェクト容器
		private var imgArray:Array = [];

		public function FlashTest173c ():void
		{
			//ステージ関連の設定をする、ほぼ共通
			stage.align = StageAlign.TOP_LEFT;
			stage.quality = StageQuality.HIGH;
			//stage.scaleMode = StageScaleMode.NO_SCALE;//使用しない
			stage.fullScreenSourceRect = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);

			//ステージACTION
			stage.addEventListener(MouseEvent.CLICK,function(e:Event):void{
				stage.displayState = (StageDisplayState.FULL_SCREEN==stage.displayState)?StageDisplayState.NORMAL:StageDisplayState.FULL_SCREEN
			});

			//BASE/黒背景
			var s:Sprite = new Sprite();
			s.graphics.beginFill(0x000000);//0x000000
			s.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
			s.graphics.endFill();
			addChild(s);
			
			//layer1
			layer1 = new Sprite();
			addChild(layer1);
			//layer2
			layer2 = new Sprite();
			addChild(layer2);
			//layer3
			layer3 = new Sprite();
			addChild(layer3);
			//layer4
			layer4 = new Sprite();
			addChild(layer4);
			//layer5
			layer5 = new Sprite();
			addChild(layer5);
			//layer6
			layer6 = new Sprite();
			addChild(layer6);
			//layer7
			layer7 = new Sprite();
			addChild(layer7);
			//layer8
			layer8 = new Sprite();
			addChild(layer8);
			
			//text
			tf = createTextField(10, 5, stage.stageWidth - 20, 20);
			tf.textColor = 0xFFFFFF;
			tf.text = "LoaderとBitmapDataに関すること表示.FlashTest112";
			addChild(tf);
			
			//text2(x:Number, y:Number, width:Number, height:Number)
			var img_tf1:TextField = createTextField(10, 30, 460, 20);
			//--------------1--------------------------------2--------------------------------3------------------------------
			img_tf1.text = "1 通常のBitmap化画像表示  2-3 loaderオブジェクトを保持する 5 画像をBINARY形式読出";
			img_tf1.textColor = 0xFF0000;
			addChild(img_tf1);
			var img_tf2:TextField = createTextField(10, 160, 460, 20);
			img_tf2.text = "2 BitmapData化graphics流込    4 Loaderを直接表示          6 バイナリ空BitmapData取得";
			img_tf2.textColor = 0xFF0000;
			addChild(img_tf2);
			var img_tf3:TextField = createTextField(10, 290, 460, 20);
			img_tf3.text = "通常のものをコピーして加工 白黒化 Bulrフィルター        7 cloneによる画像の複製表示";
			img_tf3.textColor = 0xFF0000;
			addChild(img_tf3);
			
			//GOTO-INIT
			init();
		}

		// INIT
		private function init():void
		{
			//init

			//画像URLデータを登録する 100x100
			//testImage101.jpg
			photos[0] = "/main/images/testImage101.jpg";
			photos[1] = "/main/images/testImage102.jpg";
			photos[2] = "/main/images/testImage103.jpg";
			photos[3] = "/main/images/testImage104.jpg";

			//Loaderの準備/testImage101.jpgをLOADする
			// new LoaderContext(true);は、読み込んだ画像を描画(BitmapData.draw)するのに必要
			// これを指定しないとSecurityError #2122になる
			var image_name:String = photos[0];
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
			loader.load( new URLRequest(image_name), new LoaderContext(true) );
			//addChildは画像の多い場合、繰り返しその場所を使う場合はダウンするので使用しない
			//addChild(loader);
			
			//直ぐにaddChild(loader)する方法は画像が多く、何らかの処理をする場合に重くなる
			
		}
		
		// Show-Image
		private function onComplete(e:Event):void
		{
			e.target.removeEventListener(Event.COMPLETE, onComplete);
			
			//処理方法がいくつもある
			
			//注意、この場合の loader は private でなければならない、間違いやすいので使用しないほうが良い
			//var bmpObj:Bitmap = loader.content as Bitmap;
			//EventListener(e:Event)から取り出して処理したほうがよいと思う

			//1 Bitmapによるレイアウト
			//BitmapDataで処理表示したほうが便利であるし繰り返し同じ場所でも重くならない
			//loaderで表示させないようにBitmapDataを取り出す、Listener登録によりe.target.contentが利用できる
			var bmpd:BitmapData = e.target.content.bitmapData;
			var bitmap:Bitmap = new Bitmap(bmpd);
			//Bitmapは色々な操作が出来ないのでImage収容のBOXを作る
			var imageBox:Sprite = new Sprite();
			//原点中央補正/画像中心で回転できる
			imageBox.x = -e.target.content.width / 2;
			imageBox.y = -e.target.content.height / 2;
			imageBox.addChild(bitmap);
			//layer1に収納する/
			layer1.addChild(imageBox);
			//layer1を移動する
			layer1.x = 70;
			layer1.y = 100;

			//2 graphicsに流し込むレイアウト [重要]これが最良かも知れない
			//BitmapDataを取り出す
			//新たなLoaderを用意してコピーするようにする、Loaderを介すること
			var cliploader:Loader = e.currentTarget.loader;//onComplete(e:Event)を参照する
			var bd:BitmapData = new BitmapData(cliploader.width, cliploader.height, false);
			bd.draw(cliploader);
			var imageBox2:Sprite = new Sprite();
			imageBox2.graphics.beginBitmapFill(bd, null, false, false);
			imageBox2.graphics.drawRect(0, 0, cliploader.width, cliploader.height);
			imageBox2.graphics.endFill();
			//画像中心でではない
			addChild(imageBox2);
			//画像指定位置
			imageBox2.x = 20;
			imageBox2.y = 180;
			
			//2-2 BitmapDataを保持する、ここで表示はしない
			var cliploader2:Loader = new Loader();
			//cliploaderと同じ画像で、同じ大きさになる
			cliploader2 = cliploader;
			//保存用BitmapData・privateなのでどこででも利用できる
			backImage_bd = new BitmapData(cliploader2.width, cliploader.height, false);
			//容器にながす
			backImage_bd.draw(cliploader2);
			
			//2-3 loaderオブジェクトを保持する、ここで表示はしない、オブジェクト保存だから自由度が高いかも
			//保存用容器にtarget.contentを保持する
			imgArray[0] = e.target.content;
			
			//3 LoaderInfoを新たに作り取り込む、新たなLoaderを用意するのと同意義だと思う
			var loaderinfo:LoaderInfo = e.target as LoaderInfo;
			var bitmap3:Bitmap = loaderinfo.content as Bitmap;
			var bd3:BitmapData = bitmap3.bitmapData;
			var imageBox3:Sprite = new Sprite();
			imageBox3.graphics.beginBitmapFill(bd3, null, false, false);
			imageBox3.graphics.drawRoundRect(0, 0, 100, 100, 10);
			imageBox3.graphics.endFill();
			//画像中心でではない
			addChild(imageBox3);
			//画像指定位置
			imageBox3.x = 180;
			imageBox3.y = 50;
			
			//4 Loaderを直接表示する方法/そのばでCOMPLETE処理
			var cliploader4:Loader = new Loader();
			cliploader4.load(new URLRequest(photos[1]));
			cliploader4.contentLoaderInfo.addEventListener(Event.COMPLETE, function(event:Event):void
			{
				layer2.addChild(event.currentTarget.loader);
				layer2.x = 180;
				layer2.y = 180;
			});
			
			
			//GOTO MAIN-ACTION
			main_action();
			
		}
		
		// MAIN-ACTION
		private function main_action():void
		{
			//main_action as3 hear
			//tf.text = "MAIN-ACTION";
			
			//2-2で保持した BitmapData を加工表示する
			//layer3
			//キャンバスの生成
            var canvas:BitmapData = new BitmapData(100, 100);
			//保持した BitmapDataをcanvasに流し込む
            canvas.draw(backImage_bd);
            var rectAngle:Rectangle = new Rectangle(0, 0, 100, 100);
            var point:Point = new Point(0, 0);
            
            //グレースケール
            var grayScaleMatrix:Array = [
                1/3, 1/3, 1/3, 0,   0,
                1/3, 1/3, 1/3, 0,   0,
                1/3, 1/3, 1/3, 0,   0,
                0,   0,   0,   255, 0
            ];
            var grayScaleFilter:ColorMatrixFilter = new ColorMatrixFilter(grayScaleMatrix);
            canvas.applyFilter(canvas, rectAngle, point, grayScaleFilter);
			//Bitmap容器を作る
			var bitmap5:Bitmap = new Bitmap(canvas);
			var imageBox5:Sprite = new Sprite();
			imageBox5.addChild(bitmap5);
			//layer3に表示
			layer3.addChild(imageBox5);
			layer3.x = 20;
			layer3.y = 310;
			
			//6 imgArray[0]保存オブジェクトよりbitmapDataを取り出す、加工する
			var bitmap6:Bitmap = new Bitmap(imgArray[0].bitmapData);
			var blur:BlurFilter = new BlurFilter(12, 2, 12);
			//Bitmapにも直接かかるようだ
			bitmap6.filters = [blur];
			//layer4に表示
			layer4.addChild(bitmap6);
			layer4.x = 180;
			layer4.y = 310;
			//
			
			//BINARY画像
			loadImage2();
		}
		
		//BINARY画像をBINARY形式で読み出す
		private function loadImage2():void
		{
			//BINARY形式Loaderを準備、画像ではなくファイルとしてよみだす
			var myURLLoader:URLLoader = new URLLoader();
			//BINARY指定
			myURLLoader.dataFormat = URLLoaderDataFormat.BINARY;
			//load
			myURLLoader.load(new URLRequest(photos[2]));
			//Listenerをセット
			myURLLoader.addEventListener (Event.COMPLETE,onComplete2);
		}
		//BINARY onComplete
		private function onComplete2(e:Event):void
		{
			//5 BINARYdataとしてcurrentTarget.dataにあるのでそれをLoaderに取り込む、Base64DecodeのBINARYdata変換
			var myByteArray:ByteArray = e.currentTarget.data;
			var myLoader1:Loader = new Loader();
			//バイナリデータをロード Base64DecodeのBINARYdata変換
			myLoader1.loadBytes(myByteArray);
			layer5.addChild(myLoader1);
			layer5.x = 340;
			layer5.y = 50;
			
			//6 バイナリデータをコピーしてBitmapData取得
			var myByteArray2:ByteArray = e.currentTarget.data;
			var myLoader2:Loader = new Loader();
			//バイナリデータをロード Base64DecodeのBINARYdata変換
			myLoader2.loadBytes(myByteArray2);
			//このままではBitmapDataは取得できないのでcontentLoaderInfo.addEventListenerをかませる
			myLoader2.contentLoaderInfo.addEventListener(Event.COMPLETE, function(event:Event):void {
				//手間がかるがcontentLoaderInfo拠り取り出す
				var bd:BitmapData = new BitmapData(100, 100, false);
				bd.draw(event.target.content.bitmapData);
				var imageBox3:Sprite = new Sprite();
				imageBox3.graphics.beginBitmapFill(bd, null, false, false);
				imageBox3.graphics.drawRoundRect(0, 0, 100, 100, 10);
				imageBox3.graphics.endFill();
				//画像中心でではない
				layer6.addChild(imageBox3);
				//画像指定位置
				layer6.x = 340;
				layer6.y = 180;
				
			});
			
			//GOTO loadImage3 クローンを表示に進む
			loadImage3();
			
		}
		//クローンを表示
		private function loadImage3():void
		{
			var image_name:String = photos[3];
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete3);
			loader.load(new URLRequest(image_name), new LoaderContext(true));
		}	
		// Show-Image3
		private function onComplete3(e:Event):void
		{
			e.target.removeEventListener(Event.COMPLETE, onComplete3);
			
			//通常は下のようにとりだすが、こちらを使用せず、下のクローンを作るで表示する
			/*
			//BitmapDataをとりだす1
			var bd:BitmapData = new BitmapData(100, 100, false);
			//loaderをBitmapData容器にながす
			bd.draw(e.target.loader);
			var bitmap:Bitmap = new Bitmap(bd);
			*/
			
			/*
			//BitmapDataをとりだす2 どちらでも同じ
			var bd:BitmapData = e.target.content.bitmapData;
			var bitmap:Bitmap = new Bitmap(bd);
			//layer8に通常表示
			layer8.addChild(bitmap);
			*/
			
			//クローンを作るの方法があるが loaderを作りとりだせば、いくらでもできるのであまり画像では使用しないようだ
			
			//7 BitmapData.cloneによる画像の複製表示
			//始めBitmapに取り込む
			var bitmap3:Bitmap = e.target.loader.content as Bitmap;
			//クローンを作る
			var cloneImage:Bitmap = new Bitmap(bitmap3.bitmapData.clone());
			//Bitmapを作っていれば必要なときにBitmapDataは取り出せる
			
			//layer8にクローンを表示
			layer8.addChild(cloneImage);
			
			layer8.x = 340;
			layer8.y = 310;
		}
		
		//create-GradBox
		private function draw_grad_box(w:uint, h:uint, color1:uint, color2:uint):Sprite {
			var gb:Sprite = new Sprite();
			var colors:Array = [color1, color2];
			var alphas:Array = [1, 1];
			var ratios:Array = [0, 255];
			var matrix:Matrix = new Matrix();
			matrix.createGradientBox(w * 1.5, h * 1.5, 0, -w * 0.25, -h * 0.25);
			gb.graphics.beginGradientFill(GradientType.RADIAL, colors, alphas, ratios, matrix, SpreadMethod.PAD, InterpolationMethod.RGB, 0);
			gb.graphics.drawRect(0, 0, w, h);
			gb.graphics.endFill();
			//addChild(gb);
			return gb;
		}
		//create-box
		private function createSquare(x:Number, y:Number, width:Number, height:Number, color:Number, alpha:Number):Sprite
		{
			var s:Sprite = new Sprite();
			s.graphics.beginFill(color, alpha);
			s.graphics.drawRect(x, y, width, height);
			s.graphics.endFill();
			//addChild(s);
			return s;
		}
		//create-Roundbox
		private function createSquare2(x:Number, y:Number, width:Number, height:Number, color:Number, alpha:Number, round:Number):Sprite
		{
			var rs:Sprite = new Sprite();
			rs.graphics.beginFill(color, alpha);
			rs.graphics.drawRoundRect(x, y, width, height, round);
			rs.graphics.endFill();
			//addChild(rs);
			return rs;
		}
		//create-text
		private function createTextField(x:Number, y:Number, width:Number, height:Number):TextField
		{
			var result:TextField = new TextField();
			result.x = x;
			result.y = y;
			result.width = width;
			result.height = height;
			//addChild(result);
			return result;
		}

	}
}

使用画像

画像100x100

以上です。



[ この記事のURL ]


タグ:flash , ActionScript , as3 , photo

 

ブログ記事一覧



[1]