56 lines
1.3 KiB
TypeScript
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;
|