PHPで画像リサイズするプログラム解説

2022年10月11日プログラムPHP,プログラムサンプル

PHPで画像リサイズするプログラム解説
PHPで画像リサイズするプログラム解説

PHPで画像のサイズ変更するプログラムをサンプルコードで解説します。今回はGDを使って画像のリサイズを行います。

画像をアップロードするシステムを構築する際に「画像のサイズを変更してアップロードしてほしい」などの要件がよくあります。

今回はそういった画像アップロードする際に画像をリサイズして出力するプログラムの解説を行います。

ユート

PHPでアップロードされた画像をリサイズするプログラム解説です。

プログラムの解説部分は公開後に追記します。

PHPで画像編集するのにお悩みの人は、ぜひ参考にしてください。

環境

  • PHP
  • GD

使用する画像ファイル

ぱくたそ:https://www.pakutaso.com/20220429101post-36967.html

ぱくたそ:https://www.pakutaso.com/20220550122post-40137.html

参考記事

PHPで画像リサイズするプログラムを解説

PHPで画像のサイズを変更するプログラムの解説を行います。
(このサンプルだと画像の縦横比が崩れて画像が出力されます。なので、比率を保ちたい場合は後述するサンプルコードを参考にしてください。)

サンプルコード

PHPで画像のサイズを変更するシステムのサンプルコードです。

<?php
$error = '';
do {
    $gazo = @$_FILES['gazo'];
    if (!$gazo) {
        break;
    }

    if (!$gazo['size'] || $gazo['size'] <= 0) {
        $error = '画像がアップロードされていません。';
        break;
    }

    if (checkFileError($gazo) !== true) {
        $error = '画像のアップロードに失敗しました。';
        break;
    }

    // tmpファイル名を取得
    $file_name = $gazo['tmp_name'];

    // 画像サイズを読み込む
    list($w_src, $h_src) = getimagesize($file_name);
    if (!$w_src || !$h_src) {
        $error = '画像サイズの読み込みに失敗しました。';
        break;
    }

    // 画像タイプを判断して画像を読み込む
    $image_src = null;
    $finfo = new finfo();
    $mime_type = $finfo->file($file_name, FILEINFO_MIME_TYPE);
    switch ($mime_type) {
        case 'image/jpeg':
            $image_src = imagecreatefromjpeg($file_name);
            break;
        case 'image/png':
            $image_src = imagecreatefrompng($file_name);
            break;
        case 'image/gif':
            $image_src= imagecreatefromgif($file_name);
            break;
        default:
            break;
    }
    if (!$image_src) {
        $error = 'jpeg,png,gif以外は読み込めません。';
        break;
    }

    // 画像を変更するサイズ
    $w = $h = 250;

    // 読み込んだ画像をコピー
    $image = imagecreatetruecolor($w, $h);
    if (!$image) {
        $error = '画像の複製に失敗しました。';
        break;
    }

    // 画像をサンプリング
    imagecopyresampled($image, $image_src, 0, 0, 0, 0, $w, $h, $w_src, $h_src);
    if (!$image) {
        $error = '画像のサンプリングに失敗しました。';
        break;
    }

    // 画像を出力
    header('Content-Type: ' . $mime_type);
    switch ($mime_type) {
        case 'image/jpeg':
            imagejpeg($image);
            break;
        case 'image/png':
            imagepng($image);
            break;
        case 'image/gif':
            imagegif($image);
            break;
        default:
            break;
    }
    exit;

} while(0);

/**
 * ファイルのエラーチェック
 */
function checkFileError($file = null)
{
    if (!$file) return false;

    switch ($file['error'])
    {
        case UPLOAD_ERR_INI_SIZE:
        case UPLOAD_ERR_FORM_SIZE:
            return false;
        case UPLOAD_ERR_PARTIAL:
            return false;
        case UPLOAD_ERR_NO_FILE:
            return false;
        case UPLOAD_ERR_NO_TMP_DIR:
        case UPLOAD_ERR_CANT_WRITE:
        case UPLOAD_ERR_EXTENSION:
            return false;
        default:
            break;
    }

    return true;
}

