2010-05-16

アニメ制作者のためのAfterEffectsプラグイン作成入門(第3回) プラグインの改造(修正) スケルトンの作成

プラグインの改造(修正) PSET.aexの16bit化

今回は、PSET.aexの改造(修正)を行い、ついでにスケルトンプラグラムの紹介までやってみます。
予定ではC/C++の事をするつもりでしたが、この投稿はプログラム講座ではなくAEプラグインの作成が目的なので、端折ります。(まぁプログラムの話ばかりだと面白くないってのが、本音ですが^^;)

まず、16bitへの対応から始めます。簡単で結構重要な修正です。

16bit対応の手順

PSET.aexは8bitオンリーのプラグインですが、以下の項目を変更することで16bit対応になります。これは他のプラグインでも同様です。やる気があれば32bitにも対応可能です。
  • GlobalSetupで、out_flagsPF_OutFlag_DEEP_COLOR_AWAREを追加。
    out_flagsでこのプラグインが16bitに対応していることをホスト(AfterEffects)へ通達します。

    忘れすにPiPLリソースも変更しておきます。
  • 画像の色深度を確認。
    実際にホストから渡された画像が8bitか16bitか調べます。これはマクロが用意されていて、PF_WORLD_IS_DEEP(output)で判別できます。

    他にもAEGPのPF_WorldSuite2PF_GetPixelFormatでもっと詳細な情報(8/16/32bit)が得られます。32bit対応の場合はこちらで判別します。
  • 8bit/16bitで画像の実サイズの計算が違う。
    画像の実サイズは、PF_EffectWorldrowbytesを1ピクセルのバイト数で割ることで求めていますので、対処します。

  • 8bit/16bitで処理コードを変える。
    C++の機能で同一コードで対応してもいいですが、オーバーヘッドで処理速度がイマイチなので、僕は8bit/16bitで処理コードを分けてコーディングしています。
  • 画像データをキャストしなおす。
    画像データはの型はPF_PixelPtrで、8Bitの場合そのまま扱えますが、16bit時は(PF_Pixel16 *)へキャストし直します。

以上の項目で16bit対応ができます。
ちょっとプログラムのこと(ポインタとか)が分からないとちんぷんかんだと思いますが、慣れればたいしたことないです。

参考に16bit対応済みのソースです。修正前のソースと比較した方がわかりやすかもしれません

PSET_16Bit.zipのダウンロード

画像の扱い。その1 ピクセル(PF_Pixel)

以上の16bit対応の説明は、わかる人には簡単だがそうでない人には?って感じだと思います。基本的な画像処理についての知識が有るか無いかで分かれると思います。
ここでは、Effectプラグイン作成では流石に避けて通れない画像処理の基本を説明します。

まず、ピクセルから。
AfterEffectsを触ってる人ならピクセルって概念はわかると思いますが、プログラム的にピクセルとはどんな意味でしょうか?

ウィキペディアで調べるとピクセルとは「情報(色調や階調)を持つ最小単位」って定義されてます(今では無意味となったドットとピクセルの違いとか思い出しますな)
普通の画像処理ソフトをを作る場合は、まずピクセルの定義から始めますが、AEプラグインの場合はすでにSDKの中で既に定義されています(これは結構幸せな事です)

PF_Pixelがピクセルを定義した型になります。具体的には以下のように定義された構造体変数にしかすぎません。


A_u_charは符号なし8bitサイズの変数で、それが4つ(alpha/red/green/blue)のメンバとなっています。ごく普通の変数です。画像処理といっても実は別に特別な事はしてません。ごく普通に値を代入したり、計算することができます。

メンバの型をA_u_short(unsigned short)に変えたものはPF_Pixel16と定義されていてこれが16bit画像のピクセルになります。AfterEffectsは他にもA_FpShort(float)PF_Pixel32もあります。(AfterEffect.hを確認のこと) 
これらのピクセル構造体に適当な値を入れて処理すれば、それが画面に描画されます。AfterEffectsのプロジェクト設定の色深度の設定は、内部で扱うピクセルの型(サイズ)を切り替えているって事になります。

