Files
goGin/frontend/lib/image-optimizer.ts
Beyhan Oğur 2a5b661443 first commit
2026-04-26 21:46:42 +03:00

55 lines
1.9 KiB
TypeScript

import sharp from "sharp"
export interface ImageOptions {
width?: number
height?: number
quality?: number
format?: string // "webp", "jpeg", "png", "avif"
}
export async function optimizeImage(buffer: Buffer, options: ImageOptions): Promise<{ buffer: Buffer; contentType: string; filename: string }> {
let pipeline = sharp(buffer)
// Resize if width or height is provided and greater than 0
if ((options.width && options.width > 0) || (options.height && options.height > 0)) {
pipeline = pipeline.resize({
width: options.width && options.width > 0 ? options.width : undefined,
height: options.height && options.height > 0 ? options.height : undefined,
fit: "cover", // Or 'contain', 'fill' based on requirement. Cover is usually good for heroes.
withoutEnlargement: true,
})
}
// Default format is AVIF if not specified
const format = options.format?.toLowerCase() || "avif"
const quality = options.quality && options.quality > 0 ? options.quality : 80
switch (format) {
case "jpeg":
case "jpg":
pipeline = pipeline.jpeg({ quality })
break
case "png":
pipeline = pipeline.png({ quality, compressionLevel: 9 }) // PNG quality is different, usually compression level
break
case "webp":
pipeline = pipeline.webp({ quality })
break
case "avif":
pipeline = pipeline.avif({ quality })
break
default:
pipeline = pipeline.avif({ quality })
break
}
const processedBuffer = await pipeline.toBuffer()
const extension = format === "jpg" ? "jpeg" : format
return {
buffer: processedBuffer,
contentType: `image/${extension}`,
filename: `image.${extension}`, // Generic filename, caller can prepend/append if needed
}
}