Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- [BREAKING CHANGE] Restrict AcroForm options to documented mappings and explicit escape hatches.
- [BREAKING CHANGE] Stop automatically uppercasing annotation option keys.
- Do not mutate options passed to `doc.annotate()` and its convenience methods (link, note, strike, lineAnnotation, rectAnnotation, ellipseAnnotation, textAnnotation, fileAnnotation)
- Accept `Uint8Array` (and other `ArrayBuffer` views) as an image source in `doc.image()` ([#1446](https://github.com/foliojs/pdfkit/issues/1446))

### [v0.19.1] - 2026-06-10

Expand Down
4 changes: 4 additions & 0 deletions lib/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ class PDFImage {
data = src;
} else if (src instanceof ArrayBuffer) {
data = Buffer.from(new Uint8Array(src));
} else if (ArrayBuffer.isView(src)) {
// Typed arrays (e.g. Uint8Array) and DataView. Buffer is handled above,
// so this covers views that are not Node Buffers, preserving byteOffset/length.
data = Buffer.from(src.buffer, src.byteOffset, src.byteLength);
} else {
const match = /^data:.+?;base64,(.*)$/.exec(src);
if (match) {
Expand Down
17 changes: 17 additions & 0 deletions tests/unit/image.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,23 @@ describe('Image', function () {
expect(document.y).toBe(originalY + imageHeight);
});

test('accepts a Uint8Array as image source (issue #1446)', () => {
const bytes = new Uint8Array(fs.readFileSync('./tests/images/bee.png'));
expect(bytes).toBeInstanceOf(Uint8Array);
expect(Buffer.isBuffer(bytes)).toBe(false);
expect(() => document.image(bytes, 0, 0, { width: 50 })).not.toThrow();
});

test('accepts a Uint8Array view with a byteOffset as image source (issue #1446)', () => {
const file = fs.readFileSync('./tests/images/bee.png');
// Place the PNG bytes inside a larger buffer so the view has a non-zero offset.
const backing = new Uint8Array(file.length + 8);
backing.set(file, 8);
const view = backing.subarray(8);
expect(view.byteOffset).toBe(8);
expect(() => document.image(view, 0, 0, { width: 50 })).not.toThrow();
});

test('parse JPEG with null byte padding in EXIF (issue #1175)', () => {
const data = fs.readFileSync('./tests/images/issue-1175.jpeg');
const jpeg = new JPEG(data, 'test');
Expand Down