大重美幸の「これ見落としてませんか? ActionScript 3.0」

第5回 スクリプトでフィルタを適用する方法

スクリプトでフィルタを適用する方法と聞けば、難しそうに感じするかもしれませんが、実は簡単にできます。しかも、プロパティインスペクタの[フィルタの追加]メニューにあるのは7種類ですが、スクリプトではそれ以外にも3種類のフィルタを扱うことができます。ムービークリップとビットマップへフィルタを適用する方法を丁寧に解説していきますので、ぜひこの機会にマスターしてください。

サンプルファイル : edge_oshige_05_sample_fla.zip (533KB)

表示オブジェクトにフィルタをかける

前回の宿題を覚えていますか? そうです。コレです。FLVに何やら模様が合成されているというやつですが、これはCS4から利用できるようになったShaderフィルタをFLVに適用しています。そこで今回はShaderフィルタの解説を……と思いましたが、いきなりShaderの説明に入るのはハードルが高いので、今回は基礎知識としてのフィルタの話をしましょう。

さて、ご存じのようにムービークリップのインスタンスにはフィルタをかけることができます。フィルタをかけるにはステージでインスタンスを選択し、プロパティインスペクタの[フィルタの追加]メニューからフィルタを選びます。例えば、ドロップシャドウを追加すればインスタンスにフィルタが適用されます。

ドロップシャドウ
fig1 ムービークリップのインスタンスにドロップシャドウを適用します。

このフィルタの適用はActionScriptを使って行うことができます。インスタンスgirl_mcにドロップシャドウをかけるスクリプトは次のとおりです。ドロップシャドウというフィルタはDropShadowFilterクラスで作ります。DropShadowFilterクラスのインスタンスdsfを作り、それをムービークリップインスタンスのfiltersプロパティに設定すればフィルタを適用したことになります。filtersプロパティの値は複数のフィルタを追加できる配列です。適用するフィルタが1種類の場合でも[dsf]のように配列で指定します。

[sample] filters_DropShadow.fla
ムービークリップインスタンスgirl_mcにドロップシャドウを適用します。

var dsf:DropShadowFilter=new DropShadowFilter();
girl_mc.filters=[dsf];

ActionScriptでインスタンスにドロップシャドウを適用
fig2 ActionScriptでインスタンスにドロップシャドウを適用します。

[フィルタの追加]メニューには7種類のフィルタがあります。ドロップシャドウ以外のフィルタにもそれぞれ対応するクラスがあります。

[フィルタの追加]メニューから選べるフィルタとクラスの対応

ドロップシャドウ DropShadowFilter
ぼかし BlurFilter
光彩 GlowFilter
ベベル BevelFilter
グラデーショングロー GradientGlowFilter
グラデーションベベル GradientBevelFilter
カラー調整 ColorMatrixFilter

 

例えば、ぼかしとベベルの2つのフィルタを同時に適用したいならば、2つのフィルタのインスタンスを作り、filtersの配列に追加します。スクリプトで設定したフィルタを解除するにはfiltersの値を[]にします。複数のフィルタを適用している場合は、取り去りたいフィルタを取り除いた配列を再設定します。

[sample] filters.fla
ぼかしとベベルの2つのフィルタを適用します。

var blf:BlurFilter=new BlurFilter();
var bvf:BevelFilter=new BevelFilter();
girl_mc.filters=[blf, bvf];

ぼかしとベベル
fig3 ぼかしとベベルの2つのフィルタを適用します。

プロパティインスペクタでフィルタを適用するとわかるように、フィルタには影の色や方向など、それぞれに様々なオプション設定があります。それらの設定値は個々のフィルタのプロパティで指定します。プロパティを指定しなければ初期値の値でフィルタが適用されます。

次の例では光彩フィルタ(GlowFilter)のぼかしXY(blurXblurY)、カラー(color)、画質(quality)、ノックアウト(knockout)の値を設定して適用しています。knockouttrueにしているので、インスタンスの輪郭のぼかしだけが表示されます。

[sample] filters_property.fla
光彩フィルタのプロパティを設定して適用します。

var glf:GlowFilter=new GlowFilter();
glf.blurX = glf.blurY= 32;
glf.color = 0xFF0000;
glf.quality = 3;
glf.knockout = true;
girl_mc.filters=[glf];

光彩フィルタ(GlowFilter)をノックアウトの設定で適用
fig4 光彩フィルタ(GlowFilter)をノックアウトの設定で適用しています。

プロパティインスペクタの[フィルタの追加]メニューには7種類のフィルタがありますが、ActionScriptを使えばさらに次の3つのフィルタを利用できます。ConvolutionFilterはエンボス処理などを行うフィルタ、DisplacementMapFilterは波打つような湾曲処理などを行うフィルタ、ShaderFilterではPixel Benderで作成したカスタムフィルタを利用できます。最初に書いたように前回のFLVにはShaderFilterが適用されており、高速な画像処理が特長です。

スクリプトでのみ利用できるフィルタの種類
畳み込み ConvolutionFilter
置き換えマップ DisplacementMapFilter
シェーダー ShaderFilter

フィルタを使ったアニメーション

フィルタはアニメーションしているムービークリップインスタンスにも適用できますが、フィルタのプロパティの設定値を変化させることでアニメーションの効果を作ることができます。ただし、フィルタのインスタンスのプロパティを変更しても適用している効果はそれだけでは反映されません。

例えば次の例ではGlowFilterフィルタのblurXblurYを変化させてアニメーションを行っていますが、GlowFilterフィルタのインスタンスglfのプロパティを変更しても、その結果はgirl_mcに適用したフィルタには反映されません。ぼかし量の変化を反映させるには、girl_mcのfiltersに[glf]を再設定します。

[sample] filters_animation.fla
GlowFilterフィルタのぼかし量が変化するアニメーション。

var glf:GlowFilter=new GlowFilter();
glf.color = 0xFFFF00;
girl_mc.filters=[glf];
var deg:int=0;
addEventListener(Event.ENTER_FRAME, enterframeHandler);
//ぼかし量が変化するアニメーション
function enterframeHandler(eventObj:Event):void{
	deg=(deg+10)%360;
	glf.blurX = glf.blurY= Math.abs(Math.cos(deg/180*Math.PI))*64+16;
	//フィルタを再設定しなければ反映されません。
	girl_mc.filters=[glf];
}


fig5 黄色く光る量が変化するアニメーションになります。

ビットマップにフィルタを適用する

これまでムービークリップのインスタンスにフィルタを適用する例を見てきましたが、フィルタを適用できるのはムービークリップだけではありません。そもそも、filtersというプロパティはMovieClipクラスが継承しているDisplayObjectクラスで定義してあるプロパティです。つまり、DisplayObjectクラスを継承しているクラス、すなわち表示オブジェクトならばフィルタを適用できるわけです。表示オブジェクトであるSpriteやTextFieldでも適用できるフィルタの種類や設定方法は同じです。

しかし、フィルタを利用できるのは表示オブジェクトだけではありません。ビットマップデータにもフィルタを適用できるのを忘れてはなりません。ビットマップとビットマップデータを混同しがちですが、ビットマップはBitmapクラス、ビットマップデータはBitmapDataクラスです。

この関係はテキストフィールドとテキストデータの関係に似ています。テキストフィールドは容器でテキストデータがその中身です。テキストフィールドfldにテキストデータを入れるにはfld.textにテキストデータ(String型の値)を設定します。これと同じようにビットマップは容器でビットマップデータがその中身です。ビットマップbmpのビットマップデータはbmp.bitmapDataで参照でき、また、Bitmapのインスタンスを作る際のコンストラクターの引数で指定することもできます。

前置きが長くなりました。さっそくビットマップデータを使ってみましょう。ビットマップデータはBitmapDataのコンストラクターで作ることもできますが、写真などの外部イメージファイルから読み込むこともできます。ここではもっと簡単にライブラリに読み込んでおいたイメージからビットマップデータを作る方法を使います。

