Apply on-the-fly transformations: resize, crop, rotate, blur, grayscale, sepia. Support query parameters for dynamic transformations. Cache transformed results for performance. By the end, clients can request any image with any transformation without pre-generating every variant.
← Back to Module 06 overview?width=400&height=300&format=webp&quality=80.?blur=10&grayscale=1&sepia=1&rotate=90.GET /images/:id/transform?...params returns transformed image.Create src/utils/imageTransform.ts:
import sharp, { Sharp } from 'sharp';
export interface TransformOptions {
width?: number;
height?: number;
format?: 'jpeg' | 'png' | 'webp' | 'avif';
quality?: number;
blur?: number;
grayscale?: boolean;
sepia?: boolean;
rotate?: number;
}
export async function transformImage(
buffer: Buffer,
options: TransformOptions
): Promise {
let image = sharp(buffer);
// Validate and constrain dimensions
const maxDim = 4000;
const width = options.width ? Math.min(options.width, maxDim) : undefined;
const height = options.height ? Math.min(options.height, maxDim) : undefined;
if (width || height) {
image = image.resize(width, height, { fit: 'inside', withoutEnlargement: true });
}
if (options.rotate) {
image = image.rotate(options.rotate);
}
if (options.blur) {
image = image.blur(Math.min(options.blur, 50));
}
if (options.grayscale) {
image = image.grayscale();
}
if (options.sepia) {
image = image.tint({ r: 112, g: 66, b: 20 });
}
const format = options.format || 'jpeg';
const quality = Math.min(Math.max(options.quality || 80, 0), 100);
return image.toFormat(format, { quality }).toBuffer();
}