FX 特殊効果画像オペレータ
FX 特殊効果画像演算子 • FX 式の構造
FX 特殊効果画像演算子は、画像の各ピクセルチャンネルに数式を適用します。FX 式言語は、画像を操作する強力で柔軟な手段を提供し、画像に対して幅広い演算や変換を実行できます。FX を使うと、次のことができます:
- キャンバス、グラデーション、数学的なカラーマップを作成する
- 画像やチャンネル間で色値を移動する
- 画像を平行移動・反転・鏡映・回転・拡大縮小・せん断、その他一般的に歪ませる
- 複数の画像をマージまたは合成する
- 近傍ピクセルを畳み込んだりマージしたりする
- 画像の指標や「指紋」を生成する
この演算子は、画像のすべてのピクセルと各ピクセルのすべてのチャンネルをループし、結果を含む新しい画像を返します。式は画像シーケンス内の任意の画像を参照できますが、返されるのは最初の画像のコピーに、式に応じた適切な更新を加えたものだけです。
式は単純にもできます:
$ magick -size 64x64 canvas:black -channel blue -fx "1/2" fx_navy.png
ここでは、黒い画像をネイビーブルーの画像に変換します:
あるいは、式は複雑にもできます:
$ magick rose: \
-fx "(1.0/(1.0+exp(10.0*(0.5-u)))-0.006693)*1.0092503" \
rose-sigmoidal.png
この式は、元画像の高コントラスト版を生成します:
式には変数の代入を含められます。代入はたいてい式の複雑さを減らし、他の方法では不可能な操作を可能にします。たとえば、ラジアルグラデーションを作ってみましょう:
$ magick -size 70x70 canvas: \
-fx "Xi=i-w/2; Yj=j-h/2; 1.2*(0.5-hypot(Xi,Yj)/70.0)+0.5" \
radial-gradient.png
上記コマンドはこの画像を返します:
この FX 式は画像にランダムノイズを加えます:
$ magick photo.jpg -fx 'iso=32; rone=rand(); rtwo=rand(); \
myn=sqrt(-2*ln(rone))*cos(2*Pi*rtwo); myntwo=sqrt(-2*ln(rtwo))* \
cos(2*Pi*rone); pnoise=sqrt(p)*myn*sqrt(iso)* \
channel(4.28,3.86,6.68)/255; max(0,p+pnoise)' noisy.png
この FX スクリプトは、ループを使ってジュリア集合を作成します:
$ magick -size 400x400 xc:gray -fx " \
Xi=2.4*i/w-1.2; \
Yj=2.4*j/h-1.2; \
for (pixel=0.0, (hypot(Xi,Yj) < 2.0) && (pixel < 1.0), \
delta=Xi^2-Yj^2; \
Yj=2.0*Xi*Yj+0.2; \
Xi=delta+0.4; \
pixel+=0.00390625 \
); \
pixel == 1.0 ? 0.0 : pixel" \
\( -size 1x1 xc:white xc:red xc:orange xc:yellow xc:green1 xc:cyan xc:blue \
xc:blueviolet xc:white -reverse +append -filter Cubic -resize 1024x1! \) \
-clut -rotate -90 julia-set.png
この FX スクリプトは、最初の 10 個の素数を表示します:
$ magick xc:gray -fx " \
for (prime=2, prime < 30, composite=0; \
for (nn=2, nn < (prime/2+1), if ((prime % nn) == 0, composite++, ); nn++); \
if (composite <= 0, debug(prime), ); prime++)" null:
さらに多くの例は Using FX, The Special Effects Image Operator を参照してください。
-fx オプションは、画像シーケンスを、式の結果で更新した最初の画像のクローンで置き換えます。式をシーケンス内の各画像に適用したい場合は、代わりに +fx を使います。
FX 式は単一スレッドで解釈されますが、式に debug() 関数が含まれない限り、複数スレッドで実行されます。
次のセクションでは FX 式言語を説明します。
FX 式の構造
FX 式言語
正式な FX 式言語をここで定義します:
- numbers:
- 整数、浮動小数点、科学表記(+/− が必要、例: 3.81469e-06)、国際単位系の数値接尾辞(例: KB, Mib, GB など)
- constants:
- E(オイラー数)、Epsilon、Opaque、Phi(黄金比)、Pi、QuantumRange、QuantumScale、Transparent
- FX 演算子(優先順位順):
- ^(べき乗)、単項 -、*、/、%(剰余)、+、-、<<、>>、<、<=、>、>=、+=、-=、*=、/=、%=、<<=、>>=、&=、|=、++、--、==、!=、&(ビット AND)、|(ビット OR)、&&(論理 AND)、||(論理 OR)、~(論理 NOT)、?:(三項条件)
- array:
- 画像は、その幅と高さで境界づけられた配列ストレージを提供します(例: p[-1,-1].r)。画像シーケンスは複数の配列を表します(例: u.p[0,0].r, v.p[0,0].r)。ストレージは Quantum 値に制限されます(例: Q16 ビルドでは [0..65535]、HDRI 有効ビルドでは浮動小数点)。
- math functions:
- abs(), acos(), acosh(), airy(), alt(), asin(), asinh(), atan(), atanh(), atan2(), ceil(), clamp(), cos(), cosh(), debug(), drc(), epoch(), erf(), exp(), floor(), gauss(), gcd(), hypot(), int(), isnan(), j0(), j1(), jinc(), ln(), log(), logtwo(), magicktime(), max(), min(), mod(), not(), pow(), rand(), round(), sign(), sin(), sinc(), sinh(), sqrt(), squish(), tan(), tanh(), trunc()
- channel functions:
- 最大 5 つのピクセルチャンネルを定義する
- color names:
- red, cyan, black など
- color functions:
- srgb(), srgba(), rgb(), rgba(), cmyk(), cmyka(), hsl(), hsla() など
- color hex values:
- #ccc, #cbfed0, #b9e1cc00 など
symbols:
`u`: リスト内の最初の画像
`v`: リスト内の 2 番目の画像
`s`: リスト内の現在の画像(%[fx:] 用。それ以外では = u)
`t`: リスト内の現在の画像(s)のインデックス
`n`: リスト内の画像数
`i`: 列オフセット
`j`: 行オフセット
`p`: 使用するピクセル(絶対、または現在のピクセルからの相対)
`w`: この画像の幅
`h`: この画像の高さ
`z`: チャンネル深度
`r`: 赤値(RGBA から)、特定または現在のピクセルの
`g`: 緑
`b`: 青
`a`: アルファ
`o`: 不透明度
`c`: ピクセルの CMYK 色のシアン値
`y`: イエロー
`m`: マゼンタ
`k`: ブラック
`all`: 全チャンネル
`this`: このチャンネル
`intensity`: ピクセル強度
`hue`: ピクセルの色相
`saturation`: ピクセルの彩度
`lightness`: ピクセルの明度
`luma`: ピクセルのルマ
`page.width`: ページ幅
`page.height`: ページ高さ
`page.x`: ページ x オフセット
`page.y`: ページ y オフセット
`printsize.x`: x 印刷サイズ
`printsize.y`: y 印刷サイズ
`resolution.x`: x 解像度
`resolution.y`: y 解像度
`depth`: 画像深度
`extent`: 画像エクステント
`minima`: 画像の最小値
`maxima`: 画像の最大値
`mean`: 画像の平均
`median`: 画像の中央値
`standard_deviation`: 画像の標準偏差
`kurtosis`: 画像の尖度
`skewness`: 画像の歪度(チャンネル指定子を付けるとそのチャンネルの統計を計算する、例: depth.r)
- iterators:
- do(), for(), while()
- image attributes:
- s.depth, s.kurtosis, s.maxima, s.mean, s.minima, s.resolution.x, s.resolution.y, s.skewness, s.standard_deviation
- user settings:
-
FX シンボルをユーザー設定として定義します。例:
$ magick ... -set option:wd1 "%[fx:w/2]" -resize "%[fx:wd1-5]" ...
FX 式
FX 式には、以下の任意の組み合わせを含められます:
- x
^y - べき乗(x の y 乗)
(...)- グループ化
- x
*y - 乗算
- x
/y - 除算
- x
%y - 剰余
- x
+y - 加算
- x
-y - 減算
- x
<<y - 左シフト
- x
>>y - 右シフト
- x
<y - ブール関係。x < y なら 1.0、それ以外は 0.0 を返す
- x
<=y - ブール関係。x <= y なら 1.0、それ以外は 0.0 を返す
- x
>y - ブール関係。x > y なら 1.0、それ以外は 0.0 を返す
- x
>=y - ブール関係。x >= y なら 1.0、それ以外は 0.0 を返す
- x
==y - ブール関係。epsilon(1e-12)以内で x == y なら 1.0、それ以外は 0.0 を返す。2 値は差が約 1e-12 以内のとき等しいとみなされる。
- x
!=y - ブール関係。epsilon(1e-12)以内で x != y なら 1.0、それ以外は 0.0 を返す
- x
&y - ビット AND
- x
|y - ビット OR
- x
&&y - 論理 AND。x > 0 かつ y > 0 なら 1.0、それ以外は 0.0 を返す
- x
||y - 論理 OR(包含的)。x > 0 または y > 0(両方含む)なら 1.0、それ以外は 0.0 を返す
~x- 論理 NOT 演算子。x > 0 でなければ 1.0、それ以外は 0.0 を返す
+x- 単項プラス。1.0*値 を返す
-x- 単項マイナス。-1.0*値 を返す
- condition
?true-statements:false-statements - 三項条件式。condition != 0 なら true-statements、それ以外は false-statements を返す
- x
=y - 代入。1 文字の変数は予約済みなので、2 文字以上(英字の組み合わせのみ)を使う(例: X1 ではなく Xi)
- x
;y - 文の区切り
phi- 定数(1.618034...)
pi- 定数(3.14159265359...)
e- 定数(2.71828...)
QuantumRange- 最大ピクセル値の定数(Q8 で 255、Q16 で 65535)
QuantumScale- 定数 1.0/
QuantumRange intensity- -intensity オプションを尊重するピクセル強度
hue- ピクセルの色相
saturation- ピクセルの彩度
lightness- ピクセルの明度。0.5*max(red,green,blue) + 0.5*min(red,green,blue) に等しい
luminance- ピクセルの輝度。
0.212656*red + 0.715158*green + 0.072186*blueに等しい red, green, blueなど- 色名
#ccc, #cbfed0, #b9e1cc00など- 色の 16 進数値
rgb(), rgba(), cmyk(), cmyka(), hsl(), hsla()- 色関数
s, t, u, v, n, i, j, w, h, z, r, g, b, a, o, c, y, m, k- シンボル
abs(x)- 絶対値関数
acos(x)- 逆余弦関数
acosh(x)- 逆双曲線余弦関数
airy(x)- エアリー関数(最大 1、最小 0)。airy(x)=[jinc(x)]2=[2*j1(pi*x)/(pi*x)]2
alt(x)- 符号交代関数(int(x) が偶数なら 1.0、奇数なら -1.0 を返す)
asin(x)- 逆正弦関数
asinh(x)- 逆双曲線正弦関数
atan(x)- 逆正接関数
atanh(x)- 逆双曲線正接関数
atan2(y,x)- 2 変数の逆正接関数
ceil(x)- 引数以上の最小の整数値
channel(...)- 0〜5 個の引数をサポートする。例: channel(0.1) は最初のチャンネルを 0.1 に設定し、他のチャンネルを 0 にする
clamp(x)- 値をクランプする
cos(x)- 余弦関数
cosh(x)- 双曲線余弦関数
debug(x)- x を表示する(式のデバッグに有用)
do(statements, condition)- condition が 0 でない間、反復する
drc(x,y)- ダイナミックレンジ圧縮(ニーカーブ)。drc(x,y)=(x)/(y*(x-1)+1); -1<y<1
epoch(date-time)- date-time プロパティを、エポック(00:00:00 UTC)からの秒数に変換する
erf(x)- 誤差関数
exp(x)- 自然指数関数(e の x 乗)
floor(x)- 引数以下の最大の整数値
for(initialize, condition, statements)- condition が 0 でない間、反復する
gauss(x)- ガウス関数。gauss(x)=exp(-x*x/2)/sqrt(2*pi)
gcd(x,y)- 最大公約数
hypot(x,y)- x の 2 乗 + y の 2 乗 の平方根
if(condition, nonzero-statements, zero-statements)- condition に応じて式を解釈する
int(x)- 最大整数関数(x 以下の最大の整数を返す)
isnan(x)- x が NaN なら 1.0、それ以外は 0.0 を返す
j0(x)- x の第 1 種 0 次ベッセル関数
j1(x)- x の第 1 種 1 次ベッセル関数
jinc(x)- jinc 関数(最大 1、最小 -0.1323)。jinc(x)=2*j1(pi*x)/(pi*x)
ln(x)- 自然対数関数
log(x)- 10 を底とする対数
logtwo(x)- 2 を底とする対数
ln(x)- 自然対数
- magicktime()(訳注: 原文は
$ magicktime()。余分な$が混入しています) - エポック(00:00:00 UTC)からの現在時刻(秒)
max(x, y)- x と y の最大値
min(x, y)- x と y の最小値
mod(x, y)- 浮動小数点剰余関数
not(x)- x が 0 なら 1.0、それ以外は 0.0 を返す
pow(x,y)- べき乗関数(x の y 乗)
rand()- 区間 [0.0, 1.0) で一様分布する値(周期は 2 の 128 乗 -1)
round()- 丸め方向によらず整数値に丸める
sign(x)- x が 0.0 未満なら -1.0、それ以外は 1.0 を返す
sin(x)- 正弦関数
sinc(x)- sinc 関数(最大 1、最小 -0.21)。sinc(x)=sin(pi*x)/(pi*x)
squish(x)- squish 関数。squish(x)=1.0/(1.0+exp(-x))
sinh(x)- 双曲線正弦関数
sqrt(x)- 平方根関数
tan(x)- 正接関数
tanh(x)- 双曲線正接関数
trunc(x)- 0 方向へ整数に丸める
while(condition, statements)- condition が 0 でない間、反復する
image.depth, image.kurtosis, image.maxima, image.mean, image.median, image.minima, image.resolution.x, image.resolution.y, image.skewness, image.standard_deviation- 画像属性
式のセマンティクスには次のルールがあります:
- シンボルは大文字小文字を区別しない
- 1 つの文につき三項条件(例: x ? y : z)は 1 つだけ
- 文は代入か、返すための最終式である
- 代入は文を開始する。演算子ではない
- 1 文字の変数は予約済み。予約済み組み込みへの代入は例外をスローする。例:
r=3.0; rは Attempted assignment to non-UserSymbol 'r' at '3.0' を返す - 単項演算子は二項演算子より優先順位が低い。つまり単項マイナス(否定)はべき乗より優先順位が低いため、-3^2 は -(3^2) = -9 と解釈される。意図を明確にするには括弧を使う(例: (-3)^2 = 9)
- スラッシュ('/')記号の使用には注意が必要。文字列 1/2x は (1/2)x と解釈される。逆の解釈は明示的に 1/(2x) と書くべき。ここでも括弧が意味を明確にするので、誤解の余地があるときは常に使うべき
--は変数のデクリメント演算子なので、負の数を引くには括弧を使う。例:-4-(-5)
ソース画像
シンボル u と v は、現在の画像シーケンスのそれぞれ最初と 2 番目の画像を指します。シーケンス内の特定の画像を参照するには、任意の画像参照(通常は u)にそのインデックスを付加します。シーケンスの先頭は 0 です。負のインデックスは末尾から数えます。たとえば u[0] はシーケンスの最初の画像、u[2] は 3 番目、u[-1] は最後の画像、u[t] は現在の画像です。現在の画像は s でも参照できます。シーケンス番号がシーケンス長を超えると、カウントはラップされます。したがって 3 画像のシーケンスでは、u[-1]、u[2]、u[5] はすべて同じ(3 番目の)画像を指します。
例として、最初の画像と 3 番目の画像を平均して画像を作ります(2 番目(インデックス 1)の画像は無視され破棄されます):
$ magick image1.jpg image2.jpg image3.jpg -fx "(u+u[2])/2" image.jpg
既定では、p, r, g, b, a などが適用される画像は、画像リスト内の現在の画像 s です。これは、エスケープシーケンス %[fx:...] 内で使う場合を除いて u と等価です。
最初の画像が果たす特別な役割に注意することが重要です。これは画像シーケンス内で変更される唯一の画像で、他の画像はデータのためだけに使われます。例として次を考えます。設定 -channel red は -fx に緑チャンネルのみを変更するよう指示し、赤や青チャンネルは何も変わりません。結果が対称でない理由を考えてみると有益です。
$ magick logo: -flop logo: -resize "20%" -channel green -fx "(u+v)/2" image.jpg
ピクセルへのアクセス
すべての色値は 0.0〜1.0 の範囲に正規化されます。アルファチャンネルは 0.0(完全透明)から 1.0(完全不透明)の範囲です。
ピクセルは 1 つずつ処理されますが、p で表されるピクセルインデックスを使って画像の別のピクセルを指定できます。例:
p[-1].g 現在のピクセルのすぐ左のピクセルの緑値
p[-1,-1].r 現在のピクセルから斜め左上のピクセルの赤値
絶対位置を指定するには、角括弧ではなく波括弧を使います。
p{0,0}.r 画像の左上隅のピクセルの赤値
p{12,34}.b 画像の列 12、行 34 のピクセルの青値
位置が整数値なら参照先ピクセルの色を取得し、非整数値なら現在の -interpolate 設定に従ってブレンドされた色を返します。
画像の境界外の位置は、-virtual-pixel オプション設定で決まる値を取得します。
現在の画像の赤チャンネルを指定するには u.r とします。チャンネル修飾子を指定しないと、現在のチャンネルが得られます。出力チャンネルを入力チャンネルだけの平均に設定するには mean.this を、入力チャンネル全体の平均に設定するには mean.all を使います。
式を選択した画像チャンネルに適用する
結果の出力チャンネルを指定するには -channel 設定を使います。出力チャンネルが指定されない場合、結果は不透明度チャンネルを除くすべてのチャンネルに設定されます。たとえば、alpha.png の赤チャンネルを、画像 alpha.png と beta.png の緑チャンネルの平均で置き換えるには:
$ magick alpha.png beta.png -channel red -fx "(u.g+v.g)/2" gamma.png
結果
-fx 演算子は、シーケンスの最初の画像(u)の各ピクセルの各チャンネル(-channel で設定)について、与えられた式を評価します。計算された値は、すべてのピクセルが処理されるまでその最初の画像のコピー(クローン)に一時的に格納され、その後この単一の新しい画像が現在の画像シーケンスのリストを置き換えます。したがって前の例では、更新版の alpha.png が、gamma.png として保存される前に、元の 2 つの画像 alpha.png と beta.png の両方を置き換えます。
現在の画像 s はシーケンスの最初の画像(u)に、t はそのインデックス 0 に設定されます。シンボル i と j は処理中の現在のピクセルを参照します。
-format と併用する場合、値エスケープ %[fx:] は現在の画像シーケンスの各画像につき 1 回だけ評価されます。シーケンスの各画像が評価される際、s と t はそれぞれ現在の画像とそのインデックスを参照し、i と j は 0 に、現在のチャンネルは赤に設定されます(-channel は無視されます)。例:
$ magick canvas:'rgb(25%,50%,75%)' rose: -colorspace gray \
-format 'Red channel of NW corner of image #%[fx:t] is %[fx:s]\n' info:
Red channel of NW corner of image #0 is 0.464883
Red channel of NW corner of image #1 is 0.184582
ここでは画像インデックスを使って各画像を異なる角度で回転させ、-set と画像インデックスを使ってアニメーションの最初の画像に異なる一時停止遅延を設定します:
$ magick rose: -duplicate 29 -virtual-pixel Gray -distort SRT '%[fx:360.0*t/n]' \
-set delay '%[fx:t == 0 ? 240 : 10]' -loop 0 rose.gif
この例は、RMSE で測定した 2 枚の画像の差分をテストします。差分が 0.1 より大きければ 1 を、それ以外は 0 を返します:
$ magick water.png reference.png -metric RMSE -compare -format "%[fx:%[distortion]>0.1]" info:
色エスケープ %[pixel:] や %[hex:] は、画像ごと・その画像の色チャンネルごとに 1 回評価されます(-channel は無視されます)。生成された値は色文字列(色名または 16 進色値)に変換されます。シンボル i と j は 0 に設定され、s と t はそれぞれ順次の現在の画像とインデックスを参照します。
epoch() メソッドは date-time プロパティを取ります。例:
$ magick rose.png -precision 16 -format '%[fx:epoch(%%[date:modify])]' info:






