AS3 でヒストグラムを作る (1)

今週は ActionScript でヒストグラムを作っていきます。画像の色分布をグラフ表示したやつです。

ヒストグラム (吉島家)

手順:

1. グレースケール化
最初に各チャンネルの平均をとるために白黒画像にします。ColorMatrixFilter を使えば一発ですね。
2. threshold でカウント
各階調のピクセル数を調べるために threshold を使います。threshold は戻り値でマッチしたピクセル数が返ってくるので、これを利用します。
3. 描画
lineTo で描画します。

高速化の余地はありそうだけど、複雑になりそうなのでこのへんで。

次回からはヒストグラムを操作できるようにしていきます。

ソースコードは以下に(45行)。

package {
    import flash.display.*;
    import flash.filters.ColorMatrixFilter;
    import flash.geom.Point;

    [SWF(width="256", height="276")]
    public class Histogram1 extends Sprite {
        [Embed(source="yoshijima.jpg")]
        private var SampleImage:Class;

        public function Histogram1() {
            var bmd:BitmapData = Bitmap(addChild(new SampleImage())).bitmapData;
            var s:Sprite = new Sprite();
            createHistogram(bmd,s);
            addChild(s).y = bmd.height + 10;
        }

        // ヒストグラムを作成する
        private function createHistogram(bmd:BitmapData, s:Sprite):void {
            // グレースケール化
            var cmf:ColorMatrixFilter = new ColorMatrixFilter(
                [1 / 3, 1 / 3, 1 / 3, 0, 0, 
                 1 / 3, 1 / 3, 1 / 3, 0, 0, 
                 1 / 3, 1 / 3, 1 / 3, 0, 0]
            );
            var bmd2:BitmapData = bmd.clone();
            bmd2.applyFilter(bmd2, bmd2.rect, new Point(), cmf);

            // threshold でカウント
            var values:Array = [];
            for(var i:int = 0; i < 0x100; i++) {
                values[i] = bmd2.threshold(bmd2, bmd2.rect, new Point(), "==", i, 0, 0xff, false);
            }
            bmd2.dispose();

            // 描画
            var max:int = bmd.width * bmd.height / 50;
            s.graphics.lineStyle(1);
            for(i = 0; i < 0x100; i++) {
                s.graphics.moveTo(i, 100);
                s.graphics.lineTo(i, Math.max(0, 100 - values[i] / max * 100));
            }
        }
    }
}