From 1f8e96c6eb63d4555ecf43efc5ed8f746d87844e Mon Sep 17 00:00:00 2001 From: Yufeng He <40085740+he-yufeng@users.noreply.github.com> Date: Tue, 16 Jun 2026 18:40:38 +0800 Subject: [PATCH 1/2] fix(core): read WebP VP8X canvas height from the correct byte offset --- .../request-tokenizer/imageTokenizer.test.ts | 25 +++++++++++++++++++ .../utils/request-tokenizer/imageTokenizer.ts | 4 +-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/packages/core/src/utils/request-tokenizer/imageTokenizer.test.ts b/packages/core/src/utils/request-tokenizer/imageTokenizer.test.ts index cdb5f35f5c9..57f8994ee0a 100644 --- a/packages/core/src/utils/request-tokenizer/imageTokenizer.test.ts +++ b/packages/core/src/utils/request-tokenizer/imageTokenizer.test.ts @@ -102,6 +102,31 @@ describe('ImageTokenizer', () => { }); }); + describe('WebP dimension extraction', () => { + it('should extract canvas dimensions from VP8X', async () => { + const width = 100; + const height = 80; + + const buf = Buffer.alloc(30); + buf.write('RIFF', 0, 'ascii'); + buf.writeUInt32LE(22, 4); + buf.write('WEBP', 8, 'ascii'); + buf.write('VP8X', 12, 'ascii'); + buf.writeUInt32LE(10, 16); // VP8X chunk size + buf.writeUInt8(0, 20); // flags + buf.writeUIntLE(width - 1, 24, 3); // canvas width minus one (24-bit LE) + buf.writeUIntLE(height - 1, 27, 3); // canvas height minus one (24-bit LE) + + const metadata = await tokenizer.extractImageMetadata( + buf.toString('base64'), + 'image/webp', + ); + + expect(metadata.width).toBe(width); + expect(metadata.height).toBe(height); + }); + }); + describe('batch processing', () => { it('should process multiple images serially', async () => { const pngBase64 = diff --git a/packages/core/src/utils/request-tokenizer/imageTokenizer.ts b/packages/core/src/utils/request-tokenizer/imageTokenizer.ts index 76933a0c80d..596e1f4aabd 100644 --- a/packages/core/src/utils/request-tokenizer/imageTokenizer.ts +++ b/packages/core/src/utils/request-tokenizer/imageTokenizer.ts @@ -222,8 +222,8 @@ export class ImageTokenizer { const height = ((bits >> 14) & 0x3fff) + 1; return { width, height }; } else if (format === 'VP8X') { - const width = (buffer.readUInt32LE(24) & 0xffffff) + 1; - const height = (buffer.readUInt32LE(26) & 0xffffff) + 1; + const width = buffer.readUIntLE(24, 3) + 1; + const height = buffer.readUIntLE(27, 3) + 1; return { width, height }; } From 09c53bbcc9a07fcbee48f87c63c3261ea75505fb Mon Sep 17 00:00:00 2001 From: Yufeng He <40085740+he-yufeng@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:54:02 +0800 Subject: [PATCH 2/2] docs(core): document WebP dimension byte offsets Address review: the VP8/VP8L/VP8X branches read width and height from bare numeric offsets. Add a short comment per branch noting the byte positions and little-endian layout, matching the convention already used by extractPngDimensions/extractJpegDimensions/extractBmpDimensions. --- packages/core/src/utils/request-tokenizer/imageTokenizer.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/core/src/utils/request-tokenizer/imageTokenizer.ts b/packages/core/src/utils/request-tokenizer/imageTokenizer.ts index 596e1f4aabd..bf9dc20996f 100644 --- a/packages/core/src/utils/request-tokenizer/imageTokenizer.ts +++ b/packages/core/src/utils/request-tokenizer/imageTokenizer.ts @@ -213,15 +213,18 @@ export class ImageTokenizer { const format = buffer.subarray(12, 16).toString('ascii'); if (format === 'VP8 ') { + // Lossy: 14-bit width/height at bytes 26-27 and 28-29 (little-endian) const width = buffer.readUInt16LE(26) & 0x3fff; const height = buffer.readUInt16LE(28) & 0x3fff; return { width, height }; } else if (format === 'VP8L') { + // Lossless: 14-bit (width-1) then (height-1) packed from byte 21 (little-endian) const bits = buffer.readUInt32LE(21); const width = (bits & 0x3fff) + 1; const height = ((bits >> 14) & 0x3fff) + 1; return { width, height }; } else if (format === 'VP8X') { + // Extended: 24-bit (canvas width-1) at bytes 24-26 and (height-1) at bytes 27-29 (little-endian) const width = buffer.readUIntLE(24, 3) + 1; const height = buffer.readUIntLE(27, 3) + 1; return { width, height };