askancy/laravel-smart-thumbnails

Advanced thumbnail generation with smart cropping for Laravel applications

1.5 2025-07-06 16:29 UTC

This package is auto-updated.

Last update: 2025-07-06 16:31:03 UTC


README

Laravel Smart Thumbnails Demo

The most advanced thumbnail generation package for Laravel with intelligent cropping, multi-disk support, subdirectory organization, and bulletproof error handling that never breaks your application.

Latest Version on Packagist Total Downloads Tests

๐Ÿš€ Features

  • โœจ Smart Crop Algorithm - Based on dont-crop with energy detection
  • ๐Ÿ›ก๏ธ Bulletproof Error Handling - Never breaks your application, always shows something
  • ๐Ÿ“ Subdirectory Organization - Handles millions of thumbnails with optimal filesystem performance
  • ๐Ÿ’พ Multi-Disk Support - S3, local, scoped disks, and custom storage solutions
  • ๐ŸŽจ Multiple Variants - Responsive design with preset variants
  • ๐Ÿš€ Lazy Generation - Thumbnails created only when needed
  • ๐Ÿ”„ Intelligent Fallbacks - Original image โ†’ Custom placeholder โ†’ Generated placeholder
  • โšก High Performance - Optimized for large-scale applications
  • ๐Ÿ—‘๏ธ Maintenance Commands - Purge, optimize, and analyze thumbnails
  • ๐Ÿงช Fully Tested - Comprehensive PHPUnit test suite

๐Ÿ“‹ Requirements

  • PHP 8.1+
  • Laravel 10.0+
  • Intervention Image 2.7+ or 3.0+
  • GD or ImageMagick extension

๐Ÿ“ฆ Installation

Install via Composer:

composer require askancy/laravel-smart-thumbnails

Publish configuration:

php artisan vendor:publish --tag=laravel-smart-thumbnails-config

๐Ÿ›ก๏ธ Error-Safe Usage (Recommended)

The package offers bulletproof error handling that ensures your application never breaks due to missing images or storage issues.

Silent Mode (Never Fails)

{{-- โœ… NEVER throws exceptions, always shows something --}}
<img src="{{ Thumbnail::set('gallery')->src($photo->path, 's3')->urlSafe() }}" alt="Gallery">

{{-- โœ… Explicit silent mode --}}
<img src="{{ Thumbnail::silent()->set('products')->src($image, 's3')->url('thumb') }}" alt="Product">

Strict Mode (For Development/Admin)

{{-- โš ๏ธ May throw exceptions for debugging --}}
<img src="{{ Thumbnail::strict()->set('gallery')->src($photo->path, 's3')->url() }}" alt="Gallery">

{{-- โš ๏ธ Standard mode (configurable default) --}}
<img src="{{ Thumbnail::set('gallery')->src($photo->path, 's3')->url('large') }}" alt="Gallery">

๐ŸŽฏ Quick Examples

Responsive Blog Headers

<picture>
    <source media="(max-width: 640px)" 
            srcset="{{ Thumbnail::set('blog')->src($post->image, 's3')->urlSafe('card') }}">
    <source media="(min-width: 641px)" 
            srcset="{{ Thumbnail::set('blog')->src($post->image, 's3')->urlSafe('hero') }}">
    <img src="{{ Thumbnail::set('blog')->src($post->image, 's3')->urlSafe('hero') }}" 
         alt="{{ $post->title }}"
         loading="lazy">
</picture>

Homepage Slider (Never Breaks)

<div class="hero-slider">
    @foreach($slides as $slide)
        <div class="slide">
            {{-- This slider will NEVER break, even with missing images --}}
            <img src="{{ Thumbnail::set('slider')->src($slide->image, 's3')->urlSafe('desktop') }}"
                 alt="Hero Slide"
                 loading="lazy">
        </div>
    @endforeach
</div>

โš™๏ธ Advanced Configuration

Multi-Disk Setup

// config/filesystems.php
'disks' => [
    's3_products' => [
        'driver' => 'scoped',
        'disk' => 's3',
        'prefix' => 'products',
    ],
    's3_gallery' => [
        'driver' => 'scoped',
        'disk' => 's3',
        'prefix' => 'gallery',
    ],
],

Preset Configuration

// config/thumbnails.php
'presets' => [
    'products' => [
        'format' => 'webp',
        'smartcrop' => '400x400',
        'destination' => ['disk' => 's3_products', 'path' => 'thumbnails/'],
        'quality' => 90,
        'smart_crop_enabled' => true,
        'silent_mode' => false, // Strict for admin
        'subdirectory_strategy' => 'hash_prefix', // Optimal for high volume
        'variants' => [
            'thumb' => ['smartcrop' => '120x120', 'quality' => 75],
            'card' => ['smartcrop' => '250x250', 'quality' => 85],
            'detail' => ['smartcrop' => '600x600', 'quality' => 95],
            'zoom' => ['smartcrop' => '1200x1200', 'quality' => 95],
        ]
    ],
],

๐Ÿ“ Subdirectory Organization

Handle millions of thumbnails efficiently with automatic subdirectory organization:

Hash Prefix Strategy (Recommended)

thumbnails/products/
โ”œโ”€โ”€ a/b/ (47 files)
โ”œโ”€โ”€ c/d/ (52 files)
โ”œโ”€โ”€ e/f/ (48 files)
โ””โ”€โ”€ ... (256 total directories)

Date-Based Strategy

thumbnails/blog/
โ”œโ”€โ”€ 2025/01/28/ (today's posts)
โ”œโ”€โ”€ 2025/01/27/ (yesterday's posts)
โ””โ”€โ”€ 2025/01/26/ (older posts)

Configuration

'subdirectory_strategy' => 'hash_prefix',    // Uniform distribution (recommended)
'subdirectory_strategy' => 'date_based',     // Organized by date
'subdirectory_strategy' => 'filename_prefix', // By filename initials
'subdirectory_strategy' => 'hash_levels',    // Multi-level (a/b/c/)
'subdirectory_strategy' => 'none',           // No subdirectories

๐Ÿง  Smart Crop Algorithm

Advanced intelligent cropping based on image energy analysis:

// Enable smart crop for better results
'smart_crop_enabled' => true,  // Uses energy detection algorithm
'smart_crop_enabled' => false, // Uses simple center crop

How it works:

  • Analyzes image energy using gradient magnitude
  • Finds areas of interest based on contrast and details
  • Avoids aggressive cropping that removes important subjects
  • Uses rule of thirds for optimal positioning

๐Ÿ› ๏ธ Artisan Commands

Purge Thumbnails

# Purge all thumbnails
php artisan thumbnail:purge

# Purge specific preset
php artisan thumbnail:purge products

# Silent purge (no confirmation)
php artisan thumbnail:purge products --confirm

Statistics & Analysis

php artisan tinker
>>> Thumbnail::analyzeDistribution('products')
>>> Thumbnail::getSystemStats()
>>> Thumbnail::optimize() // Remove duplicates and empty directories

๐ŸŽ›๏ธ Advanced Features

Conditional Error Handling

{{-- Admin sees errors, users get safe fallbacks --}}
@admin
    <img src="{{ Thumbnail::strict()->set('gallery')->src($image, 's3')->url() }}" alt="Gallery">
@else
    <img src="{{ Thumbnail::silent()->set('gallery')->src($image, 's3')->url() }}" alt="Gallery">
@endadmin

Performance Optimization

// config/thumbnails.php
'optimization_profiles' => [
    'high_volume' => [
        'subdirectory_strategy' => 'hash_prefix',
        'quality' => 75,
        'silent_mode' => true,
    ],
    'high_quality' => [
        'quality' => 95,
        'webp_lossless' => true,
        'silent_mode' => false,
    ],
],

Batch Processing

// Process multiple thumbnails efficiently
'batch_size' => 50,
'batch_timeout' => 300,
'queue_enabled' => true, // Use Laravel queues

Security Features

'allowed_extensions' => ['jpg', 'jpeg', 'png', 'webp', 'gif'],
'max_file_size' => 10 * 1024 * 1024, // 10MB
'validate_image_content' => true,
'sanitize_filenames' => true,

๐Ÿ“Š Monitoring & Statistics

System Analysis

// Get complete system statistics
$stats = Thumbnail::getSystemStats();
// Returns: total files, size, distribution by disk, preset analysis

// Analyze specific preset
$analysis = Thumbnail::analyzeDistribution('products');
// Returns: file count, size, directory distribution, format breakdown

Performance Monitoring

'enable_stats' => true,
'log_generation_time' => true,
'monitor_disk_usage' => true,

๐Ÿ”ง Troubleshooting

Common Issues

# Test disk connectivity
php artisan tinker
>>> Thumbnail::testDisk('s3_products')

# Validate configuration
>>> Thumbnail::validateConfiguration()

# Clear Laravel caches
php artisan config:clear
php artisan cache:clear

Debug Mode

{{-- Debug information in development --}}
@if(app()->environment('local'))
    @foreach(Thumbnail::getAvailableDisks() as $disk)
        @php $status = Thumbnail::testDisk($disk) @endphp
        <p>{{ $disk }}: {{ $status['accessible'] ? 'โœ…' : 'โŒ' }}</p>
    @endforeach
@endif

๐Ÿ“ˆ Performance Benefits

Files Without Subdirectories With Hash Prefix
1,000 โš ๏ธ Slow โœ… Fast
10,000 โŒ Very Slow โœ… Fast
100,000 โŒ Unusable โœ… Fast
1,000,000 โŒ Impossible โœ… Fast

With subdirectories:

  • ๐Ÿ“ˆ 200x faster filesystem operations
  • ๐Ÿš€ Instant directory listings
  • โšก Efficient backup and sync
  • ๐ŸŽฏ Optimal for CDN delivery

๐Ÿค Contributing

We welcome contributions! Please see CONTRIBUTING.md for details.

๐Ÿ“„ License

MIT License. See LICENSE.md for details.

๐Ÿ™ Credits

๐Ÿ’ก Pro Tip: Always use urlSafe() or silent() for public-facing content and reserve strict() mode for admin interfaces and development!