?>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Image</title>
    </head>
    <body>
        <h1>Image</h1>
        <form method="post" action="/sample/php/image/index.php" enctype="multipart/form-data">
            <input type="file" name="gazo">
            <?php if ($error) : ?>
            <p><?php echo $error ?></p>
            <?php endif; ?>
            <input type="submit">
            <!-- button type="submit">送信</button -->
        </form>
    </body>
</html>

出力画像

出力画像は、500×500で画像をリサイズしているので画像の比率が変わって圧縮されて出力されます。
(比率を保ってリサイズするプログラムは後述します)

HTMLの解説

PHPで画像のサイズを変更するシステムのサンプルコードのHTML部分を解説します。

文字コードをUTF-8で指定

HTMLの文字コードをUTF-8で指定します。これで文字化けが起こらないようにします。

<meta charset="UTF-8">

formタグを設置

<form method="post" action="/sample/php/image/index.php" enctype="multipart/form-data">

input type="file"タグを設置

<input type="file" name="gazo">

PHPの解説

PHPで画像のサイズを変更するシステムのサンプルコードのPHP部分を解説します。

do{}while(0)で処理を囲む

do {
    ・・・
} while(0);

アップロードされたファイルを取得

$gazo = @$_FILES['gazo'];
if (!$gazo) {
    break;
}

アップロードされたファイルのサイズを確認

if (!$gazo['size'] || $gazo['size'] <= 0) {
    $error = '画像がアップロードされていません。';
    break;
}

アップロードされた画像ファイルの縦横サイズを取得

list($w_src, $h_src) = getimagesize($file_name);
if (!$w_src || !$h_src) {
    $error = '画像サイズの読み込みに失敗しました。';
    break;
}

アップロードされた画像ファイルを読み込む

$image_src = null;
$finfo = new finfo();
$mime_type = $finfo->file($file_name, FILEINFO_MIME_TYPE);
switch ($mime_type) {
    case 'image/jpeg':
        $image_src = imagecreatefromjpeg($file_name);
        break;
    case 'image/png':
        $image_src = imagecreatefrompng($file_name);
        break;
    case 'image/gif':
        $image_src= imagecreatefromgif($file_name);
        break;
    default:
        break;
}
if (!$image_src) {
    $error = 'jpeg,png,gif以外は読み込めません。';
    break;
}

画像を250×250で作成

$w = $h = 250;
$image = imagecreatetruecolor($w, $h);
if (!$image) {
    $error = '画像の複製に失敗しました。';
    break;
}

作成した250×250の画像にアップロードした画像をサンプリング

  • imagecopyresampled()
    • $image → コピー先の画像
    • $image_src → コピー元の画像
    • 0 → コピー先の x 座標
    • 0 → コピー先の y 座標
    • 0 → コピー元の x 座標
    • 0 → コピー元の y 座標
    • $w → コピー先の幅
    • $h → コピー先の高さ
    • $w_src → コピー元の幅
    • $h_src → コピー元の高さ
imagecopyresampled($image, $image_src, 0, 0, 0, 0, $w, $h, $w_src, $h_src);
if (!$image) {
    $error = '画像のサンプリングに失敗しました。';
    break;
}

画像を出力

画像のバイナリーデータが表示されるので「header('Content-Type: ' . $mime_type);」でヘッダーを出力します。

header('Content-Type: ' . $mime_type);
switch ($mime_type) {
    case 'image/jpeg':
        imagejpeg($image);
        break;
    case 'image/png':
        imagepng($image);
        break;
    case 'image/gif':
        imagegif($image);
        break;
    default:
        break;
}
exit;

PHPで画像リサイズするプログラムを解説<縦横比を保つ>

PHPで画像の縦横比率を保ってリサイズするプログラムのサンプルコードです。
(このサンプルだと画像を縮小して出力されます。なので、縮小したくない場合は後述するサンプルコードを参考にしてください。)

