/** * Visually lossless re-encode for imported raster images (same pixel dimensions). * Node-only; shared by the main app and ../project-converter (monorepo sibling). */ import sharp from 'sharp'; /** @typedef {import('node:buffer').Buffer} Buffer */ /** * @typedef {Object} OptimizeImageImportResult * @property {Buffer} buffer * @property {string} mime * @property {string} ext filename extension without dot (e.g. webp, jpg, png) * @property {number} width * @property {number} height * @property {boolean} passthrough true if original bytes were kept */ const WEBP_EFFORT = 6; const RASTER_QUALITY = 95; /** * @param {Buffer} buf * @param {import('sharp').Metadata | null} meta * @returns {OptimizeImageImportResult} */ function makePassthrough(buf, meta) { const fmt = meta?.format; if (fmt === 'jpeg' || fmt === 'jpg') { return { buffer: buf, mime: 'image/jpeg', ext: 'jpg', width: meta?.width ?? 0, height: meta?.height ?? 0, passthrough: true, }; } if (fmt === 'png') { return { buffer: buf, mime: 'image/png', ext: 'png', width: meta?.width ?? 0, height: meta?.height ?? 0, passthrough: true, }; } if (fmt === 'webp') { return { buffer: buf, mime: 'image/webp', ext: 'webp', width: meta?.width ?? 0, height: meta?.height ?? 0, passthrough: true, }; } if (fmt === 'gif') { return { buffer: buf, mime: 'image/gif', ext: 'gif', width: meta?.width ?? 0, height: meta?.height ?? 0, passthrough: true, }; } if (fmt === 'tiff' || fmt === 'tif') { return { buffer: buf, mime: 'image/tiff', ext: 'tiff', width: meta?.width ?? 0, height: meta?.height ?? 0, passthrough: true, }; } if (fmt === 'bmp') { return { buffer: buf, mime: 'image/bmp', ext: 'bmp', width: meta?.width ?? 0, height: meta?.height ?? 0, passthrough: true, }; } return { buffer: buf, mime: 'application/octet-stream', ext: 'bin', width: meta?.width ?? 0, height: meta?.height ?? 0, passthrough: true, }; } /** * @param {Buffer} outBuf * @param {number} w0 * @param {number} h0 */ async function sameDimensionsOrThrow(outBuf, w0, h0) { const m = await sharp(outBuf).metadata(); if ((m.width ?? 0) !== w0 || (m.height ?? 0) !== h0) { const err = new Error('encode changed dimensions'); err.code = 'DIM'; throw err; } } /** * @param {Buffer} src * @returns {Promise} */ export async function optimizeImageBufferVisuallyLossless(src) { const input = Buffer.isBuffer(src) ? src : Buffer.from(src); if (input.length === 0) { return makePassthrough(input, { width: 0, height: 0, format: 'png' }); } let meta0; try { meta0 = await sharp(input, { failOn: 'error', unlimited: true }).metadata(); } catch { return makePassthrough(input, null); } const width = meta0.width ?? 0; const height = meta0.height ?? 0; if (width <= 0 || height <= 0) { return makePassthrough(input, meta0); } const pages = meta0.pages ?? 1; if (pages > 1) { return makePassthrough(input, meta0); } const rawFmt = meta0.format; if (rawFmt === 'svg' || rawFmt === 'pdf' || rawFmt === 'heif' || rawFmt === 'jxl' || rawFmt === 'vips') { return makePassthrough(input, meta0); } const hasAlpha = meta0.hasAlpha === true; try { if (hasAlpha) { const webpLo = await sharp(input) .rotate() .ensureAlpha() .webp({ lossless: true, effort: WEBP_EFFORT }) .toBuffer(); const pngOut = await sharp(input) .rotate() .ensureAlpha() .png({ compressionLevel: 9, adaptiveFiltering: true }) .toBuffer(); await sameDimensionsOrThrow(webpLo, width, height); await sameDimensionsOrThrow(pngOut, width, height); const pickWebp = webpLo.length <= pngOut.length; const outBuf = pickWebp ? webpLo : pngOut; if (outBuf.length >= input.length) { return makePassthrough(input, meta0); } return { buffer: outBuf, mime: pickWebp ? 'image/webp' : 'image/png', ext: pickWebp ? 'webp' : 'png', width, height, passthrough: false, }; } const webpColor = await sharp(input) .rotate() .webp({ quality: RASTER_QUALITY, nearLossless: true, effort: WEBP_EFFORT, smartSubsample: false, }) .toBuffer(); const jpegColor = await sharp(input) .rotate() .jpeg({ quality: RASTER_QUALITY, chromaSubsampling: '4:4:4', mozjpeg: true, optimizeScans: true, }) .toBuffer(); await sameDimensionsOrThrow(webpColor, width, height); await sameDimensionsOrThrow(jpegColor, width, height); const useWebp = webpColor.length <= jpegColor.length; const outBuf = useWebp ? webpColor : jpegColor; if (outBuf.length >= input.length) { return makePassthrough(input, meta0); } return { buffer: outBuf, mime: useWebp ? 'image/webp' : 'image/jpeg', ext: useWebp ? 'webp' : 'jpg', width, height, passthrough: false, }; } catch (e) { if (e && typeof e === 'object' && /** @type {{ code?: string }} */ (e).code === 'DIM') { return makePassthrough(input, meta0); } return makePassthrough(input, meta0); } }