UNPKG

pica-resize-image

Version:
230 lines (228 loc) 7.81 kB
var __create = Object.create; var __getProtoOf = Object.getPrototypeOf; var __defProp = Object.defineProperty; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __toESM = (mod, isNodeMode, target) => { target = mod != null ? __create(__getProtoOf(mod)) : {}; const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target; for (let key of __getOwnPropNames(mod)) if (!__hasOwnProp.call(to, key)) __defProp(to, key, { get: () => mod[key], enumerable: true }); return to; }; var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) { if (typeof require !== "undefined") return require.apply(this, arguments); throw Error('Dynamic require of "' + x + '" is not supported'); }); // src/index.ts import Pica from "pica"; var heic2any = null; if (typeof window !== "undefined") { try { heic2any = __require("heic2any"); if (heic2any && heic2any.default) { heic2any = heic2any.default; } } catch (e) { console.log("heic2any not available (will load dynamically if needed)"); } } var OUTPUT_TYPE = { file: "file", blob: "blob", base64: "base64" }; var MIME_TYPE = { png: { mimeType: "image/png", extension: "png" }, jpeg: { mimeType: "image/jpeg", extension: "jpeg" }, webp: { mimeType: "image/webp", extension: "webp" } }; var isHEIC = (file) => { const heicTypes = [ "image/heic", "image/heif", "image/heic-sequence", "image/heif-sequence" ]; if (heicTypes.includes(file.type.toLowerCase())) { return true; } const extension = file.name.split(".").pop()?.toLowerCase(); return extension === "heic" || extension === "heif"; }; var getHeic2any = async () => { if (heic2any) { console.log("heic2any available from top-level import"); return heic2any; } try { console.log("Trying dynamic import of heic2any..."); const module = await import("heic2any"); const h2a = module.default || module; console.log("heic2any loaded via dynamic import"); return h2a; } catch (error) { console.error("Failed to load heic2any:", error); throw new Error("heic2any library not available. Please ensure it's installed: npm install heic2any"); } }; var convertHEICToBlob = async (file) => { try { console.log("Converting HEIC to JPEG..."); const h2a = await getHeic2any(); const convertedBlob = await h2a({ blob: file, toType: "image/jpeg", quality: 0.9 }); console.log("HEIC conversion completed"); if (Array.isArray(convertedBlob)) { return convertedBlob[0]; } return convertedBlob; } catch (error) { console.error("HEIC conversion error:", error); throw new Error(`Failed to convert HEIC image: ${error}`); } }; var coverImage = (image, options) => { const targetRatio = options.width / options.height; const imageRatio = image.width / image.height; let cropWidth, cropHeight, cropX, cropY; if (imageRatio > targetRatio) { cropHeight = image.height; cropWidth = image.height * targetRatio; cropX = (image.width - cropWidth) / 2; cropY = 0; } else { cropWidth = image.width; cropHeight = image.width / targetRatio; cropX = 0; cropY = (image.height - cropHeight) / 2; } const tempCanvas = document.createElement("canvas"); const tempCtx = tempCanvas.getContext("2d"); tempCanvas.width = cropWidth; tempCanvas.height = cropHeight; tempCtx.drawImage(image, cropX, cropY, cropWidth, cropHeight, 0, 0, cropWidth, cropHeight); const croppedImage = new Image; croppedImage.src = tempCanvas.toDataURL(); return new Promise((resolve, reject) => { croppedImage.onload = () => resolve(croppedImage); croppedImage.onerror = (error) => reject(error); }); }; var readFileBeforeResize = async (file, options) => { console.log("readFileBeforeResize started:", file.name); let fileToProcess = file; if (isHEIC(file)) { console.log("HEIC file detected, converting..."); const convertedBlob = await convertHEICToBlob(file); fileToProcess = new File([convertedBlob], file.name.replace(/\.(heic|heif)$/i, ".jpg"), { type: "image/jpeg" }); console.log("HEIC converted to:", fileToProcess.name); } console.log("Creating image element..."); const canvas = document.createElement("canvas"); const image = new Image; const objectUrl = URL.createObjectURL(fileToProcess); image.src = objectUrl; return new Promise((resolve, reject) => { image.onload = async () => { console.log("Image loaded successfully"); URL.revokeObjectURL(objectUrl); if (!options) { const percent = 100 / image.height; canvas.width = percent * image.width; canvas.height = 100; return resolve({ from: image, to: canvas }); } else if (options.width && options.height && options.cover) { const croppedImage = await coverImage(image, options); canvas.width = options.width; canvas.height = options.height; return resolve({ from: croppedImage, to: canvas }); } else if (options.width && options.height) { canvas.width = options.width; canvas.height = options.height; return resolve({ from: image, to: canvas }); } else if (options.width) { const percent = options.width / image.width; canvas.width = options.width; canvas.height = percent * image.height; return resolve({ from: image, to: canvas }); } else if (options.height) { const percent = options.height / image.height; canvas.width = percent * image.width; canvas.height = options.height; return resolve({ from: image, to: canvas }); } }; image.onerror = (error) => { URL.revokeObjectURL(objectUrl); reject(error); }; }); }; var blobToFile = (blob, mimeType) => { const prefix = new Date().getTime(); const suffix = Math.random().toString(36).slice(2); return new File([blob], `image-${prefix}-${suffix}.${mimeType.extension}`, { type: mimeType.mimeType }); }; var blobToBase64 = (blob) => { return new Promise((resolve, reject) => { const reader = new FileReader; reader.onload = () => resolve(reader.result); reader.onerror = reject; reader.readAsDataURL(blob); }); }; var resize = ({ from, to, mimeType, quality, output }) => { const pica = Pica(); return pica.resize(from, to).then((result) => pica.toBlob(result, mimeType.mimeType, quality)).then((resizedBlob) => { switch (output) { case OUTPUT_TYPE.file: return blobToFile(resizedBlob, mimeType); case OUTPUT_TYPE.base64: return blobToBase64(resizedBlob); case OUTPUT_TYPE.blob: return resizedBlob; } }); }; var resizeImage = async (image, options) => { const { from, to } = await readFileBeforeResize(image, options); const mimeType = options?.mimeType || MIME_TYPE.webp; const quality = options?.quality || 1; const output = options?.output || "file"; return resize({ from, to, mimeType, quality, output }); }; var resizeImages = async (images, options) => { const mimeType = options?.mimeType || MIME_TYPE.webp; const quality = options?.quality || 1; const output = options?.output || "file"; const readImagesBeforeResize = await Promise.all(images.map((image) => readFileBeforeResize(image, options))); return Promise.all(readImagesBeforeResize.map(({ from, to }) => resize({ from, to, mimeType, quality, output }))); }; export { resizeImages, resizeImage, OUTPUT_TYPE, MIME_TYPE };