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.

263 lines (260 loc) 7.55 kB
import { __esm, __export } from "./chunk-BaU5PcSi.js"; //#region src/utils/lruCache.ts var LRUCache; var init_lruCache = __esm({ "src/utils/lruCache.ts"() { LRUCache = class { cache; maxSize; constructor(maxSize = 50) { this.cache = /* @__PURE__ */ new Map(); this.maxSize = maxSize; } /** * 获取缓存项,如果存在则将其移到最新位置 */ get(key) { const value = this.cache.get(key); if (value !== void 0) { this.cache.delete(key); this.cache.set(key, value); } return value; } /** * 设置缓存项,如果超过最大容量则淘汰最久未使用的项 */ set(key, value) { if (this.cache.has(key)) this.cache.delete(key); else if (this.cache.size >= this.maxSize) { const firstKey = this.cache.keys().next().value; if (firstKey !== void 0) { this.cache.delete(firstKey); console.log(`LRU Cache: Removed least recently used entry for key: ${String(firstKey)}`); } } this.cache.set(key, value); } /** * 检查缓存中是否存在指定的key */ has(key) { return this.cache.has(key); } /** * 清空所有缓存 */ clear() { this.cache.clear(); } /** * 获取当前缓存大小 */ get size() { return this.cache.size; } /** * 获取最大缓存大小 */ get maxCapacity() { return this.maxSize; } /** * 设置新的最大缓存大小 */ setMaxSize(newMaxSize) { this.maxSize = newMaxSize; while (this.cache.size > this.maxSize) { const firstKey = this.cache.keys().next().value; if (firstKey !== void 0) { this.cache.delete(firstKey); console.log(`LRU Cache: Removed entry due to size reduction: ${String(firstKey)}`); } } } /** * 获取所有缓存条目的迭代器 */ entries() { return this.cache.entries(); } /** * 获取所有缓存的key */ keys() { return this.cache.keys(); } /** * 获取所有缓存的value */ values() { return this.cache.values(); } /** * 删除指定的缓存项 */ delete(key) { return this.cache.delete(key); } /** * 获取缓存统计信息 */ getStats() { return { size: this.cache.size, maxSize: this.maxSize, usageRate: this.cache.size / this.maxSize * 100 }; } }; } }); //#endregion //#region src/tools/compressWithTinyPng.ts var compressWithTinyPng_exports = {}; __export(compressWithTinyPng_exports, { clearTinyPngCache: () => clearTinyPngCache, compressWithTinyPng: () => compressWithTinyPng, configureTinyPngCache: () => configureTinyPngCache, getTinyPngCacheInfo: () => getTinyPngCacheInfo, getTinyPngCacheSize: () => getTinyPngCacheSize }); function generateFileKey(file, options) { const relevantOptions = { targetWidth: options.targetWidth, targetHeight: options.targetHeight, maxWidth: options.maxWidth, maxHeight: options.maxHeight, mode: options.mode === "keepQuality" ? options.mode : void 0 }; return `${file.name}_${file.size}_${file.lastModified}_${JSON.stringify(relevantOptions)}`; } function compressWithTinyPng(file, options) { return new Promise(async (resolve, reject) => { try { const cacheKey = generateFileKey(file, options); if (compressionCache.has(cacheKey)) { console.log("TinyPNG: Using cached result for file:", file.name); resolve(compressionCache.get(cacheKey)); return; } const apiKey = options.key; if (!apiKey) { reject("TinyPNG API key is required. Please set TINYPNG_API_KEY environment variable or window.TINYPNG_API_KEY"); return; } const supportedTypes = [ "image/jpeg", "image/jpg", "image/png", "image/webp" ]; if (!supportedTypes.includes(file.type)) { reject(`Unsupported file type: ${file.type}. TinyPNG supports JPEG, PNG, and WebP images.`); return; } const uploadResponse = await fetch("https://api.tinify.com/shrink", { method: "POST", headers: { Authorization: `Basic ${btoa(`api:${apiKey}`)}`, "Content-Type": file.type }, body: file }); if (!uploadResponse.ok) { const errorText = await uploadResponse.text(); reject(`TinyPNG upload failed: ${uploadResponse.status} - ${errorText}`); return; } const outputUrl = uploadResponse.headers.get("Location"); if (!outputUrl) { reject("No output URL received from TinyPNG"); return; } let resizeOptions = null; if (options.mode === "keepQuality" && (options.targetWidth || options.targetHeight || options.maxWidth || options.maxHeight)) { resizeOptions = {}; if (options.targetWidth && options.targetHeight) { resizeOptions.method = "fit"; resizeOptions.width = options.targetWidth; resizeOptions.height = options.targetHeight; } else if (options.maxWidth && options.maxHeight) { resizeOptions.method = "scale"; resizeOptions.width = options.maxWidth; resizeOptions.height = options.maxHeight; } else if (options.targetWidth) { resizeOptions.method = "scale"; resizeOptions.width = options.targetWidth; } else if (options.targetHeight) { resizeOptions.method = "scale"; resizeOptions.height = options.targetHeight; } } let finalUrl = outputUrl; if (resizeOptions) { const resizeResponse = await fetch(outputUrl, { method: "POST", headers: { Authorization: `Basic ${btoa(`api:${apiKey}`)}`, "Content-Type": "application/json" }, body: JSON.stringify({ resize: resizeOptions }) }); if (!resizeResponse.ok) { const errorText = await resizeResponse.text(); reject(`TinyPNG resize failed: ${resizeResponse.status} - ${errorText}`); return; } finalUrl = resizeResponse.headers.get("Location") || outputUrl; } const downloadResponse = await fetch(finalUrl, { headers: { Authorization: `Basic ${btoa(`api:${apiKey}`)}` } }); if (!downloadResponse.ok) { reject(`Failed to download compressed image: ${downloadResponse.status}`); return; } const compressedBlob = await downloadResponse.blob(); if (compressedBlob.size >= file.size * .98) { console.warn("TinyPNG compression did not significantly reduce file size, returning original file"); compressionCache.set(cacheKey, file); resolve(file); } else { const finalBlob = new Blob([compressedBlob], { type: file.type }); compressionCache.set(cacheKey, finalBlob); resolve(finalBlob); } } catch (error) { console.error("TinyPNG compression error:", error); reject(error); } }); } function clearTinyPngCache() { compressionCache.clear(); console.log("TinyPNG cache cleared"); } function getTinyPngCacheSize() { return compressionCache.size; } function getTinyPngCacheInfo() { const cacheEntries = Array.from(compressionCache.entries()).map(([key, blob]) => ({ key, size: blob.size, type: blob.type })); const stats = compressionCache.getStats(); return { totalEntries: stats.size, maxSize: stats.maxSize, usageRate: stats.usageRate, entries: cacheEntries }; } function configureTinyPngCache(maxSize = 50) { compressionCache.setMaxSize(maxSize); console.log(`TinyPNG cache reconfigured with max size: ${maxSize}`); } var compressionCache; var init_compressWithTinyPng = __esm({ "src/tools/compressWithTinyPng.ts"() { init_lruCache(); compressionCache = new LRUCache(50); } }); //#endregion export { LRUCache, clearTinyPngCache, compressWithTinyPng, compressWithTinyPng_exports, configureTinyPngCache, getTinyPngCacheInfo, getTinyPngCacheSize, init_compressWithTinyPng, init_lruCache };