勉強したことのメモ

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で画像を上下反転させ保存する

やりたかった事は、下記の通り。 ・既にフォルダに保存されている画像を上下反転させ ...

PHPからWebAPI(screendot)経由で他サイトのスクリーンショットを取得する方法

PHPで他サイトのスクリーンショットを取得したい。今回はライブラリは無しで実現し ...

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

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

PHPで画像にモザイクをかけて保存

やりたかった事はPHPで ・モザイク処理 ・元の画像とは別にファイル名をつけて保 ...

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

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