サンプルコード

PHPで画像の縦横比率を保ってリサイズするプログラムのサンプルコードです。

<?php
$error = '';
do {
    $gazo = @$_FILES['gazo'];
    if (!$gazo) {
        break;
    }

    if (!$gazo['size'] || $gazo['size'] <= 0) {
        $error = '画像がアップロードされていません。';
        break;
    }

    if (checkFileError($gazo) !== true) {
        $error = '画像のアップロードに失敗しました。';
        break;
    }

    // tmpファイル名を取得
    $file_name = $gazo['tmp_name'];

    // 画像サイズを読み込む
    list($w_src, $h_src) = getimagesize($file_name);
    if (!$w_src || !$h_src) {
        $error = '画像サイズの読み込みに失敗しました。';
        break;
    }

    // 画像タイプを判断して画像を読み込む
    $image_src = null;
    $finfo = new finfo();
    $mime_type = $finfo->file($file_name, FILEINFO_MIME_TYPE);
    switch ($mime_type) {
        case 'image/jpeg':
            $image_src = imagecreatefromjpeg($file_name);
            break;
        case 'image/png':
            $image_src = imagecreatefrompng($file_name);
            break;
        case 'image/gif':
            $image_src= imagecreatefromgif($file_name);
            break;
        default:
            break;
    }
    if (!$image_src) {
        $error = 'jpeg,png,gif以外は読み込めません。';
        break;
    }

    $w = $h = 250;
    $x_diff = $y_diff = 0;
    $w_diff = $h_diff = 0;

    if ($w_src > $h_src) {
        // 横長
        $w_diff = $h_src;
        $h_diff = $h_src;
        $x_diff = ($w_src - $h_src) * 0.5;
        $y_diff = 0;
    }
    else if ($w_src < $h_src) {
        // 縦長
        $w_diff = $w_src;
        $h_diff = $w_src;
        $x_diff = 0;
        $y_diff = ($h_src - $w_src) * 0.5;
    }
    else if ($w_src == $h_src) {
        $w_diff = $w_src;
        $h_diff = $h_src;
        $x_diff = 0;
        $y_diff = 0;
    }

    // 読み込んだ画像をコピー
    $image = imagecreatetruecolor($w, $h);
    if (!$image) {
        $error = '画像の複製に失敗しました。';
        break;
    }

    // 画像をサンプリング
    imagecopyresampled($image, $image_src, 0, 0, $x_diff, $y_diff, $w, $h, $w_diff, $h_diff);
    if (!$image) {
        $error = '画像のサンプリングに失敗しました。';
        break;
    }

    // 画像を出力
    header('Content-Type: ' . $mime_type);
    switch ($mime_type) {
        case 'image/jpeg':
            imagejpeg($image);
            break;
        case 'image/png':
            imagepng($image);
            break;
        case 'image/gif':
            imagegif($image);
            break;
        default:
            break;
    }
    exit;

} while(0);

/**
 * ファイルのエラーチェック
 */
function checkFileError($file = null)
{
    if (!$file) return false;

    switch ($file['error'])
    {
        case UPLOAD_ERR_INI_SIZE:
        case UPLOAD_ERR_FORM_SIZE:
            return false;
        case UPLOAD_ERR_PARTIAL:
            return false;
        case UPLOAD_ERR_NO_FILE:
            return false;
        case UPLOAD_ERR_NO_TMP_DIR:
        case UPLOAD_ERR_CANT_WRITE:
        case UPLOAD_ERR_EXTENSION:
            return false;
        default:
            break;
    }

    return true;
}

?>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
        <meta name="robots" content="noindex">
        <title>Image</title>
    </head>
    <body>
        <h1>Image</h1>
        <form method="post" action="/sample/php/image/index2.php" enctype="multipart/form-data">
            <input type="file" name="gazo">
            <?php if ($error) : ?>
            <p><?php echo $error ?></p>
            <?php endif; ?>
            <input type="submit">
            <!-- button type="submit">送信</button -->
        </form>
    </body>
