share 画像のアウトラインを一筆書き xlune forked:3favorite:11lines : 196license : All rights reserved modified : 2009-04-01 13:39:58 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; } } Code Fullscreen Preview Fullscreen Bitmap line outline ms_space hacker_fimwf.. taxponation abakane 024t910 paq nabe OneInchPunch.. HaraMakoto TUNCAYS: Bitmapoutline ibu4gin: Bitmap LoaderContext Boolean every Point forEach Error graphics Point.distance Event.COMPLETE alpha removeEventListener URLRequest uint height width addChild trace addEventListener push Event.ENTER_FRAME sort new page view favorite forked pv155 forked from: 画像のアウトラインを一筆書き hacker_m7kirhoe forked:0 fav:0 lines:196 tag: pv196 forked from: 画像のアウトラインを一筆書き sr_forest forked:0 fav:2 lines:196 tag: pv1226 forked from: 画像のアウトラインを一筆書きじゃない xlune forked:1 fav:3 lines:188 tag: Bitmap line outline 一筆書きじゃない 重い