In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

画像のアウトラインを一筆書き

Get Adobe Flash player
by xlune 01 Apr 2009
package {
	import __AS3__.vec.Vector;
	import flash.display.BitmapData;
	import flash.display.CapsStyle;
	import flash.display.Graphics;
	import flash.display.JointStyle;
	import flash.display.LineScaleMode;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	
	[SWF(width=465, height=465, frameRate=15, backgroundColor=0xFFFFFF)]
	public class main extends Sprite
	{
		//画面幅
		private var _width:uint = 465;
		//画面高さ
		private var _height:uint = 465;
		//精度
		private var _prec:uint = 1;
		//描画スピード
		private var _speed:uint = 3;
		//閾値
		private var _threshold:uint = 0xD0;
		//ガイド画像
		private var _imgUrl:String = 'http://farm4.static.flickr.com/3616/3403716568_61e499c7f5.jpg';
		//開始位置
		private var _startPoint:Point = new Point(0, 0);
		//終了位置
		private var _endPoint:Point = new Point(_width, _height);
		
		private var _img:Loader;
		private var _guide:BitmapData;
		private var _canvas:Sprite;
		private var _gp:Graphics;
		private var _pointStatus:Vector.<PointStatus>;
		private var _basePoint:Point;
		
		/**
		 * コンストラクタ
		 */
		public function main()
		{
			var request:URLRequest = new URLRequest(_imgUrl);
			var context:LoaderContext = new LoaderContext(true);
			_img = new Loader();
			_img.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
			_guide = new BitmapData(_width, _height, false, 0x00FFFFFF);
			_canvas = new Sprite();
			try {
				_img.load(request, context);
			} catch (error:Error) {
				trace("image load failed.");
			}
		}
		
		/**
		 * Event Complete Handler
		 */
		private function completeHandler(event:Event):void
		{
			_img.x = _width / 2 - _img.width / 2;
			_img.y = _height / 2 - _img.height / 2;
			_img.alpha = 0.1;
			
			var gMatrix:Matrix = new Matrix();
			gMatrix.tx = _img.x;
			gMatrix.ty = _img.y;
			
			_guide.draw(_img, gMatrix);
			_pointStatus = new Vector.<PointStatus>();
			makePoints();
			
			addChild(_img);
			addChild(_canvas);
			_gp = _canvas.graphics;
			_gp.lineStyle(1, 0xFF0000, 1, true, LineScaleMode.NONE, CapsStyle.ROUND, JointStyle.MITER, 2);
			_basePoint = new Point(_startPoint.x, _startPoint.y);
			_gp.moveTo(_basePoint.x, _basePoint.y);
			this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
		}
		
		/**
		 * Event EnterFrame Handler
		 */
		private function enterFrameHandler(event:Event):void
		{
			if(isAllSelected())
			{
				_basePoint = new Point(_endPoint.x, _endPoint.y);
				_gp.lineTo(_basePoint.x, _basePoint.y);
				this.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
			}
			else
			{
				for(var i:uint=0; i<_speed; i++)
				{
					_basePoint = getNearPoint(_basePoint);
					if(_basePoint) _gp.lineTo(_basePoint.x, _basePoint.y);
				}
			}
		}
		
		/**
		 * 近いポイント取得
		 */
		private function getNearPoint(base:Point):Point
		{
			var minNum:Number = 0, selectItem:PointStatus, rePoint:Point;
			_pointStatus.forEach(function(item:PointStatus, index:uint, vector:Vector.<PointStatus>):void
			{
				if(!item.isSelected){
					var n:Number = Point.distance(base, new Point(item.x, item.y));
					if(!selectItem || n < minNum){
						minNum = n;
						selectItem = item;
					}
				}
			});
			if(selectItem)
			{
				selectItem.isSelected = true;
				rePoint = new Point(selectItem.x, selectItem.y);
				return rePoint;
			}
			return null;
		}
		
		/**
		 * 全通過チェック
		 */
		private function isAllSelected():Boolean
		{
			var flg:Boolean = true;
			_pointStatus.every(function(item:PointStatus, index:uint, vector:Vector.<PointStatus>):Boolean
			{
				if(!item.isSelected)
				{
					flg = false;
					return false;
				}
				return true;
			}, this);
			return flg;
		}
		
		/**
		 * 境界点生成
		 */
		private function makePoints():void
		{
			for(var j:uint=0,jMax:uint=_height; j<jMax; j+=_prec){
				for(var i:uint=0,iMax:uint=_width; i<iMax; i+=_prec){
					if(isUniquePoint(i, j)){
						_pointStatus.push(new PointStatus(i,j));
					}
				}
			}
		}
		
		/**
		 * 境界点を抽出
		 */
		private function isUniquePoint(posX:uint, posY:uint):Boolean
		{
			if(isFillPoint(posX, posY))
			{
				if(!isFillPoint(posX, posY-_prec)
					|| !isFillPoint(posX+_prec, posY)
					|| !isFillPoint(posX, posY+_prec)
					|| !isFillPoint(posX-_prec, posY))
				{
					return true;
				}
			}
			return false;
		}
		
		/**
		 * 2値化
		 */
		private function isFillPoint(posX:int, posY:int):Boolean
		{
			if(posX < 0 || posX > _width) return false;
			if(posY < 0 || posY > _height) return false;
			var color:uint = _guide.getPixel(posX, posY);
			color = (((color >> 16) & 0xff) + ((color >> 8) & 0xff) + (color & 0xff)) / 3;
			if(color < _threshold) return true;
			return false;
		}
	}
}

class PointStatus
{
	private var _x:uint;
	private var _y:uint;
	private var _group:uint = 0;
	private var _isSelected:Boolean = false;
	
	public function PointStatus(numX:uint, numY:uint, numGroup:uint=0)
	{
		x = numX;
		y = numY;
		group = numGroup;
	}
	
	public function set x(val:uint):void
	{
		_x = val;
	}

	public function get x():uint
	{
		return _x;
	}
	public function set y(val:uint):void
	{
		_y = val;
	}

	public function get y():uint
	{
		return _y;
	}

	public function set group(val:uint):void
	{
		_group = val;
	}

	public function get group():uint
	{
		return _group;
	}
	public function set isSelected(val:Boolean):void
	{
		_isSelected = val;
	}

	public function get isSelected():Boolean
	{
		return _isSelected;
	}
}