</html>

出力画像

出力画像は、500×500で画像をリサイズしています。さっきのサンプルと違い画像の比率は保っています。

PHPの解説

PHPで画像の縦横比率を保ってリサイズするプログラムのサンプルコードのPHP部分を解説します。

画像のXY座標位置とサイズを算出(画像の真ん中を起点に)

$w = $h = 250;
$x_diff = $y_diff = 0;
$w_diff = $h_diff = 0;

if ($w_src > $h_src) {
    // 横長
    $w_diff = $h_src;
    $h_diff = $h_src;
    $x_diff = ($w_src - $h_src) * 0.5;
    $y_diff = 0;
}
else if ($w_src < $h_src) {
    // 縦長
    $w_diff = $w_src;
    $h_diff = $w_src;
    $x_diff = 0;
    $y_diff = ($h_src - $w_src) * 0.5;
}
else if ($w_src == $h_src) {
    $w_diff = $w_src;
    $h_diff = $h_src;
    $x_diff = 0;
    $y_diff = 0;
}

作成した250×250の画像にアップロードした画像をサンプリング

  • imagecopyresampled()
    • $image → コピー先の画像
    • $image_src → コピー元の画像
    • 0 → コピー先の x 座標
    • 0 → コピー先の y 座標
    • $x_diff → コピー元の x 座標
    • $y_diff → コピー元の y 座標
    • $w → コピー先の幅
    • $h → コピー先の高さ
    • $w_diff → コピー元の幅
    • $h_diff → コピー元の高さ
imagecopyresampled($image, $image_src, 0, 0, $x_diff, $y_diff, $w, $h, $w_diff, $h_diff);
if (!$image) {
    $error = '画像のサンプリングに失敗しました。';
    break;
}

PHPで画像リサイズするプログラムを解説<縮小しない>

PHPで画像を縮小しないでリサイズするプログラムのサンプルコードを解説します。簡単に言うと画像をトリミングするサンプルです。

サンプルコード

PHPで画像を縮小しないでリサイズするプログラムのサンプルコードです。

<?php
$error = '';
do {
    $gazo = @$_FILES['gazo'];
    if (!$gazo) {
        break;
    }

    if (!$gazo['size'] || $gazo['size'] <= 0) {
        $error = '画像がアップロードされていません。';
        break;
    }

    if (checkFileError($gazo) !== true) {
        $error = '画像のアップロードに失敗しました。';
        break;
    }

    // tmpファイル名を取得
    $file_name = $gazo['tmp_name'];

    // 画像サイズを読み込む
    list($w_src, $h_src) = getimagesize($file_name);
    if (!$w_src || !$h_src) {
        $error = '画像サイズの読み込みに失敗しました。';
        break;
    }

    // 画像タイプを判断して画像を読み込む
    $image_src = null;
    $finfo = new finfo();
    $mime_type = $finfo->file($file_name, FILEINFO_MIME_TYPE);
    switch ($mime_type) {
        case 'image/jpeg':
            $image_src = imagecreatefromjpeg($file_name);
            break;
        case 'image/png':
            $image_src = imagecreatefrompng($file_name);
            break;
        case 'image/gif':
            $image_src= imagecreatefromgif($file_name);
            break;
        default:
            break;
    }
    if (!$image_src) {
        $error = 'jpeg,png,gif以外は読み込めません。';
        break;
    }

    // 画像を変更するサイズ
    $w = $h = 250;

    // 読み込んだ画像をコピー
    $image = imagecreatetruecolor($w, $h);
    if (!$image) {
        $error = '画像の複製に失敗しました。';
        break;
    }

    $w_diff = $w_src;
    $h_diff = $h_src;
    $x_diff = ($w_src * 0.5) - ($w * 0.5);
    $y_diff = ($h_src * 0.5) - ($h * 0.5);

    // 画像を再サンプリング
    imagecopyresampled($image, $image_src, 0, 0, $x_diff, $y_diff, $w, $h, $w, $h);

    if (!$image) {
        $error = '画像のサンプリングに失敗しました。';
        break;
    }

    // 画像を出力
    header('Content-Type: ' . $mime_type);
    switch ($mime_type) {
        case 'image/jpeg':
            imagejpeg($image);
            break;
        case 'image/png':
            imagepng($image);
            break;
        case 'image/gif':
            imagegif($image);
            break;
        default:
            break;
    }
    exit;

} while(0);


