勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

画像をアップロードすると複数サムネイルを生成する方法

   2024/04/18  PHP

フォームで画像をアップロードすると、予め定めておいた大中小のサイズでサムネイル画像を生成する方法のメモ。

 

ソースコード

<?php
$resizeList = array(
    0 => array(
        'width' => '500', 
        'height' => '500', 
        'title' => 'サイズ大', 
    ),
    1 => array(
        'width' => '300', 
        'height' => '300', 
        'title' => 'サイズ中', 
    ),
    2 => array(
        'width' => '100', 
        'height' => '100', 
        'title' => 'サイズ小', 
    ),
);

define('MAIN_PATH','/var/www/html');
define('IMAGE_PATH', MAIN_PATH.'/test/img_resize/img/');
define('TMP_PATH', MAIN_PATH.'/test/img_resize/tmp/');

/* ランダム英数字作成 
 * 引数 $length(int)
 * 返り値 false or string
 */
function randomStr ($length = 1) {
    if( $length < 1 ) return false;
    
    $str = array_merge(range('a', 'z'), range('0', '9'), range('A', 'Z"'));
    for ($i = 0; $i < $length; $i++) {
        $r_str .= $str[rand(0, count($str)-1)];
    }
    return $r_str;
}

/* 画像のリサイズ 
 * 返り値 bool
*/
function smart_resize_image(
    $file,
    $width = 0,
    $height = 0,
    $proportional = false,
    $output = 'file',
    $delete_original = true,
    $use_linux_commands = false,
     $quality = 100
) {
        
    if ( $height <= 0 && $width <= 0 ) return false;

    $info = getimagesize($file);
    $image = '';
    $final_width = 0;
    $final_height = 0;
    list($width_old, $height_old) = $info;

    if ($proportional) {
        if ($width == 0) $factor = $height/$height_old;
        elseif ($height == 0) $factor = $width/$width_old;
        else $factor = min( $width / $width_old, $height / $height_old );

        $final_width = round( $width_old * $factor );
        $final_height = round( $height_old * $factor );
    }
    else {
        $final_width = ( $width <= 0 ) ? $width_old : $width;
        $final_height = ( $height <= 0 ) ? $height_old : $height;
    }

    switch ( $info[2] ) {
        case IMAGETYPE_GIF: $image = imagecreatefromgif($file); break;
        case IMAGETYPE_JPEG: $image = imagecreatefromjpeg($file); break;
        case IMAGETYPE_PNG: $image = imagecreatefrompng($file); break;
        default: return false;
    }
    
    $image_resized = imagecreatetruecolor( $final_width, $final_height );
    if ( ($info[2] == IMAGETYPE_GIF) || ($info[2] == IMAGETYPE_PNG) ) {
        $transparency = imagecolortransparent($image);

        if ($transparency >= 0) {
            $transparent_color = imagecolorsforindex($image, $trnprt_indx);
            $transparency = imagecolorallocate($image_resized, $trnprt_color['red'], $trnprt_color['green'], $trnprt_color['blue']);
            imagefill($image_resized, 0, 0, $transparency);
            imagecolortransparent($image_resized, $transparency);
        }
        elseif ($info[2] == IMAGETYPE_PNG) {
            imagealphablending($image_resized, false);
            $color = imagecolorallocatealpha($image_resized, 0, 0, 0, 127);
            imagefill($image_resized, 0, 0, $color);
            imagesavealpha($image_resized, true);
        }
    }
    imagecopyresampled($image_resized, $image, 0, 0, 0, 0, $final_width, $final_height, $width_old, $height_old);
    
    if ( $delete_original ) {
        if ( $use_linux_commands ) exec('rm '.$file);
        else @unlink($file);
    }

    switch ( strtolower($output) ) {
        case 'browser':
            $mime = image_type_to_mime_type($info[2]);
            header("Content-type: $mime");
            $output = NULL;
        break;
        case 'file':
            $output = $file;
        break;
        case 'return':
            return $image_resized;
        break;
        default:
        break;
    }
    
    switch ( $info[2] ) {
        case IMAGETYPE_GIF: imagegif($image_resized, $output); break;
        case IMAGETYPE_JPEG: imagejpeg($image_resized, $output, $quality); break;
        case IMAGETYPE_PNG:
            $quality = 9 - (int)((0.9*$quality)/10.0);
            imagepng($image_resized, $output, $quality);
            break;
        default: return false;
    }

    return true;
}


