CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pdfkit

A PDF generation library for Node.js with comprehensive text, graphics, and form support

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

image-handling.mddocs/

Image Handling

Image embedding and rendering with support for JPEG and PNG formats, including transparent PNGs, EXIF orientation, and flexible sizing options.

Capabilities

Image Embedding

Core image embedding with automatic format detection and comprehensive sizing options.

/**
 * Embed and render image
 * @param src - Image source
 * @param x - X coordinate (optional)
 * @param y - Y coordinate (optional)
 * @param options - Image rendering options
 * @returns Document instance for chaining
 */
image(src: ImageSource, x?: number, y?: number, options?: ImageOptions): PDFDocument;

/**
 * Open image for later use (preload)
 * @param src - Image source
 * @returns Image object for reuse
 */
openImage(src: ImageSource): PDFImage;

type ImageSource = string | Buffer | ArrayBuffer;

interface ImageOptions {
  /** Image width in points */
  width?: number;
  /** Image height in points */
  height?: number;
  /** Uniform scaling factor */
  scale?: number;
  /** Fit image within bounds [width, height] */
  fit?: [number, number];
  /** Cover bounds [width, height] completely */
  cover?: [number, number];
  /** Horizontal alignment for fit/cover */
  align?: 'left' | 'center' | 'right';
  /** Vertical alignment for fit/cover */
  valign?: 'top' | 'center' | 'bottom';
  /** Add hyperlink to image */
  link?: string;
  /** Add internal link to image */
  goTo?: string;
  /** Add named destination */
  destination?: string;
  /** Ignore EXIF orientation data */
  ignoreOrientation?: boolean;
}

Usage Examples:

// Basic image placement
doc.image('photo.jpg', 100, 100);

// Image with specific dimensions
doc.image('logo.png', 200, 100, {
  width: 150,
  height: 75
});

// Scaled image (maintains aspect ratio)
doc.image('diagram.png', 100, 200, {
  scale: 0.5
});

// Fit image within bounds
doc.image('large-photo.jpg', 300, 200, {
  fit: [200, 150],
  align: 'center',
  valign: 'center'
});

// Cover area completely (may crop)
doc.image('background.jpg', 100, 350, {
  cover: [400, 200],
  align: 'center',
  valign: 'center'
});

Image Sources

Multiple ways to provide image data to PDFKit.

// File path (Node.js only)
doc.image('./images/photo.jpg', 100, 100);

// URL (with proper loading)
const response = await fetch('https://example.com/image.png');
const buffer = await response.arrayBuffer();
doc.image(buffer, 100, 100);

// Buffer (Node.js)
import fs from 'fs';
const imageBuffer = fs.readFileSync('./images/photo.jpg');
doc.image(imageBuffer, 100, 100);

// Base64 data URL
const dataUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==';
doc.image(dataUrl, 100, 100);

// ArrayBuffer (browser)
const fileInput = document.querySelector('input[type="file"]');
const file = fileInput.files[0];
const arrayBuffer = await file.arrayBuffer();
doc.image(arrayBuffer, 100, 100);

Image Reuse

Optimize performance by preloading images for multiple uses.

/**
 * Preload image for reuse
 * @param src - Image source
 * @returns Reusable image object
 */
openImage(src: ImageSource): PDFImage;

Usage Examples:

// Preload image once
const logo = doc.openImage('company-logo.png');

// Use multiple times without reloading
doc.image(logo, 50, 50, { width: 100 });
doc.image(logo, 50, 700, { width: 50 });   // Smaller on second page
doc.addPage();
doc.image(logo, 50, 50, { width: 100 });   // Reuse on new page

Sizing Modes

Different approaches to image sizing and positioning.

// Explicit dimensions
doc.image('photo.jpg', 100, 100, {
  width: 200,
  height: 150
});

// Proportional scaling
doc.image('photo.jpg', 100, 100, {
  scale: 0.75  // 75% of original size
});

// Fit within bounds (maintains aspect ratio)
doc.image('photo.jpg', 100, 100, {
  fit: [200, 150]  // Will fit within 200x150 box
});

// Cover bounds (may crop to fill)
doc.image('photo.jpg', 100, 100, {
  cover: [200, 150]  // Will fill 200x150 box completely
});

// Width only (height calculated from aspect ratio)
doc.image('photo.jpg', 100, 100, {
  width: 200
});

