Installation
composer require gregwar/image
Add to composer.json if not using autoloading:
"autoload": {
"psr-4": {
"App\\": "app/",
"Gregwar\\Image\\": "vendor/gregwar/image/src/"
}
}
Run composer dump-autoload.
First Use Case Load and resize an image:
use Gregwar\Image\Image;
$image = Image::open('path/to/image.jpg');
$image->resize(300, 200); // Width, height
$image->save('path/to/resized.jpg');
Key Classes
Gregwar\Image\Image: Core class for image manipulation.Gregwar\Image\Geometry\Size: For width/height calculations.Gregwar\Image\Geometry\Point: For positioning (e.g., watermarks).Where to Look First
src/Gregwar/Image/Image.php for core methods.tests/ for usage examples and edge cases.Dynamic Thumbnails
$image = Image::open($request->file('image')->getRealPath());
$image->resize(800, 600, ['mode' => 'outbound']);
$image->save(storage_path("app/thumbs/{$request->id}.jpg"));
'mode' => 'outbound' to maintain aspect ratio with padding.Watermarking
$watermark = Image::open(public_path('watermark.png'));
$image->stamp($watermark, 10, 10, 0.5); // Position, opacity
Batch Processing
$files = Storage::disk('s3')->files('originals/');
foreach ($files as $file) {
$image = Image::open(storage_path("app/{$file}"));
$image->resize(1200, 800);
$image->save(storage_path("app/thumbs/{$file}"));
}
Integration with Laravel Filesystem
$stream = fopen($request->file('image')->getRealPath(), 'r+');
$image = Image::open($stream);
// Process...
$image->saveToStream($stream);
$stream->seek(0);
return response()->stream(fn() => $stream, 200, ['Content-Type' => 'image/jpeg']);
try-catch for Gregwar\Image\Exception.
try {
$image->resize(100, 100);
} catch (\Gregwar\Image\Exception $e) {
Log::error("Image resize failed: {$e->getMessage()}");
}
save() instead of saveToStream() for large files to avoid memory spikes.if (!in_array($request->file('image')->getClientMimeType(), ['image/jpeg', 'image/png'])) {
throw new \InvalidArgumentException('Unsupported image type.');
}
Service Provider: Register a facade for cleaner syntax:
// app/Providers/AppServiceProvider.php
use Gregwar\Image\Facades\Image as ImageFacade;
public function boot()
{
app()->bind('image', function () {
return new ImageFacade();
});
}
Now use Image::open() directly in controllers/views.
Middleware for Validation:
public function handle($request, Closure $next)
{
if ($request->hasFile('image')) {
$image = Image::open($request->file('image')->getRealPath());
if ($image->width > 2000 || $image->height > 2000) {
abort(422, 'Image too large.');
}
}
return $next($request);
}
GD vs. Imagick
imagick is installed:
pecl install imagick
$image = Image::open('file.jpg', ['driver' => 'imagick']);
Memory Limits
memory_limit. Increase it temporarily:
ini_set('memory_limit', '512M');
save() with a temporary file path to avoid loading the entire image into memory.File Permissions
chmod -R 755 storage/app/thumbs
Aspect Ratio Distortion
$image->resize(300, 200, ['mode' => 'aspect']); // Maintains ratio
$image = Image::open('file.unknown');
if (!$image) {
throw new \RuntimeException('Unsupported image format.');
}
try {
$image->resize(100, 100);
} catch (\Gregwar\Image\Exception $e) {
Log::debug("Image error: " . $e->getMessage(), ['file' => 'image.jpg']);
}
Custom Drivers
Override the default driver (GD/Imagick) by extending Gregwar\Image\Driver\AbstractDriver.
Filters Create reusable filters:
class SharpenFilter {
public static function apply(Image $image) {
$image->sharpen(50);
}
}
Event Listeners Trigger actions post-processing:
$image->on('save', function () {
// Log or notify after save
});
config/gregwar-image.php (if available) or via:
Image::setDriver('imagick');
Image::setDefaultQuality(85); // 0-100
$width = $image->width; // Cache this if reused
$stream = fopen('large_image.jpg', 'r+');
$image = Image::open($stream);
$image->resize(1000, 1000);
$image->saveToStream($stream);
fclose($stream);
How can I help you explore Laravel packages today?