0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Laravelで画像を圧縮する手順(ImageManager使用)

Last updated at Posted at 2025-03-08

手順

1. Intervention Image をインストール

まず、Intervention Image ライブラリをインストールします。

composer require intervention/image

2-1. 画像の圧縮処理を実装(新規アップロード):サービスクラス

✅の箇所

/Applications/MAMP/htdocs/Laravel/collections/app/Service/Admin/CollectionService.php
namespace App\Service\Admin;
use App\Models\Collection;
use App\Models\CollectionImage;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Intervention\Image\ImageManager; // ✅
use Intervention\Image\Encoders\JpegEncoder; // ✅
use Intervention\Image\Drivers\Gd\Driver; // ✅


  public static function storeRequestImage($request, $collection)
  {
      $orderData = json_decode($request->input('image_order'), true) ?? [];
      $sessionTmpImages = $request->input('tmp_images');

      // ✅ `ImageManager`を`gd`ドライバー指定で作成
      $manager = new ImageManager(new Driver());

      // 🔹 通常アップロードされた画像の保存
      if($request->hasFile('image_path') && is_null($sessionTmpImages)) {
          $uploadedFiles = $request->file('image_path');
  
          foreach($uploadedFiles as $imagePath) {
              $fileName = trim($imagePath->getClientOriginalName()); // アップロードファイル名取得
              $order = collect($orderData)->first(fn($item) => str_starts_with($item['uniqueId'], $fileName)); // position取得
              $imageName = time() . '_' . uniqid() . '.' . $imagePath->getClientOriginalExtension(); // テーブル保存用

              // ✅ 拡張子を取得(小文字変換)
              $extension = strtolower($imagePath->extension());

              // ✅ 画像に合わせた拡張子選択
              switch ($extension) {
                  case 'png':
                      $encoder = new PngEncoder(9); // PNG 圧縮
                      break;
                  case 'webp':
                      $encoder = new WebpEncoder(80); // WebP 圧縮
                      break;
                  default:
                      $encoder = new JpegEncoder(75); // それ以外はJPEG(品質75)
              }

              // ✅ 画像を圧縮
              $compressedImage = $manager->read($imagePath->getRealPath())->encode($encoder);

              // ✅ 圧縮画像を保存
              Storage::disk('public')->put('collection_images/' . $imageName, (string)$compressedImage);
  
              CollectionImage::create([
                  'collection_id' => $collection->id,
                  'image_path' => $imageName,
                  'position' => $order ? $order['position'] : 0
              ]);
          }
      }

2-2. 画像の圧縮処理を実装(セッション+ストレージのアップロード):リクエストクラス

✅の箇所

/Applications/MAMP/htdocs/Laravel/collections/app/Http/Requests/CollectionRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\ImageManager; // ✅
use Intervention\Image\Drivers\Gd\Driver; // ✅
use Intervention\Image\Encoders\JpegEncoder; // ✅
use Intervention\Image\Encoders\PngEncoder; // ✅
use Intervention\Image\Encoders\WebpEncoder; // ✅

class CollectionRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, mixed>
     */
    public function rules()
    {
        return [
            'title' => ['required', 'string', 'max:50'],
            'description' => ['nullable', 'string', 'max:10000'],
            'url_qiita' => ['nullable', 'url', 'max:500'],
            'url_webapp' => ['nullable', 'url', 'max:500'],
            'url_github' => ['nullable', 'url', 'max:500'],
            'is_public' => ['required', 'boolean'],
            'position' => ['required', 'integer'],
            'image_path' => ['nullable'],
            'image_order' => ['nullable'],
        ];
    }

    protected function failedValidation(\Illuminate\Contracts\Validation\Validator $validator)
    {
        // ✅ GDドライバーで ImageManager を作成
        $manager = new ImageManager(new Driver());

        $tmpImagePaths = session('tmp_images', []);
        $fileNames = session('file_names', []);
        $imageOrder = session('image_order', []);

        // フォームの hidden input から画像順序データを取得
        if($this->has('image_order')) {
            $imageOrder = json_decode($this->input('image_order'), true);
        }

        if ($this->hasFile('image_path')) {
            $images = $this->file('image_path');

            foreach ($images as $image) {
                // $base64Image = 'data:image/' . $image->extension() . ';base64,' . base64_encode(file_get_contents($image->getRealPath()));
                $fileName = $image->getClientOriginalName(); // ファイル名取得
                $extension = strtolower($image->extension()); // 拡張子を取得(小文字変換)

                // ✅ 画像に合わせた拡張子を選択
                switch ($extension) {
                    case 'png':
                        $encoder = new PngEncoder(9); // PNG 圧縮
                        break;
                    case 'webp':
                        $encoder = new WebpEncoder(80); // WebP 圧縮
                        break;
                    default:
                        $encoder = new JpegEncoder(75); // それ以外はJPEG(品質75)
                }

                // ✅ 画像を圧縮
                $compressedImage = $manager->read($image->getRealPath())->encode($encoder);

                $tmpImageName = time() . '_' . uniqid() . '.' . $extension;
                Storage::disk('public')->put("tmp/{$tmpImageName}", (string)$compressedImage);

                $tmpImagePaths[] = "tmp/{$tmpImageName}";
                $fileNames[] = $fileName;

                // `imageOrder` に `fileName` がすでに存在するかチェック
                $foundIndex = array_search($fileName, array_column($imageOrder, 'fileName'));

                if ($foundIndex !== false) {
                    // すでに `imageOrder` に登録済みなら `src` を更新
                    $imageOrder[$foundIndex]['src'] = "tmp/{$tmpImageName}";
                } else {
                    // 新規画像の場合
                    $imageOrder[] = [
                        'fileName' => $fileName,
                        'src' => "tmp/{$tmpImageName}",
                    ];
                }
            }
        }

        // セッションに保存
        Session::put('tmp_images', $tmpImagePaths);
        Session::put('file_names', $fileNames);
        Session::put('image_order', $imageOrder);

        parent::failedValidation($validator);
    }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?