Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Image Laravel Package

spatie/image

Expressive PHP image manipulation by Spatie. Load an image, chain operations like resize/crop, rotate, greyscale, brightness, sharpen, and quality, then save. Supports common formats and integrates cleanly in Laravel or any PHP app.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require spatie/image
    

    Ensure exif PHP extension is enabled (required since v1.5.3).

  2. First Use Case: Load and resize an image:

    use Spatie\Image\Image;
    
    Image::load('path/to/image.jpg')
        ->width(300)
        ->height(200)
        ->save('path/to/resized.jpg');
    
  3. Key Entry Points:

    • Image::load(): Load an image from a file path.
    • Chain methods like width(), height(), greyscale(), etc.
    • save(): Save the manipulated image (optionally to a new path).
  4. Where to Look First:


Implementation Patterns

Common Workflows

  1. Dynamic Thumbnail Generation:

    $image = Image::load(storage_path('images/product.jpg'))
        ->fit(Fit::Cover, 400, 400)
        ->save(storage_path("images/thumbs/{$product->id}.jpg"));
    
  2. Batch Processing with Laravel:

    $images = Storage::files('uploads/products');
    foreach ($images as $image) {
        Image::load($image)
            ->resize(800, 600)
            ->save(str_replace('uploads', 'processed', $image));
    }
    
  3. Image Validation and Processing:

    public function store(Request $request) {
        $request->validate(['image' => 'required|image']);
        $path = $request->file('image')->store('uploads');
    
        Image::load(storage_path("app/{$path}"))
            ->resize(1024, null) // Maintain aspect ratio
            ->save();
    
        // Store path in DB
    }
    
  4. Art Director Pattern (Laravel):

    // app/ArtDirectors/ImageArtDirector.php
    public function resize(Image $image, int $width, int $height) {
        return $image->fit(Fit::Cover, $width, $height);
    }
    
  5. Queue Jobs for Heavy Processing:

    // app/Jobs/ProcessImage.php
    public function handle() {
        Image::load($this->path)
            ->resize(1200, 800)
            ->watermark($this->watermarkPath, 0.2)
            ->save($this->outputPath);
    }
    

Integration Tips

  • Laravel Filesystem: Use Storage::disk('public')->put() for saving processed images.
  • Model Observers: Trigger image processing after model creation:
    // app/Observers/ProductObserver.php
    public function created(Product $product) {
        if ($product->image) {
            Image::load($product->image_path)
                ->resize(800, 600)
                ->save();
        }
    }
    
  • API Responses: Return processed image URLs:
    return response()->json([
        'image_url' => Storage::url('processed/' . $product->id . '.jpg')
    ]);
    
  • Caching: Cache processed images with tags:
    Cache::tags(['product-images'])->put("product_{$product->id}_thumb", $thumbPath, now()->addDays(7));
    

Gotchas and Tips

Pitfalls

  1. Driver Conflicts:

    • Imagick is preferred for advanced features (e.g., HEIC support), but GD is more widely available.
    • Fix: Explicitly set the driver:
      Image::useImageDriver(ImageDriver::Gd)->load($path);
      
  2. Aspect Ratio Distortion:

    • Methods like width() and height() ignore aspect ratio unless paired with fit().
    • Fix: Use fit(Fit::Cover, $width, $height) or resize($width, $height, Fit::Constraint).
  3. Transparency Issues:

    • PNGs with transparency may render incorrectly when converted to JPG.
    • Fix: Set a background color:
      ->background('white')->save('output.jpg');
      
  4. EXIF Data:

    • orientation() relies on EXIF data, which may be missing or corrupted.
    • Fix: Fallback to default orientation:
      ->orientation(Orientation::Rotate0);
      
  5. Memory Limits:

    • Large images (e.g., 100MB+) may hit PHP memory limits.
    • Fix: Use ImageDriver::Vips (lower memory usage) or process in chunks.

Debugging

  • Check Driver Availability:
    if (!Image::isDriverAvailable(ImageDriver::Imagick)) {
        throw new \RuntimeException('Imagick not available');
    }
    
  • Log Image Properties:
    $image = Image::load($path);
    \Log::info("Original: {$image->getWidth()}x{$image->getHeight()}");
    
  • Compare Before/After:
    $original = file_get_contents($path);
    $processed = file_get_contents($outputPath);
    if (!hash_equals(hash('md5', $original), hash('md5', $processed))) {
        \Log::warning('Image processing altered content');
    }
    

Configuration Quirks

  1. Default Driver:

    • Set globally in config/spatie/image.php:
      'default_driver' => ImageDriver::Gd,
      
    • Override per request:
      Image::useImageDriver(ImageDriver::Imagick)->load($path);
      
  2. Quality Settings:

    • JPEG quality defaults to 80. Lower values (e.g., 20) reduce file size but degrade quality.
    • Tip: Use quality(75) for a balance.
  3. Path Handling:

    • save() uses relative paths unless an absolute path is provided.
    • Tip: Use storage_path() or public_path() for consistency:
      ->save(public_path('images/processed.jpg'));
      

Extension Points

  1. Custom Drivers:

    • Implement Spatie\Image\Contracts\ImageDriver for specialized needs (e.g., cloud storage).
    • Example:
      class S3ImageDriver implements ImageDriver {
          public function load(string $path): void { /* ... */ }
          public function save(string $path): void { /* ... */ }
          // Implement all required methods
      }
      
  2. Macros:

    • Extend the Image class with custom methods:
      Image::macro('addLogo', function ($logoPath, $position = 'bottom-right') {
          return $this->insert($logoPath, $position, 0.2);
      });
      
      Usage:
      Image::load($path)->addLogo('logo.png')->save();
      
  3. Event Listeners:

    • Trigger events before/after processing:
      Image::load($path)
          ->onProcess(function () {
              \Log::info('Processing started');
          })
          ->onSave(function () {
              \Log::info('Processing completed');
          })
          ->resize(800, 600)
          ->save();
      
  4. Fallback Logic:

    • Handle unsupported formats gracefully:
      try {
          $image = Image::load($path)->resize(800, 600);
      } catch (\Spatie\Image\Exceptions\UnsupportedFormatException $e) {
          \Log::warning("Unsupported format: {$e->getMessage()}");
          // Fallback to a placeholder
      }
      

Performance Tips

  • Batch Processing: Use Laravel queues for CPU-intensive tasks.
  • Lazy Loading: Process images on-demand (e.g., in API responses).
  • Disk Caching: Cache processed images to avoid reprocessing:
    $cacheKey = "image_{$product->id}_thumb";
    if (!Cache::has($cacheKey)) {
        Image::load($product->image_path)
            ->resize(300, 200)
            ->save($outputPath);
        Cache::put($cacheKey, $outputPath, now()->addHours(1));
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport