Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions src/handlers/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,18 @@ export const resize: Handler = {
height = width;
}
// sharp's `withoutEnlargement` doesn't respect the requested aspect ratio, so we need to do it ourselves
if (!context.enlarge) {
const clamped = clampDimensionsPreservingAspectRatio(context.meta, {
width,
height,
});
// By default don't clamp svgs unless explicitly desired with enlarge=false
if (
context.meta?.type === "svg" ? context.enlarge === false : !context.enlarge
) {
const clamped = clampDimensionsPreservingAspectRatio(
context.fit,
context.meta,
{
width,
height,
},
);
width = clamped.width;
height = clamped.height;
}
Expand Down
24 changes: 20 additions & 4 deletions src/handlers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,34 @@ export function applyHandler(
}

export function clampDimensionsPreservingAspectRatio(
fit: HandlerContext["fit"],
sourceDimensions: ImageMeta,
desiredDimensions: { width: number; height: number },
) {
const desiredAspectRatio = desiredDimensions.width / desiredDimensions.height;
const sourceAspectRatio = sourceDimensions.width / sourceDimensions.height;
let { width, height } = desiredDimensions;
if (sourceDimensions.width && width > sourceDimensions.width) {
width = sourceDimensions.width;
height = Math.round(sourceDimensions.width / desiredAspectRatio);
if (
["contain", "fill", "inside"].includes(fit) &&
sourceAspectRatio < desiredAspectRatio
) {
width = Math.round(height * desiredAspectRatio);
} else {
width = sourceDimensions.width;
height = Math.round(sourceDimensions.width / desiredAspectRatio);
}
}
if (sourceDimensions.height && height > sourceDimensions.height) {
height = sourceDimensions.height;
width = Math.round(sourceDimensions.height * desiredAspectRatio);
if (
["contain", "fill", "inside"].includes(fit) &&
sourceAspectRatio > desiredAspectRatio
) {
height = Math.round(width / desiredAspectRatio);
} else {
height = sourceDimensions.height;
width = Math.round(sourceDimensions.height * desiredAspectRatio);
}
}

return { width, height };
Expand Down
3 changes: 2 additions & 1 deletion src/ipx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ export function createIPX(userOptions: IPXOptions): IPX {
if (mFormat === "jpg") {
mFormat = "jpeg";
}

const format =
mFormat && SUPPORTED_FORMATS.has(mFormat)
? mFormat
Expand All @@ -295,7 +296,7 @@ export function createIPX(userOptions: IPXOptions): IPX {
: "jpeg";

// Use original SVG if format is not specified
if (imageMeta.type === "svg" && !mFormat) {
if (imageMeta.type === "svg" && (!mFormat || mFormat === "svg")) {
if (options.svgo === false) {
return {
data: sourceData,
Expand Down
2 changes: 1 addition & 1 deletion test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ const ipx = createIPX({
});

const source = await ipx("../assets2/bliss.jpg"); // access file outside ./public dir because of same prefix folder
const { data, format } = await source.process();
const { format } = await source.process();
console.log(format); // print image format
48 changes: 41 additions & 7 deletions test/handlers/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,46 @@ describe("utils", () => {
});

it("clampDimensionsPreservingAspectRatio", () => {
const sourceDimensions = { width: 200, height: 100 };
const desiredDimensions = { width: 300, height: 150 };
const result = clampDimensionsPreservingAspectRatio(
sourceDimensions,
desiredDimensions,
);
expect(result).toEqual({ width: 200, height: 100 });
const dimensions = [
{
source: [200, 100],
desired: [300, 150],
expected: [200, 100],
},
{
source: [200, 150],
desired: [150, 200],
expected: [113, 150],
},
{
source: [150, 200],
desired: [200, 150],
expected: [150, 113],
},
{
source: [211, 40],
desired: [170, 170, "contain"],
expected: [170, 170],
},
{
source: [211, 40],
desired: [220, 110, "contain"],
expected: [211, 106],
},
{
source: [40, 211],
desired: [110, 220, "contain"],
expected: [106, 211],
},
];

for (const d of dimensions) {
const result = clampDimensionsPreservingAspectRatio(
d.desired[2] ?? null,
{ width: d.source[0], height: d.source[1] },
{ width: d.desired[0], height: d.desired[1] },
);
expect(result).toEqual({ width: d.expected[0], height: d.expected[1] });
}
});
});