diff --git a/src/core/embedders/JpegEmbedder.ts b/src/core/embedders/JpegEmbedder.ts index 94e6dc490..7513e0f00 100644 --- a/src/core/embedders/JpegEmbedder.ts +++ b/src/core/embedders/JpegEmbedder.ts @@ -29,7 +29,11 @@ const ChannelToColorSpace: { [idx: number]: ColorSpace | undefined } = { */ class JpegEmbedder { static async for(imageData: Uint8Array) { - const dataView = new DataView(imageData.buffer); + const dataView = new DataView( + imageData.buffer, + imageData.byteOffset, + imageData.byteLength, + ); const soi = dataView.getUint16(0); if (soi !== 0xffd8) throw new Error('SOI not found in JPEG'); diff --git a/tests/core/embedders/JpegEmbedder.spec.ts b/tests/core/embedders/JpegEmbedder.spec.ts index 18a2f164a..250e5630d 100644 --- a/tests/core/embedders/JpegEmbedder.spec.ts +++ b/tests/core/embedders/JpegEmbedder.spec.ts @@ -59,4 +59,17 @@ describe(`JpegEmbedder`, () => { expect(embedder.width).toBe(500); expect(embedder.colorSpace).toBe('DeviceCMYK'); }); + + it(`can extract properties of JPEG images have offset backing buffers`, async () => { + // This can happen with buffers that are pooled or sprite sheets + const oddCmykJpg = Buffer.alloc(10 + cmykJpg.byteLength); + cmykJpg.copy(oddCmykJpg, 10); + const oddCmykJpgView = oddCmykJpg.subarray(10); + const embedder = await JpegEmbedder.for(oddCmykJpgView); + + expect(embedder.bitsPerComponent).toBe(8); + expect(embedder.height).toBe(333); + expect(embedder.width).toBe(500); + expect(embedder.colorSpace).toBe('DeviceCMYK'); + }); });