各メンバの最大値は、AfterEffect.hで定義されていています。コード内に直接数値を打ち込むより、この定数マクロをなるべく使った方が幸せになります(8bitのコードから16bitへ変換が簡単な置換でできる)


ちなみにPF_Pixelのサイズは4Byte・PF_Pixel16のサイズは8BytePF_Pixel32のサイズは16Byteとなり、16bitモードでは2倍、floatモードでは4倍のメモリ消費量になります。

画像の扱い。その2 画像データへのアクセス

ピクセルについて簡単に説明した後は、具体的な画像について。

AfterEfefctsの画像を扱うための型にはPF_InData/PF_OutData/PF_EffectWorldと3種類あり、それぞれインプット画面の情報・アウトプット画面の情報・画像データそのもの型となってます。
インプット画像とは、Effectをかける元画像でAfterEffectsはこれを作成してプラグインに渡します。PF_InDataは画像データでなくコールバック関数の呼び出しアドレスやらプラグインの動作に必要な情報が入っている構造体です。
アウトプット画面はエフェクトを処理が終わった画像をいれるところで、この画面に描画を行いプラグインのRender関数を正常終了すれば、必要なレイヤ合成を行い画面に表示します。PF_OutDataはプラグインからホスト(AfterEffects)へ動作を設定したりするための構造体となります。(out_flags等)

なんだか言葉で説明してもよくわからないですな^^; 
実は僕もよくわかってなかったりします。必要になったらその定義を見て対処する程度の認識でいいです。しっかりと覚えないといけないのがPF_EffectWorldです。(定義ではPF_LayerDefなので注意してね)
二つのPF_EffectWorld(画像データ)とインプット用の情報(PF_InData)とアウトプット用の情報(PF_OutData)があるって覚えるだけで、詳細は作っていく過程でなんとなくわかればいいです。

PF_EffectWorld(PF_LayerDef)が画像データそのものの型で、そのメンバのdataに、画像配列の先頭アドレスが収納されています。

ここからその画像配列の説明をします。

以下の図は5Pixelx5Pixelサイズの画像の画像配列データのイメージになります。
画像配列は、PF_Pixelの1次元配列で左上(x0,y0)の位置を起点にして並んでいます。この図で(x?,y?)はXY座標・大きい二桁の数字は画像配列のインデックスを意味してます。



任意の位置(XY座標)にアクセスするためには、XY位置を1次元インデックスに変換する必要があります。しかし、AfterEffectsの画像は扱いを楽にするために適当なサイズに切り上げます。イメージ画像で右側の白い円(ピクセル)がそれに相当します。なんか一見無駄に感じますが、切りの良いサイズ(32bitの整数倍・64bitの整数倍とか)にすればCPUは高速にデータを転送します(つまり実行速度が早くなる)実は、windows BMPファイルの内部データも同じだったりします。

具体的には画像配列へのアクセスは、
画像配列のインデックス = 横Xの位置  + (縦Yの位置 × 実際の横幅)
という計算式で求められます。(位置のスタートは0です)
プラグインでは高速化のため最適化して計算をしないようにするのでわかりづらいですが、これが基本となります。
Cのコードだと、

と入った感じになります。
Cの参考書で、ポインターとキャスト及び配列へのアクセスを勉強するのが習得への近道です。

スケルトンプログラム

PSET.aexのソースは説明には都合が良いが普通にプラグインを作るときには手間が増えるので、少し直してスケルトンプログラムへ改造しました。
改造と言っても、ほとんど作り直し状態になってますが、基本的には変わっていません。

ということで、今回作成したAEプラグイン作成用のスケルトンプラグインです。

MySkeletonのダウンロード

(追記)
構成を追加した物に差し替えました(2010/5/2)

