daiyanmozumder / image-wizard
Enterprise Laravel Image Processing Package powered by Python
Requires
- php: ^8.1|^8.2|^8.3
- illuminate/contracts: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
- symfony/process: ^6.2|^7.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0|^10.0
- phpunit/phpunit: ^10.0|^11.0
README
Enterprise Laravel Image Processing powered by Python
Image Wizard is an enterprise-grade Laravel image processing package. Instead of relying on PHP's memory-hungry GD/Imagick libraries, it bridges Laravel to a high-performance Python engine powered by the Pillow library.
Laravel handles the orchestration, fluent API, and background queueing, while Python executes the heavy CPU-bound image manipulation.
✨ Features
- Blazing Fast: Image processing runs in an isolated Python process. No more
Allowed memory size exhaustederrors in PHP! - Fluent API: Clean, intuitive, and chainable syntax (
->resize()->watermark()->save()). - Laravel Queues: Send massive batch jobs to the background instantly with
->queue(). - Cloud Storage (S3): Seamlessly pull/push to AWS S3 or Local disks with
->fromDisk()and->toDisk(). - Variant Generator: Automatically spawn
thumbnail,medium, andlargeresponsive variants based on config presets. - Watermark Engine: Apply image watermarks with CSS-like positioning, alpha opacity, automatic wide-logo cropping, smart dynamic rescaling, and auto-margins.
- Next-Gen Formats: Built-in support for converting to WebP and AVIF.
📦 Requirements
- PHP 8.1+
- Laravel 10.0, 11.0, or 12.0+
- Python 3+
- Pillow (
pip install Pillow>=10.0.0)
🚀 Installation
- Require the package via Composer:
composer require daiyanmozumder/image-wizard
- Publish the configuration file:
php artisan vendor:publish --tag=image-wizard-config
- Ensure you have Python and the Pillow library installed on your server/environment:
pip install Pillow
⚙️ Configuration
Open config/image-wizard.php. Here you can define default formats, compression quality, queue settings, and responsive variant presets.
return [ 'default_format' => 'webp', // Convert everything to webp by default 'python' => [ 'executable' => env('IMAGE_WIZARD_PYTHON_EXECUTABLE', 'python3'), 'timeout' => 60, // Maximum execution time in seconds ], 'quality' => [ 'jpeg' => 80, 'webp' => 80, 'avif' => 50, ], 'variants' => [ 'thumbnail' => ['width' => 150, 'height' => 150, 'fit' => 'crop'], 'medium' => ['width' => 800, 'height' => 800, 'fit' => 'contain'], 'large' => ['width' => 1200, 'height' => 1200, 'fit' => 'contain'], ], ];
🌐 Setting up Python on cPanel
On cPanel hosting environments, do not use cPanel's "Setup Python App" GUI web application tool (as it overrides your domain's web traffic with Python WSGI instead of serving your Laravel PHP application).
Instead, create a standalone command-line Python virtual environment via cPanel Terminal / SSH:
- Open cPanel Terminal (under Advanced) or connect via SSH.
- Create a Python virtual environment (
--without-pippreventsensurepiperrors common on cPanel):python3 -m venv --without-pip ~/image_wizard_env - Activate the environment:
source ~/image_wizard_env/bin/activate
- Install
pipandPillow:- For Python 3.10+:
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py python get-pip.py rm get-pip.py pip install Pillow
- For Python 3.9:
curl https://bootstrap.pypa.io/pip/3.9/get-pip.py -o get-pip.py python get-pip.py rm get-pip.py pip install Pillow
- For Python 3.10+:
- Set the executable path in your Laravel
.env:IMAGE_WIZARD_PYTHON_EXECUTABLE=/home/YOUR_CPANEL_USERNAME/image_wizard_env/bin/python
- Clear your Laravel config cache:
php artisan config:clear
📖 Usage Guide
Basic Processing
Chain commands together effortlessly. Execution is delayed until you call save(), allowing for clean architecture.
use ImageWizard; ImageWizard::load('public/uploads/raw.jpg') ->resize(800, 600, 'cover') ->format('webp') ->quality(85) ->save('public/images/optimized.webp');
Advanced Resizing (Fit Strategies)
Pass a fit strategy as the third argument to resize() to control how the image scales.
ImageWizard::load('image.jpg') ->resize(500, 500, 'contain') // (Default) Scale to fit within bounds // ->resize(500, 500, 'cover') // Scale to fill bounds exactly, cropping overflow // ->resize(500, 500, 'stretch') // Ignore aspect ratio, force to exact dimensions // ->resize(500, 500, 'pad') // Fit within bounds, adding transparent/white padding ->save('output.jpg');
Watermarks
Overlay logos onto your images with intelligent scaling, automatic cropping for wide logos, CSS-like positioning, opacity, and dynamic margins.
ImageWizard::load('photo.jpg') ->watermark('logo.png', [ 'position' => 'bottom-right', // CSS-like positioning: top-left, center, bottom-right, etc. 'opacity' => 0.6, // 60% opacity (0.0 to 1.0) 'size_ratio' => 0.12, // Auto-scales watermark to 12% of main image's smaller dimension (default: 0.12) 'margin' => 20, // Explicit margin offset in px (auto-calculated as 3% min 10px if omitted) ]) ->save('photo-watermarked.jpg');
Smart Watermark Features:
- Aspect Ratio Crop (Wide Logos): If a logo has an aspect ratio
width / height > 1.5(e.g. logo with company text), Image Wizard automatically crops(0, 0, height, height)to isolate the left square icon mark. - Smart Dynamic Rescaling: Automatically resizes the watermark relative to the target image (
size_ratio, default 12%), so watermarks stay proportionally sized on high-res and low-res photos alike. - Smart Dynamic Margin: If no
marginis provided, margin is auto-calculated as 3% of the target image's smaller dimension (minimum 10px).
Cloud Storage (AWS S3)
Image Wizard integrates natively with Laravel's Storage facade. It automatically streams files from S3 to a local temp folder, processes them via Python, streams them back to S3, and cleans up the temp files.
ImageWizard::fromDisk('s3', 'raw-uploads/user.jpg') ->resize(1200) ->watermark('watermark.png') ->toDisk('s3', 'optimized/user.jpg');
Background Processing (Queues)
Processing large 4K images blocks the PHP thread. Use queue() to dispatch a background job instantly instead of save().
// Instantly returns a response to the user ImageWizard::load('massive-raw-file.tiff') ->format('avif') ->resize(2000) ->queue('public/optimized.avif');
Automatic Responsive Variants
Instead of manually creating multiple sizes, use your config presets to generate them all at once.
ImageWizard::load('hero.png') ->generateVariants('public/hero.jpg', ['thumbnail', 'medium', 'large']);
This generates:
public/hero-thumbnail.jpgpublic/hero-medium.jpgpublic/hero-large.jpg
Batch Processing
Apply a strict pipeline to an entire array of files.
$files = ['img1.jpg', 'img2.png', 'img3.webp']; ImageWizard::resize(500, 500, 'crop') ->format('webp') ->batch($files, 'public/batch-output/');
Preserving Metadata (EXIF)
By default, EXIF data (GPS, camera info) is stripped to optimize file size. If you are building a photography portfolio, preserve it easily:
ImageWizard::load('photo.jpg') ->preserveMetadata() ->save('photo-preserved.jpg');
🛠️ Troubleshooting
-
Python execution failed / File not found: Ensure
pythonorpython3is available in your server's$PATH. If using Docker or a specific environment, update theexecutablepath inconfig/image-wizard.php. -
JSON Decode Error: The PHP bridge expects strict JSON from Python. If you have modified the Python environment to print debug warnings to
stdout, it will break the bridge. Ensure your Python script runs silently. -
Missing Pillow: If you get an internal engine error mentioning
PIL, runpip install Pillowon your host machine.
🛡️ Security
If you discover any security related issues, please email hello@example.com instead of using the issue tracker.
📄 License
The MIT License (MIT). Please see License File for more information.
