nitropage
Version:
A free and open source, extensible visual page builder based on SolidStart.
91 lines (79 loc) • 2.1 kB
text/typescript
import type { Dimensions } from "../server/media/crop";
export const getImageOptimizationTarget = ({
size,
original,
aspectRatio,
dpr,
}: {
size: number;
original: Dimensions;
aspectRatio?: string;
dpr?: number;
}) => {
const proportionalHeight = Math.round(
(size / original.width) * original.height,
);
const target = !aspectRatio
? {
width: size,
height: proportionalHeight,
}
: getTargetFromAspectRatio(aspectRatio, size);
if (dpr === 2) {
((target.width = target.width * 2), (target.height = target.height * 2));
}
return target;
};
const ratioCache: Record<string, number> = {};
export const convertAspectRatio = function (aspectRatio: string) {
if (ratioCache[aspectRatio]) {
return ratioCache[aspectRatio];
}
const parts = aspectRatio.split("/");
if (parts.length !== 2) {
return 1;
}
const result = Number.parseInt(parts[1]) / parseInt(parts[0]);
ratioCache[aspectRatio] = result;
return result;
};
export const getTargetFromAspectRatio = function (
aspectRatio: string,
size: number,
) {
const ar = convertAspectRatio(aspectRatio);
if (ar > 1) {
return {
width: Math.round(size / ar),
height: size,
};
}
return {
width: size,
height: Math.round(size * ar),
};
};
/**
* Shrinks the crop target size, fitting it proportionally inside the original size
*
* E.g. if the original size is 300/300 and target is 400/300, this returns 300/225.
* With target 300/400, this returns 225/300.
*
* In either case, the new target size is never larger than the original size
*
*/
export const getProportionalCropTarget = function (
original: Dimensions,
target: Dimensions,
) {
target = { ...target };
if (target.width > original.width) {
target.height = Math.round((target.height / target.width) * original.width);
target.width = original.width;
}
if (target.height > original.height) {
target.width = Math.round((target.width / target.height) * original.height);
target.height = original.height;
}
return target;
};