astro-ghostcms/.pnpm-store/v3/files/d9/fa404874e886e157e137b5ab175...

112 lines
3.3 KiB
Plaintext

import { preprocessors, codecs as supportedFormats } from "./codecs.js";
import ImageData from "./image_data.js";
const DELAY_MS = 1e3;
let _promise;
function delayOnce(ms) {
if (!_promise) {
_promise = new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
return _promise;
}
function maybeDelay() {
const isAppleM1 = process.arch === "arm64" && process.platform === "darwin";
if (isAppleM1) {
return delayOnce(DELAY_MS);
}
return Promise.resolve();
}
async function decodeBuffer(_buffer) {
const buffer = Buffer.from(_buffer);
const firstChunk = buffer.slice(0, 16);
const firstChunkString = Array.from(firstChunk).map((v) => String.fromCodePoint(v)).join("");
if (firstChunkString.includes("GIF")) {
throw Error(`GIF images are not supported, please use the Sharp image service`);
}
const key = Object.entries(supportedFormats).find(
([, { detectors }]) => detectors.some((detector) => detector.exec(firstChunkString))
)?.[0];
if (!key) {
throw Error(`Buffer has an unsupported format`);
}
const encoder = supportedFormats[key];
const mod = await encoder.dec();
const rgba = mod.decode(new Uint8Array(buffer));
return rgba;
}
async function rotate(image, numRotations) {
image = ImageData.from(image);
const m = await preprocessors["rotate"].instantiate();
return await m(image.data, image.width, image.height, { numRotations });
}
async function resize({ image, width, height }) {
image = ImageData.from(image);
const p = preprocessors["resize"];
const m = await p.instantiate();
await maybeDelay();
return await m(image.data, image.width, image.height, {
...p.defaultOptions,
width,
height
});
}
async function encodeJpeg(image, opts) {
image = ImageData.from(image);
const e = supportedFormats["mozjpeg"];
const m = await e.enc();
await maybeDelay();
const quality = opts.quality || e.defaultEncoderOptions.quality;
const r = await m.encode(image.data, image.width, image.height, {
...e.defaultEncoderOptions,
quality
});
return r;
}
async function encodeWebp(image, opts) {
image = ImageData.from(image);
const e = supportedFormats["webp"];
const m = await e.enc();
await maybeDelay();
const quality = opts.quality || e.defaultEncoderOptions.quality;
const r = await m.encode(image.data, image.width, image.height, {
...e.defaultEncoderOptions,
quality
});
return r;
}
async function encodeAvif(image, opts) {
image = ImageData.from(image);
const e = supportedFormats["avif"];
const m = await e.enc();
await maybeDelay();
const val = e.autoOptimize.min;
const quality = opts.quality || 75;
const r = await m.encode(image.data, image.width, image.height, {
...e.defaultEncoderOptions,
// Think of cqLevel as the "amount" of quantization (0 to 62),
// so a lower value yields higher quality (0 to 100).
cqLevel: quality === 0 ? val : Math.round(val - quality / 100 * val)
});
return r;
}
async function encodePng(image) {
image = ImageData.from(image);
const e = supportedFormats["oxipng"];
const m = await e.enc();
await maybeDelay();
const r = await m.encode(image.data, image.width, image.height, {
...e.defaultEncoderOptions
});
return r;
}
export {
decodeBuffer,
encodeAvif,
encodeJpeg,
encodePng,
encodeWebp,
resize,
rotate
};