UNPKG

@imjano/compress_image

Version:

Compresses an image file while allowing control over quality, file size, and format.

94 lines (91 loc) 2.92 kB
interface CompressImageOptions { qualityPercent?: number maxFileSize?: number minFileSize?: number format?: | 'image/jpeg' | 'image/png' | 'image/webp' | 'image/gif' | 'image/bmp' | 'image/tiff' | 'image/svg+xml' } /** * Compresses an image file while allowing control over quality, file size, and format. * * @param file - The File object representing the image to compress. * @param options - Configuration options for image compression. * @returns A Promise that resolves to the compressed image as a Blob. * @example * // Compress an image with custom options * const compressionOptions = { * qualityPercent: 80, // Set compression quality to 80% * maxFileSize: 1024 * 1024, // Limit the output file size to 1MB * format: 'image/jpeg', // Convert to JPEG format * }; * compressImage(imageFile, compressionOptions) * .then((compressedBlob) => { * // Handle the compressed image Blob * }) * .catch((error) => { * console.error('Compression error:', error); * }); */ export default async function compressImage( file: File, options: CompressImageOptions ): Promise<Blob> { const { format } = options let { qualityPercent, minFileSize, maxFileSize } = options minFileSize = minFileSize ?? 512 maxFileSize = maxFileSize ?? file.size qualityPercent = qualityPercent ?? 100 if (!maxFileSize && !qualityPercent) throw Error('qualityPercent must be a number between 0 and 100') if (qualityPercent) if (qualityPercent > 100 || qualityPercent < 0) throw Error('qualityPercent must be a number between 0 and 100') let blob = await compression(file, format, qualityPercent) if (maxFileSize) { if (maxFileSize > file.size) throw Error( `maxFileSize (${maxFileSize}) must not be larger than the original file size (${file.size})` ) while (blob.size > maxFileSize || blob.size < minFileSize) { if (blob.size > maxFileSize) { qualityPercent = qualityPercent -= 10 blob = await compression(file, format, qualityPercent) } else if (blob.size > minFileSize) { qualityPercent += 5 blob = await compression(file, format, qualityPercent) } } } return blob } const compression = ( file: File, format?: string, qualityPercent?: number ): Promise<Blob> => { return new Promise((resolve, reject) => { const canvas = document.createElement('canvas') const image = new Image() image.onload = () => { canvas.width = image.width canvas.height = image.height canvas.getContext('2d')?.drawImage(image, 0, 0) canvas.toBlob( (blob) => { URL.revokeObjectURL(image.src) if (blob) return resolve(blob) return reject(new Error('Failed to create blob')) }, format ? format : file.type, (qualityPercent ?? 100) / 100 ) } image.src = URL.createObjectURL(file) }) }