Adobe Pixel Bender Toolkit による
Flash Player 10 向けカスタムフィルタの作成

Flash Player 10 では、アドビが独自に開発した高パフォーマンスイメージプロセッシング言語「Adobe Pixel Bender」がサポートされます。これによって、クリエイター自身が Pixel Bender を使って作成したカスタムフィルタやカスタムエフェクトを、Flash 開発で利用できるようになります。カスタムフィルタやカスタムエフェクトは、専用ツール「Adobe Pixel Bender Toolkit」を使って作成します。本記事では、このツールを使ってオリジナルフィルタを作成する方法から、作成したフィルタを Flash 開発で利用する方法までを解説します。

Pixel Bender Toolkit のダウンロードとインストール

まず Adobe Labs にアクセスし、Pixel Bender Toolkit のダウンロードとインストールを行います。Windows 用のインストーラは ZIP ファイル、Macintosh 用のインストーラは DMG ファイルとなっていますので、それぞれご利用環境に合わせてダウンロードして下さい。なお、Pixel Bender Toolkit のシステム要件は以下のようになっています。ご利用の環境が条件を満たしているかどうかご確認下さい。

Macintosh
G4/G5/Intel プロセッサ
メモリ 512 MB以上
80 MBのHDD容量
Mac OS 10.4.10 以上

Windows
Pentium 4 以降のプロセッサ
メモリ512MB以上
50MBのHDD容量
Windows XP SP2 以上

Pixel Bender はビデオカードによる描画処理機能を使用して高速処理されますが、ご利用のシステムに OpenGL 2.0 対応のビデオカードが搭載されている必要があります。対応しているビデオカードを検出できない場合は起動時に警告が表示されますが、その場合フィルタの実行は CPU によってソフトウェア処理され、Pixel Bender のテスト自体は行えるようになっています。ビデオカードを使用せずに強制的にソフトウェア処理で実行させる場合は、Preference の Advanced タブにある「Force filters to run on the CPU」にチェックをつけます。これによって Pixel Bender による描画処理は常にソフトウェアで実行されるようになり、起動時のビデオカードのチェックも行われなくなります。

Preferencesパネルで描画処理にCPUを使用する
常にソフトウェアで処理させる場合

それでは実際に Pixel Bender Toolkit を使ってフィルタを動作させてみましょう。Pixel Bender Toolkit を起動させたらまず画像ファイルを読み込みます。「File」メニューの「Load image1」をクリックし、任意の画像ファイルを選択して下さい。画像は JPEG または PNG 形式のファイルであれば結構です。

次に、フィルタの処理内容が記述された、拡張子.pbk の Pixel Bender カーネルファイルを開きます。ファイルそのものは一般的なテキストエディタで編集可能なテキストファイルです。インストールされた Pixel Bender Toolkit と同階層にある「pixel bender files」フォルダにあるサンプルを開くか、以下のサイトで公開されているファイルをダウンロードしてご利用下さい。

Pixel Bender Exchange

Pixel Bender Toolkit:Gallery

「File」メニューの「Open Pixel Bender Kernel Filter」から任意の .pbk ファイルを選択して開きます。

フィルタをテストする場合は下部にある「Run」ボタンをクリックします。カーネルファイルによってはスライドバーが表示され、フィルタのパラメータを操作することで画面上でフィルタの効果をリアルタイムに確認することができます。

Pixel Bender Toolkit のメイン画面
「Run」 ボタンをクリックするとフィルタが実行される

オリジナルフィルタの作成

それでは実際にフィルタの作成に挑戦してみましょう。フィルタには入力と出力をまず定義し、その間に画像処理を行うモジュールを追加する形をイメージしてみると分かりやすいかもしれません。「File」メニューにある「New Kernel Filter」をクリックします。この状態は、画像の持つ4つのチャンネルを格納し、それをそのまま出力する最もシンプルな構造となっています。実際のソースコードを解説します。

kernel NewFilter
<   namespace : "Your Namespace";
    vendor : "Your Vendor";
    version : 1;
    description : "your description";
>
{
    input image4 src;
    output pixel4 dst;

    void
    evaluatePixel()
    {
        dst = sampleNearest(src,outCoord());
    }
}

