はじめに
iPhoneの画像をアップロードした時に意図せぬ方向に回転してしまう不具合を解消したので手順をメモしておきます
調べた限りではintervention/image
を使った記事が多かったですが、なぜかうまくいかなかったのでImagick
を利用しました。
ただintervention/image
の方が簡単っぽいのでまずはこの記事ではなく、一番下にある参考記事の通りにやってみるのをオススメしますw
環境
- Mac Catalina 10.15.3
- Laravel Framework 7.10.3
不具合の再現
Chromeだと発生しません!
Safariだと発生します!
- iPhoneで縦向きで写真を撮る
- LINEやSlackなどを経由してPCに送る(※AirDropだとダメ。拡張子がHEICのままになるので。)
- アプリから画像をアップロードする(不具合1→プレビューで意図せぬ回転)
- DBに保存する
- DBから画像を取得してアプリで表示する(不具合2→表示時に意図せぬ回転)
事前準備
imagickが利用できるか確認します
imagickが表示されない場合はインストールしてください。
imagickを使うためにImageMagickの最新版をインストールする話
解決策
以下の2つを行う必要があります
- プレビュー時点の回転を補正する
- DBに保存する時点で回転を補正する
プレビュー時点の回転補正
以下のライブラリを利用します
https://github.com/blueimp/JavaScript-Load-Image
https://github.com/blueimp/JavaScript-Load-Image/blob/master/js/load-image.all.min.js
のソースの中身をコピーします
public/js/load-image.all.min.js
を作成して、貼り付けます
プレビューの処理を以下のように修正します
修正前
1 2 3 4 5
| <script type="text/javascript"> const file = $(id).prop('files')[0]; var blobUrl = window.URL.createObjectURL(file); $(id + '_preview').attr('src', blobUrl); </script>
|
修正後
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <script src="/js/load-image.all.min.js"></script> <script type="text/javascript"> const file = $(id).prop('files')[0];
load(file, function(canvas) { console.log('読み込み完了') canvas.toBlob(function(blob) { var blobUrl = window.URL.createObjectURL(blob); $(id + '_preview').attr('src', blobUrl); $(id).attr('src', canvas.toDataURL()); }); });
function load(file, callback) { var options = { canvas: true, }; loadImage.parseMetaData(file, function(data) { if (data.exif) { options.orientation = data.exif.get('Orientation'); } loadImage(file, callback, options); }); } </script>
|
サーバ側で実際の画像の回転補正
コントローラに以下の処理を追加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| Storage::putFileAs("public/image/hoge.jpeg");
\Log::info('回転補正開始'); $imagick = new \Imagick(); $url = env("APP_URL") . '/storage/image/hoge.jpeg'; $image = file_get_contents($url); $imagick->readImageBlob($image); $format = strtolower($imagick->getImageFormat()); if ($format === 'jpeg') { $orientation = $imagick->getImageOrientation(); $isRotated = false; if ($orientation === \Imagick::ORIENTATION_RIGHTTOP) { $imagick->rotateImage('none', 90); $isRotated = true; } elseif ($orientation === \Imagick::ORIENTATION_BOTTOMRIGHT) { $imagick->rotateImage('none', 180); $isRotated = true; } elseif ($orientation === \Imagick::ORIENTATION_LEFTBOTTOM) { $imagick->rotateImage('none', 270); $isRotated = true; } if ($isRotated) { $imagick->setImageOrientation(\Imagick::ORIENTATION_TOPLEFT); } } $imagick->writeImage(ltrim('/storage/image/hoge.jpeg', "/"));
|
以上
参考
iPhoneで撮った写真が回転している問題 in Laravel
(もう1つすごく参考にした記事があったのだけれどタブを消してしまい、検索しても出てこず、、分かったら追記します、、)