ありそうで無かったので作ってみました。
php_jpegtransform-0.0.1.tgz
このモジュールのソースコードには IJG JPEG Library (libjpeg) より以下のファイルを拝借しています。
README (libjpeg のライセンスにより) jinclude.h jpegint.h transupp.c transupp.h
インストールはいつもの通りです。
tar xfz php_jpegtransform-0.0.1.tgz cd php_jpegtransform phpize ./configure --with-jpegtransform=/path/to/libjepeg-install-dir make sudo make install
この通り、画質を保ったまま JPEG 画像を回転できます。
オリジナル | 90度・1回目 | 2回目 | 3回目 | 4回目 |
---|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
デジカメで縦位置撮影した画像にどうぞ。
関数はただ一つ、bool jpegtransform(string $src_path, string $dst_path, int $flags)
のみ。
$src_path に元となる JPEG 画像のパス、$dst_path に出力先のパス、$flags に変形オプションを指定します。
$flags は以下の定数のビット和で指定します。
- JT_FLIP_H
- 水平方向に反転
- JT_FLIP_V
- 垂直方向に反転
- JT_TRANSPOSE
- 左上-右下の軸を転置 (JT_FLIP_H | JT_ROT_90 に等しい)
- JT_TRANSVERSE
- 右上-左下の軸を転置 (JT_FLIP_V | JT_ROT_90 に等しい)
- JT_ROT_90
- 時計回りに 90度回転
- JT_ROT_180
- 180度回転 (JT_FLIP_H | JT_FLIP_V に等しい)
- JT_ROT_270
- 時計回りに 270度回転 (JT_FLIP_H | JT_FLIP_V | JT_ROT_90 に等しい)
- JT_COPY_NONE
- 必要最低限のマーカー以外はコピーしない
- JT_COPY_COMMENTS
- 必要最低限のマーカーに加え、COM (Comment) マーカーもコピーする
- JT_COPY_ALL
- APP1 (Exif) マーカー等のすべてのマーカーをコピーする。Exif 情報を残したまま回転させたいときはこのフラグを使う
- JT_KEEP_MTIME
- 出力ファイルの更新時刻をオリジナルと同じにする
JT_COPY_* の優先順位は JT_COPY_ALL > JT_COPY_COMMENTS > JT_COPY_NONE です。これらのいずれも指定されなかった場合は JT_COPY_COMMENTS が指定されたものとして処理します。
JT_KEEP_MTIME が指定された場合、stat(2) や utimes(2) を直接使わずに、PHP 関数 filemtime() と touch() をコールして更新時刻の取得・変更を行っています。
以下はとりあえず全部のフラグを試してみるコードです。
<?php !extension_loaded('jpegtransform') && (dl('jpegtransform.so') || exit(1)); var_dump(jpegtransform('sample.jpg', 'jt_flip_h.jpg', JT_FLIP_H)); var_dump(jpegtransform('sample.jpg', 'jt_flip_v.jpg', JT_FLIP_V)); var_dump(jpegtransform('sample.jpg', 'jt_transpose.jpg', JT_TRANSPOSE)); var_dump(jpegtransform('sample.jpg', 'jt_transverse.jpg', JT_TRANSVERSE)); var_dump(jpegtransform('sample.jpg', 'jt_rot_90.jpg', JT_ROT_90)); var_dump(jpegtransform('sample.jpg', 'jt_rot_180.jpg', JT_ROT_180)); var_dump(jpegtransform('sample.jpg', 'jt_rot_270.jpg', JT_ROT_270)); var_dump(jpegtransform('sample.jpg', 'jt_copy_none.jpg', JT_ROT_90 | JT_COPY_NONE)); var_dump(jpegtransform('sample.jpg', 'jt_copy_comments.jpg', JT_ROT_90 | JT_COPY_COMMENTS)); var_dump(jpegtransform('sample.jpg', 'jt_copy_all.jpg', JT_ROT_90 | JT_COPY_ALL)); var_dump(jpegtransform('sample.jpg', 'jt_keep_mtime.jpg', JT_ROT_90 | JT_COPY_ALL | JT_KEEP_MTIME)); function exif_binary_data_filter($data) { if (is_array($data)) { return array_map('exif_binary_data_filter', $data); } elseif (is_string($data)) { if (preg_match('/[^\\x20-\\x7e]/', $data)) { return sprintf('binary or non-ascii character data (%d bytes)', strlen($data)); } else { return $data; } } else { return $data; } } $exif1 = exif_binary_data_filter(exif_read_data('jt_copy_none.jpg')); $exif2 = exif_binary_data_filter(exif_read_data('jt_copy_comments.jpg')); $exif3 = exif_binary_data_filter(exif_read_data('jt_copy_all.jpg')); var_dump($exif1, $exif2, $exif3); var_dump(filemtime('sample.jpg'), filemtime('jt_copy_all.jpg'), filemtime('jt_keep_mtime.jpg'));