朝顔日記

アップロードしてリサンプルする何か

2006-04-21

業務(何)で rNote を使ったサイトをひとつ制作中なんですが、オンラインで更新する仕組みもつけようと思っています。ていうか、必須なんです。で、画像付きのエントリーをアップできるようにする必要もあるんですが、お客さん(誰)はフォトレタッチとか知らない人たちが想定されるんで、デジカメなどで撮影した画像を無加工のままアップしても適当な縦横サイズにリサンプルしてやる必要があります。ということで、それ用に部品を作る前に単体で動くものを作ったので公開してみます。ま、ありがちなものですが。:p)

アップロードした巨大画像の縦横サイズを設定した大きさまでに縮小して指定した場所に保存するというようなものです。保存するのは縮小した画像だけで、アップされたオリジナル画像はサーバ上には保存されないという仕様です。

以下その php スクリプトですが、画像の加工に GD を使っているので、GD が使えるようになっていないと使えません。動作を確認した php のバージョンは、5.1.2 です。


<?php
// 設定
$skin = "./default.skin";  // テンプレ(何)
$img_dir = "/home/hogehoge/public_html/fugafuga/img/";  // 縮小されたイメージの保存場所(絶対パス)
$img_path = "./img/";      // 縮小されたイメージの保存場所 (スクリプトからの相対パス)
$max_width = 500;          // 縮小イメージの幅の最大ピクセル数
$max_height = 250;         // 縮小イメージの高さの最大ピクセル数
$max_file_size = 3000000;  // アップロード可能なファイルサイズの上限

// 設定ここまで

$skin = file_get_contents($skin);
if(!Is_Uploaded_File($_FILES["userfile"]["tmp_name"])) {
  $html_data .=<<<EOD
<p>jpg、gif、png 以外は駄目です。</p>
<form method="post" action="{$_SERVER['PHP_SELF']}" enctype="multipart/form-data">
<p><label for="userfile">アップロードファイル</label> : <input type="file" name="userfile" id="userfile" size="40" value="参照" /></p>
<p><input type="hidden" name="MAX_FILE_SIZE" value="$max_file_size" />
<input type="submit" value="submit" /></p>
</form>
EOD;
} else {
  $old_img = $_FILES["userfile"]["tmp_name"];
  // 元の画像の情報を調べる
  @list($old_width, $old_height, $old_type, $old_attr) = getimagesize($old_img);
  if($old_type == 1){                   // 1 = GIF, 2 = JPG, 3 =PNG
    $ext = ".gif";
    $src_im = imagecreatefromgif($old_img);
  } elseif($old_type == 2) {
    $ext = ".jpg";
    $src_im = imagecreatefromjpeg($old_img);
  } elseif($old_type == 3) {
    $ext = ".png";
    $src_im = imagecreatefrompng($old_img);
  } else {
    $ext = "";
  }
  if($ext == "") {
    $html_data .= "<p>失敗です</p>\n";
    $html_data .= "<p><a href=\"".$_SERVER['PHP_SELF']."\">やり直す</a></p>\n";
  } else {
    if($old_width > $max_width || $old_height > $max_height) {
      $key_w = $max_width/$old_width;
      $key_h = $max_height/$old_height;
      ($key_w < $key_h) ? $keys = $key_w : $keys = $key_h;

      $new_width = $old_width * $keys;
      $new_height = $old_height * $keys;
    } else {
      $new_width = $old_width;
      $new_height = $old_height;
    }
    $new_width = round($new_width);
    $new_height = round($new_height);

    $new_img = $img_dir.date("ymdHi").$ext;
    $dst_im = imagecreatetruecolor($new_width, $new_height);//先画像
    imagealphablending($dst_im, false);
    imagecopyresampled($dst_im, $src_im, 0, 0, 0, 0, $new_width, $new_height, $old_width, $old_height);

    if($old_type == 1){
      imagegif($dst_im, $new_img);
    } elseif($old_type == 2) {
      imagejpeg($dst_im, $new_img);
    } else {
      imagesavealpha($dst_im, true);
      imagepng($dst_im, $new_img);
    }

    ImageDestroy($dst_im);
    ImageDestroy($src_im);
    $new_img = str_replace($img_dir, "", $new_img);
    $html_data .= "<p><img src=\"".$img_path.$new_img."\" width=\"".$new_width."\" height=\"".$new_height."\" alt=\"\" /></p>";
    $html_data .= "<p>width: ".$old_width."→".$new_width."</p>\n";
    $html_data .= "<p>height: ".$old_height."→".$new_height."</p>\n";
  }
}

$skin = str_replace('<%=$content%>', $html_data, $skin);
print($skin);
?>

設定の一番最初にある、default.skin ですが、これに基づいてページを生成します。おおむね以下のようなものです。


<html>
<head>
<title>アップロード &amp; リサンプル</title>
</head>
<body>
<h1>アップロード &amp; リサンプル</h1>
<%=$content%>
</body>
</html>

要するに、<%=$content%> を置換するようになっています。

しばらくの間だけ、動作サンプルを設置しておきますので興味のある方はお試しください。無駄に画像が溜まってもアレなんでしばらくしたら取り外します。

アルファを持った png 画像の場合に不具合があったので修正しました。透過色を持った gif の場合も不具合がありますが、とりあえず放置の予定。:p)

「アップロードしてリサンプルする何か」へコメントをつける

書き込み時の挙動について
URI らしき文字列には自動的にリンクが張られます。また "<" や、">" は実体参照化されます。
スパム対策のため、リファラを切っていると投稿できません。

この記事へのツッコミ

1: くでん (2006-04-19T20:21:03+09:00)
アルファチャンネルを持ったpngだと、アルファチャンネルの部分が真っ黒になります……
2: のり (2006-04-19T23:02:54+09:00)
うは、ホンマですね。試してみたら gif もでした。ちょっと調べたらそういう時用の関数がちゃんと用意されているようですね。とりあえず、png には対応しましたが、gif のほうはとりあえず放置ということで。(ぉ
ていうか、たぶんお客さん用は jpg のみでよさげです。:p)
3: pcook (2009-05-08T02:49:03+09:00)
すばらしい!!これを探していました。
ひとつ、保存される画質の調整はどこを書き換えればよいでしょうか。サンプルよりももうちょっときれいにリサイズしたいです。
4: pcook (2009-05-08T02:52:11+09:00)
↑jpgのお話です。
5: pcook (2009-05-08T02:54:35+09:00)
自己レスです。imagejpegの第3引数みたいですね。アップロードするときに、名前を変更できるようにして(ブログでは日付をファイル名につけるので)使わせてもらいます!
この記事の永続的 URI ならびに トラックバック ping URI
http://diary.noasobi.net/2006/04/diary_060419a.html