UNPKG

@awesome-compressor/browser-compress-image

Version:

🚀 A powerful, lightweight browser image compression library with TypeScript support. Compress JPEG, PNG, GIF images with multiple output formats (Blob, File, Base64, ArrayBuffer) and zero dependencies.

104 lines (102 loc) • 3.84 kB
import { __esm, __export } from "./chunk-BaU5PcSi.js"; //#region src/tools/compressWithCanvas.ts var compressWithCanvas_exports = {}; __export(compressWithCanvas_exports, { default: () => compressWithCanvas }); async function compressWithCanvas(file, options) { const { quality, targetWidth, targetHeight, maxWidth, maxHeight } = options; let finalWidth = targetWidth || maxWidth, finalHeight = targetHeight || maxHeight; if (!finalWidth && !finalHeight) { const { width, height } = await getImageDimensions(file); finalWidth = width; finalHeight = height; } return await smartCanvasCompress(file, finalWidth, finalHeight, quality); } async function smartCanvasCompress(file, targetWidth, targetHeight, quality) { const originalSize = file.size; const { width: originalWidth, height: originalHeight } = await getImageDimensions(file); if (targetWidth === originalWidth && targetHeight === originalHeight && originalSize < 100 * 1024) return file; if (file.type.includes("png")) { const pngResult = await canvasCompressWithFormat(file, targetWidth, targetHeight, "image/png", void 0); if (pngResult.size < originalSize * .98) return pngResult; if (quality < .8) { const jpegResult = await canvasCompressWithFormat(file, targetWidth, targetHeight, "image/jpeg", Math.max(.7, quality)); if (jpegResult.size < Math.min(pngResult.size, originalSize * .98)) return jpegResult; } if (pngResult.size >= originalSize * .98) return file; return pngResult; } if (file.type.includes("jpeg") || file.type.includes("jpg")) { const qualities = [ quality, Math.max(.5, quality - .2), Math.max(.3, quality - .4) ]; for (const q of qualities) { const result$1 = await canvasCompressWithFormat(file, targetWidth, targetHeight, file.type, q); if (result$1.size < originalSize * .98) return result$1; } return file; } const result = await canvasCompressWithFormat(file, targetWidth, targetHeight, file.type, quality); if (result.size >= originalSize * .98) return file; return result; } async function canvasCompressWithFormat(file, targetWidth, targetHeight, outputType, quality) { return new Promise((resolve, reject) => { const img = new Image(); const url = URL.createObjectURL(file); img.onload = () => { URL.revokeObjectURL(url); const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d", { alpha: outputType.includes("png"), willReadFrequently: false }); if (!ctx) { reject(/* @__PURE__ */ new Error("Failed to get canvas context")); return; } canvas.width = targetWidth; canvas.height = targetHeight; ctx.imageSmoothingEnabled = true; ctx.imageSmoothingQuality = "high"; if (outputType.includes("jpeg") && !file.type.includes("jpeg")) { ctx.fillStyle = "#FFFFFF"; ctx.fillRect(0, 0, targetWidth, targetHeight); } ctx.drawImage(img, 0, 0, targetWidth, targetHeight); canvas.toBlob((blob) => { if (blob) resolve(blob); else reject(/* @__PURE__ */ new Error("Failed to create blob")); }, outputType, quality); }; img.onerror = () => { URL.revokeObjectURL(url); reject(/* @__PURE__ */ new Error("Failed to load image")); }; img.crossOrigin = "anonymous"; img.src = url; }); } function getImageDimensions(file) { return new Promise((resolve, reject) => { const img = new Image(); const url = URL.createObjectURL(file); img.onload = () => { URL.revokeObjectURL(url); resolve({ width: img.width, height: img.height }); }; img.onerror = () => { URL.revokeObjectURL(url); reject(/* @__PURE__ */ new Error("Failed to load image")); }; img.src = url; }); } var init_compressWithCanvas = __esm({ "src/tools/compressWithCanvas.ts"() {} }); //#endregion export { compressWithCanvas, compressWithCanvas_exports, init_compressWithCanvas };