畳み込みフィルター

(サンプル一覧を表示する)

FlashDevelop を使って、画像に畳み込みフィルターを設定してみました。
畳み込みフィルターは、なんとも表現がしにくいフィルターで、処理対象のピクセルと、
その周りのピクセルとの色を指定された重み付けの比率に合わせて加算して、
最終的に任意の値で割って色を作るというフィルターです。

使い方によってはエンボス効果やぼかしのような効果を出せるみたいですが、
周りの何ピクセルをどのような重み付けで足し合わせたら目的の効果が得られるのか分かりにくく、
使いどころが難しいフィルターだと思います。
他のフィルターは処理内容がある程度固定化されているのでいじりにくいですが、
畳み込みフィルターをうまく使えば独自の働きをするフィルターを作ることができそうです。
処理対象の周辺ピクセルの数は自由に決めることができます。

左が処理前の画像、右がFlashで処理済みの画像です。

Flash の実行画面
畳み込みフィルター

Flashプレーヤーが入っていないか、JavaScriptが無効になっているようです。

Get Adobe Flash player

元の画像 畳み込みフィルター

ソースコード

package 
{
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.display.Bitmap;
	
	import flash.filters.BitmapFilter;
	import flash.filters.BitmapFilterQuality;
	import flash.filters.ConvolutionFilter;
	
	/**
	 * 畳み込みフィルターのサンプル
	 * @author Hikipuro
	 */
	public class Main extends Sprite 
	{
		/**
		 * 埋め込み画像
		 */
		[Embed(source='../image/test001.png')]
		private var image1:Class;
		
		/**
		 * コンストラクタ
		 */
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		/**
		 * 初期化メソッド
		 * @param	e
		 */
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point

			var bitmap1:Bitmap = Bitmap(new image1);
			RegisterBitmap(bitmap1, 10, 10, 2.0);
			applyBrightness(bitmap1);

			var bitmap2:Bitmap = Bitmap(new image1);
			RegisterBitmap(bitmap2, 100, 10, 2.0);
			applySharpness(bitmap2);

			var bitmap3:Bitmap = Bitmap(new image1);
			RegisterBitmap(bitmap3, 190, 10, 2.0);
			applyOutline(bitmap3);
		}
		
		/**
		 * ステージにビットマップを登録して表示する
		 * @param	bitmap	表示するビットマップ
		 * @param	x		X 座標
		 * @param	y		Y 座標
		 * @param	scale	拡大率
		 */
		private function RegisterBitmap(bitmap:Bitmap, x:int, y:int, scale:Number):void
		{
			bitmap.smoothing = true;
			bitmap.cacheAsBitmap = true;
			bitmap.x = x;
			bitmap.y = y;
			bitmap.scaleX = scale;
			bitmap.scaleY = scale;
			addChild(bitmap);
		}

		/**
		 * 輝度強調?
		 * @param	bitmap	適用先ビットマップ
		 */
        private function applyBrightness(bitmap:Bitmap):void {
            var child:DisplayObject = DisplayObject(bitmap);
            var matrix:Array = [5, 5, 5,
                                5, 0, 5,
                                5, 5, 5];
            applyFilter(child, matrix);
        }

		/**
		 * 画像をシャープにする?
		 * @param	bitmap	適用先ビットマップ
		 */
        private function applySharpness(bitmap:Bitmap):void {
            var child:DisplayObject = DisplayObject(bitmap);
            var matrix:Array = [0, -1, 0,
                               -1, 20, -1,
                                0, -1, 0];
            applyFilter(child, matrix);
        }

		/**
		 * アウトライン強調?
		 * @param	bitmap	適用先ビットマップ
		 */
        private function applyOutline(bitmap:Bitmap):void {
            var child:DisplayObject = DisplayObject(bitmap);
            var matrix:Array = [-30, 30, 0,
                                -30, 30, 0,
                                -30, 30, 0];
            applyFilter(child, matrix);
        }

		/**
		 * 畳み込みフィルターを作成して、指定されたオブジェクトに適用する
		 * @param	child	適用先ディスプレイオブジェクト
		 * @param	matrix	重み付け情報が入った行列
		 */
        private function applyFilter(child:DisplayObject, matrix:Array):void {
            var matrixX:Number = 3;
            var matrixY:Number = 3;
            var divisor:Number = 9;
            var filter:BitmapFilter = new ConvolutionFilter(matrixX, matrixY, matrix, divisor);
            var filters:Array = new Array();
            filters.push(filter);
            child.filters = filters;
        }

		
	}
	
}		

プログラムはコンストラクタから開始されますが、コンストラクタ内に直接処理を入れると、表示したはずの画像が表示されない等の問題が出ることがあるようなので、いったんコンストラクタ内で init() イベントを設定することで開始時間をずらして、init() 内からコードを開始するような書き方になっています。これは、FlashDevelop で ActionScript3 のプロジェクトを作成すると最初からこういう構造になっています。

21 行目に、 image1 という変数が宣言されていますが、上の行に Embed 属性が付いていて、埋め込み画像を指すクラスをあらわしてます。埋め込み画像とは、SWF ファイルの中に入れてしまう画像のことです。Flash 実行時に URL から画像をダウンロードする必要がなくなるので、実験には便利です。埋め込み画像は Bitmap クラスに実体化して使用します。

42 〜 52行目が処理の中心になります。 畳み込みフィルターを作って、画像を表示した後、フィルターを適用しています。 フィルターをいったん配列に入れていますが、これは、フィルターを複数かけるための構造で、 畳み込み以外のフィルターを重ねてかねる時に使用します。 今回は 1 つだけフィルターをかけているので、配列に入れるのはおかしい気もしますが、 bitmap.filters のインターフェイスが配列型を要求するので、filters プロパティに設定するためだけに フィルターを配列に入れています。

参照

外部リンク