Declarative image-processing presets - one option, one workflow
5 built-in presets bundle the common combinations of auto-orient + resize + crop + compress. Pick one name and the entire image pipeline shapes the output for that use case. Custom specs pass through unchanged for one-off needs.
Try it: pick a preset, drop a high-res image (4000x3000 from any modern camera works great). Look at the queue's reported file size - it'll be a fraction of the original. Inspect the network request: the bytes match the preset spec.
Built-in presets
| Name | auto-orient | resize | compress | Typical use |
|---|---|---|---|---|
avatar | OK | 512x512 contain, JPEG 0.9 | JPEG 0.9 | User profile photos |
thumbnail | - | 320x320 contain, JPEG 0.85 | JPEG 0.85 | Gallery grid tiles |
web-banner | OK | 1600w max (no height cap), JPEG 0.88 | - | Hero images, marketing cards |
document | OK | - | JPEG 0.85 | Scanned forms, receipts (preserves dimensions) |
social-card | OK | 1200x630 contain, JPEG 0.9 | - | OG image / Twitter Card |
API
// Built-in preset by name:
new MultipleUpload('#uploader', {
uploadUrl: '/api/upload',
imagePreset: 'avatar'
});
// Custom spec - pass an object:
new MultipleUpload('#uploader', {
uploadUrl: '/api/upload',
imagePreset: {
autoOrient: true,
resize: { maxWidth: 2048, maxHeight: 2048, quality: 0.92, outputType: 'image/webp' },
compress: { quality: 0.92, outputType: 'image/webp' }
}
});
// Inspect a preset's expanded shape (useful for testing):
const spec = MultipleUpload.expandImagePreset('avatar');
console.log(spec);
// { autoOrient: true,
// resize: { maxWidth: 512, maxHeight: 512, quality: 0.9, outputType: 'image/jpeg' },
// compress: { quality: 0.9, outputType: 'image/jpeg' } }Pipeline order
When imagePreset is set, the pipeline runs in this order:
queue file -> HEIC convert (if convertHeic + .heic file) -> imagePreset.autoOrient (EXIF rotation applied) -> imagePreset.resize (contain into bounds) -> imagePreset.crop (only for fixed-dimension custom specs) -> imagePreset.compress (JPEG/WebP quality) -> transformPipeline (user-defined transforms) -> ... rest of pipeline (encrypt, virus scan, ...)
Why presets instead of individual options
- Single source of truth: 90% of teams want one of these 5 workflows. One option captures intent better than 6 individual settings.
- Composable:
imagePreset+convertHeic+imageRotate+watermarkall stack - the preset doesn't disable other options. - Overrideable per-task: custom transforms in
transformPipelinerun AFTER the preset, so per-file tweaks still work. - Inspectable:
MultipleUpload.expandImagePreset(name)returns the spec - useful for unit testing your config.
Combine with HEIC convert for the full Apple iPhone story
// User drops IMG_1234.HEIC from iPhone - output is a 512x512 JPEG avatar.
new MultipleUpload('#uploader', {
uploadUrl: '/api/upload',
convertHeic: true, // HEIC -> JPEG via ImageDecoder
imagePreset: 'avatar' // 512x512 JPEG 0.9
});
// 4032x3024 HEIC (12 MP iPhone) -> 38 KB 512x512 avatar JPEG.
// All client-side. Server sees a single ready-to-use 38 KB file.