silarhi / picasso-bundle
Responsive image component for Symfony, inspired by next/image
Installs: 1
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 2
Type:symfony-bundle
pkg:composer/silarhi/picasso-bundle
Requires
- php: >=8.2
- symfony/framework-bundle: ^6.4 || ^7.0
- symfony/ux-twig-component: ^2.13
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.94
- league/glide: ^2.0
- league/glide-symfony: ^2.0
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.0
- rector/rector: ^2.3
- symfony/twig-bundle: ^6.4 || ^7.0
- vich/uploader-bundle: ^2.0
- vincentlanglet/twig-cs-fixer: ^3.13
Suggests
- league/flysystem: Required for the Flysystem loader
- league/glide: Required for the Glide transformer (local image transformation)
- league/glide-symfony: Required for the Glide transformer
- vich/uploader-bundle: Required for the VichUploader loader
This package is auto-updated.
Last update: 2026-02-27 22:54:10 UTC
README
Responsive image component for Symfony, inspired by Next.js Image.
PicassoBundle automatically generates optimized, responsive <picture> elements with multiple formats (AVIF, WebP, JPEG), srcset generation, and blur placeholders — all from a single Twig component.
Features
- Responsive
<picture>output with automatic srcset and multiple format generation - Blur placeholders (LQIP) for smooth loading transitions
- Pluggable loaders — Filesystem, Flysystem, VichUploaderBundle
- Pluggable transformers — Glide (local) or Imgix (CDN)
- Twig component (
<Picasso:Image>) and Twig function (picasso_image_url()) - Automatic image dimension detection from streams
- URL signing for secure on-demand transformation
- Extensible via
#[AsImageLoader]and#[AsImageTransformer]attributes
Requirements
- PHP 8.2+
- Symfony 6.4+ or 7.0+
- Symfony UX Twig Component 2.13+
Installation
composer require silarhi/picasso-bundle
If not using Symfony Flex, register the bundle in config/bundles.php:
return [ // ... Silarhi\PicassoBundle\PicassoBundle::class => ['all' => true], ];
Install a transformer — at least one is required:
# Option A: Glide (local image transformation) composer require league/glide league/glide-symfony # Option B: Imgix (CDN-based transformation) # No extra package needed, just configure your Imgix domain
Configuration
The bundle works out of the box with sensible defaults. A minimal setup with Glide:
# config/packages/picasso.yaml picasso: transformers: glide: enabled: true sign_key: '%env(PICASSO_SIGN_KEY)%'
That's it — images are loaded from public/uploads by default and transformed locally via Glide.
Full configuration reference
picasso: default_loader: filesystem default_transformer: ~ # auto-detected when only one is enabled device_sizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840] image_sizes: [16, 32, 48, 64, 96, 128, 256, 384] formats: [avif, webp, jpg] # last entry is the <img> fallback default_quality: 75 # 1–100 default_fit: contain # contain | cover | crop | fill placeholders: blur: enabled: true size: 10 blur: 50 quality: 30 loaders: filesystem: enabled: true base_directory: '%kernel.project_dir%/public/uploads' flysystem: enabled: false service: ~ # Flysystem storage service ID vich: enabled: false transformers: glide: enabled: false sign_key: ~ cache: '%kernel.project_dir%/var/glide-cache' driver: gd # gd | imagick max_image_size: ~ imgix: enabled: false domain: ~ # your-source.imgix.net sign_key: ~ use_https: true
Usage
Twig Component (recommended)
<Picasso:Image src="photo.jpg" width="800" height="600" sizes="(max-width: 768px) 100vw, 800px" alt="A beautiful landscape" />
This renders a <picture> element with <source> tags for each configured format and a responsive srcset on the fallback <img>.
Component Properties
| Property | Type | Description |
|---|---|---|
src |
string |
Image path relative to the loader's base |
width |
int |
Display width in pixels |
height |
int |
Display height in pixels |
sizes |
string |
Responsive sizes attribute |
sourceWidth |
int |
Explicit source width (skips detection) |
sourceHeight |
int |
Explicit source height (skips detection) |
loader |
string |
Override default loader (filesystem, vich, flysystem) |
transformer |
string |
Override default transformer (glide, imgix) |
quality |
int |
Override quality (1–100) |
fit |
string |
Fit mode: contain, cover, crop, fill |
placeholder |
bool |
Enable/disable blur placeholder |
unoptimized |
bool |
Serve the original image without transformation |
context |
array |
Extra context for the loader (e.g. Vich entity/field) |
Twig Function
For generating a single image URL:
<img src="{{ picasso_image_url('photo.jpg', {width: 300, format: 'webp'}) }}" alt="Thumbnail">
With explicit loader/transformer:
{{ picasso_image_url('photo.jpg', {width: 300, loader: 'vich', transformer: 'imgix'}) }}
Available parameters: width, height, format, quality, fit, blur, dpr, loader, transformer.
VichUploaderBundle Integration
# config/packages/picasso.yaml picasso: loaders: vich: enabled: true
<Picasso:Image src="product-photo.jpg" :context="{ entity: product, field: 'imageFile' }" width="400" height="300" alt="Product image" />
Flysystem Integration
# config/packages/picasso.yaml picasso: loaders: flysystem: enabled: true service: 'default.storage' # Your Flysystem service ID
Custom Loaders and Transformers
Register custom implementations using PHP attributes:
use Silarhi\PicassoBundle\Attribute\AsImageLoader; use Silarhi\PicassoBundle\Loader\ImageLoaderInterface; #[AsImageLoader('s3')] class S3Loader implements ImageLoaderInterface { // ... }
use Silarhi\PicassoBundle\Attribute\AsImageTransformer; use Silarhi\PicassoBundle\Transformer\ImageTransformerInterface; #[AsImageTransformer('cloudinary')] class CloudinaryTransformer implements ImageTransformerInterface { // ... }
Then use them by name:
<Picasso:Image src="photo.jpg" loader="s3" transformer="cloudinary" width="800" />
Testing
composer install vendor/bin/phpunit
Static Analysis & Code Style
vendor/bin/phpstan analyse vendor/bin/php-cs-fixer fix --dry-run --diff vendor/bin/twig-cs-fixer lint
License
MIT License. See LICENSE for details.