まず kernel の変数を定義します。Pixel Bender の変数定義は、<修飾子> <データ型> <名前>の形で指定します。修飾子inputに設定しているimage4型は、元画像イメージを4つのチャンネルに分割して格納するものです。srcがプログラム内で使用する名前になります。なお、inputのデータ型は image1image2image3 image4 のいずれかである必要があります。対して出力側は修飾子をoutputとし、データ型は pixel1pixel2pixel3pixel4 のいずれかである必要があります。なお、それぞれのプロパティには、dst.rgb=1のようにドットシンタックスを使ってアクセスすることもできます。

次のevaluatePixel関数は、カーネル内で最低限1つ使用する必要のある関数で、ピクセル処理を並行して実行することを定義しています。具体的な処理内容はその中括弧の中です。元画像srcからoutCoord関数を使って取得したグローバル座標を、sampleNearest関数を使ってピクセルに変換し、最終出力dstに渡しています。

ここでは各関数の機能や意味については深く考えず、inputoutputで画像の入力とピクセルの出力を定義し、evaluatePixelという関数内で具体的な画像処理を行うとだけ考えておきましょう。各関数やデータ型の詳細については Pixel Bender Toolkit 付属のリファレンス(英語)を参照して下さい(「Help」メニューの「Pixel Bender Specification ...」 をクリックするか、インストールされた Pixel Bender Toolkit と同階層の「docs」フォルダにある「PixelBenderLanguage10.pdf」に記載されています)。

それではこのソースコードを変更してオリジナルフィルタを作成してみましょう。画像のイメージは RGBA の4つのチャンネルで出力されていますので、それぞれのチャンネルをパラメータで操作して色を変化させられるようにしてみたいと思います。ソースコードを以下のように変更します。

kernel NewFilter
<   namespace : "Your Namespace";
    vendor : "Your Vendor";
    version : 1;
    description : "your description";
>
{
   parameter float4 ColorRatio
    <       
        defaultValue:float4(1,1,1,1);
    >;

    input image4 src;
    output pixel4 dst;
    
    void
    evaluatePixel()
    {
        // Obtain the input pixel color
        float4 inputColor = sampleNearest(src, outCoord());

        // filtered RGBA channels
        dst = inputColor * ColorRatio;
        
    }
}

まず、evaluatePixel関数の中括弧の中に処理を追加しました。これまで最終出力dstに直接渡していた処理の前に4つの値を値を格納できる float4 型の変数inputColorを追加し、元画像のピクセルから取り出した4つのチャンネル情報を格納するようにしました。

次に、コードの先頭部分にパラメータ変数ColorRatioを追加しました。Pixel Bender ではこのように、外部からの値の操作を想定した変数をパラメータ変数として定義することができます。さらに<>記号の中では、パラメータの初期値や最大値、最小値を設定することができます。ここでは、inputColorの各チャンネルに対して同じように操作が行えるよう float4 型で定義しました。初期値は1です。

そして再度中括弧の中です。inputColorの各チャンネルに対してColorRatioの値を掛け合わせた値を、最終出力dstに渡しています。

それでは「Run」ボタンをクリックしてみて下さい。パラメータを操作することで、画像の色が変化することがお分かり頂けるのではないでしょうか。

パラメータを操作
G のチャンネルの値が最大。緑の画像へ変化

なお、ここでは画像の色チャンネルのみをパラメータで操作可能にしましたが、Pixel Bender は画像のピクセル位置を変更させたり、IF 文を使って複雑な条件分岐によるフィルタ変化を設定したりすることも可能です。サンプルやギャラリー等を参考にご自身で研究してみて下さい。

ここまでで動作が問題ないようであれば、Flash Player 10 の外部フィルタファイルとして書き出しを行います。「File」メニューの「Export Kernel Filter for Flash Player...」をクリックし、任意の場所にファイルを書き出して下さい。このファイルは後ほど使用します。

Flex Builder 3 による Flash Player 10 開発環境の準備