ファイルの構成は以下の通り。
ファイル名説明
MySkeleton.hプラグインのヘッダーファイル。各種の定義。プロトタイプ宣言
MySkeleton.cppプラグインのメイン
MySkeletonMain.cppプラグイン描画関係のコード用
MySkeletonPiPL.rPiPLリソース定義ファイル
Win/MySkeleton.vcprojプロジェクトファイル。
Win/MySkeleton.slnソリューションファイル。複数のプロジェクトを管理できる。
Win/MySkeletonPiPL.rcリソース作成時の中間ファイル

MySkeletonMain.cppはソースをわかりやすくするために、描画関係のコードをMySkeleton.cppから分離したものです。最初から8bit/16bit対応をさせてあります。

重要な箇所は次の通り。
  1. MySkeleton.h パラメータUIのインデックス
    enum定義されたパラメータUIのインデックス定数。

    enumは並べて定義するだけで、自動に数値を定義できる便利な機能で、順番が重要な定数定義を行う場合便利です。
    INPUTとNUM_PARAMSの間に自分が定義したい項目を追加していきます。
  2. MySkeleton.h 文字列・その他定数の定義
    #defineで定数の定義を行っています。スケルトンでは、パラメータUIの表示文字列の定義とかバージョンの定義とか行っています。

    defineは定数の定義だけではなくマクロ定義も行えます。これはかなり使えますので、Cの参考書等で覚えましょう。
  3. MySkeleton.h AE_params構造体
    このスケルトンの重要な項目です。プラグインの画像描画に必要な変数を構造体にまとめたものです。
    typedef structで構造体を定義しています。



    各メンバの説明は次の通り。
    構造体のサイズを無理やり64Byteにするために最後に適当なメンバが二つ入れてあります。ただし、PF_Booleanのサイズは2Byteなのでプロジェクトのプロパティで構造体のアライメントを4Byteにしておかないと行けない(構成プロパティ:C/C++:コード生成]構造体メンバのアライメントを4バイト(/Zp4)に設定)

    メンバ名説明
    in_dataPF_InData *インプット画像情報の構造体のポインタ
    out_dataPF_OutData *アウトプット画像情報の構造体のポインタ
    inputPF_EffectWorld *インプット画像の構造体のポインタ
    outputPF_EffectWorld *アウトプット画像の構造体のポインタ
    inDataPF_PixelPtrインプット画像データの先頭アドレス
    outDataPF_PixelPtrアウトプット画像データの先頭アドレス
    is16BitPF_Boolean16bitならTRUE。8bitならFALSE
    widthA_long画像の横ピクセル
    heightA_long画像の縦ピクセル
    inWidthA_longインプット画像データの実際の横ピクセル
    outWidthA_longアウトプット画像データの実際の横ピクセル
    offsetInWidthA_longインプット画像データの横幅のオフセット。 (inWidth – width)の値
    offsetOutWidthA_longアウトプット画像データの横幅のオフセット。 (outWidth – width)の値
    currentFrameA_longRenderが呼び出されたタイムライン上のフレーム。(0スタート)
    reserve1A_long穴埋め
    reserve2A_long穴埋め

    MySkeleton.cppのGetAE_Params関数で処理を行っていますので、このスケルトンをつかえば、以上の情報は簡単に獲得できるようになります。

    PF_で始まる型は、SDKで定義されているAfterEffects独自の型。A_で始まる型はA.hで定義されているMac/Windowsや32bit/64bitアプリケーション作成時の変数の互換性を保つために定義されているものです。

  4. MySkeleton.h MySkeleton_params構造体
    プラグイン独自のパラメータをまとめた構造体。
    MySkeleton.cppGet_MySkeleton_Params関数で処理を行ってます。
    MySkeletonの文字列は、後で説明するAE_ProjectRename.exeでリネームを行うと同時に変更されるので注意のこと。


  5. MySkeleton.h 関数のプロトタイプ宣言


    MySkeleton.cppとMySkeletonMain.cppと分離したため、MySkeletonMain.cppのMainRender関数をMySkeleton.cppから呼び出せるように宣言を行っています。

  6. MySkeleton.cpp GlobalSetup
    バージョンとout_flagsの設定を行っています。
    スケルトンではout_flagの値を2種類用意してあります。通常のプラグインならばこの2種類でほとんど用が足ります。
  7. MySkeleton.cpp ParamsSetup
    パラメータUIのセットアップを行っています。
    スケルトンでは、色(PF_Pixel)・整数のスライダ(A_long)・固定小数のスライダ(PF_Fixed)・チェックボックス(PF_Boolean)・角度(PF_Fixed)・ポップアップメニュー(PF_Fixed)・位置のUIを登録してあります。

  8. MySkeleton.cpp GetAE_Params
    AE_Params構造体の各メンバの値を獲得します。
    このスケルトンを使う限りこの部分は変更する必要がありません。
  9. MySkeleton.cpp GetMySkeleton_Params


    My_Sketeton構造体へUIから得られた数値を獲得します。
    各UIからの獲得方法のサンプルになっています。
  10. MySkeleton.cpp ERRマクロ


    ERRマクロは、AE_Macros.hで定義されている便利なマクロです。変数PF_Err errを使っていて、関数がエラーを戻したときにERRマクロを使っていれば以後の関数の呼び出しをキャンセルできます。コーディングのタイプ量をかなり減らせます。

    この他にもSDKには便利なマクロがいっぱい定義されているので、積極的に使いましょう。
  11. MytSkeletonMain.cpp
    ソースをわかりやすくするために、描画関係のコードをMytMySkeleton.cppから分離しました。まぁ、このスケルトンには描画コードは一切入っていませんが^^;