/**
 * ファイルのエラーチェック
 */
function checkFileError($file = null)
{
    if (!$file) return false;

    switch ($file['error'])
    {
        case UPLOAD_ERR_INI_SIZE:
        case UPLOAD_ERR_FORM_SIZE:
            return false;
        case UPLOAD_ERR_PARTIAL:
            return false;
        case UPLOAD_ERR_NO_FILE:
            return false;
        case UPLOAD_ERR_NO_TMP_DIR:
        case UPLOAD_ERR_CANT_WRITE:
        case UPLOAD_ERR_EXTENSION:
            return false;
        default:
            break;
    }

    return true;
}

?>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
        <meta name="robots" content="noindex">
        <title>Image</title>
    </head>
    <body>
        <h1>Image</h1>
        <form method="post" action="/sample/php/image/index3.php" enctype="multipart/form-data">
            <input type="file" name="gazo">
            <?php if ($error) : ?>
            <p><?php echo $error ?></p>
            <?php endif; ?>
            <input type="submit">
            <!-- button type="submit">送信</button -->
        </form>
    </body>
</html>

出力画像

出力画像は、500×500で画像を切り抜いています。
(切り抜く位置は、画像の中央を基準にしています。)

PHPの解説

PHPで画像を縮小しないでリサイズするプログラムのサンプルコードのHTML部分を解説します。

画像の切り抜き位置を算出(画像の真ん中を起点に)

$w_diff = $w_src;
$h_diff = $h_src;
$x_diff = ($w_src * 0.5) - ($w * 0.5);
$y_diff = ($h_src * 0.5) - ($h * 0.5);

作成した250×250の画像にアップロードした画像をサンプリング

  • imagecopyresampled()
    • $image → コピー先の画像
    • $image_src → コピー元の画像
    • 0 → コピー先の x 座標
    • 0 → コピー先の y 座標
    • $x_diff → コピー元の x 座標
    • $y_diff → コピー元の y 座標
    • $w → コピー先の幅
    • $h → コピー先の高さ
    • $w → コピー元の幅
    • $h → コピー元の高さ
imagecopyresampled($image, $image_src, 0, 0, $x_diff, $y_diff, $w, $h, $w, $h);
if (!$image) {
    $error = '画像のサンプリングに失敗しました。';
    break;
}

GDについて

今回のPHPで画像サイズを変更するプログラムはGDを利用しています。ということでGDについて少し解説します。

GDのインストール手順

LinuxへGDをインストールする手順を紹介します。

GDがインストールされているか確認

$ yum list installed | grep php
php.x86_64                           8.0.20-1.amzn2                 @amzn2extra-php8.0
php-cli.x86_64                       8.0.20-1.amzn2                 @amzn2extra-php8.0
php-common.x86_64                    8.0.20-1.amzn2                 @amzn2extra-php8.0
php-fpm.x86_64                       8.0.20-1.amzn2                 @amzn2extra-php8.0
php-intl.x86_64                      8.0.20-1.amzn2                 @amzn2extra-php8.0
php-mbstring.x86_64                  8.0.20-1.amzn2                 @amzn2extra-php8.0
php-mysqlnd.x86_64                   8.0.20-1.amzn2                 @amzn2extra-php8.0
php-opcache.x86_64                   8.0.20-1.amzn2                 @amzn2extra-php8.0
php-pdo.x86_64                       8.0.20-1.amzn2                 @amzn2extra-php8.0

