After Effects エフェクトプラグインをゼロから作って見よう 6回目 "Mult"
今回から実用的なエフェクトを作っていきます。
"Mult"とはMultiplication(乗算)の事でまぁ画像処理の基本みたいなものです。わかりやすく言うと"Unmult"ですね。
Next F's Plugins
今回から実用的なプラグインとして作るので、ちゃんとした方針を決めようと思ってます。
F's Pluginsではバージョン管理がアバウトで上位互換に注意して作っていたせいでもありますが、バージョン違いでトラブルが多かった反省があります。
最初、リリースから1年しか動かない機能をつけて強制バージョンアップを企んでいましたが、結局いろいろな副作用が出るのが怖いので、バージョン名をつけてわかりやすくすることにしました。
NFP-Avior_Channel / NF-Mult
今後"NFP-Avior_Channl" とメニューに表示します。
NFP-"バージョン名称"_”エフェクトカテゴリ"って感じです。
ベータ版のプラグインはNFP-Avior(Beta)になります。
NFPはNext F's pluginの略語、Avior(アヴィオール)はバージョン名称でとりあえずAで始まる星の名前から決めました。
使用プラグインリストに NFP-Avior「エフズプラグイン、アヴィオール」って書いておけば区別しやすいかなと。次のバージョンはNFP-Bellatrix(ベラトリクス)にしようかなとか思ってます(まだ未定)
Download
いつも通りGtihubからDL出来ます。_dlフォルダにWindowsバイナリーがあります。正式版になったらちゃんとリリースします。
NF-Mult.aexからもDL出来ます。
NF-Mult(乗算)
このプラグインは乗算関係のエフェクトで以下の機能を持っています。
Unmult まぁ有名なプラグインありますが、あれと同じ機能です別名「黒抜き」
Mult Unmultの逆、透明部分を黒で塗りつぶす物です。F's AlphaFixと同じ機能です。
ToStraight
ToPremultiplited
ToStraightとToPremultiplitedはわかりにくいですが、以下のリンクで説明されています。
AfterEffectsの「フッテージを設定」の「ストレート」「合成チャンネル」の事です。
まぁ簡単に言うと「RGBの値にalphaの値を乗算した状態」がPremultiplited、そうじゃない状態をStraightです。
通常AfterEffectsの内部データは基本Straight(ストレート-マットなし)で扱われています。
なんでPremultiplitedがあるのかというと説明がとても難しいのですが、まぁ画像合成する場合必ずPremultiplitedにしないといけないので、昔の非力のPCでは都合が良かったって事です。
このプラグインのその状態を変換するエフェクトってことになります。標準プラグインでは「チャンネルコンバイナー」でもその機能があります。
まぁ基本的な機能ってことです。
Multエフェクト
Mult8(
void* refcon,
A_long xL,
A_long yL,
PF_Pixel8* inP,
PF_Pixel8* outP)
{
PF_Err err = PF_Err_NONE;
if (inP->alpha == PF_MAX_CHAN8)
{
*outP = *inP;
}
else if (inP->alpha==0) {
outP->red = 0;
outP->green = 0;
outP->blue = 0;
outP->alpha = PF_MAX_CHAN8;
}
else {
PF_FpLong a = (PF_FpLong)inP->alpha / PF_MAX_CHAN8;
outP->red = RoundByteFpLong((PF_FpLong)inP->red * a);
outP->green = RoundByteFpLong((PF_FpLong)inP->green * a);
outP->blue = RoundByteFpLong((PF_FpLong)inP->blue * a);
outP->alpha = PF_MAX_CHAN8;
}
return err;
}
Multエフェクトのソースですが、簡単です。
RGBの値にアルファーの値を乗算しているだけです。アルファーが0と最大値の場合は計算する必要がないので分岐させて高速化をしています。
Unmultエフェクト
Unmult8(
void* refcon,
A_long xL,
A_long yL,
PF_Pixel8* inP,
PF_Pixel8* outP)
{
PF_Err err = PF_Err_NONE;
if (inP->alpha == 0) {
*outP = { 0,0,0,0 };
}
else {
PF_FpLong r = 0;
PF_FpLong g = 0;
PF_FpLong b = 0;
PF_FpLong a = PF_MAX_CHAN8;
if (inP->alpha == PF_MAX_CHAN8)
{
r = (PF_FpLong)inP->red;
g = (PF_FpLong)inP->green;
b = (PF_FpLong)inP->blue;
}
else {
PF_FpLong a = (PF_FpLong)inP->alpha / PF_MAX_CHAN8;
r = ((PF_FpLong)inP->red * a);
g = ((PF_FpLong)inP->green * a);
b = ((PF_FpLong)inP->blue * a);
}
a = MAX(r, MAX(g, b));
outP->alpha = RoundByteFpLong(a);
a = PF_MAX_CHAN8 / a;
outP->red = RoundByteFpLong(r * a);
outP->green = RoundByteFpLong(g * a);
outP->blue = RoundByteFpLong(b * a);
}
return err;
}
Unmultのコードです。
まずPremultiplitedの状態(上記のMultの処理)にします。これでアルファーの値は無視できることになります。
その後RGBの値の最大値をアルファーとして、RGBの値をStraight状態に戻します。
多分Unmultも同じアルゴリズムだと思います。ポイントはアルファーの値をRGBの最大値にすること。輝度や光度ではないです。
後はアルファーの値を除算するだけです。
ToPremultiplitedエフェクト
ToPremult8(
void* refcon,
A_long xL,
A_long yL,
PF_Pixel8* inP,
PF_Pixel8* outP)
{
PF_Err err = PF_Err_NONE;
if (inP->alpha == 0) {
*outP = { 0,0,0,0 };
}
else {
if (inP->alpha == PF_MAX_CHAN8)
{
*outP = *inP;
}
else {
PF_FpLong a = (PF_FpLong)inP->alpha / PF_MAX_CHAN8;
outP->red = RoundByteFpLong((PF_FpLong)inP->red * a);
outP->green = RoundByteFpLong((PF_FpLong)inP->green * a);
outP->blue = RoundByteFpLong((PF_FpLong)inP->blue * a);
outP->alpha = inP->alpha;
}
}
return err;
}
Multエフェクトでアルファーを最大値にしないでアルファーをそのままにしただけです。
ToStraightエフェクト
static PF_Err
ToStraight8(
void* refcon,
A_long xL,
A_long yL,
PF_Pixel8* inP,
PF_Pixel8* outP)
{
PF_Err err = PF_Err_NONE;
if (inP->alpha == 0) {
*outP = { 0,0,0,0 };
}
else {
if (inP->alpha == PF_MAX_CHAN8)
{
*outP = *inP;
}
else {
PF_FpLong a = PF_MAX_CHAN8/(PF_FpLong)inP->alpha;
outP->red = RoundByteFpLong((PF_FpLong)inP->red * a);
outP->green = RoundByteFpLong((PF_FpLong)inP->green * a);
outP->blue = RoundByteFpLong((PF_FpLong)inP->blue * a);
outP->alpha = inP->alpha;
}
}
return err;
}
これも簡単でアルファーの値でRGB値を除算しているだけです。
MultプラグインとF's Plugins
F's AlphaFix
F's Premultiply
F's CreateAlpha
上記の三つをまとめたプラグインになります。機能的には全部同じなのでまとめました。将来的にはMultの処理はかなり使うのでLibraryの方へ移動させようと思っています(実はすでにNFWorldクラスには実装されている)
最後に
こんな感じにF's PluginsをNFPへ移植していくつもりです。
とりあえず今年いっぱい目標です。
頑張ります。