swf ファイルのコンパイル環境としても利用できる Flex SDK は日々バージョンアップが行われており、Flex Builder 3 を使用することで驚くほど容易に最新の開発環境に触れることが出来ます。もちろん、まだベータ版である Flash Player 10 向けのコンテンツ作成も可能です。まだ Flex Builder 3 をお持ちでない皆さん、製品版とまったく同じ機能をご利用いただけるトライアル製品をダウンロードし、これを機にFlex Builder 3 による開発に挑戦してみて下さい。

最新の Flex SDK は、Adobe Open Source 内の All Flex 3 Downloads からダウンロード可能です。Milestone Release Builds はリリース候補版、Stable Builds は安定版、Nightly Builds は開発版の位置づけで、バージョン番号の大きなものほど開発段階が進んでいるものです。Flex Builder で使用する場合は、Adobe Flex SDK のリストの中から選択してダウンロードします。ダウンロードが終わったら任意の場所に解凍して下さい。

Adobe Open Source から Adobe Flex SDK をダウンロード

解凍が終わったら、解凍した以下の階層に Flash Player 10 用の swc が同梱されているかどうかを確認して下さい。FLEX_SDK/frameworks/libs/player/10/playerglobal.swc

もし存在しない場合は別の SDK をダウンロードして下さい。問題ないようであれば Flex Builder 3 を起動します。

新規 Flex プロジェクトウィンドウFlex Builder 3 の「ファイル」メニュー「新規」の項目内にある「Flex プロジェクト」をクリックし、ファイルの保存場所とプロジェクト名を指定します。

プロジェクト名は必須で、半角英数字、$(ドル記号)、_(アンダーバー)のみをご利用下さい。

プロジェクトの保存場所は、左図のように特定の場所を指定しても構いませんし、「デフォルトの場所を使用する」にチェックをつけて Flex Builder の既定のフォルダを使用するように設定することもできます。

「アプリケーションの種類」は 「Webアプリケーション(Flash Player で実行)」を選択します。

サーバーへの接続は行いませんので、「アプリケーションサーバーの種類」は「なし」を選択したままの状態にします。

設定を確認したら「終了」をクリックして設定を確定して下さい。Flex Builder が指定した「プロジェクト」フォルダの中にフォルダ構造と MXML ファイルが生成されます。


Flex コンパイラの「Flex SDKの設定」リンクをクリック

MXMLファイルが開かれたら、Flex Builder 3 の左ペインにあるプロジェクトファイル上で右クリックして「プロパティー」を選択するか、Flex Builder 3 の「プロジェクト」メニューにある「プロパティー」をクリックします。右図のようなダイアログが表示されますので、「Flex コンパイラ」カテゴリにある「Flex SDKの設定」リンクをクリックして下さい。以下のような「Flex SDK 設定」ダイアログが表示されます。

Flex SDK 設定ダイアログ

右側にある「追加」をクリックすると 「Flex SDKを追加」ダイアログが表示されます。「Flex SDKの場所」の右側にある「参照」をクリックし、先ほどダウンロードして解凍を行った Flex SDK フォルダを選択します。選択が完了したらその下の Flex SDK 名に任意の名前をつけます。

「OK」をクリックしてそれぞれの設定を確定し、「プロパティー」のダイアログ画面に戻ったら、「Flex SDKのバージョン」の「特定のSDKを使用する」にチェックをつけ、先ほど追加した Flex SDK 名を選択して下さい。

ライブラリパスアイテムオプション

次に、同じ「プロパティー」のダイアログ内の「Flex ビルドパス」カテゴリを選択します。

「ライブラリパス」タブをクリックし、右側にある「SWC の追加」をクリックして下さい。ここでダウンロードした Flex SDK の中にある Flash Player 10 用の playerglobal.swc を選択します。

以下の階層を確認し、もし存在しないような場合は他の Flex SDKをダウンロードします。

frameworks/libs/player/10/playerglobal.swc

playerglobal.swc を追加した後、「リンクタイプ」を選択した状態で「編集」をクリックします。「ライブラリパスアイテムオプション」ダイアログが表示されたら、「リンクタイプ」プルダウンから「外部」を選択し、「OK」をクリックして設定を確定します。

以上で Flex Builder 3 における Flash Player 10 用コンテンツ作成環境の準備が整いました。次に、Flex の コンポーネントを使って、Pixel Bender Toolkit から作成した外部フィルタを操作するコンテンツを作ってみましょう。