yumでインストールできるGDパッケージを確認

$ yum list | grep php*-gd
php-gd.x86_64                          8.0.20-1.amzn2                 amzn2extra-php8.0

yumでGDをインストール

$ sudo yum install php-gd.x86_64
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
amzn2-core                                                                                   | 3.7 kB  00:00:00
amzn2extra-docker                                                                            | 3.0 kB  00:00:00
amzn2extra-kernel-5.10                                                                       | 3.0 kB  00:00:00
amzn2extra-nginx1                                                                            | 3.0 kB  00:00:00
amzn2extra-php8.0                                                                            | 3.0 kB  00:00:00
snapd-amzn2                                                                                  | 3.0 kB  00:00:00
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ php-gd.x86_64 0:8.0.20-1.amzn2 を インストール
--> 依存性解決を終了しました。

依存性を解決しました

===========================================================================================================================================================================================================================================================================================================================================================================
 Package                                                                             アーキテクチャー                                                                    バージョン                                                                                   リポジトリー                                                                                    容量
===========================================================================================================================================================================================================================================================================================================================================================================
インストール中:
 php-gd                                                                              x86_64                                                                              8.0.20-1.amzn2                                                                               amzn2extra-php8.0                                                                              169 k

トランザクションの要約
===========================================================================================================================================================================================================================================================================================================================================================================
インストール  1 パッケージ

総ダウンロード容量: 169 k
インストール容量: 749 k
Is this ok [y/d/N]: y
Downloading packages:
php-gd-8.0.20-1.amzn2.x86_64.rpm                                                                                                                                                                                                                                                                                                                    | 169 kB  00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  インストール中          : php-gd-8.0.20-1.amzn2.x86_64                                                                                                                                                                                                                                                                                                               1/1
  検証中                  : php-gd-8.0.20-1.amzn2.x86_64                                                                                                                                                                                                                                                                                                               1/1

インストール:
  php-gd.x86_64 0:8.0.20-1.amzn2

完了しました!

GDがインストールされたか確認

$ yum list installed | grep php
php.x86_64                      8.0.20-1.amzn2                @amzn2extra-php8.0
php-cli.x86_64                  8.0.20-1.amzn2                @amzn2extra-php8.0
php-common.x86_64               8.0.20-1.amzn2                @amzn2extra-php8.0
php-fpm.x86_64                  8.0.20-1.amzn2                @amzn2extra-php8.0
php-gd.x86_64                   8.0.20-1.amzn2                @amzn2extra-php8.0
php-intl.x86_64                 8.0.20-1.amzn2                @amzn2extra-php8.0
php-mbstring.x86_64             8.0.20-1.amzn2                @amzn2extra-php8.0
php-mysqlnd.x86_64              8.0.20-1.amzn2                @amzn2extra-php8.0
php-opcache.x86_64              8.0.20-1.amzn2                @amzn2extra-php8.0
php-pdo.x86_64                  8.0.20-1.amzn2                @amzn2extra-php8.0

PHP-fpmを再起動

PHP-fpmを再起動してGDをPHPで利用できるようにします。

$ sudo systemctl restart php-fpm.service

Imagickについて<余談>

PHPではGD以外にもImagickで画像編集する方法があります。

Imagickとは、ImageMagickをPHPで利用するための拡張モジュールです。
※ImagickとImageMagickは別物なので注意

Imagickは、GDよりも画像加工の機能が豊富です、その反面やや重いライブラリでもあります。

ちなみに今回のサンプルのように画像のリサイズ程度であればGDで十分なのでImagickを用意する必要はありません。

まとめ

今回はPHPでGDを使った画像リサイズのサンプルプログラムを解説しました。

ぜひ参考にプログラミングしてみてください。

ユート
ユート

1985年生まれ1児の父親です。Web系エンジニアを10年以上しています。
プロフィール
Amazon欲しいものリスト

2022年10月11日プログラムPHP,プログラムサンプル

Posted by ユート