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`
This commit is contained in:
@@ -360,6 +360,7 @@ export async function resizeAndTransformImageSizes({
|
||||
const prioritizeHeight = resizeAspectRatio < originalAspectRatio
|
||||
// Scales the image before extracting from it
|
||||
resized = imageToResize.resize({
|
||||
fastShrinkOnLoad: false,
|
||||
height: prioritizeHeight ? resizeHeight : undefined,
|
||||
width: prioritizeHeight ? undefined : resizeWidth,
|
||||
})
|
||||
|
||||
@@ -390,6 +390,10 @@ export default buildConfigWithDefaults({
|
||||
height: 300,
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
name: 'undefinedHeight',
|
||||
width: 300,
|
||||
},
|
||||
],
|
||||
pasteURL: false,
|
||||
},
|
||||
|
||||
@@ -400,6 +400,20 @@ describe('Uploads', () => {
|
||||
await expect(page.locator('.row-3 .cell-title')).toContainText('draft')
|
||||
})
|
||||
|
||||
test('should upload edge case media when an image size contains an undefined height', async () => {
|
||||
await page.goto(mediaURL.create)
|
||||
await page.setInputFiles(
|
||||
'input[type="file"]',
|
||||
path.resolve(dirname, './test-image-1500x735.jpeg'),
|
||||
)
|
||||
|
||||
const filename = page.locator('.file-field__filename')
|
||||
|
||||
await expect(filename).toHaveValue('test-image-1500x735.jpeg')
|
||||
|
||||
await saveDocAndAssert(page)
|
||||
})
|
||||
|
||||
describe('filterOptions', () => {
|
||||
test('should restrict mimetype based on filterOptions', async () => {
|
||||
const audioDoc = (
|
||||
|
||||
@@ -64,6 +64,7 @@ export interface Config {
|
||||
auth: {
|
||||
users: UserAuthOperations;
|
||||
};
|
||||
blocks: {};
|
||||
collections: {
|
||||
relation: Relation;
|
||||
audio: Audio;
|
||||
@@ -327,6 +328,14 @@ export interface Media {
|
||||
filesize?: number | null;
|
||||
filename?: string | null;
|
||||
};
|
||||
undefinedHeight?: {
|
||||
url?: string | null;
|
||||
width?: number | null;
|
||||
height?: number | null;
|
||||
mimeType?: string | null;
|
||||
filesize?: number | null;
|
||||
filename?: string | null;
|
||||
};
|
||||
};
|
||||
}
|
||||
/**
|
||||
@@ -2018,6 +2027,16 @@ export interface MediaSelect<T extends boolean = true> {
|
||||
filesize?: T;
|
||||
filename?: T;
|
||||
};
|
||||
undefinedHeight?:
|
||||
| T
|
||||
| {
|
||||
url?: T;
|
||||
width?: T;
|
||||
height?: T;
|
||||
mimeType?: T;
|
||||
filesize?: T;
|
||||
filename?: T;
|
||||
};
|
||||
};
|
||||
}
|
||||
/**
|
||||
|
||||
BIN
test/uploads/test-image-1500x735.jpeg
Normal file
BIN
test/uploads/test-image-1500x735.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
Reference in New Issue
Block a user