ミニカーコレクションSNSサービス開発⑦▶️開発81日目
7回目の投稿となる「ミニカーコレクションSNSサービス開発」の記事ですが、僕自身物忘れしやすい性格ということもあり、備忘録としてまとめておいた方が後々便利であったり、普段の開発でどんなことをしているのか発信できればいいなと思い、これまで記事を書いてきました。
しかしながら、ミニカーの記事を楽しみに見られている方は、開発回の記事は全然スルーしてもらって構いませんので、今後ともよろしくお願いします!😂
①画像サイズを横幅1000pxに変更
The garageへの画像アップロードはiPhoneやアンドロイドのスマホ経由でアップロードされることが多いと想定しており、例えばiPhoneで写真を撮影した時はHEIC形式且つ4:3のアスペクト比で、サイズは4,032 [px] × 3,024 [px]あり、容量は約2MB前後あります。
この様な無加工の画像の場合、アプリケーション上で画像を読み込む際に、データ量が大きいがゆえに読み込みに時間がかかる場合がありました。時間帯によっては10秒以上かかる場合もあり、流石に読み込みが遅いとUXを損なうと思い、今回読み込み速度の改善を行いました。
まず取り組んだのは4,032 [px] × 3,024 [px]の画像サイズを横幅1,000 [px]まで圧縮し、縦幅もアスペクト比を維持したまま圧縮したのちに、保存する方法です。
実装に関してはLaravelにcomposer経由でIntervention Imageをインストールしました。
しかしながら、インストール後いくら設定を確認しても、キャッシュを消してもエラーになり上手くいかなかったため、敢えて最新のIntervention Imageパッケージ(バージョン3)を使うことを諦め、旧型パッケージのバージョン2.7を指定してcomposerでインストールし直しました。
バージョン2.7をインストール後、画像保存の処理を記述しているコントローラーを開き、Intervention Imageを使うために以下を冒頭で記述し、
use Illuminate\Support\Facades\File;
use Intervention\Image\ImageManagerStatic as Image;
また、保存処理のコードに以下の画像サイズ圧縮のコードを追加しました。
// 幅を1000pxに縮小し、アスペクト比を維持
$image->resize(1000, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
これでアップロードされた画像の横幅を1,000 [px]に圧縮し、縦幅もアスペクト比を維持したサイズまで圧縮して画像保存が可能になりました。
②画像を85%の画像品質に下げて保存
続いて行なったことは、画像サイズを下げて保存するだけでなく、画像品質を85%に少し下げて保存させることを行いました。
画像品質の変更は、保存する際のパスを渡す記述に併せて、新たな「85(%)」という引数を渡すを記述を追加することにより、品質をコントロールする記述方法が使えました。
$image->save($savePath, 85);
こちらの記述を追記するだけで実装できました。
③jpeg形式からwebp形式での保存に変更
元々は上記の①と②の画像サイズの圧縮のみで、読み込み速度の改善を行おうと思っていましたが、実装完了後テストしてみると、もう少し読み込み速度が必要だなと思い、Laravelプロジェクトへの画像の保存形式をjpegからwebpに変更しました。
webpについて調べてみると、
とあり、圧縮効果を発揮しつつ、画像品質も担保できるとのことで、今回3つ目の方法として織り込みました。
まずは画像を保存する際の画像ファイル名の生成の箇所で、
// ファイル名を生成
$filenameA = time() . '_' . pathinfo($imageA->getClientOriginalName(), PATHINFO_FILENAME) . '.webp';
画像ファイル名の拡張子を「.webp」形式で保存する様に設定し
// WebP形式で保存(85%の品質)
$image->save($savePath, 85, 'webp');
②で85%の品質を設定したコードに、新たに3つ目の引数「'webp'」を追記しました。
この変更で無事webp形式で画像保存ができる様になりました。
今回織り込んだ①〜③を統合したコードを以下に貼ります。
$imageA = $request->file('CarImageA');
$filenameA = null;
if ($imageA) {
// ファイル名を生成
$filenameA = time() . '_' . pathinfo($imageA->getClientOriginalName(), PATHINFO_FILENAME) . '.webp';
try {
// Intervention Imageを使用して画像を読み込む
$image = Image::make($imageA);
// 幅を1000pxに縮小し、アスペクト比を維持
$image->resize(1000, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
// 保存パスを指定
$savePath = storage_path('app/public/CarImages/' . $filenameA);
// WebP形式で保存(85%の品質)
$image->save($savePath, 85, 'webp');
// 保存後の容量をチェックし、再調整(1MB以下にする)
while (filesize($savePath) > 1024 * 1024) { // 1MBを超えている場合
$image->save($savePath, 50, 'webp'); // 圧縮率を下げて再保存
}
} catch (\Exception $e) {
// エラーメッセージを表示
dd($e->getMessage());
}
}
このコードはコントローラーのstoreメソッド内に書いています。
上記の記述後は、バリデーションを設定し、DBにファイル名を保存する処理にしています。
今回は、読み込み速度改善に向けて、保存する画像を圧縮してデータ容量を下げた形で保存させる形式を取りました。当初は画像を圧縮し容量を小さくしたら、表示される画像の解像度が下がり、せっかくの車の写真がカッコよくなくなってしまうのではないかと思っていましたが、もともとスマホなどで撮影された画像は品質が高いので、多少画像を圧縮しても大差は無かったので良かったです。
ちなみに上記のコードを埋め込んだ後では、ファイル容量が2.4MBから74KBまで削減することができました。読み込み速度も随分改善されて0.5秒くらいで表示される様になりました。
このnoteではミニカーやプラモデルなどのクルマ模型特化型のオンラインディスプレイサービス" The Garage "の開発に関する記事や、ミニカーに関する記事などを書いています。
⬇️The Garageのβ版はこちらのURLよりご利用いただけます!
ご興味のある方、ぜひご利用いただけたら嬉しいです😊
今後とも改善を繰り返して使いたくなるサービスを目指していきますので、応援の程どうぞよろしくお願い致します。
それでは失礼します🚘