Weave 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

Wideimage Laravel Package

smottt/wideimage

WideImage is a PHP image manipulation library built on GD. It provides an easy API for resizing, cropping, rotating, flipping, watermarking, and applying filters to images, with support for common formats. The smottt/wideimage package is a maintained fork for modern PHP projects.

Deep Wiki
Context7

Getting Started

composer require smottt/wideimage
php -m | grep -i gd   # WideImage requires ext-gd, no Imagick path

There is no service provider, config file, or facade — it's a plain PHP library. Look first at vendor/smottt/wideimage/lib/WideImage.php for the entry point and lib/operations/ for the available verbs (resize, crop, rotate, merge, applyFilter, drawText, …). The README examples are enough to get productive in minutes.

Smallest useful flow — thumbnail an upload in a controller:

use WideImage\WideImage; // some forks expose a global `WideImage` class instead

public function store(Request $request)
{
    $path = $request->file('photo')->store('originals', 'public');

    $image = WideImage::load(Storage::disk('public')->path($path));
    $thumb = $image->resize(320, 240, 'inside'); // keeps aspect ratio
    $thumb->save(Storage::disk('public')->path('thumbs/'.basename($path)), 85);

    return back()->with('ok', true);
}

First real use case: upload → normalize → generate thumbnail/hero variants → persist to the public disk.

Implementation Patterns

Wrap it in one service, not scattered calls. WideImage is procedural in spirit; keep the fluent chains inside a small ImageProcessor class so controllers and jobs don't grow image logic.

class ImageProcessor
{
    public function variant(string $absSource, string $absTarget, int $w, int $h): void
    {
        WideImage::load($absSource)
            ->resize($w, $h, 'inside')
            ->crop('center', 'center', $w, $h)   // square-ish hero
            ->save($absTarget, 82);
    }
}

Chaining returns new objects. resize(), crop(), rotate(), merge(), applyFilter() all return a new WideImage instance. Nothing is written until save(), output(), or asString(), which makes it easy to build a pipeline and only persist the final image.

Queue the heavy work. Image decoding is CPU- and memory-bound; dispatch a GenerateImageVariants job after upload and let the request return immediately. The job receives the stored path, resolves it with Storage::disk(...)->path(), and writes variants back.

Use asString() for non-local disks. S3/R2 have no local path, so load from a temp file or string and push the bytes back:

$bytes = WideImage::load($tmpPath)->resize(1200, null)->asString('jpg', 85);
Storage::disk('s3')->put("photos/{$id}.jpg", $bytes);

Streaming responses. ->output('png') writes directly to the browser; good for a signed “download resized” route, but set Content-Type yourself since the library won't.

Overlays and branding. merge($watermark, 'bottom-right', 10, 10, 40) for logos (opacity is a percent), and drawText($text, $x, $y, $size, $color, $fontPath) for captions. Fonts must be absolute paths to .ttf files — copy them into resources/fonts and resolve with resource_path().

Smart thumbnails. crop('center', 'center', $w, $h) after a resize(..., 'inside') is the standard grid-thumbnail recipe; resize($w, $h, 'fill') stretches and is almost never what you want.

Dynamic resize endpoint. A route like /img/{path}?w=800 that caches the resized file on disk is a common Laravel integration; guard it with a signed URL or an allow-list of source paths.

Gotchas and Tips

  • GD only. No Imagick backend, so quality and format support depend on your GD build (WebP support varies by PHP version). Check gd_info() before relying on imagewebp.
  • Memory. The whole image is decoded into RAM. A 4000×3000 JPEG can push past a 128M memory_limit and fail with a fatal error rather than an exception. Raise memory_limit in the job/command, not globally.
  • Alpha and transparency. Palette PNGs and alpha edges often break on resize. Convert first with ->asTrueColor() (and save as PNG) when transparency matters.
  • EXIF orientation is not applied. Phone uploads will appear rotated. Read exif_read_data() and call ->rotate(90 * $orientation) yourself before resizing, then strip EXIF on save.
  • Coordinates are (x, y) with origin top-left, and crop() has several overloads (crop($left, $top, $w, $h) vs. crop($posX, $posY, $w, $h) with string anchors). Pin down which signature your version uses; off-by-one crops are the usual bug.
  • Format is inferred from the save path/extension. save('x.jpg', 85) sets JPEG quality; save('x.png') ignores the quality argument and uses PNG compression. asString('jpg', 85) needs the format passed explicitly.
  • Exceptions are library-specific (WideImage\Exception\... or WideImage_Exception depending on the fork). Catch that, not \Exception, and wrap it into a domain error so a corrupt upload doesn't 500.
  • Laravel Storage paths. Storage::path() only works for local disks. For remote disks, download to tempnam(sys_get_temp_dir(), 'img'), process, upload, and unlink() in a finally.
  • No Laravel integration ships with it. No facade, no config, no validation rules — you supply the mime/size validation (image, mimes:jpg,png,webp, max:10240) and the cleanup.
  • Maintenance signals. Last release was 2021 and the license is NOASSERTION (originally LGPL-3.0), which is worth a legal check before shipping. Pin the Composer version, run composer audit, and consider wrapping it behind your ImageProcessor interface so swapping to Intervention Image later is a one-class change.
  • Extension point: subclassing WideImage or registering a custom operation is possible but undocumented; for anything beyond the built-ins, doing the raw GD work in your own method and returning a new image is safer than fighting the operation registry.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle