@paroicms/server-image-cache-engine
Version:
The image variant engine that we use at Paroi.
59 lines • 2.29 kB
JavaScript
import sharp from "sharp";
import { authorizedMediaTypes } from "../constants.js";
import { sharpQueue } from "../image-processor-setup.js";
const icoEndec = (await import("ico-endec")).default;
export async function resizeImage(options) {
if (options.formatTo?.mediaType === "image/x-icon")
return await resizeIcoImage(options);
const sharpFormat = options.formatTo
? convertMediaTypeToSharpFormat(options.formatTo.mediaType)
: "webp";
const sharpInst = sharp(options.binaryFile)
.resize({ width: options.rawSize.rawWidth, height: options.rawSize.rawHeight })
.toFormat(sharpFormat, {
quality: getQuality(options.rawSize),
lossless: options.formatTo?.lossless,
});
const { data, info } = await sharpQueue(() => sharpInst.toBuffer({ resolveWithObject: true }));
return {
rawWidth: info.width,
rawHeight: info.height,
weightB: data.byteLength,
mediaType: convertSharpFormatToMediaType(info.format),
binaryFile: data,
};
}
export async function resizeIcoImage(options) {
const { data, info } = await sharpQueue(() => sharp(options.binaryFile)
.resize({ width: options.rawSize.rawWidth, height: options.rawSize.rawHeight })
.toFormat("png")
.toBuffer({ resolveWithObject: true }));
const binaryFile = icoEndec.encode([data]);
return {
rawWidth: info.width,
rawHeight: info.height,
weightB: binaryFile.byteLength,
mediaType: "image/x-icon",
binaryFile,
};
}
function convertMediaTypeToSharpFormat(mediaType) {
if (!mediaType.startsWith("image/") || !authorizedMediaTypes.has(mediaType)) {
throw new Error(`invalid media-type '${mediaType}'`);
}
return mediaType.substring(6);
}
export function convertSharpFormatToMediaType(format) {
if (format === "svg")
return "image/svg+xml"; // Sharp omit +xml
return `image/${format}`;
}
export function getQuality({ rawWidth, rawHeight }, qualityPolicy) {
const area = rawWidth * rawHeight;
for (const { quality, areaLimitPx } of qualityPolicy ?? []) {
if (areaLimitPx === undefined || area <= areaLimitPx)
return quality;
}
return 70;
}
//# sourceMappingURL=resizer.js.map