MytSkeleton 構成プロパティ

MytSkeletonは、三つの構成を用意してあります。
  1. Debug
    Debug用のランタイム等をリンクしてある構成。
    デバッカーの設定はしてませんので、デバッカーを使用するときは一部設定を変更する必要があります。
  2. Release
    Relese用のランタイム等をリンクしてある構成。ただし、ランタイムパッケージを必要とする物になります。
    ランタイムを要求する代わりにファイルサイズが小さくなります。
  3. Release-MT
    Relese用のランタイム等をリンクしてある構成。ただし、ランタイムパッケージを必要しないものです。
    ランタイムが要らない代わりに、ファイルサイズがでかい。ちょっと遅くて、メモリも少し多く使う(最近のPCでは無視していいレベル)
構成ごとに出力されるaexファイル名を変えていますので、注意です。

プロジェクトのリネーム

スケルトンから新しいプロジェクトを作るのは第2回目の投稿で行った手順でできますが、かなり面倒なので専用のツールを作成しました。

使い方は簡単で、スケルトンの入ったフォルダごと適当に複製してから、(僕はスケルトンをフォルダごとZIP圧縮しておいて使うときに展開してます)このツールのウィンドウにドラッグ&ドロップするか、選択ボタンを押してファイル選択ダイアログで適当なファイルを選びます。



上の図のように読み込まれますので、後は新しい名前を入力し実行するだけです。
ファイル名の変更とファイルの中身の古い名前新しい名前にすべて置換します。
ただし、フォルダの名前は変えませんので、手動でお願いします。

