Help us understand the problem. What is going on with this article?

Laravelで画像をリサイズ&勝手に回転しないようにする【EXIF情報も削除】

はじめに

Laravelで画像投稿機能を作ったは良いけど、

 「投稿される画像が大きかったり小さかったりする..」
 「アップロード後に画像が勝手に回転してしまう..」
 「画像に埋め込まれた隠し情報が危険って聞いたけど..」

そんな問題を解消していきます。

画像の大きさの問題はCSSで縮尺などを指定すれば表示は小さくできますが、
それだと表示を変えるだけで保存される画像は大きいままです。
これではストレージや通信に負荷がかかってしまいます。

また画像にはEXIF情報というものが埋め込まれていて、撮影したスマートフォンの情報だったり画像の向き、さらには撮影した場所などが記録されているものもあります。
少し怖いですね。

今回はこれらを同時に最適化する方法をシェアしていきます。

やること

以下の手順で行います。
 ① 現状のEXIF情報をみてみる
 ② InterventionImageをインストールする(Composerを使用)
 ③ InterventionImageを使えるようにする(Configをいじる)
 ④ Controllerで実際に画像処理を行う

実際にやってみる

① まず現状の画像のEXIF情報をみてみる

これは別にやらなくても良いのですが、
現在画像処理を行っているControllerにおいてdd()メソッドを実行してみます。

〇〇Controller.php
dd($image->exif()); // $imageが画像データです

これでブラウザにEXIF情報が表示できます。
ずらっと配列で表示されて、撮影した機種など色々な情報が格納されているのがわかると思います。。

ちなみにdd()は「dump and die」の略なんですね。(知らないで使ってた)

② InterventionImageをインストールする

この余計なEXIFの削除とリサイズ処理と回転(画像の向き)の最適化処理を同時に簡単にできるのがInterventionImageというものです。
PHPの画像処理ライブラリであるGDとImagickをサポートするパッケージで、
Laravelで画像処理をするならこれ一択、という位置付けのものですね。
GDやImagickを簡単に扱うことができます。

公式はこちら
http://image.intervention.io/getting_started/installation#laravel

以下のコマンドを実行してインストールします。

$php composer.phar require intervention/image


③ InterventionImageを使えるようにする

Config/app.phpに以下の記述を追加します。
追加するのはprovidersaliasesの2箇所です。
プロバイダとエイリアスの設定ですね。

Config/app.php
'providers' => [
    Intervention\Image\ImageServiceProvider::class,
],

~中略~

'aliases' => [
    'Image' => Intervention\Image\Facades\Image::class,
],



さらにdriver設定の追加を行います。(以下のコマンドを実行)

$php artisan vendor:publish --provider="Intervention\Image\ImageServiceProviderLaravelRecent"



最後に、Configで設定をいじったのでキャッシュをクリアします。(以下のコマンドを実行)

$php artisan config:clear


③ Controllerで実際に処理を行う

ファサードを使う宣言をする

まずは画像処理を行うControllerにおいて以下を記述します。

〇〇Controller.php
use Intervention\Image\Facades\Image; // Imageファサードを使う
use Illuminate\Support\Facades\Storage; // Storageファサードを使う

画像処理を行う

InterventionImageでは本当に色々なことができるのですが、
ここでは実際によく使うであろう縦横比を維持したリサイズと、
ファイルをjpg形式に変換する例を示します。

〇〇Controller.php
$resized_image = Image::make($posted_image)->fit(640, 360)->encode('jpg');



$posted_imageが加工前の画像で、make()でInterventionImageに加工前の画像を読み込んでいます。
fit()は幅と高さを指定しつつ、縦横比が合わない場合はトリミングしてくれるメソッドです。

単純なリサイズならresize()でも良いのですが、画像がゆがんでしまうのでこのfit()が便利だと思います。

※InterventionImageでの網羅的な画像処理はこちらのサイトが参考になります。
https://blog.capilano-fw.com/?p=1574#_resize

画像の回転とEXIF情報の処理

最後に本題(?)の画像が勝手に回転する問題とEXIF情報の処理です。
これにはorientate()を使います。

〇〇Controller.php
$resized_image->orientate()->save();

これで自動回転しつつEXIF情報を削除してくれます。
->save()がないと処理が反映されないので注意です。

ファイル保存する

ファイル保存はstoreメソッドが使えない(GDがサポートしていないというエラーになる)ので
Laravelの機能(ファサード)のStorage::putを使います。

〇〇Controller.php
Storage::put('public/image/' . $image_name, $resized_image); 



これで良い感じの大きさになり、画像の向きも正しい向きになり、不要な埋め込み情報も削除された画像が投稿できるようになったはずです!
おつかれさまでした〜。

paleo_engineer
PHP/Laravelを中心に日々勉強中。
https://twitter.com/paleo_engineer
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away