Skip to content

Commit 9d6583d

Browse files
authored
fix: incorrect height rounding when resizing images with sharp (#11634)
This PR fixes an issue where the Sharp `.resize()` function would round down an auto-scaled dimension when `fastShrinkOnLoad` was enabled (enabled by default). This caused slight discrepancies in height calculations in certain edge cases. Be default (`fastShrinkOnLoad: true`), Sharp: - Uses the built-in shrink-on-load feature for JPEG and WebP - It is an optimization that prioritizes speed over precision when resizing images By setting `fastShrinkOnLoad: false`, we force Sharp to: - Perform a more accurate resize operation instead of relying on quick pre-shrink methods. ### Before / Context: - Upload an image with original dimensions of 1500 × 735 - Define an `imageSize` of the following: ``` { name: 'thumbnail', width: 300, }, ``` #### Calculation: `originalAspectRatio = 1500 / 735 ≈ 2.04081632653` `resizeHeight = 300 / 2.04081632653` `resizeHeight = 147` However, Sharp's `.resize()` calculation would output: `resizeHeight = 146` This lead to an error of: ``` [17:05:13] ERROR: extract_area: bad extract area err: { "type": "Error", "message": "extract_area: bad extract area", "stack": Error: extract_area: bad extract area } ``` ### After: Sharp's `.resize()` calculation now correctly outputs: `resizeHeight = 147`
1 parent 7be0219 commit 9d6583d

File tree

5 files changed

+38
-0
lines changed

5 files changed

+38
-0
lines changed

packages/payload/src/uploads/imageResizer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ export async function resizeAndTransformImageSizes({
360360
const prioritizeHeight = resizeAspectRatio < originalAspectRatio
361361
// Scales the image before extracting from it
362362
resized = imageToResize.resize({
363+
fastShrinkOnLoad: false,
363364
height: prioritizeHeight ? resizeHeight : undefined,
364365
width: prioritizeHeight ? undefined : resizeWidth,
365366
})

test/uploads/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,10 @@ export default buildConfigWithDefaults({
390390
height: 300,
391391
width: 300,
392392
},
393+
{
394+
name: 'undefinedHeight',
395+
width: 300,
396+
},
393397
],
394398
pasteURL: false,
395399
},

test/uploads/e2e.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,20 @@ describe('Uploads', () => {
400400
await expect(page.locator('.row-3 .cell-title')).toContainText('draft')
401401
})
402402

403+
test('should upload edge case media when an image size contains an undefined height', async () => {
404+
await page.goto(mediaURL.create)
405+
await page.setInputFiles(
406+
'input[type="file"]',
407+
path.resolve(dirname, './test-image-1500x735.jpeg'),
408+
)
409+
410+
const filename = page.locator('.file-field__filename')
411+
412+
await expect(filename).toHaveValue('test-image-1500x735.jpeg')
413+
414+
await saveDocAndAssert(page)
415+
})
416+
403417
describe('filterOptions', () => {
404418
test('should restrict mimetype based on filterOptions', async () => {
405419
const audioDoc = (

test/uploads/payload-types.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export interface Config {
6464
auth: {
6565
users: UserAuthOperations;
6666
};
67+
blocks: {};
6768
collections: {
6869
relation: Relation;
6970
audio: Audio;
@@ -327,6 +328,14 @@ export interface Media {
327328
filesize?: number | null;
328329
filename?: string | null;
329330
};
331+
undefinedHeight?: {
332+
url?: string | null;
333+
width?: number | null;
334+
height?: number | null;
335+
mimeType?: string | null;
336+
filesize?: number | null;
337+
filename?: string | null;
338+
};
330339
};
331340
}
332341
/**
@@ -2018,6 +2027,16 @@ export interface MediaSelect<T extends boolean = true> {
20182027
filesize?: T;
20192028
filename?: T;
20202029
};
2030+
undefinedHeight?:
2031+
| T
2032+
| {
2033+
url?: T;
2034+
width?: T;
2035+
height?: T;
2036+
mimeType?: T;
2037+
filesize?: T;
2038+
filename?: T;
2039+
};
20212040
};
20222041
}
20232042
/**

test/uploads/test-image-1500x735.jpeg

25.6 KB
Loading

0 commit comments

Comments
 (0)