Flash から外部フィルタを操作する

まず、使用する任意の画像ファイルと、Pixel Bender Toolkit から書き出した 拡張子.pbj のファイルを、先ほど作成したFlex Builder のプロジェクトフォルダ内にある「src」フォルダの中に入れます。直接フォルダを開いてその中に移動させるか、Flex Bulder の左ペインにある「Flex ナビゲータ」に表示されている src フォルダに直接ドラッグしてコピーしてください。

Flexナビゲータパネルにドラッグ
「Flex ナビゲータ 」パネル内の src フォルダへ直接ドラッグしてコピー

Flex Builder 3 に戻り、MXMLデザインビューの状態で「ウィンドウ」メニューの「コンポーネント」をクリックします。コントロールコンポーネントの中から、画像表示用の image コンポーネント、イメージの各チャンネルを操作する HSlider コンポーネントをステージ上に配置します。各コンポーネントを選択し、プロパティパネルを使ってそれぞれの設定を行います。

Flex Builder のデザイン画面
コンポーネントの各プロパティを設定

各コンポーネントにはスクリプトから制御できるように IDを設定し、image コンポーネント の Source プロパティに表示する任意の画像ファイルのファイル名を入力します。また、HSlider は、リアルタイムに設定が反映されるよう、liveDragging を true にします。

ここで表示を「ソース」に切り替えると、「デザイン」ウィンドウで行った設定が MXMLのコードとして生成されていることが確認できます。ここでは MXML のコードの解説はしませんが、HTML のようなシンプルで分かりやすいものだということがお分かり頂けるのではないでしょうか。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

 <mx:Script>
      <![CDATA[
            //Action Script
      ]]>
 </mx:Script>

 <mx:Image id="myImageRaw" source="ShrineNearDarjeeling.png" scaleContent="false" autoLoad="true"/>
 
 <mx:HSlider x="608" y="10" id="Col_Red" maximum="1" minimum="0" allowTrackClick="true" enabled="true" liveDragging="true" labels="R" value="1"/>
 <mx:HSlider x="608" y="48" id="Col_Green" maximum="1" minimum="0" allowTrackClick="true" enabled="true" liveDragging="true" labels="G" value="1"/>
 <mx:HSlider x="608" y="85" id="Col_Blue" maximum="1" minimum="0" allowTrackClick="true" enabled="true" liveDragging="true" labels="B" value="1"/>
 <mx:HSlider x="608" y="129" id="Col_Alpha" maximum="1" minimum="0" allowTrackClick="true" enabled="true" liveDragging="true" labels="A" value="1"/>
  
</mx:Application>

それでは次に、コンポーネントの制御を行う ActionScript を記述して、コンポーネントの操作がフィルタに反映されるようにしていきます。

Flash における外部フィルタファイルは、通常のビットマップ画像と同じように読み込んで、バイトコードとして Shader クラスに渡して動作させます。Shader クラス等、Flash Player 10 から追加された新しいクラスのリファレンスにつきましては以下をご確認下さい。現在のところ提供されている情報は英語のみとなります。

Download the ActionScript 3.0 Language Reference, which provides information on the syntax and usage of the new APIs in Flash Player 10*

まず、外部フィルタファイルを Flash 内に読み込む必要があります。今回の場合、画像を表示する image コンポーネントが自動的に実行されるので、imageコンポーネントが有効化された時点をイベントとしてフィルタの読み込み動作を行いたいと思います。image コンポーネントに以下の値を追加します。


<mx:Image id="myImageRaw" activate="imageLoadHandler(event);" source="ShrineNearDarjeeling.png" scaleContent="false" autoLoad="true"/>

<mx:Script>タグの中に、このイベントを処理する ActionScript を以下のように記述します。ここでは、URLLoaderクラスを使って同階層にある外部エフェクトファイル(ここではchangeRGB.pbj)の読み込みを行い、読み込みが完了したらShaderクラスに ByteCode としてデータを渡す処理を行う別の関数が呼び出される形にしています。

