Help us understand the problem. What is going on with this article?

PHPで画像のリサイズ&圧縮する方法を比較する

More than 1 year has passed since last update.

この記事は一人PHP総復習 Advent Calendar 20164日目の記事です。
いきなり内容が飛びますが、進捗がやばいので一旦書きます汗

PHPで画像をリサイズ&圧縮する際、どのライブラリを使うのがよいのか迷っていくつか調べたのでまとめておきます。
Laravelの記法などを大いに含むので、How toは参考程度にしてください。

サンプルでは保存をjpgにしてますが、元ファイルの拡張子を取得などしてください。あと本来必要なエラー処理とかも省いています。

試した環境

  • PHP7
  • Laravel5.3

php-gd

PHP拡張モジュールのGDを使う方法です。
導入はこちらの記事などを参考に。

PHPの拡張モジュールGDが動くまでの試行錯誤

How to

$h = 200; // リサイズしたい大きさを指定
$w = 200;

$file = $request->file; // 加工したいファイルを指定

// 加工前の画像の情報を取得
list($original_w, $original_h, $type) = getimagesize($file);

// 加工前のファイルをフォーマット別に読み出す(この他にも対応可能なフォーマット有り)
switch ($type) {
    case IMAGETYPE_JPEG:
        $original_image = imagecreatefromjpeg($file);
        break;
    case IMAGETYPE_PNG:
        $original_image = imagecreatefrompng($file);
        break;
    case IMAGETYPE_GIF:
        $original_image = imagecreatefromgif($file);
        break;
    default:
        throw new RuntimeException('対応していないファイル形式です。: ', $type);
}

// 新しく描画するキャンバスを作成
$canvas = imagecreatetruecolor($w, $h);
imagecopyresampled($canvas, $original_image, 0,0,0,0, $w, $h, $original_w, $original_h);

$resize_path = public_path('image/new.jpg'); // 保存先を指定

switch ($type) {
    case IMAGETYPE_JPEG:
        imagejpeg($canvas, $resize_path);
        break;
    case IMAGETYPE_PNG:
        imagepng($canvas, $resize_path, 9);
        break;
    case IMAGETYPE_GIF:
        imagegif($canvas, $resize_path);
        break;
}

// 読み出したファイルは消去
imagedestroy($original_image);
imagedestroy($canvas);

特徴

  • フォーマット別に処理を分けなくてはいけない
  • フォーマット別に圧縮率を分けやすい
  • 元画像の情報を取得しなくてはいけない
  • 基本の処理だけなら十分

Imagick

画像処理ツールImageMagickをPHPから使う拡張モジュールです。
導入はこちらの記事などを参考に。
CentOS6 上のPHPでImageMagickを動かす

How to

$w = 200; // リサイズしたい大きさを指定
$h = 200;

$file = $request->file; // 加工したいファイルを指定
$resize_path = public_path('image/new.jpg'); // 保存先を指定

// 加工するファイルを読み出し
$original_image =  new Imagick($file);
$original_image->resizeImage($w, $h, Imagick::FILTER_LANCZOS, 1);
$original_image->writeImage($resize_path);

// 読み出したイメージは消去
$original_image->destroy();

特徴

  • 対応フォーマット、できる処理はかなり多い
  • 加工後のファイルサイズが大きくなる
  • リサイズ・圧縮だけならオーバースペック感

Intervention/Image

LaravelプラグインのIntervention/Imageを使う方法です。
GDとImagickをラップしています。

導入、設定などはこちらの記事などを参考に。
Laravel5 Intervention Image 2.xを利用した画像加工

How to

$h = 200; // リサイズしたい大きさを指定
$w = 200;

$resize_path = public_path('image/new.jpg'); // 保存先を指定

$original_image = Image::make($file->path);
$original_image->resize($w, $h);

$original_image->save($resize_path);

サイズが片方だけ指定されているときは元画像の縦横比に合わせてリサイズしてくれます。

$image->resize(200, null, function ($constraint) {
    $constraint->aspectRatio();
});

特徴

  • 簡潔に記述できる
  • 圧縮率は一括指定できるが、PNG、GIFなどは未対応
  • 基本的にこれで良さそう

まとめ

Intervention/ImageはGDもImagickもラップしてくれているので、基本的にこれを選択するので良さそうです。(他にユースケースがあれば教えてください:bow:
あとIntervention/Imageでもpngとか圧縮したい場合はどうするのがベストなのでしょう・・。場合分けしてベタの関数書くしかないのかな。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away