AE_ProjectRename.zipのダウンロード
ソースコードはここからダウンロードできます(C# 2008 express editionで作成)
C#は、ちょっとしたツールを作るのにすごく便利です。機会があればC#も覚えると幸せになれます。
昔はborland Delphiがオススメだったのですが、最近Delphi無料版の使用制限が厳しすぎてほとんどまともなツールが作れなくなったので。

ちょっと作った。 Firework.aex

今回これだけだと寂しかったので、スケルトンから一つプラグインを作ってみました。
単純に適当なアルゴリズムで点を打つプラグインで、パーティクルもどきです。

Firework.zipのダウンロード

パラメータはこんな感じ。


追加したコードは主に二つ。


描画のメイン。ソースとしてはこれだけ。ポイントは乱数の発生をフレームごとに固定化してると,lMinを計算しているところの計算順。固定小数の桁あふれが起きてしまったので、計算の順番を変えて対処してある。

次に角度と距離をXY方向へ変換する関数。パラメータ構造体を定義している。あとコールバック関数を呼び出すサンプルにもなっている。


詳しいアルゴリズムはソースコードから追って欲しい。この短さなら十分に理解できると思う。

FireworkMain.cppではわざと16bit対応のコードを書いていないが、out_flagsでは16bitと設定しているので、16bitモードにすると単純に描画されなくなる。
ここまであれば簡単なので、16bit対応の練習用に使って欲しい。

さらに作った。 aeGraphicsクラス

本当はC++の説明用に作ったモノだけどここで紹介します。

PF_EfefctsWorldを引数にして作成するaeGraphicsクラス。

MyGraphics.zipのダウンロード

C++の機能で具体的には、acGraphics.hをインクルードするだけで使えるようになる(インライン機能)
使い方は簡単で、以下のように使う。


線を描画したり、枠線を描いたり、四角を描く事がBASIC位の気分で行えます。拡張すればN88-BASICのグラフィックと同等くらいの機能は簡単に追加できるでしょう。
acGraphics.hにすべてのコードが入っているのでC++と画像処理の基本の勉強位にはなるので目を通しておいてください。

今回のまとめ

C/C++の事はスルーする言いながら、今回は殆どCの説明でした。C++は流石にやらなかったけど、aeGraphicsクラスのサンプルを見てもらえば分かりますが、覚えると確実に楽になります。
予定してたことでできなかった事にビット演算がありますが、結構面白いので別の機会に説明したいと思います。画像処理を行う上でポインタと同じくらい絶対に覚えないと事ですので。

今後も必ず一回の投稿でサンプルのプラグインを必ず作ってそれをネタにして説明していきたいと思ってます。

次は予定では「PiPLリソースについて」でしたが、「オリジナルノイズフィルタを作ってみよう!」にします。
今回作ったスケルトンを使った簡単なエフェクトフィルタを作成してみます。こっそりPiPlリソースの説明もしますが^^;



タグ : , [タグを追加する]


この記事の投稿者について:bryful

フィードバック

1 Star2 Stars3 Stars4 Stars5 Stars
(評価回数:4 , 平均:5.00)
Loading...Loading...

この記事に対する 6 の反応があります


  1. 1 AEUSERS(AEP Project) 5月 15th, 2010 at 15:33

    新着記事 : アニメ制作者のためのAfterEffectsプラグイン作成入門(第3回) プラグインの改造(修正) スケルトンの作成 http://bit.ly/9uDGiK

  2. 2 遊太郎 5月 15th, 2010 at 16:43

    キタワァ RT @AEUSERS アニメ制作者のためのAfterEffectsプラグイン作成入門(第3回) プラグインの改造(修正) スケルトンの作成 http://bit.ly/bcrxKz #aejp

  3. 3 かれん 5月 16th, 2010 at 10:11

    Now browsing:アニメ制作者のためのAfterEffectsプラグイン作成入門(第3回) プラグインの改造(修正) スケルトンの作成 | AEP Project… http://bit.ly/9F7t6Y

  4. 4 TDG Visual image 5月 16th, 2010 at 10:51

    RT @AEUSERS: 新着記事 : アニメ制作者のためのAfterEffectsプラグイン作成入門(第3回) プラグインの改造(修正) スケルトンの作成 http://bit.ly/9uDGiK

  1. 1 アニメ制作者のためのAfterEffectsプラグイン作成入門(第3回)プラグインの改造(修正)スケルトンの作成 | Tips - After Effects - 動画編集ソフト - アプリケーション | Jishuu.net Pingback on 4月 21st, 2012 at 05:07
  2. 2 アニメ制作者のためのAfter Effectsプラグイン作成入門(第3回)プラグインの改造(修正)スケルトンの作成 | チュートリアル・Tips - After Effects - 動画編集ソフト - アプリケーション | Jishuu.net Pingback on 10月 3rd, 2012 at 20:43

コメントをどうぞ!




特集