デジカメで撮った写真をサーバに置いて,自動でサムネイルを生成して一覧HTMLファイルを作るスクリプトを書いて,写真の管理に使っています.
ところがサムネイルを作る時にただ単に画像を縮小するだけだと,縦で撮った写真も横向きの画像になっちゃうんですね.
なので,Exifからカメラの向きの情報を読み出して,サムネイルをちゃんと回転させて生成するようにしたかったんですが.
画像縮小・回転・Exifそれぞれ独立した情報は見つかっても,総合的に1ページで解決する情報がみつけられなかったので,それら情報を総合した内容をメモ.
まずはExifの仕様(PDFファイル)から画像の向きについて書いてる部分を読むと,
The image orientation viewed in terms of rows and columns.
Tag = 274 (112.H)
Type = SHORT
Count = 1
Default = 1
1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.
2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side.
3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side.
4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side.
5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top.
6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top.
7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom.
8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom.
Other = reserved
こんな風に書いてる.
回転の角度が書いてあると思ったんだけど,思ったよりいっぱい種類があってびっくり.反転のことも考えてるんですね.散髪屋さん用でしょうか?
とりあえず画像ファイルは,カメラが普通の向きになった状態のデータになってるので,その1番上(0行目)と1番左(1列目)をどっちに表示すればいいの?って意味のよう.
2は,1行目が上,1列目が右ってことは,左右反転なだけ.私には不要.
3は,1行目が下,1列目が右ってことで,180度回転...いるのかな?スマホならあるかも?
4は,1行目が下,1列目が左って?上下反転・・・絶対いらない.
5は,1行目が左,1列目が上・・・90度左に回って左右反転.なんやそら.
6は,1行目が右,1列目が上なので,右に90度回転.これは必要.
7は,1行目が右,1列目が下か・・・右に90度で左右反転?5の逆か.いらんて.
8は,1行目が左,1列目が下なので,左に90度回転.これも必要.
つまり,必要なのは1,3,6,8の4つ.そら必要なのは直感的にも4つよね.だから8個もあって多いと感じたわけで.
てことで,Exif情報からorientationの値を読み出して,switchでサムネイルを回転させます.
画像の縮小・回転にはGDを使います.
$outputSize = 320; //縦か横かの最大サイズ
$inputFile = "hogein.jpg"; //元画像指定
$outputFile = "hogethumb.jpg";
$size = getimagesize($inputFile); //元画像画像サイズ取得
$inputWidth = $size[0]; //元幅
$inputHeight = $size[1]; //元高さ
$exif = exif_read_data($inputFile,'IFD0'); //Exif読み込み
$orientation = $exif['Orientation']; //Orientation取得←今回テーマ
switch($orientation){ //Orientationの値によって分ける
case 1:
$rotate = 0; //1はそのまま
break;
case 3:
$rotate = 180; //3は180度回転
break;
case 6:
$rotate = 270; //6は右に90度(左に270度)
break;
case 8:
$rotate = 90; //8は右に270度(左に90度)
break;
default:
$rotate = 0; //他は無視
}
if($inputWidth < $inputHeight){ //元から縦長画像ってことも意識しとく
$outputHeight = $outputSize; //元が縦長なら縦がサムネの最大サイズで
$outputWidth = $inputWidth * $outputSize / $inputHeight; //横はそれに併せて縮める
}else{
$outputWidth = $outputSize; //逆なら
$outputHeight = $inputHeight * $outputSize / $inputWidth; //逆で
}
$inputImage = imagecreatefromjpeg($inputFile); //元画像読み込み
$outputImage = imagecreatetruecolor($outputWidth, $outputHeight); //出力サイズの画像を作って
imagecopyresampled($outputImage, $inputImage, 0, 0, 0, 0, $outputWidth, $outputHeight, $inputWidth, $inputHeight); //元画像をリサイズして出力する
/**** 今回のテーマ ****/
if($rotate){ //$rotateが0じゃなかったら
$outputImage = imagerotate($outputImage, $rotate, 0); //$rotateだけ回転させてから
}
imagejpeg($outputImage, $outputFile); //ファイルに出力する
?>
て感じで.
これを関数化して,処理したいファイルの分だけ繰り返してやればよし.
一回目軽くやらかしたのは,GDのimagerotateは左に回るってことに気づかなくて.
最初逆にして縦写真が軒並みひっくり返っちゃった.