forked from: 外部SWFアニメから画像の輪郭抽出してPixel表示

by hacker_9p8x8mco forked from 外部SWFアニメから画像の輪郭抽出してPixel表示 feat.chibitami (diff: 1)
♥0 | Line 190 | Modified 2009-10-13 12:05:36 | MIT License
play

ActionScript3 source code

/**
 * Copyright hacker_9p8x8mco ( http://wonderfl.net/user/hacker_9p8x8mco )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/jU4B
 */

// forked from yooKo's 外部SWFアニメから画像の輪郭抽出してPixel表示
/**
 * 1.外部SWFから輪郭を取得する。
 * 2.Papervision3DのPixcel3Dで描画 
 * 
 * @author yooKo@serialField
 * @version 0.1
 * Let's Click!
 * Click毎に3段階表示が切り替わる
 * 
 * ↓の画像をお借りしました
 * http://zeloma.com/article/92211940.html
 * 
 * なんか動きしょぼいなー・・・
 * 
 **/
package {
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.StageQuality;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.text.TextFieldAutoSize;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.events.MouseEvent;
	import flash.filters.BlurFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Point;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	//import flash.system.SecurityDomain;
	import flash.system.Security;
	import flash.utils.Timer;
	import flash.utils.getTimer;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import org.papervision3d.core.effects.BitmapLayerEffect;
	import org.papervision3d.core.effects.BitmapColorEffect;
	import org.papervision3d.core.effects.utils.BitmapClearMode;
	import org.papervision3d.core.geom.Pixels;
	import org.papervision3d.core.geom.renderables.Pixel3D;
	import org.papervision3d.view.BasicView;
	import org.papervision3d.view.layer.BitmapEffectLayer;
	
	import net.hires.debug.Stats;
	
	[SWF(width="465", height="465", backgroundColor="0x000000", frameRate="40")]

	public class Pixcel3DAnime extends BasicView {
		private var _loader:Loader;
		private var _pixels:Pixels;
		private var _rotateX:Number = 0;
		private var _rotateY:Number = 0;
		private var _currentNum:int = 0;
		private var _bmd:BitmapData;
		private var _pre:Number;
		private var _a:Number;
		private var _y:Number;
		private var _x:Number;
		private var _c:uint;
		
		private const CAMERA_DISTANCE:int = -150;
		private const IMAGE_URL:String = "http://selflash.jp/wonderfl/miku.swf";
		// ソース画像のどの部分を解析するか
		private const TRIMMING_WIDTH:int = 80;
		private const TRIMMING_HEIGHT:int = 50;		
		private const SIZE_WIDHT:int = 220;
		private const SIZE_HEIGHT:int = 163;
		// 中央に持ってくる為に使う
	    private const W:Number = TRIMMING_WIDTH + SIZE_WIDHT * .5;
	    private const H:Number = TRIMMING_HEIGHT + SIZE_HEIGHT * .5;
		
		//========================================================================
		// コンストラクタ	
		//========================================================================
		public function Pixcel3DAnime() {	
			super(0, 0, true, true);			
			StageQuality.LOW;
			/**
			 *crossdomainにやらSecurity.allowDomain()やらまだまだ理解が浅くてわかんなかった、、
			 * 読み込む事はできるがdraw()ができなくて悩んだ。
			 * 結局呼び出す子swfの1フレーム目にSecurity.allowDomain("*")と記述した事でおk。
			 * ※Security.allowDomain("http://www.selflash.jp/")ではダメだった・・この辺はなんでか分かんない
			 *  http://cocoasaurus.com/blog/2009/09/as3allowdomain-1.html
			 * ↑のリンク先の情報によると読み込む方と読み込まれる方の両方に Security.allowDomain() を記述しないといけないらしいが
			 * ↓はコメントアウトしても draw() 出来てる。これもなぜだかわかんない、、、
			 */ 
			//Security.allowDomain("*");
			if (!stage)
                addEventListener(Event.ADDED_TO_STAGE, init);
            else
                init();
        }
		//========================================================================
		// 画像の読み込み	
		//========================================================================
        private function init(e:Event = null):void {	
            removeEventListener(Event.ADDED_TO_STAGE, init);
			
			_loader = new Loader(); 
			_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteHandler);
			_loader.load(new URLRequest(IMAGE_URL), new LoaderContext(true));
		}		
		//========================================================================
		// ロード完了後の処理
		//========================================================================
		private function onCompleteHandler(e:Event):void {
			e.target.removeEventListener(Event.COMPLETE, init);
			//こいつから色、座標を解析
			_bmd = new BitmapData(_loader.width, _loader.height, true, 0xFFFFFF);
			//左下に表示するためのやつね
			var bmp:Bitmap = new Bitmap(_bmd, "auto", true);
			bmp.scaleX = .4;
			bmp.scaleY = .4;
			bmp.y = stage.stageHeight - bmp.height;			
			addChild(bmp);
			
			camera.z = CAMERA_DISTANCE;	
			
			var _layer:BitmapEffectLayer = new BitmapEffectLayer(viewport, stage.stageWidth, stage.stageHeight, true, 0, BitmapClearMode.CLEAR_PRE, false);
			viewport.containerSprite.addLayer(_layer);
			_layer.addEffect(new BitmapColorEffect(1.2, 1.2, 1.2, .7));
			//_layer.addEffect(new BitmapLayerEffect(new BlurFilter(16, 16, 1), false));
			_pixels = new Pixels(_layer);
			scene.addChild(_pixels);	
			
			addEventListener(Event.ENTER_FRAME, upDate);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, onDownHandler);		
			
			startRendering();	
			
			addChild(new Stats());
		}	
		//========================================================================
		// 表示の切り替え
		// 切り替えの仕組みがしょぼすぎる・・・なんか挙動が変、、スマートな方法あったら教えてください、、
		//========================================================================
		private function onDownHandler(e:MouseEvent = null):void {
			_currentNum++;
			if (_currentNum > 4) {
				_currentNum = 0;
			}
			//_currentNum = (_currentNum < 4) ?  _currentNum += 1 : 0;
		}		
		//========================================================================
		// 常に行う処理
		//========================================================================
		private function upDate(e:Event):void {
			_rotateX += (- viewport.containerSprite.mouseX - _rotateX) * 0.1;
			_rotateY += (- viewport.containerSprite.mouseY - 170 - _rotateY) * 0.1;
			_pixels.rotationY = _rotateX;
			_pixels.rotationX = _rotateY;
			//毎回drawさせるよん
			_bmd.draw(_loader);
			//毎回消すよん
			_pixels.removeAllpixels();	
			//表示の切り替え
			switch (_currentNum) {
                case 0: 
				    createBody(0, 2);
                break;
				case 1:
				    //createBody(-16, 2);
				    //createFrame(-20, 3, 0xFFFF0066);
				    //createFrame(-16, 3, 0xFFFF0066);
				    createBody(-8, 4, 0xFFFF0066);
				    createFrame(-6, 4, 0xFFFF0066);
				    createFrame(-4, 4, 0xFFFF0066);
				    createFrame(-2, 4, 0xFFFF0066);
				    //createFrame(0, 4, 0xFFFF0066);
				    //createFrame(1, 4, 0xFFFF0066);
				    //createFrame(2, 4, 0xFFFF0066);
				    //createFrame(3, 4, 0xFFFF0066);
				    createFrame(0, 4, 0xFFFF0066);
				    //createFrame(5, 4, 0xFFFF0066);
				    createFrame(2, 4, 0xFFFF0066);
				    //createFrame(7, 4, 0xFFFF0066);
				    createFrame(4, 4, 0xFFFF0066);
				    createFrame(6, 4, 0xFFFF0066);
				    createBody(8, 4, 0xFFFF0066);
				    //createFrame(4, 3, 0xFFFF0066);
				    //createFrame(8, 3, 0xFFFF0066);
				    //createBody(16, 2);
				break;
				case 2:
				    createBody(0, 2, 0xFFCCFF00);
				break;
				case 3:
				    createFrame(0, 2, 0xFFCCFF99);
				break;
				//default :
				    //createBody(0, 2);
            };
		}	
		//========================================================================
		// 中身を作成するメソッド
		// 呼び出されたら白以外全部解析する
		// ※ 引数に色の指定がなければ抽出した色を使う
		//========================================================================
		private function createBody(depth:Number = 0, distance:Number = 2, color:Number = NaN):void {
			for ( _y = TRIMMING_HEIGHT; _y < TRIMMING_HEIGHT + SIZE_HEIGHT; _y += distance ) {
				for ( _x = TRIMMING_WIDTH; _x < TRIMMING_WIDTH + SIZE_WIDHT; _x += distance ) {
					_c = _bmd.getPixel( _x, _y );
					if (_c != 0xFFFFFF) {
						_c = (color)?color:rgb2argb(_c, 1);
						_pixels.addPixel3D(new Pixel3D(_c, _x - W, _y - H, depth));
					}
				}
			}
		}		
		//========================================================================
		// 枠組みを作成するメソッド
		// 呼び出されたらキャラクターの外枠だけ解析する
		// ※ 引数に色の指定がなければ抽出した色を使う
		//========================================================================
		private function createFrame(depth:Number = -4, distance:Number = 2, color:Number = NaN):void {			
			for ( _y = TRIMMING_HEIGHT; _y < TRIMMING_HEIGHT + SIZE_HEIGHT; _y += distance ) {
				for ( _x = TRIMMING_WIDTH; _x < TRIMMING_WIDTH + SIZE_WIDHT; _x += distance ) {
					_c = _bmd.getPixel( _x, _y );
					if (_c != 0xFFFFFF) {
						_a = (_y == 0)?0:_x - W - _pre;
						if (_a > distance || _a < - distance) {
							_c = (color)?color:rgb2argb(_c, 1);
							_pixels.addPixel3D(new Pixel3D(_c, _x - W, _y - H, depth));
						}
						_pre = _x - W;
					}
				}
			}
			
			for ( _x = TRIMMING_WIDTH; _x < TRIMMING_WIDTH + SIZE_WIDHT; _x += distance ) {
				for ( _y = TRIMMING_HEIGHT; _y < TRIMMING_HEIGHT + SIZE_HEIGHT; _y += distance ) {
					_c = _bmd.getPixel( _x, _y );
					if (_c != 0xFFFFFF) {
						_a = (_x == 0)?0:_y - H - _pre;
						if(_a > distance || _a < - distance) {
							_c = (color)?color:rgb2argb(_c, 1);
							_pixels.addPixel3D(new Pixel3D(_c, _x - W, _y - H, depth));
						}
						_pre = _y - H;
					}
				}
			}
			
			for ( _y = TRIMMING_HEIGHT + SIZE_HEIGHT; _y > TRIMMING_HEIGHT; _y -= distance ) {
				for ( _x = TRIMMING_WIDTH + SIZE_WIDHT; _x > TRIMMING_WIDTH; _x -= distance ) {
					_c = _bmd.getPixel( _x, _y );
					if (_c != 0xFFFFFF) {
						_a = (_y == TRIMMING_HEIGHT + SIZE_HEIGHT)?0:_x - W - _pre;
						if(_a > distance || _a < - distance) {
							_c = (color)?color:rgb2argb(_c, 1);
							_pixels.addPixel3D(new Pixel3D(_c, _x - W, _y - H, depth));
						}
						_pre = _x - W;
					}
				}
			}
			
			for ( _x = TRIMMING_WIDTH + SIZE_WIDHT; _x > TRIMMING_WIDTH; _x -= distance ) {
				for ( _y = TRIMMING_HEIGHT + SIZE_HEIGHT; _y > TRIMMING_HEIGHT; _y -= distance ) {
					_c = _bmd.getPixel( _x, _y );
					if (_c != 0xFFFFFF) {
						_a = (_x == TRIMMING_WIDTH + SIZE_WIDHT)?0:_y - H - _pre;
						if(_a > distance || _a < - distance) {
							_c = (color)?color:rgb2argb(_c, 1);
							_pixels.addPixel3D(new Pixel3D(_c, _x - W, _y - H, depth));
						}
						_pre = _y - H;
					}
				}
			}
		}		
		//========================================================================
		// RGBをARGBに変換する
		//========================================================================
		private function rgb2argb(rgb:uint, alpha:Number):uint {
            return ((alpha * 0xff) << 24) + rgb;
        }
	}
}