// Height only (width calculated from aspect ratio)  
doc.image('photo.jpg', 100, 100, {
  height: 150
});

Image Alignment

Control how images are positioned within their bounds when using fit or cover modes.

// Horizontal alignment options
doc.image('photo.jpg', 100, 100, {
  fit: [200, 150],
  align: 'left'    // 'left' | 'center' | 'right'
});

// Vertical alignment options
doc.image('photo.jpg', 100, 100, {
  fit: [200, 150],
  valign: 'top'    // 'top' | 'center' | 'bottom'
});

// Combined alignment
doc.image('photo.jpg', 100, 100, {
  cover: [200, 150],
  align: 'center',
  valign: 'center'
});

Usage Examples:

// Fit image in top-left corner of bounds
doc.image('photo.jpg', 100, 100, {
  fit: [200, 150],
  align: 'left',
  valign: 'top'
});

// Center image within bounds
doc.image('photo.jpg', 100, 300, {
  fit: [200, 150],
  align: 'center',
  valign: 'center'
});

// Cover bounds with image centered
doc.image('background.jpg', 300, 100, {
  cover: [200, 150],
  align: 'center',
  valign: 'center'
});

Interactive Images

Add links and destinations to images.

// Hyperlink
doc.image('banner.jpg', 100, 100, {
  width: 300,
  height: 100,
  link: 'https://example.com'
});

// Internal link
doc.image('thumbnail.jpg', 100, 200, {
  width: 50,
  height: 50,
  goTo: 'page2'
});

// Named destination
doc.image('figure1.png', 100, 300, {
  width: 200,
  height: 150,
  destination: 'figure1'
});

EXIF Orientation

Handle image orientation metadata automatically or manually.

// Automatic EXIF orientation (default)
doc.image('rotated-photo.jpg', 100, 100, {
  width: 200
  // ignoreOrientation: false (default)
});

// Ignore EXIF orientation
doc.image('rotated-photo.jpg', 300, 100, {
  width: 200,
  ignoreOrientation: true
});

Supported Image Formats

JPEG (.jpg, .jpeg)

  • Compression: Lossy compression, smaller file sizes
  • Color Modes: RGB, CMYK, Grayscale
  • Features: EXIF metadata support, progressive encoding
  • Best For: Photographs, images with many colors
  • Transparency: Not supported

PNG (.png)

  • Compression: Lossless compression
  • Color Modes: RGB, RGBA (with alpha channel), Indexed, Grayscale
  • Features: Transparency support, gamma correction
  • Best For: Graphics with transparency, screenshots, diagrams
  • Transparency: Full alpha channel support

Image Processing Features

Automatic Format Detection

PDFKit automatically detects image format from:

  • File extension
  • Magic bytes in image data
  • MIME type in data URLs

Memory Management

  • Images are embedded once and referenced multiple times
  • Large images are streamed to reduce memory usage
  • Automatic cleanup of temporary image data

Quality Preservation

  • Original image quality maintained in PDF
  • No recompression for JPEG images
  • PNG transparency preserved accurately

Performance Considerations

  1. Preload Frequently Used Images: Use openImage() for images used multiple times
  2. Optimize Image Sizes: Resize images before embedding rather than scaling in PDF
  3. Choose Appropriate Formats: JPEG for photos, PNG for graphics with transparency
  4. Consider File Sizes: Large images increase PDF file size significantly
  5. Use Appropriate Compression: Balance quality vs. file size for your use case

Browser Compatibility

When using PDFKit in browsers:

  • File paths not supported (use Buffers or data URLs)
  • fetch() API for loading remote images
  • FileReader API for user-uploaded images
  • Canvas API for programmatically created images

Browser Example:

// Load image in browser
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const img = new Image();

img.onload = () => {
  canvas.width = img.width;
  canvas.height = img.height;
  ctx.drawImage(img, 0, 0);
  
  canvas.toBlob(blob => {
    const reader = new FileReader();
    reader.onload = () => {
      doc.image(reader.result, 100, 100);
    };
    reader.readAsArrayBuffer(blob);
  });
};

img.src = 'path/to/image.jpg';

Install with Tessl CLI

npx tessl i tessl/npm-pdfkit

docs

accessibility-features.md

attachments.md

color-management.md

document-management.md

font-management.md

image-handling.md

index.md

interactive-elements.md

outline.md

tables.md

text-rendering.md

vector-graphics.md

tile.json