アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

AS3のBitmapFilterを片っぱしから試してみる

こんにちは。松田です。
今年も早いものでいつの間にかエイプリルフールをむかえてしまったようですが、なんのネタも用意して無かったのでいたってふつうのブログです。
今回はActionScriptで画像処理をするには欠かせない、BitmapFilter類を試してみます。

今回はflash.filtersから以下のフィルターを試しています。


BevelFilter
BlurFilter
GlowFilter
DropShadowFilter
ColorMatrixFilter
ConvolutionFilter
DisplacementMapFilter


片っ端からとかいいながら全部のフィルターは試してないです。ごめなさい。
ちょっとだけ嘘つきました。
それぞれどんな効果があるのか、Adobeの解説ページを読むよりも実際に見てみた方が分かりやすいと思うので、実際に実装したswfを置いています。
ボタンをいろいろ押しまくって確認してみてください。



動かしてみるとそれぞれのフィルターの使い道が何となく分かるかと思います。
が、ColorMatrixFilter, ConvolutionFilter, DisplacementMapFilterあたりは使用方法が幅広く、使い方次第でいろんなことが出来てしまうフィルターです。
ですので、今回はその中から使い道を一つだけ選んで使用してます。

ソースコードは上のフラッシュ内で右クリックして「ソースの表示」を押してください。
一応下にも載せておきますが上記方法のほうが見やすいと思います。
こんなに簡単なコードでこれだけ多彩な画像処理が行えてしまうのもASの魅力ですね。



