Prompt
I'm building a CMS plugin and need an image resize/compress service
Latest observation
Here’s a solid way to think about an image resize/compress service for a CMS plugin, plus a practical implementation outline.
What the service should do
A good image optimization service usually handles:
-
Resize
- Constrain images to max width/height
- Preserve aspect ratio
- Optionally crop or fit within bounds
-
Compress
- Reduce file size while keeping acceptable visual quality
- Support per-format settings
-
Format handling
- JPEG / WebP / PNG / GIF / AVIF if supported
- Keep transparency for PNG/WebP
- Avoid quality loss when possible for already-optimized images
-
Metadata cleanup
- Strip EXIF/IPTC/XMP metadata optionally
- This helps privacy and reduces size
-
Safety and limits
- File size limits
- Dimensions limits
- Timeout handling
- Validate MIME type and file extension
-
Non-destructive workflow
- Preserve original
- Save optimized copy
- Generate thumbnails / variants
Suggested architecture
For a CMS plugin, it’s best to split this into 3 layers:
1) Upload hook
Triggered when media is uploaded.
Responsibilities:
- Validate file
- Queue optimization job
- Save original
- Pass file path/ID to processing
2) Image processor
Does the actual work:
- Read image
- Resize if needed
- Compress/convert
- Save output
- Return metadata
3) Storage/update layer
Handles:
- Replacing attachment metadata
- Updating DB record
- Storing optimization stats
- Keeping backups if enabled
Recommended processing pipeline
A robust pipeline:
- Detect image type
- Load image safely
- Auto-rotate using EXIF orientation
- Resize if larger than target max
- Convert if needed
- JPEG for photos
- WebP for smaller size if supported
- PNG if transparency required
- Strip metadata if enabled
- Save optimized file
- Compare size reduction
- Replace or store alongside original
Important implementation details
Resize logic
Use one of these modes:
- Contain: fit inside max width/height without cropping
- Cover: fill exact dimensions, crop edges
- No upscale: never enlarge small images
Example rule:
- Max width:
1920 - Max height:
1080 - If input is
4000x3000, scale down proportionally
Compression settings
Typical safe defaults:
- JPEG:
75–85 - WebP:
70–80 - PNG: lossless or mild optimization
- AVIF:
40–60depending on library
Format conversion strategy
A common policy:
- Photos → JPEG or WebP
- Images with transparency → PNG or WebP
- Animations → preserve GIF/WebP animation if supported
- If converting PNG to JPEG, require a fallback background color
Tech stack options
If your plugin is PHP-based
Use:
- Imagick if available
- Fallback to GD
Imagick is usually better for:
- Quality
- WebP/AVIF support
- Metadata handling
- Better resizing filters
Example PHP service structure
You could define a service like this:
class ImageOptimizerService
{
public function optimize(string $inputPath, array $options = []): array
{
$defaults = [
'max_width' => 1920,
'max_height' => 1080,
'quality' => 82,
'strip_metadata' => true,
'convert_format' => null, // 'webp', 'jpg', etc.
];
$options = array_merge($defaults, $options);
$info = getimagesize($inputPath);
if (!$info) {
throw new \RuntimeException('Invalid image');
}
$mime = $info['mime'];
// Load image depending on type...
// Resize if necessary...
// Compress and save...
// Return stats...
return [
'original_size' => filesize($inputPath),
'optimized_size' => filesize($outputPath),
'saved_bytes' => filesize($inputPath) - filesize($outputPath),
'output_path' => $outputPath,
];
}
}
Return values you should expose
For CMS integration, return:
- original path
- optimized path
- original dimensions
- new dimensions
- original size
- optimized size
- savings percentage
- output format
- whether metadata was stripped
- any warnings/errors
Example:
{
"original_size": 2483921,
"optimized_size": 742188,
"saved_bytes": 1741733,
"saved_percent": 70.1,
"width": 1600,
"height": 900,
"format": "webp"
}
Extra features worth adding
- Bulk optimization
- Background queue
- Duplicate detection
- Image quality presets: low / balanced / high
- Per-folder rules
- Admin preview before replacing originals
- CDN integration
- Logging/auditing
If you want an API-based service instead
If you don’t want to process images locally, you can expose/use an external service:
- Upload image
- Service returns optimized file URL or binary
- Easier scaling
- But adds latency and cost
Good for:
- Large CMS installs
- Multi-tenant systems
- Server environments without Imagick
My recommendation
For a CMS plugin, the best default is:
- Local processing
- Imagick first, GD fallback
- Optional WebP output
- Non-destructive originals
- Queue-based bulk optimization
- Configurable size/quality presets
If you want, I can also provide:
- a complete PHP class for this service,
- a WordPress plugin integration example, or
- an API design for a standalone resize/compress microservice.