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 mchang 23 Nov 2010
    Embed
/**
 * Copyright mchang ( http://wonderfl.net/user/mchang )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/xzNN
 */

/**
 * このサイトのを AS でやってみました
 * そのまま AS で書いただけ。
 * 「パターン認識の前処理に必要な二値画像の細線化」
 * http://codezine.jp/article/detail/98
 */
package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Graphics;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.text.TextField;
    import flash.text.TextFormat;

    [SWF(width="465", height="465", backgroundColor="#ffffff", frameRate="60")]
    
    public class ThinningSample extends Sprite
    {
        private static const UPPER_LEFT:int = 2;
        private static const LOWER_RIGHT:int = 6;
        private static const UPPER_RIGHT:int = 0;
        private static const LOWER_LEFT:int = 4;

        private var _bd:BitmapData;
        private var _width:int;
        private var _height:int;        
        private var _newPixels:Array;
        private var _oldPixels:Array;
        private var _change:Boolean;

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

        private function initialize(e:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, initialize);

            // テキストフィールドを作成します
            var field:TextField = new TextField();
            field.defaultTextFormat = new TextFormat("_ゴシック", 18);
            field.text = "て";

            // テキストを BitmapData にします
            var textBitmapData:BitmapData = new BitmapData(465, 465, true, 0x000000);
            var matrix:Matrix = new Matrix();
            matrix.scale(10, 10);
            textBitmapData.draw(field, matrix);
            addChild(new Bitmap(textBitmapData));
            
            // 不透明の黒(0xff000000) ではない領域を、透明(0x00000000)にします
            textBitmapData.threshold(textBitmapData, textBitmapData.rect, new Point(0, 0), '!=', 0xff000000, 0x00000000, 0xffffffff, true);

            // BitmapData をコピーします
            _bd = new BitmapData(textBitmapData.width, textBitmapData.height, true, 0x000000);
            _bd.copyPixels(textBitmapData, textBitmapData.rect, new Point(0,0));
            
            var bitmap:Bitmap = new Bitmap(_bd);
            addChild(bitmap);

            _width = _bd.width;
            _height = _bd.height;

            paint();
        }

        private function paint():void
        {
            _bd.lock();
            
            _newPixels = [];
            _oldPixels = [];
            
            // 1 が黒で、 0 が白
            
            var y:int, x:int;

            for (x = 0; x < _width + 2; x++) {
                _newPixels[x] = [];
                _oldPixels[x] = [];
                for (y = 0; y < _height + 2; y++) {
                    _newPixels[x][y] = 0;
                    _oldPixels[x][y] = 0;
                }
            }
            
            for (x = 1; x < _width + 1; x++) {
                for (y = 1; y < _height + 1; y++) {
                    if (_bd.getPixel32(x - 1, y - 1) == 0xff000000) {
                        _newPixels[x][y] = 1;
                        _oldPixels[x][y] = 1;
                    }
                }
            }

            var width:int = _width + 2;
            var height:int = _height + 2;

            for (;;) {
                
                _change = false;

                // 左上から細線化
                drawAndCopy();
                for (y = 1; y < height - 1; y++) {
                    for (x = 1; x < width - 1; x++) {
                        if (_oldPixels[x][y] == 1) {
                            thinImage(x, y, UPPER_LEFT);
                        }
                    }
                }

                // 右下から細線化
                drawAndCopy();
                for (y = height - 2; 1 <= y; y--) {
                    for (x = width - 2; 1 <= x; x--) {
                        if (_oldPixels[x][y] == 1) {
                            thinImage(x, y, LOWER_RIGHT);
                        }
                    }
                }


                // 右上から細線化
                drawAndCopy();
                for (y = 1; y < height - 1; y++) {
                    for (x = width - 2; 1 <= x; x--) {
                        if (_oldPixels[x][y] == 1) {
                            thinImage(x, y, UPPER_RIGHT);
                        }
                    }
                }

                // 左上から細線化
                drawAndCopy();
                for (y = height - 2; 1 <= y; y--) {
                    for (x = 1; x < width - 1; x++) {
                        if (_oldPixels[x][y] == 1) {
                            thinImage(x, y, LOWER_LEFT);
                        }
                    }
                }

                if (!_change) {
                    break;
                }
            }
            _bd.unlock();
        }

        /**
         * 描画とコピーします
         */
        private function drawAndCopy():void
        {
            var x:int, y:int;
            for(y = 0; y < _height + 2; y++) {
                for(x = 0; x < _width + 2; x++){
                    if (_newPixels[x][y] == 1) {
                        _bd.setPixel32(x, y, 0xffff0000);
                    } else {
                        
                        // 透明
                        _bd.setPixel32(x, y, 0x00000000);

                        // 次の細線化のためのコピー
                        _oldPixels[x][y] = _newPixels[x][y];
                    }      
                }
            }
        }

        /**
         * 細線化を実行します
         */
        private function thinImage(x:int, y:int, start:int):void
        {
            var p:Array = [];
            var product:int, sum:int;

            p[0] = _oldPixels[x - 1][y - 1];
            p[1] = _oldPixels[x - 1][y];
            p[2] = _oldPixels[x - 1][y + 1];
            p[3] = _oldPixels[x][y + 1];
            p[4] = _oldPixels[x + 1][y + 1];
            p[5] = _oldPixels[x + 1][y];
            p[6] = _oldPixels[x + 1][y - 1];
            p[7] = _oldPixels[x][y - 1];

            for (var i:int = start; i < start + 3; i++) {
                product = p[i % 8] * p[(i + 1) % 8] * p[(i + 2) % 8];
                sum = p[(i + 4) % 8] + p[(i + 5) % 8] + p[(i + 6) % 8];
                
                if (product == 1 && sum == 0) {
                    _newPixels[x][y] = 0;
                    _change = true;
                    break;
                }
            }
        }


    }
}