ライブラリに読み込んだ写真からビットマップデータを取り出すには、写真にリンケージ書き出しの設定をします。サンプルではphotoのクラス名で書き出しています。

ビットマッププロパティ
fig6 ビットマップのビットマップデータにぼかしフィルタを適用します。

これをスクリプトで扱えるビットマップデータにするには、new photo(0,0)を実行してbmpdataに取り出します。コンストラクターの引数の2個の数値は何でも構いませんが省略できません。

次にビットマップデータに適用するぼかしフィルタを作ります。これまでフィルタをfiltersプロパティに設定することでフィルタを適用してきましたが、ビットマップデータにはfiltersプロパティがありません。ビットマップデータにはapplyFilter()を使ってフィルタを適用します。そして最後にビットマップデータを表示するビットマップを作ってステージに表示します。

ビットマップのビットマップデータにぼかしフィルタを適用
fig7 ビットマップのビットマップデータにぼかしフィルタを適用します。

[sample] bmpdata_filter.fla
ビットマップデータにぼかしフィルタを適用します。

//ビットマップデータbmpdataを作ります。
var bmpdata:BitmapData = new photo(0,0);
//ぼかしフィルタを作ります。
var blf:BlurFilter = new BlurFilter();
blf.blurX=blf.blurY=32;
//ビットマップデータbmpdataにフィルタを適用します。
var rect:Rectangle=new Rectangle(0,0,bmpdata.width,bmpdata.height);
var pt:Point=new Point(0,0);
bmpdata.applyFilter(bmpdata,rect,pt,blf);
//ビットマップデータbmpdataを表示するビットマップbmpを作ります。
var bmp:Bitmap = new Bitmap(bmpdata);
bmp.x=(stage.stageWidth-bmp.width)/2;
bmp.y=(stage.stageHeight-bmp.height)/2;
addChild(bmp);

ビットマップデータでは、ビットマップデータの一部分の領域にフィルタを適用することもできます。それがapplyFilter()の第2引数、第3引数の設定です。第2引数は加工に使用するデータの領域です。第3引数は処理後のデータを書き出す座標です。次の例ではちょうどバケツが並んでいる領域をぼかしています。

ビットマップ内の一部にだけぼかしを適用
fig8 バケツが並んでいる領域だけをぼかします。

[sample] bmpdata_filter2.fla
ビットマップデータの一部分の領域をぼかします。

//ビットマップデータbmpdataを作ります。
var bmpdata:BitmapData = new photo(0,0);
//ぼかしフィルタを作ります。
var blf:BlurFilter = new BlurFilter();
blf.blurX=blf.blurY=32;
//ビットマップデータbmpdataにフィルタを適用します。
var rect:Rectangle=new Rectangle(0,0,160,80);
var pt:Point=new Point(80,120);
rect.offset(pt.x,pt.y);
bmpdata.applyFilter(bmpdata,rect,pt,blf);
//ビットマップデータbmpdataを表示するビットマップbmpを作ります。
var bmp:Bitmap = new Bitmap(bmpdata);
bmp.x=(stage.stageWidth-bmp.width)/2;
bmp.y=(stage.stageHeight-bmp.height)/2;
addChild(bmp);

それでは最後に宿題です。次回へ持ち越しの宿題があるので今回はちょっと簡単な問題。次の写真にはぼかしフィルタが適用してありますが、先のぼかしの結果と違って輪郭もぼけています。この違いの原因はどこにあるのでしょうか?

写真の輪郭もぼけている図
fig9 写真の輪郭もぼけていますよね? なぜこうなるのでしょうか?

関連情報


大重美幸氏写真大重美幸
(おおしげよしゆき)

日立情報システムズ、コミュニケーションシステム研究所を経て独立。株式会社ロクナナ顧問。執筆、講師、ソフトウェア開発を行う。趣味はサーフィンとジョギング。茅ヶ崎在住。著著は約50冊。
twitter : @oshige@as3note

近著:Adobe Flash CS4 詳細!ActionScript 3.0入門ノート[完全改訂版]ActionScript3.0辞典[FlashPlayer10/9対応]