今回のお題
画像の縦横比から透かし文字の角度とサイズを自動設定する
前回の記事シェルスクリプトで画像処理(6)ImageMagick編2その後になります
メンテナンスの簡略化こそ達成しましたが、結局画像の縦横比が違うものについてはスクリプトを別に作っていたために、似たようなスクリプトが乱立する事態になってしまいました
問題は透かし文字の入れ方で、斜めに入れているため結構面倒なことになります
単純に3:2の拡大縮小ならば文字サイズを変えるだけで良いのですが
・縦横比が変わると角度を変えなければいけない
・角度が変わると単純に長辺(あるいは短辺)の比という訳にいかない
ということになります
真面目に数学をしないといけませんね\(;゚∇゚)/
「数学できんが、なんで悪いとや!」
なんて言ってると、こんな時困るという見本ですw
●まず角度の算出
幅と高さが解れば三角関数から角度を導けます
tanθ= height(pixel) / width(pixel) が成立するので
θ= arctan(height / width) となります ※arctan(a / b)はtanθの逆関数です
シェルスクリプトに実装する場合は
theta=`echo "a(${height}/${width})" | bc -l`
height…高さのピクセル数を入れた変数
width…幅のピクセル数を入れた変数
bcコマンドにオプション”-l”を付けることで関数a(arctan)が使えるようになります
結果は変数thetaに格納されますが、単位はラジアン(radian)です
ラジアンって何?って人は「弧度法」で検索して勉強すべし
しかしImagemagickのannotateオプションの角度はお馴染みの度数法(degree)なので変換が必要です(1rad≒57.3°)
thetaD=`echo "${theta}*57.2957795130823" | bc`
まぁ定数変換なので、お手軽にこれで良いんではないかと、scaleはお好みで
どうしてもπ絡みの数値をベタうちではなく、算出したい場合は先ほどのarctanが使えます
垂辺と底辺の長さが等しい直角三角形、つまり直角二等辺三角形の鋭角は 45°=π/4rad なので、tan(π/4)=1/1
逆関数を使って arctan(1/1)=π/4 すなわち arctan(1)*4=π となりますから、シェルスクリプトに実装すると(変数PIに円周率を格納)
PI=`echo "scale=12; a(1)*4" | bc -l`
になります
また1radは
RAD=`echo "scale=12; 180/(a(1)*4)" | bc -l`
となりますね(変数 RAD には 57.295779513082…が格納されます)
●次に文字サイズの算出
文字の全体長、つまり直角三角形の斜辺をcとするとピタゴラスの定理から
c ^ 2 = width ^ 2 + height ^ 2 ※” ^ “は、べき乗を表します
c = √(width ^ 2 + height ^ 2) となります
シェルスクリプトに実装する場合は
c=`echo "sqrt(${widthN} ^ 2 + ${heightN} ^ 2) " | bc -l`
bcコマンドにオプション”-l”を付けることで関数sqrt(平方根)が使えるようになります
あとはcを文字種/テキスト長に合わせて適当な定数を決めて割れば良い訳ですね
上記スクリプトにその割り算も加えて、cを文字サイズとしてを算出するのも良いでしょう
後は
convert -pointsize ${c} (中略) -annotate -${thetaD} (以下略)
とすれば良い訳です(変数cは定数で割った後という前提)
—
さて、もう一つ厄介な問題ですが、縦横を任意の整数比で縮小するのが意外に面倒なんです
元々シェル自体小数を扱うのが面倒な上に、四捨五入が「ほぼ」できないんですね
さらに追い打ちをかけるのが、デジタル一眼レフカメラのセンサーのアスペクト比がぴったり3:2ではないことです
上手い具合に端数を丸めてなるべく綺麗な整数比に縮小しなければなりません
まぁ早い話、縦横比3:2だろうが4:3だろうが16:9だろうが、ターゲットの長辺サイズを決めてあげれば、何とか上手い具合に縦横比を維持したまま、キリの良いpixel数に縮小してくれるものを作ろうというわけです
手順
1.長辺サイズ(任意)を入力
web掲載等を考えるとあまり中途半端な数字は嫌なのと、今まで掲載した画像サイズから40の倍数というルールにしました
とりあえず”LONG”という変数に入れることにします
2.ターゲットの長辺に縮小するための係数(比率)を求める
coef=`echo “scale=6; ${width} / ${LONG}” | bc`
ここでは横長画像を例にしています
オリジナルの幅widthをターゲットサイズのLONGで割り、係数をcoefに代入
3.係数とオリジナルの高さから縮小後の高さを算出
heightN=`awk ‘BEGIN {print int(‘${height}’ / ‘${coef}’ / 40 + 0.5)*40}’`
ここが肝ですね
シェルコマンドではscaleを使うことで任意の桁で切り捨てができますが、式(ライン)全体に適用されてしまいます
ここではawkコマンドに入ることで、式の前半の括弧内で小数点以下の計算をして、最終的に40pixelブロックの個数(整数)に四捨五入しています
あとはこの数値を40倍すれば、40pixel単位の数値が出てくるという仕組みです
※awkコマンドのintは切り捨てなので、”+0.5″で事実上四捨五入にしています
heightはオリジナルの高さ、heightNはターゲットの高さ(短辺)が入ります
ここまでやって、やっとこさ
・ブログ作成用サイズ何でも来いバージョン(基本形)
・透かし文字が違うよバージョン
・透かしとjpeg圧縮しないよバージョン(納品用)
の3つに集約できました
DLのたびに通知が出てすごく邪魔だったんで助かりました。