利用シーン
Laravelで開発をしていて、サーバーに画像を沢山アップすることが想定されるとき。
背景
Intervention ImageはPHPで扱える画像処理のライブラリ。
blurをかけたり、縦横幅をリサイズしたり、回転させたりと多岐にわたる機能を実現している。
http://image.intervention.io/
しかし, 画像の容量を1MB未満に抑えたい、という要求に対してストレートに応えてくれる機能はない。(もし見つけたらご教示ください)
他のライブラリを探すのも面倒なので、機能を組み合わせて自分で作ってしまえばいいやということで関数を作ってみました。
コード
/**
* @param UploadedFile $img_file 画像ファイル(*今回はUploadedFileを利用)
* @param string $path 画像の保存パス
* @param int $quality 画像の解像度の初期設定
* @param int $size ここまで下げたいという画像サイズの値
*/
public function compressImage(UploadedFile $img_file, string $path, int $quality, $size)
{
$image = Image::make($img_file);
$image->save($path, $quality);
// クオリティを下げた後のファイルサイズが十分下がっていなければもう一度関数を呼び出す
$image = Image::make($path);
if($image->filesize() > $size){
$quality -= 5;
return $this->compressImage($img_file, $path, $quality, $size);
}
}
解説
$image = Image::make($img_file);
$image->save($path, $quality);
画像ファイルを読み込み、save()メソッドで任意の解像度に下げて保存。
*ドキュメントにはデフォルトで90と書いてありますが80未満で設定しておくと吉。
http://image.intervention.io/api/save
$image = Image::make($path);
if($image->filesize() > $size){
$quality -= 5;
return $this->compressImage($img_file, $path, $quality, $size);
}
保存した画像を改めて読み込み、
filesize()メソッドで画像のファイル容量を確認。
ファイル容量が設定したサイズ(1MBなら1024000を入力)よりも大きければ、
解像度を5低く設定してもう一度同じ関数を再帰的に呼び出す。
使い方
この関数をヘルパ関数として登録して
$file = $request->file('img');
$path = "your/path";
$quality = 80;
$size = 1024000;
$resized_img = compressImage($file, $path, $quality, $size);
とすれば使えます。
終わりに
もし他に良い方法や改善できる箇所がありましたらご教示ください。