Guide
Images
Add PNG and JPEG images with pdf-image from a data URL, a URL, a Blob, an ArrayBuffer or a Uint8Array, and control their size with width, height and object-fit.
pdf-image draws a PNG or JPEG image. Its one input, src, is required.
@Component({
selector: 'app-badge-document',
imports: [PDF_ELEMENTS],
template: `
<pdf-document>
<pdf-page size="A5" style="padding: 24">
<pdf-view style="flex-direction: row; gap: 12; align-items: center">
<pdf-image src="/assets/logo.png" style="width: 48" />
<pdf-text style="font-size: 16">Visitor badge</pdf-text>
</pdf-view>
<pdf-image
[src]="photo()"
style="width: 120; height: 160; object-fit: cover; margin-top: 12; border: 1 solid #cccccc"
/>
</pdf-page>
</pdf-document>
`,
})
export class BadgeDocument {
readonly photo = input.required<Blob>();
}Sources
src is a string, a Blob, an ArrayBuffer or a Uint8Array.
| Source | How ngpdf reads it |
|---|---|
a string starting with data: |
decoded in place, base64 or percent-encoded |
| any other string | downloaded with the browser's fetch |
a Blob (or a File) |
read with blob.arrayBuffer() |
an ArrayBuffer |
used as it is |
a Uint8Array, such as a Node Buffer |
its bytes, as it is (a view into a larger buffer reads only its own bytes) |
The format is detected from the bytes, not from the URL, the file name or the MIME type. PNG and JPEG are supported. GIF, WebP and other formats fail with image is neither PNG nor JPEG, and so does SVG: draw an SVG with pdf-svg instead, which keeps it as vector shapes. To use the other formats, draw them on a <canvas> and pass canvas.toBlob(…, 'image/png'):
export function canvasToPng(canvas: HTMLCanvasElement): Promise<Blob> {
return new Promise((resolve, reject) => {
canvas.toBlob((blob) => (blob ? resolve(blob) : reject(new Error('Could not encode the chart'))), 'image/png');
});
}Other typed arrays, such as Uint16Array, are not accepted.
The data: prefix and its ;base64 marker are matched in any case, so DATA:image/png;BASE64,… is decoded in place too.
Fetching URLs
- ngpdf calls
fetch(src, { credentials: 'same-origin' }). A relative URL such as/assets/logo.pngresolves against your page, as anyfetchdoes. - The request runs under your page's CORS rules and Content-Security-Policy. An image on another origin needs CORS headers that allow your origin; cookies are sent only to your own origin.
- A response that is not OK fails, for example with
HTTP 404. - There is no timeout, and no size limit unless you set
maxImageBytes(below). - All images of a document load in parallel before layout. The same string
srcused several times in one render is fetched once. - On the server,
renderToBufferreads an absolute URL only through yourfetchImage, and refuses a relative one. See Images and fonts on the server.
A size cap
By default a fetched image is downloaded in full, however large. If image URLs in your documents come from users or another service, set maxImageBytes, a render option next to inputs:
await this.pdf.download(InvoiceDocument, {
inputs: { customer, lines },
fileName: 'invoice.pdf',
maxImageBytes: 10_000_000, // 10 MB
});- It caps images fetched from a URL only. Data URLs,
Blobs,ArrayBuffers andUint8Arrays are already in memory and are not counted, and neither are emoji images or fonts. - A response whose
Content-Lengthis over the cap is refused before its body is read. Otherwise ngpdf counts the bytes as they arrive and stops the download as soon as they pass the cap. An image of exactlymaxImageBytesbytes loads. - Past the cap the render rejects with
ngpdf: could not load image "<source>": larger than N bytes, where N is the cap. - It must be a positive whole number. Any other value rejects the render with
ngpdf: invalid maxImageBytes "<value>"before any image loads. - Every way to render takes it:
PdfRenderer.toBloband.download,renderToBlob,downloadPdf,pdfResource,renderToBuffer, thepdfMaxImageBytesinput ofPdfDownloadand themaxImageBytesinput ofpdf-viewer. See Rendering API. - On the server, ngpdf checks the bytes your
fetchImagereturns, but it cannot stop your function's download. Put a size limit infetchImageitself as well.
Errors
The first image that fails rejects the whole render with:
ngpdf: could not load image "<source>": <reason>
<source> is the URL without its query string and fragment (they often carry a token), or data URL, Blob, ArrayBuffer or Uint8Array. <reason> is the cause, such as HTTP 404, larger than N bytes, the browser's network error, ngpdf: image is neither PNG nor JPEG, or the image data is corrupt or cut off for a PNG whose pixel data is broken or truncated; where it repeats the URL, the URL is shortened the same way. On failure no PDF is downloaded, though part of the image may have been fetched before the error, and the document component is destroyed.
Size
The image keeps its aspect ratio unless you give it both dimensions.
| You set | Result |
|---|---|
| nothing | natural size, 1 image pixel = 1pt (72 / dpi points with a dpi on the page), capped to the width available |
width only |
the height follows the aspect ratio |
height only |
the width follows the aspect ratio |
width and height |
the box you set; object-fit places the image in it |
A JPEG with an EXIF orientation, as phone photos usually have, is drawn turned the way browsers show it, and its size and aspect ratio are those of the turned picture: a photo stored 4000x3000 with a quarter-turn orientation (5 to 8) is 3000 wide and 4000 high. The orientation is read from the first Exif APP1 segment before the image data, which is where cameras write it, so an XMP segment or a comment in front of it does not hide it. Its value is read as a 16-bit number, because that is how pdfkit reads it; a value outside 1 to 8 is ignored.
A 2x image (for example a canvas captured at twice the screen size) therefore comes out twice as large as on screen. Set a width to scale it.
An image with no size set is not stretched by its parent's default align-items: stretch. Set align-self: stretch to make it take the full width, with its height following.
object-fit
When the box and the image have different proportions:
contain(the default) scales the image to fit inside the box and centers it.coverscales it to fill the box, centers it, and clips what overflows.
The image is drawn inside the content box, so padding and borders on a pdf-image frame it. opacity applies to the image.
Things to avoid
- Do not put elements inside
pdf-image. The render rejects withngpdf: pdf-image cannot have children, naming the first one, before any image is fetched. Text inside it is ignored. - Do not rely on
srcchanging after the render starts. The component is rendered once.