amati/apps/backend/src/utils/compressImage.ts
sianida26 1259c3421a lint
2024-06-01 21:44:23 +07:00

56 lines
1.3 KiB
TypeScript

import sharp from "sharp";
/**
* Options for compressing an image.
*/
export interface CompressImageOptions {
/** The input file to compress */
inputFile: File;
/** The target size for the compressed image in bytes (optional) */
targetSize?: number;
/** The minimum quality for the compressed image (optional, default is 10) */
minQuality?: number;
/** Flag to force compression even if not necessary (optional, default is true) */
forceCompress?: boolean;
}
/**
* Compresses an image according to the specified options
*
* @param options - The compression options.
* @returns a promise that resolves with the compressed image as a buffer.
*/
async function compressImage(options: CompressImageOptions) {
let quality = 80;
const forceCompress = options.forceCompress ?? true;
/**
* Processes the image compression
*
* @returns compressed image as a buffer
*/
async function processImage() {
return await sharp(await options.inputFile.arrayBuffer())
.jpeg({ quality, mozjpeg: true })
.toBuffer();
}
let buffer = forceCompress
? await processImage()
: Buffer.from(await options.inputFile.arrayBuffer());
if (options.targetSize) {
while (
buffer.length > options.targetSize &&
quality > (options.minQuality ?? 10)
) {
quality -= 5;
buffer = await processImage();
}
}
return buffer;
}
export default compressImage;