import flash.filters.ShaderFilter;
            
    private var loader:URLLoader;
    private var shader:Shader;
    private var myFilter:ShaderFilter;
               
    private function imageLoadHandler(event:Event):void {
            
            loader = new URLLoader();
            loader.dataFormat = URLLoaderDataFormat.BINARY;
            loader.addEventListener(Event.COMPLETE, onLoadComplete);
            loader.load(new URLRequest("changeRGB.pbj"));
            
              function onLoadComplete(event:Event):void {
            	shader = new Shader();
            	shader.byteCode = loader.data;                       
            	myFilter = new ShaderFilter(shader);
              }
           }

次に HSlider コンポーネントのイベント処理を追加します。マウスでスライダーが変更されると、そのスライダーの値とフィルタのパラメータの何番目を操作するかを指定しています。HSlider コンポーネントのプロパティとして、以下のコードを追加します。


<mx:HSlider change="sliderChange(event, 0)" x="608" y="10" id="Col_Red" maximum="1" minimum="0" allowTrackClick="true" enabled="true" liveDragging="true" labels="R" value="1"/> 
<mx:HSlider change="sliderChange(event, 1)" x="608" y="48" id="Col_Green" maximum="1" minimum="0" allowTrackClick="true" enabled="true" liveDragging="true" labels="G" value="1"/>
<mx:HSlider change="sliderChange(event, 2)" x="608" y="85" id="Col_Blue" maximum="1" minimum="0" allowTrackClick="true" enabled="true" liveDragging="true" labels="B" value="1"/>
<mx:HSlider change="sliderChange(event, 3)" x="608" y="129" id="Col_Alpha" maximum="1" minimum="0" allowTrackClick="true" enabled="true" liveDragging="true" labels="A" value="1"/>

最後に、このスライダーのイベントを処理する ActionScript を追加します。

   import flash.filters.ShaderFilter;
   import mx.events.SliderEvent;
   import mx.controls.sliderClasses.Slider;

//~中略~
    private function sliderChange(event:SliderEvent, targetNum:Number):void {
            var currentSlider:Slider=Slider(event.currentTarget);
            shader.data.ColorRatio.value[targetNum]=currentSlider.value;
            myImageRaw.filters = [myFilter];	
    }

スライダーが操作されると、スライダーの値と操作したいチャンネルの番号がやってきます。作成した外部フィルタにそのスライダーの値と対象チャンネルの番号が渡され、最終的にimage コンポーネントのフィルタとして配列の形で渡されます。

ここで、shader.data.ColorRatio.value[targetNum]の部分にご注目下さい。Pixel Bender Toolkit でフィルタ作成時に設定したパラメータは、このようにshader.data.パラメータ名.value = 設定したい値の形でアクセスできます。設定したパラメータのデータ型にもよりますが、基本的にはこの形式でパラメータの値を Flash 側から操作することができます。つまり、フィルタそのもののプログラム構造を理解せずとも、どのようなパラメータが設定されているかを確認するだけで Flash から自由に制御可能なフィルタを利用できるということがお分かり頂けるのではないでしょうか。

ここまでで作成したサンプルファイルを以下にアップロードしておきます。もし途中で動作に問題が発生したような場合は参考にして下さい。

Edge_FlexSample200807.zip

ブラウザ上でプレビュー表示

ブラウザ上で動作を確認する場合は以下の リンクをクリックして下さい。別ウィンドウが開きます。あらかじめ Flash Player 10 のインストールが必要です。

Flash Player 10 外部フィルタサンプル

Flex Builder 上で作成中のファイルの動作を確認する場合は、Flex Builder の ツールバーにある「実行」ボタンをクリックして下さい。ブラウザが起動し、実際に動作が確認できれば成功です。

作成中のプロジェクトを実行
「実行」ボタンをクリックしてテスト


このように、外部フィルタを Flash で利用することはそれほど難しいことではありません。面白そうなフィルタがあれば、まずはPixel Bender Toolkit に読み込んでパラメータを操作し、自身の Flash コンテンツで利用したり、自由にカスタマイズしたり、自分好みのフィルタ作成に挑戦してみて下さい。もし素晴らしいフィルタが完成した場合は、是非 Pixel Bender Exchange で公開して頂けたら幸いです。みなさんの投稿をお待ちしています。