if ( $_FILES && $_POST['mode'] == 'upload' ) { //画像アップロード時

    $tmpData = array(); //未登録用に初期化

    //拡張子チェック&名前決め
    $tmpData['img']['name'] = randomStr(12); //ファイル名は[不動産ID_フォルダID_ランダム英数字]
    $image_ext = $_FILES['img']['type'];
    if ($image_ext == 'image/jpeg' || $image_ext == 'image/jpg') {
        $tmpData['img']['ext'] = '.jpg';
    } elseif ($image_ext == 'image/png') {
        $tmpData['img']['ext'] = '.png';
    } elseif ($image_ext == 'image/gif') {
        $tmpData['img']['ext'] = '.gif';
    } else {
        echo 'For jpg / png / gif other than, it was not possible to upload the extension of the image.<br /><a href="javascript:void(0);" onClick="history.back();">return</a>';
        exit();
    }

    //フォルダにアップ
    if ($_FILES['img']['size'] > 0) {
        if (!move_uploaded_file($_FILES['img']["tmp_name"], TMP_PATH . $tmpData['img']['name'] . $tmpData['img']['ext'])){
            echo 'An error occurred while uploading the image.<br /><a href="javascript:void(0);" onClick="history.back();">return</a>';
            exit();
        } else {
            copy(TMP_PATH . $tmpData['img']['name'] . $tmpData['img']['ext'], IMAGE_PATH . $tmpData['img']['name'] . $tmpData['img']['ext']);//オリジナルサイズの画像をimageフォルダにアップ

            for ($i = 0; $i < count($resizeList); $i++) {
                $sizeName = '-' . $resizeList[$i]['width'] . 'x' . $resizeList[$i]['height'];

                copy(TMP_PATH . $tmpData['img']['name'] . $tmpData['img']['ext'], TMP_PATH . $tmpData['img']['name'] . $sizeName . $tmpData['img']['ext']);//リサイズ用画像をtmpフォルダへコピー

                smart_resize_image(
                    TMP_PATH . $tmpData['img']['name'] . $sizeName . $tmpData['img']['ext'],
                    $width = $resizeList[$i]['width'],
                    $height = $resizeList[$i]['height'],
                    $proportional = false,
                    $output = 'file',
                    $delete_original = false,
                    $use_linux_commands = false,
                    $quality = 100
                );
                copy(TMP_PATH . $tmpData['img']['name'] . $sizeName . $tmpData['img']['ext'], IMAGE_PATH . $tmpData['img']['name'] . $sizeName . $tmpData['img']['ext']);//imageフォルダにアップ
                unlink(TMP_PATH . $tmpData['img']['name'] . $sizeName . $tmpData['img']['ext']);
            }

            unlink(TMP_PATH . $tmpData['img']['name'] . $tmpData['img']['ext']); //オリジナルのtmpフォルダ分削除

        }
    }

} //画像処理ここまで

?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transtional//EN" "http://www.w3c.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
    <meta charset="utf-8">
</head>
<body>

    <form action="<?=$_SERVER['PHP_SELF'];?>" method="post" enctype="multipart/form-data">
        <input type="file" name="img">
        <input type="submit" name="送信!">
        <input type="hidden" name="mode" value="upload">
    </form>

    <? if( $_POST['mode'] == 'upload' ){ ?>
        <? for($i = 0; $i < count($resizeList); $i++){ ?>
            <?=$resizeList[$i]['title'];?>(width:<?=$resizeList[$i]['width'];?> / height:<?=$resizeList[$i]['height'];?>)<br />
            <img src="./img/<?=$tmpData['img']['name'] . '-' . $resizeList[$i]['width'] . 'x' . $resizeList[$i]['height']  .  $tmpData['img']['ext']?>"><br /><br />
        <? } ?>
        オリジナルサイズ<br />
        <img src="./img/<?=$tmpData['img']['name'] . $tmpData['img']['ext']?>"><br /><br />
    <? } ?>

</body>

 

所感

$resizeListに追加していけばどんどんサムネイルサイズを増やせるはず。

複数ってのが初めてだったので少し手間取った。具体的には1つの画像を縮小⇔拡大を繰り返すと画像が劣化というか変になる。当たり前なんだけど。

なので、リサイズ用に画像を生成してリサイズして元画像は破棄って形をとったけど、なんだかまどろっこしい。

 - PHP

  関連記事

PHP側での画像最大アップロードサイズの確認

画像がアップロードできず、恐らくサイズ指定にひっかかっているので 最大サイズを調 ...

フォルダにリンク制限をかける

imgというフォルダがあり、直接URLを叩いても 中身を見られないけど、同一サー ...

PHPで縦横どちらかが指定の長さを超えた場合、比率を保ったままリサイズ

PHPで縦横どちらかが指定の長さを超えた場合、 比率を保ったままリサイズしたかっ ...

PHPでファイル書き込み時に「failed to open stream: HTTP~~」エラー

PHPでファイルを書き込む際に「failed to open stream: H ...

PHPで画像のフォーマット(拡張子)の変換

画像のアップロードでjpg/png/gif形式を受け付けつつ、 最終的にjpgで ...