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

BitmapData の練習(なんとなくアウトラインっぽいもの取得)

Get Adobe Flash player
by mchang 23 Nov 2010
/**
 * Copyright mchang ( http://wonderfl.net/user/mchang )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/wODb
 */

/**
 * なんとなくアウトラインを取得するサンプル 
 *
 */
package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.events.Event;
    import flash.system.LoaderContext;
    import flash.net.URLRequest;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    
    [SWF(width="465", height="465", backgroundColor="#ffffff", frameRate="60")]

    public class OutlineSample1 extends Sprite
    {
        private var _loader:Loader;

        public function OutlineSample1()
        {
            addEventListener(Event.ADDED_TO_STAGE, initialize);
        }

        private function initialize(e:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, initialize);
            
            _loader = new Loader();
            _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
            _loader.load(new URLRequest('http://wonderfl.minaco.net/Outline.png'), new LoaderContext(true));
        }

        private function completeHandler(e:Event):void
        {
            var c:LoaderInfo = _loader.contentLoaderInfo;
            
            var tmpBitmapData:BitmapData = new BitmapData(c.content.width, c.content.height, true, 0x000000);
            tmpBitmapData.draw(c.content);
            
            // 不透明の黒(0xff000000) ではない領域を、透明(0x00000000)にします
            tmpBitmapData.threshold(tmpBitmapData, tmpBitmapData.rect, new Point(0, 0), '!=', 0xff000000, 0x00000000, 0xffffffff, true);
        
            // 不透明の黒(0xff000000) に一致する矩形領域を判別し、 画像が描画されている領域を取得します
            var bounds:Rectangle = tmpBitmapData.getColorBoundsRect(0xffffffff, 0xff000000, true);

            // 画像が描画されている領域を取得します
            var imageBitmapData:BitmapData = new BitmapData((bounds.right - bounds.x), (bounds.bottom - bounds.y), true, 0x000000);
            imageBitmapData.copyPixels(tmpBitmapData, bounds, new Point(0,0));
            
            var bitmap:Bitmap = new Bitmap(imageBitmapData);
            addChild(bitmap);
            
            // 破棄します
            tmpBitmapData.dispose();
            tmpBitmapData = null;

            // アウトラインを探します
            var points:Array = search(imageBitmapData);
        }

        protected function search(bd:BitmapData):Array
        {
            bd.lock();

            // アウトラインを取得するための開始座標を取得します
            var start:Point = getStartPoint(bd);
            
            if (start == null) {
                trace('おかしい');
                return null;
            }
            
            // 開始座標を青に設定します
            var startColor:uint = 0xff0000ff;
            bd.setPixel32(start.x, start.y, startColor);
            
            var current:Point = start.clone();
            
            var offsets:Array = [
                new Point(1, 0),
                new Point(1, 1),
                new Point(0, 1),
                new Point(-1, 1),
                new Point(-1, 0),
                new Point(-1, -1),
                new Point(0, -1),
                new Point(1, -1)
            ];

            // 今の進行方向です
            var direction:int = 0;
            var points:Array = [current];
            
            for (;;) {

                var found:Boolean = false;
                
                // 今の進行方向から時計回りに8方向全て順に調べます
                for (var o:int = 0; o < 8; o++) {
                    var offset:Point = offsets[(direction + o) % 8];
                    var offset2:Point = offsets[(direction + o + 6) % 8];

                    var c:uint = bd.getPixel32(current.x + offset.x, current.y + offset.y);
                    
                    // 一周し開始地点に戻ってきた場合は
                    if (c == startColor) {
                        // 終了します
                        break;
                    }

                    
                    // この方向が黒 && この方向-90度の所が白い場合だけ
                    if (c == 0xff000000 && bd.getPixel32(current.x + offset2.x, current.y + offset2.y) != 0xff000000) {
                        // そっちに進む
                        current.x += offset.x;
                        current.y += offset.y;
                        
                        // 進行方向がかわったときは
                        if (direction != o) {
                            // 座標を取得します
                            points.push(current.clone());
                        }
                        
                        // 方向を覚えておきます
                        direction = o;
                        
                        // もし右下(1, 1)の進行方向のときは
                        if (o == 1) {
                            // 右からチェックします
                            direction = 0;
                        }
                        
                        // 進行方向が見つかった
                        found = true;
                        
                        // 進行方向が見つかったのでぬける
                        break;
                    }
                }
                
                if (!found) {
                    break;
                }
                
                // アウトラインを緑にします
                bd.setPixel32(current.x, current.y, 0xff00ff00);
            }
            
            bd.unlock();
            
            return points;
        }

        protected function getStartPoint(bd:BitmapData):Point
        {
            var width:int = bd.width;
            var start:Point;
            for (var x:int = 0; x < width; x++) {
                var c:uint = bd.getPixel32(x, 0);
                if (c == 0xff000000) {
                    start = new Point(x, 0);
                    break;
                }
            }
            
            return start;
        }

    }
}