3.2 KiB
image-registry
(no submodules)
Purpose
The ImageRegistry allocates and reuses PDF Image XObjects across the
lifetime of a single renderDocument call. Each unique ImageElement
instance maps to exactly one PDF indirect object, regardless of how
many pages reference it. Per-page resource maps share the underlying
object by id so a multi-page document with a repeating logo never
allocates a copy per page. The module also owns the lower-level
registerImageXObject helper that builds the canonical /XObject /Image dictionary, choosing /DCTDecode for JPEGs and /FlateDecode
for decoded PNG RGB planes.
Features
- One PDF object per
ImageElement(identity-keyed, not src-hash). - Per-page
pageXObjectsmap populated as a side-effect ofensure. - JPEG passthrough via
/DCTDecode(no recompression). - PNG RGB plane re-emission via
/FlateDecode. DeviceRGB/DeviceGraycolour-space selection follows the decoder output.BitsPerComponentcarried straight from the decoded image.
Usage: Basic
import { ImageRegistry } from "@suaveplan/pdf/image-registry";
import { ImageElement, PdfWriter } from "@suaveplan/pdf";
const writer = new PdfWriter();
const registry = new ImageRegistry(writer);
const pageMap = new Map<string, number>();
const image = new ImageElement({ src: pngBytes, width: 100, height: 50 });
const resourceName = registry.ensure(image, pageMap);
// resourceName === "Im<id>"; pageMap now contains the entry.
Usage: Advanced
import { ImageRegistry, registerImageXObject } from "@suaveplan/pdf/image-registry";
import { ImageElement, PdfWriter } from "@suaveplan/pdf";
const writer = new PdfWriter();
const registry = new ImageRegistry(writer);
const logo = new ImageElement({ src: pngBytes, width: 80, height: 24 });
// Share `logo` across three pages — only one XObject is allocated.
for (const pageMap of pageMaps) {
registry.ensure(logo, pageMap);
}
// Build a JPEG XObject directly (e.g. from a pre-decoded blob).
const jpegId = registerImageXObject(writer, decodedJpeg);
API Reference
class ImageRegistry— constructed with aPdfWriter. Exposesensure(element, pageXObjects)which returns theIm<id>resource name and side-effects the supplied per-page map.registerImageXObject(writer, decoded)→number— low-level helper used byImageRegistry.ensure.
Implementation Notes
The registry keys by ImageElement instance identity rather than
content hash. This is intentional: callers that share the same
element across pages benefit from the cache automatically, while
callers that construct two ImageElements with identical bytes pay
for two PDF objects — the safe assumption when the bytes themselves
might differ after decodeImage runs (e.g. PNG alpha extraction).
registerImageXObject packs the dictionary entries in a fixed order
(/Type, /Subtype, /Width, /Height, /ColorSpace,
/BitsPerComponent, optional /Filter) so equal inputs produce
byte-identical objects, preserving the writer's xref-byte-offset
invariant. JPEG bytes are passed through unchanged via "None"
because the JPEG bitstream itself is what /DCTDecode consumes.