<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="330" height="300" creationComplete="init()" viewSourceURL="srcview/index.html">
  <mx:Canvas left="0" top="0" bottom="0" right="0" backgroundColor="gray">
	  <mx:Image id="image" source="@Embed(source='assets/image.png')"  x="10" y="10" />
	  <mx:Button x="10" y="146" label="もとにもどす" click="revertImage()"/>
	  <mx:Button x="10" y="176" label="Bevel" click="applyBevelFilter()"/>
	  <mx:Button x="76" y="176" label="Blur" click="applyBlurFilter()"/>
	  <mx:Button x="131" y="176" label="Glow" click="applyGlowFilter()"/>
	  <mx:Button x="192" y="176" label="DropShadow" click="applyDropShadowFilter()"/>
	  <mx:Button x="10" y="206" label="ColorMatrix (GrayScale変換)" click="applyColorMatrixFilter()"/>
	  <mx:Button x="10" y="236" label="Convolution (エッジ検出)" click="applyConvolutionFilter()"/>
	  <mx:Button x="10" y="268" label="DisplacementMap(波打ち)" click="applyDisplacementMapFilter()"/>
  </mx:Canvas>
  
  <mx:Script>
    <![CDATA[
      import flash.filters.*;
      
      // 表示されている画像のBitmapData
      private var bitmapData:BitmapData;
      
      // もともとの画像のBitmapData もとにもどす用
      private var baseBitmapData:BitmapData;
      
      /**
      * 初期設定
      */
			public function init():void 
      {
        // Imageオブジェクトに読み込んだ画像をBitmapDataに変換して変数に格納しておく
        // このbitmapDataを操作してImageに上書きすることでフィルターをかける
        // もとの画像より大きくなるフィルターもあるので大きめに作っておきますん
        this.bitmapData = new BitmapData(this.image.width + 50, this.image.height + 50, true, 0x000000);
        this.bitmapData.draw(this.image);
        
        // もとの画像に戻すために初期のBitmapDataを別に保存しておく
        this.baseBitmapData = new BitmapData(this.image.width + 50, this.image.height + 50, true, 0x000000);
        this.baseBitmapData.copyPixels(this.bitmapData, this.bitmapData.rect, new Point(0,0));
			}
      
      
      /**
      * もとに戻す
      * 初期のBitmapDataを現在のBitmapDataにコピーして上書き
      */ 
      private function revertImage():void
      {
        this.bitmapData.copyPixels(this.baseBitmapData, this.baseBitmapData.rect, new Point(0,0));
      }
      
      
      
      /**
      * BevelFilter
      * 
      * ベベル効果?日本語での用語はないのかな
      * 縁取りをして立体っぽく見せる効果
      */
      private function applyBevelFilter():void
      {
        var filter:BevelFilter = new BevelFilter();
        
        this.applyFilterToImage(filter);
      }
      
       
      /**
      * BlurFilter
      * 
      * 画像をぼかす
      */
      private function applyBlurFilter():void
      {
        var filter:BlurFilter = new BlurFilter();
        
        this.applyFilterToImage(filter);
      }
       
      
      /**
      * GlowFilter
      * 
      * 縁取りをして光らせたりする
      */
      private function applyGlowFilter():void
      {
        var filter:GlowFilter = new GlowFilter(0xFFFFFF, 1, 10, 10, 5, 3, true, false);
        
        this.applyFilterToImage(filter);
      }
       
      
      /**
      * DropShadowFilter
      * 
      * 画像に影をつける
      */
      private function applyDropShadowFilter():void 
      {
        var filter:DropShadowFilter = new DropShadowFilter(20);
        
        this.applyFilterToImage(filter);
      }
      
      
      /**
      * ColorMatrixFilter
      * 
      * 画像のRGB+Alpha値をマトリクスを使って変換する
      * 今回はこれを使ってグレースケールに変換
      * 
      * ここの解説が分かりやすい
      * http://d.hatena.ne.jp/umezo/20090122/1232627694
      */
      private function applyColorMatrixFilter():void
      {
        var filter: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,
          1/3, 1/3, 1/3, 0, 0,
          0, 0, 0, 255, 0
        ]);
        
        this.applyFilterToImage(filter);
      }
      
      
      /**
      * ConvolutionFilter
      * 
      * 畳込みフィルタ
      * 配列で指定したフィルタリングを画像の各ピクセルに適用していく
      * ぼかし、エッジ検出、シャープ、エンボス、ベベル・・・とかがこれ1つで実現できるらしい
      * 
      * 下のコードは、対象のピクセルの周り8ピクセルを-1で弱めて、その分中心の1ピクセルを強調させてエッジ検出している例
      * 
      * 参照
      * http://www.imajuk.com/blog/archives/2009/02/convolutionflter.html
      */
      private function applyConvolutionFilter():void
      {
        var filter:ConvolutionFilter = new ConvolutionFilter(3, 3,
          [
            -1, -1, -1,
            -1, +8, -1,
            -1, -1, -1 
          ]
	      );
        
        this.applyFilterToImage(filter);
      }
      
       
      /**
      * DisplacementMapFilter
      * 
      * 置き換えフィルタ
      * 画像を波打たせたりぼかしたりできる
      * perlinNoise(ランダムな模様を生成する)と組み合わせて画像を波打たせる効果を作ることが多いらしい
      * 
	    * perlinNoiseについてはここを参照
	    * http://d.hatena.ne.jp/kkanda/20080224/p1
      * 
      * DisplacementMapFilterについてはこちらを参照
      * http://d.hatena.ne.jp/kkanda/20080305/p1
      * http://endlessblank.com/blog/2009/06/displacementmapfilter.html
      */
      private function applyDisplacementMapFilter():void
      {
        // ランダムな縞模様を生成
        var perlinNoiseBitmap:BitmapData = new BitmapData(this.bitmapData.width, this.bitmapData.height);
        perlinNoiseBitmap.perlinNoise(
          perlinNoiseBitmap.width, 
          perlinNoiseBitmap.height, 
          10, 
          Math.floor(Math.random() * 65535), 
          false, 
          true
        );
        
        // 生成したランダムな模様を利用して波打たせる
        var filter:DisplacementMapFilter = new DisplacementMapFilter(
          perlinNoiseBitmap,  // 変換の元となるBitmapData
          new Point(0, 0),    // 変換開始ポイント
          1, // x座標の変形に使用する色 1=red, 2=green, 3=blue, 4=alpha
          1, // y座標の変形に使用する色
          30,// x座標の乗数
          30 // y座標の乗数
        );
          
        this.applyFilterToImage(filter);
      }
      
      
      
      /**
      * ここで実際にフィルターをかける
      * 修正したBitmapDataをImageオブジェクトに反映させるには、
      * BitmapData を Bitmap オブジェクトに格納した後に Image.load(Bitmap) を使う
      */
      private function applyFilterToImage(filter:BitmapFilter):void 
      { 
        // フィルターかけて
        this.bitmapData.applyFilter(this.bitmapData, this.bitmapData.rect, new Point(0, 0), filter);
        
        // BitmapはBitmapDataを入れておく器
        var bitmap:Bitmap = new Bitmap(this.bitmapData);
        
        // ここでImageに反映!
        this.image.load(bitmap);
      }
      
    ]]>
  </mx:Script>
</mx:Application>




参考にさせて頂いたURL
* http://d.hatena.ne.jp/umezo/20090122/1232627694
* http://www.imajuk.com/blog/archives/2009/02/convolutionflter.html
* http://d.hatena.ne.jp/kkanda/20080224/p1
* http://d.hatena.ne.jp/kkanda/20080305/p1
* http://endlessblank.com/blog/2009/06/displacementmapfilter.html