なんか似たようなエントリが続いていて恐縮ですが、
同じようなことをしばらく続けているとやはりそういうことになるわけでして。
今回はバグと言えばバグだし、「こういう機能だ」と言われればそれまで、というものです。
さて、CodeIgniterにはimage_libというライブラリがありまして、
これがgdやImageMagickのラッパになっているわけです。
デフォルトがgdなわけですが、引数でImageMagickと渡してやるだけで使えることになっています。
で、やろうとしたことは、
・アップロードで受け取ったデジカメなどで撮った画像を定められた大きさの正方形に加工
というものです。
画像処理の流れは
・縦長か横長かを判定
・余分な部分をカット
ということになるはずです。
縦長/横長を判定するのは、まず短辺が指定のサイズになるよう縮小/拡大する必要があるためですね。
判定結果は、
$config['maintain_ratio'] = TRUE;
$config['height'] = 50;
$config['width'] = 50;
$config['master_dim'] = ‘width’;
$this->load->library(‘image_lib’, $config);
$this->image_lib->resize();
のmaster_dimをheight/widthどっちに指定するかに使います。
次にcrop()を使うわけですが、このメソッドの数値の指定はちょっと癖があります。
この部分のドキュメントは
切り抜きメソッドは、次のように切り取る場所を指定する X および Y 軸 (ピクセル) を設定する必要があるのを除いて、 リサイズメソッドと大体同じように動作します:
と書かれています。
さらっと読むと「0〜X, 0〜Y」が切り抜き範囲なのかなと思ってしまうのですが、
実はこれは逆で、「X〜, Y〜」が切り抜き範囲なのです。
(0,0は画像左上端です)
ある大きさの画像を「左上端から50×50で切り抜きたい」とした場合、
オプションへの数値が渡しようがないように見えます。
$config['x_axis'] = 50;
$config['x_axis'] = 50;
$this->load->library(‘image_lib’, $config);
$this->image_lib->crop();
では、「X=50, Y=50から画像終端まで」の切り抜きになってしまうからです。
で、ソースを見てみることにしました。
PHPでImageMagickを直接に使う場合、PECLのimageickライブラリを入れることが結構あるかと思いますが、CodeIgniterのimage_libの内部ではexecを叩いています。
つまり、
$this->load->library(‘image_lib’, $config);
とする時のオプション$configは、そのままconvertコマンドへ渡されるわけです。
ということは、先ほどのx_axis, y_axisの指定方法は、
CodeIgniterの問題ではなくImageMagickのオプションの指定方法の問題です。
ImageMagickをコマンドラインで叩く場合には、
convert -resize 50×50+25+25 file_org file_dist
というようにオプションを指定します。上記の例の場合は、
・50×50にリサイズした上でX=25, Y=25から画像の終端までを切り抜く
ということになります。
となると、「じゃあ0〜X, 0〜Yに切り取るのはどーするんだ?」ということになりますね。
covertコマンドで叩く場合、上記の例を0〜X, 0〜Yで切り抜くには
convert -resize 50×50-10-10 file_org file_dist
とします。この場合は
・50×50にリサイズした上で、画像左上端から10×10を切り抜く
ということになります。
反転させる場合にはマイナス指定、というのは、こういうものではよくある指定ですよね。
さて、ではCodeIgniterで
$config['x_axis'] = -50;
$config['x_axis'] = -50;
$this->load->library(‘image_lib’, $config);
$this->image_lib->crop();
のように指定してみるとどうなるか。
…これは動作しません。image_libライブラリの580行目に、その答えがあります。
$cmd .= ” -crop “.$this->width.”x”.$this->height.”+”.$this->x_axis.”+”.$this->y_axis.” \”$this->full_src_path\” \”$this->full_dst_path\” 2>&1″;
まさかのプラス決め打ち!!右下側切り抜くことしか想定されていないとは!
…で、あまりキレイではありませんができるだけ元を残してこんな感じに修正。
— system/libraries/Image_lib.php 2011-03-28 16:25:12.000000000 +0900
+++ application/libraries/Image_lib.php 2011-06-08 23:52:47.000000000 +0900
@@ -577,7 +577,17 @@
if ($action == ‘crop’)
{
- $cmd .= ” -crop “.$this->width.”x”.$this->height.”+”.$this->x_axis.”+”.$this->y_axis.” \”$this->full_src_path\” \”$this->full_dst_path\” 2>&1″;
+ if($this->x_axis<0){
+ $x_axis = $this->x_axis;
+ }else{
+ $x_axis = “+”.$this->x_axis;
+ }
+ if($this->y_axis<0){
+ $y_axis = $this->y_axis;
+ }else{
+ $y_axis = “+”.$this->y_axis;
+ }
+ $cmd .= ” -crop “.$this->width.”x”.$this->height.$x_axis.$y_axis.” \”$this->full_src_path\” \”$this->full_dst_path\” 2>&1″;
}
elseif ($action == ‘rotate’)
{
で、ちゃんと意図した通りに切り抜いてくれました。
system/libraries/Image_lib.php をapplication/libraries/Image_lib.php としてコピーして修正すれば上書き実行されるのでその点は便利。
このライブラリ、ExpressionEngineのコードだと冒頭コメントで宣言されているんですが、
大丈夫なのかExpressionEngine…。
バグ報告くらい上がってそうだと思ったんですが、
CodeIgniterの方にも、
https://bitbucket.org/ellislab/codeigniter/issues?q=image_lib
CI Reactorの方にも無いんですよねえ…。
https://bitbucket.org/ellislab/codeigniter-reactor/issues?q=image_lib
もうみんなそういう機能だと思って使ってるんでしょうかね?