Skip to content

Commit 12e9b4f

Browse files
committed
fix: animated webp height was wrongly reported by sharp
1 parent dc744da commit 12e9b4f

File tree

1 file changed

+17
-7
lines changed

1 file changed

+17
-7
lines changed

ts/webworker/workers/node/image_processor/image_processor.worker.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,20 +78,30 @@ function sharpFrom(inputBuffer: ArrayBufferLike | Buffer, options?: sharp.SharpO
7878
return sharp(new Uint8Array(inputBuffer), options).rotate();
7979
}
8080

81+
function metadataToFrameHeight(metadata: sharp.Metadata) {
82+
const frameCount = Math.max(metadata.pages || 0, 1);
83+
const frameHeight =
84+
metadata.height && frameCount ? metadata.height / frameCount : metadata.height;
85+
return frameHeight;
86+
}
87+
8188
/**
8289
* Wrapper around `sharp.metadata` as it throws if not a valid image, and we usually
8390
* want to just return null.
8491
*
8592
* Note: this will also orient a jpeg if needed. (i.e. calls rotate() through sharpFrom)
93+
* Note: metadata height will be set to the frame height, not the full height
94+
* of the canvas (as sharp.metadata does with animated webps)
8695
*/
8796
async function metadataFromBuffer(
8897
inputBuffer: ArrayBufferLike | Buffer,
8998
options?: sharp.SharpOptions
9099
) {
91100
try {
92101
const metadata = await sharpFrom(inputBuffer, options).metadata();
102+
const frameHeight = metadataToFrameHeight(metadata);
93103
// we do need the await above so the try/catch does its job
94-
return metadata;
104+
return { ...metadata, height: frameHeight };
95105
} catch (e) {
96106
console.info('metadataFromBuffer failed with', e.message);
97107
return null;
@@ -131,7 +141,7 @@ const workerActions: ImageProcessorWorkerActions = {
131141
return {
132142
outputBuffer: outputBuffer.buffer,
133143
width: outputMetadata.width,
134-
height: outputMetadata.height,
144+
height: outputMetadata.height, // this one is only the frame height already, no need for `metadataToFrameHeight`
135145
size: outputMetadataSize,
136146
format: 'jpeg' as const,
137147
contentType: 'image/jpeg' as const,
@@ -231,7 +241,7 @@ const workerActions: ImageProcessorWorkerActions = {
231241

232242
avatarFallback = {
233243
outputBuffer: firstFrameJpeg.outputBuffer,
234-
height: firstFrameJpeg.height,
244+
height: firstFrameJpeg.height, // this one is only the frame height already. No need for `metadataToFrameHeight`
235245
width: firstFrameJpeg.width,
236246
format: fallbackFormat,
237247
contentType: `image/${fallbackFormat}` as const,
@@ -272,7 +282,7 @@ const workerActions: ImageProcessorWorkerActions = {
272282
const format = 'jpeg' as const;
273283
return {
274284
outputBuffer: createdBuffer.buffer,
275-
height: createdMetadata.height,
285+
height: createdMetadata.height, // this one is only the frame height already, no need for `metadataToFrameHeight`
276286
width: createdMetadata.width,
277287
isAnimated: false,
278288
format,
@@ -390,7 +400,7 @@ const workerActions: ImageProcessorWorkerActions = {
390400
outputBuffer: inputBuffer,
391401
size,
392402
width: metadata.width,
393-
height: metadata.height,
403+
height: metadata.height, // this one is only the frame height already, no need for `metadataToFrameHeight`
394404
isAnimated: isAnimated(metadata),
395405
};
396406
}
@@ -414,7 +424,7 @@ const workerActions: ImageProcessorWorkerActions = {
414424
outputBuffer: inputBuffer,
415425
size,
416426
width: metadata.width,
417-
height: metadata.height,
427+
height: metadata.height, // this one is only the frame height already, no need for `metadataToFrameHeight`
418428
isAnimated: isAnimated(metadata),
419429
};
420430
}
@@ -481,7 +491,7 @@ const workerActions: ImageProcessorWorkerActions = {
481491
outputBuffer: buffer.buffer,
482492
size,
483493
width: outputMetadata.width,
484-
height: outputMetadata.height,
494+
height: outputMetadata.height, // this one is only the frame height already, no need for `metadataToFrameHeight`
485495
isAnimated: isAnimated(outputMetadata),
486496
};
487497
}

0 commit comments

Comments
 (0)