pdf-to-png-converter

repository·main·Indexed 41 days ago

https://github.com/dichovsky/pdf-to-png-converter

A high-performance Node.js utility and CLI for converting PDF files and buffers to PNG images. Version 4.2.1 uses @napi-rs/canvas to provide pre-built native binaries, eliminating the need for local compilation. It supports parallel processing, worker-thread rendering for multi-core performance, and a metadata-only mode for extracting page dimensions without full rasterization. Requires Node.js 22.13 or higher.

Tokens
5.5K
Snippets
14
Records
27
Agent score
47%

What's inside pdf-to-png-converter

  1. Understand the pdf-to-png-converter architecture

    main

    The pdf-to-png-converter is a Node.js 22.13+ CommonJS library and CLI designed to convert PDF pages into PNGs. It uses pdfjs-dist with @napi-rs/canvas for rendering.

    Core Components

    • Library API: The primary entry point is pdfToPng(), which orchestrates the conversion pipeline, including option normalization, input handling, and scheduling.
    • CLI: An adapter that parses arguments and delegates to the core pdfToPng() function.
    • Execution Modes: The library supports different rendering strategies depending on your performance and resource needs:
      • Metadata-only: Fast mode that only extracts page dimensions and rotation without rendering pixels.
      • Main-thread (Default): Uses an ordered scheduler with a window of 3, allowing async encoding/writing to overlap with the next render.
      • Parallel (Main-thread): Uses processPagesInParallel: true to run a specific number of tasks in flight on the main thread.
      • Worker Threads: Uses renderInWorkerThreads: true to spawn a dynamic worker pool. This is the most performant mode for heavy workloads as it offloads rendering to separate threads.
  2. How to inspect page metadata without rendering

    main

    If you only need to check page counts, dimensions, or rotation, use returnMetadataOnly: true. This is significantly faster than full rendering because it skips the rasterization process.

    const pages = await pdfToPng('document.pdf', {
        returnMetadataOnly: true,
    });
    
    pages.forEach((page) => {
        console.log(`Page ${page.pageNumber}: ${page.width}x${page.height}px, rotation=${page.rotation}`);
    });
  3. Understand the PngPageOutput data format

    main

    The pdfToPng function returns an array of discriminated page objects. You must branch on the kind property before accessing mode-specific fields like path or content.

    Output Object Schema

    All output objects include:

    • pageNumber: The page number in the PDF.
    • name: The PNG filename.
    • width: Image width in pixels (integer; floored from viewportScale).
    • height: Image height in pixels (integer; floored from viewportScale).
    • rotation: Page rotation in degrees (0, 90, 180, or 270).

    Discriminated kind values

    kindWhen returnedpathcontent
    metadataWhen returnMetadataOnly: true''undefined
    contentRendering without outputFolder''PNG Buffer (unless returnPageContent: false)
    fileRendering with outputFolderFile pathPNG Buffer (unless returnPageContent: false)

    Important: width and height are floored to match the bitmap canvas. If a viewportScale results in a page with 0px dimensions or exceeds internal canvas limits, the conversion will throw an error.

    [
        {
            kind: 'content',
            pageNumber: 1,
            name: 'document_page_1.png',
            content: Buffer<...>, // undefined if returnPageContent=false
            path: '',
            width: 612,
            height: 792,
            rotation: 0
        }
    ]
  4. How to handle memory-efficient processing

    main

    For large PDFs, you can avoid keeping large PNG buffers in memory by setting returnPageContent: false. When this is set, the pages are written to disk (if outputFolder is provided), and the content property in the resulting PngPageOutput objects will be undefined.

    const pngPages = await pdfToPng('large-document.pdf', {
        outputFolder: './output',
        returnPageContent: false, // Don't keep PNG buffers in memory
        processPagesInParallel: true,
        concurrencyLimit: 4,
    });
    
    pngPages.forEach((page) => {
        if (page.kind === 'file') {
            console.log(`Saved: ${page.path}`);
        }
    });
  5. How the PngPageOutput discriminated union works

    main

    The library returns an array of PngPageOutput objects. This is a discriminated union where the kind property determines the available data:

    kindMeaningcontentpath
    metadataRenderability-checked dimensionsundefined''
    contentIn-memory conversionBuffer | undefined''
    filePNG written to diskBuffer | undefinedabsolute file path

    Key Behaviors

    • Metadata mode: Only provides dimensions and rotation.
    • In-memory mode: Returns PNG Buffers. If returnPageContent is set to false, encoding may be skipped to save resources.
    • File mode: Writes PNGs to disk. If returnPageContent is false, the Buffer is dropped from the returned object after the write is complete.
  6. Migrate to version 4.0.0+

    main

    If you are upgrading from a version prior to 4.0.0, note the following breaking changes:

    1. Discriminated Outputs: PngPageOutput is now discriminated. You must check page.kind before accessing page.path or page.content.
    2. Typed Verbosity: verbosityLevel now uses the VerbosityLevel enum. Use VerbosityLevel.ERRORS, VerbosityLevel.WARNINGS, or VerbosityLevel.INFOS instead of numeric literals.
    3. Strict Page Validation: pagesToProcess now throws errors for invalid values like 0, negative numbers, or non-integers. (Note: page numbers exceeding document length are still silently ignored).
    4. Exclusive File Creation: Disk writes now use exclusive-create ('wx') mode. Re-running a conversion into the same output filenames will throw an EEXIST error. You must clear the target directory or use unique filenames for subsequent runs.
  7. Runtime requirements and build commands

    main

    To run or build pdf-to-png-converter, ensure your environment meets the following requirements and use the provided npm scripts for lifecycle management.

    Requirements

    • Node.js: Version 22.13 or newer is required. (The project uses Node.js 24 in its .nvmrc).

    Build and Validation Commands

    • npm run build: Performs a production compile after cleaning the out/ and test-results/ directories.
    • npm run build:strict: Performs a strict build that checks the upstream pdfjs-dist and @napi-rs/canvas declaration boundaries using skipLibCheck: false.
    • npm run check: The primary CI/prepublish gate. It performs clean, normal, and strict type-checks, formatting, linting, and production-license validation.
    • npm test: Runs Vitest with coverage enforcement (98% threshold for statements, lines, functions, and branches).
    npm run build
    npm run build:strict
    npm run check
    npm test
  8. Optimize performance for PDF to PNG conversion

    main

    Depending on your workload, you can tune the conversion process using specific options:

    • Parallelism vs. Memory:
      • To minimize memory and ensure strict on-disk ordering, use processPagesInParallel: true with concurrencyLimit: 1. This creates a sliding window of exactly one page in flight.
      • For CPU-bound documents (complex vector art or large embedded images), use renderInWorkerThreads: true. This rasterizes pages in a pool of worker threads. This can be ~3× faster for image-heavy documents but has higher memory costs (one PDF copy + one pdf.js instance per worker).
    • Threadpool Sizing: PNG encoding and disk writes share Node's libuv threadpool (4 threads by default). For high-concurrency file-output workloads on multi-core machines, increase the threadpool size using the environment variable: UV_THREADPOOL_SIZE=8 node app.js.

    Note on Output Order: Because PNG encoding runs on the libuv threadpool, files may finish writing out of page order. Always consume results via the resolved, page-ordered array returned by the API rather than relying on directory-watch order.

  9. Quick Start: Convert PDF to PNG

    main

    Convert a PDF file to PNG images by providing a file path and an outputFolder in the options. The library will save the images to the specified directory.

    const { pdfToPng } = require('pdf-to-png-converter');
    
    (async () => {
        const pngPages = await pdfToPng('document.pdf', {
            outputFolder: './output',
        });
    
        console.log(`Converted ${pngPages.length} pages`);
    })();
  10. Configure execution modes for rendering

    main

    You can control how the library processes pages using the following options in PdfToPngOptions:

    • Metadata only: Set returnMetadataOnly: true. This skips canvas creation, worker pools, and file writes.
    • Main-thread parallelism: Set processPagesInParallel: true. You can control the number of concurrent tasks using concurrencyLimit.
    • Worker threads: Set renderInWorkerThreads: true. This takes precedence over main-thread parallelism and uses a dynamic worker pool of size min(concurrencyLimit, selectedPages).

    All modes preserve the original order of the pages in the resulting array.

  11. Understand the `PngPageOutput` result types

    main

    The pdfToPng function returns an array of PngPageOutput objects. The specific shape of each object depends on your configuration (specifically returnMetadataOnly, outputFolder, and returnPageContent).

    All outputs include these base properties:

    • pageNumber: The 1-based page number.
    • name: The filename.
    • width: Image width in pixels.
    • height: Image height in pixels.
    • rotation: The page rotation (0 | 90 | 180 | 270).

    Output Variants

    KindWhen it occurscontent propertypath property
    'metadata'When returnMetadataOnly: trueundefined''
    'content'When outputFolder is omitted and returnPageContent: trueBuffer''
    'file'When outputFolder is providedBuffer (if returnPageContent: true)The file path on disk