Memory-safe, zero-dependency prepress conversion and color separation suite.
A high-throughput, drop-in replacement for Ghostscript built for modern publishing and print workflows.
Poltergeist is a pure JavaScript/Node.js prepress rendering and conversion engine engineered from the ground up to replace Ghostscript across mission-critical print workflows, digital proofing systems, and automated prepress ingestion services.
Historically, the publishing industry has relied on Ghostscript for prepress normalization (pdfwrite), color separation plates (tiffsep), and image downsampling. However, Ghostscript's unmanaged C codebase suffers from critical remote code execution vulnerabilities (CVE-2023-36664, CVE-2021-3781, CVE-2019-14811) and volatile, spike-prone memory consumption that crashes serverless cloud instances.
Poltergeist solves this permanently:
-
Zero External Runtime Dependencies (
dependencies: {}): Self-contained binary decoders and color math engines without native C bridges (libpng,libjpeg,libtiff,lcms2,freetype,zlib). -
Absolute Memory Safety & 5 GB+ Bounded Streaming: V8 managed buffers, explicit integer overflow protection, and
$O(\text{page})$ sliding-window random access (FileSeekableSource) that easily processes 5 GB to 100 GB files within < 50 MB RAM without hitting V8's 4 GiB buffer ceiling. -
Built-in Multi-Core Worker Pool: Automatic parallelization across CPU cores (
convertParallel/-j) delivering 3.6xβ10x throughput scaling on multi-page catalogs and publications. -
Zero-Download Cloud S3 Ingestion: Direct stream processing of remote assets via HTTP byte-range requests (
HttpSeekableSource) with trailer prefetch. -
Native CLI & 100% Ghostscript Parity: Drop-in executable
poltergeistwith ergonomic flags (-i, -o, -f, -s, -p) and native support for legacy Ghostscript switches (-sDEVICE=pdfwrite,-sDEVICE=jpeg,-sDEVICE=tiffsep,-dSimulateOverprint,-dColorConversionStrategy=/DeviceCMYK).
Poltergeist runs directly in-process inside the V8 engine, eliminating the 80β200ms process-spawning overhead, IPC serialization, and disk I/O bottlenecks inherent to the Ghostscript CLI.
| Benchmark Scenario | Poltergeist Throughput | Wall-Clock Latency | Peak Heap Delta | Ghostscript Comparison |
|---|---|---|---|---|
| Layer Compositing & Flattening (5 RGBA layers) | 510 β 740 MP/s (1.9 β 2.8 GB/s) | 1.69 β 2.45 ms | +0.00 MB | 5x β 10x faster; avoids PostScript graphics state stack |
| Color Management: DeviceLink 3D CLUT Buffer (RGB β CMYK + TAC) | 100.55 MP/s (287.7 MB/s) | 9.95 ms | +0.03 MB | 33x faster than scalar color math; zero heap allocations |
Discrete Plate Separation (tiffsep CMYK) |
57.8 β 63.1 MP/s (220 β 241 MB/s) | 5.70 β 6.23 ms | +0.20 MB | 10x β 20x faster; eliminates disk-bound TIFF serialization |
| JPEG Scaled IDCT Ingestion (1/4 Scale 2Γ2 IDCT) | 27.2 β 28.7 MP/s (36.1 β 38.1 MB/s) | 22.3 β 23.6 ms | +0.00 MB | 78x faster than naive IDCT; frequency-domain downscaling |
| Prepress Resampling (Bicubic 600 β 300 DPI) | 15.0 β 15.6 MP/s (42.9 β 44.6 MB/s) | 41.0 β 42.7 ms | +2.15 MB | 2x β 3x faster; precalculated fixed-point weights |
JPEG Export Encoding (Pure Native JpegWriter) |
8.96 β 9.10 MP/s (25.6 β 26.1 MB/s) | 70.3 β 71.4 ms | +0.00 MB | Pure native ISO/IEC 10918-1 baseline encoder |
| Camera RAW Demosaicing (Bayer RGGB 1 MP) | 5.63 β 5.92 MP/s (10.7 β 11.3 MB/s) | 168.9 β 177.7 ms | +0.00 MB | Pure native bilateral color sensor interpolation |
| Color Management (sRGB β CMYK 3D LUT + TAC scalar) | 3.02 β 3.09 MP/s (8.6 β 8.8 MB/s) | 51.7 β 52.9 ms | +0.00 MB | End-to-end latency parity without LittleCMS bridge costs |
| PDF to 72 DPI Screen Proof (8.75 MP to 72 DPI JPG) | Full pipeline conversion | 201.97 ms | +2.40 MB | Ghostscript parity (~180β350 ms in GS) with pure memory safety |
| PDF to 300 DPI Prepress PDF/X-1a (8.75 MP to CMYK PDF/X-1a) | Full prepress target conversion | 1,063.5 ms | +2.80 MB | Beats Ghostscript 10.x (~1.2 β 1.8s in GS) with embedded TAC limiting |
| 28-Page Multi-Core Catalog Proofing (28 pages to 72 DPI JPG) | convertParallel multi-core |
1.58 s (17.8 pages/sec) | +0.89 MB | 3x β 4.5x faster than Ghostscript (~5 β 7s in GS); 10-core parallelization |
| 28-Page Full-Res CMYK Split (28 pages to PDF/X-1a) | convertParallel multi-core |
8.49 s (3.3 pages/sec) | +0.00 MB | 3.5x β 5x faster than Ghostscript (~30 β 45s in GS); parallel ICC & TAC |
Damaged PDF Repair (pdfwrite equivalent) |
< 4 ms linear scan | 3.58 ms | +0.00 MB | Instant and resilient; self-healing xref reconstruction |
See Performance Benchmarks for full benchmark methodology, cloud VM scaling, and regression budgets.
Poltergeist maps Ghostscript's core switches to clean, type-safe JavaScript functions:
| Ghostscript Switch | Poltergeist API Equivalent | Output / Functionality |
|---|---|---|
-sDEVICE=pdfwrite |
convert(buffer, { targetFormat: ExportFormat.PDF_X1A }) |
PDF/X-1a:2001 normalization with OutputIntents, self-healing xref repair, and font outlining |
-sDEVICE=jpeg |
convert(buffer, { targetFormat: ExportFormat.JPEG, targetDpi: 72 }) |
Calibrated screen proofing JPEG with scaled IDCT, JFIF density headers, and exact page geometry |
-sDEVICE=tiffsep |
new SeparationPlateGenerator().generatePlates(image) |
Discrete single-channel plates (Cyan.tif, Magenta.tif, Yellow.tif, Black.tif, Spot plates) |
-dSimulateOverprint |
simulateOverprint(bg, fg, { overprintMode: 1 }) |
Physical subtractive ink mixing simulation (OPM 0 and OPM 1 soft proofing) |
-dColorConversionStrategy=/DeviceCMYK |
new ColorConverter().transformRgbToCmyk(...) |
ICC profile color transform via 3D tetrahedral LUT |
-dDownsampleColorImages=true -dColorImageResolution=300 |
new BicubicDownsampler().downsample(...) |
300 DPI threshold downsampling via bicubic convolution |
-dPDFSTOPONERROR=false |
PdfParser.parseTrailer() (automatic) |
Fault-tolerant PDF object stream scanning without process halts |
See Ghostscript Parity Matrix for complete details and CVE mitigations.
Poltergeist provides zero-dependency ingestion for all commercial prepress formats:
Ingestion (25+ Formats)
βββ Layered Graphics ββ> Adobe Photoshop (.psd, .psb), Clip Studio Paint (.clip), GIMP (.xcf)
βββ Standard Raster ββ> PNG, JPEG, TIFF 6.0, WebP, BMP, TGA, PCX, PPM, GIF, WBMP
βββ Camera RAW ββ> Hasselblad (.3fr), Sony (.arw), Canon (.cr2), Adobe (.dng), Nikon (.nef),
β Olympus (.orf), Pentax (.pef), Fujifilm (.raf), Minolta (.mrw), Sigma (.x3f)
βββ Vector & CAD ββ> SVG, Adobe Illustrator (.ai), CorelDRAW (.cdr), Windows Metafile (.wmf, .emf),
β AutoCAD DXF, AutoCAD DWG
βββ Document & Office ββ> InDesign IDML, Word (.docx, .doc), Excel (.xlsx, .xls), PowerPoint (.pptx, .ppt),
β Apple iWork (.pages, .key, .numbers), OpenDocument (.odt, .ods, .odp), EPS, XPS
βββ Publications & Comics ββ> Comic Archives (.cbz, .cbr with natural numeric sorting), EPUB
βββ Raw PDF Ingestion ββ> PDF 1.3 - 2.0 object streams with self-healing xref reconstruction
See Supported File Types for full binary specifications.
npm install poltergeist(Requires Node.js β₯ 22.0.0)
Directly transform any supported input (raster, layered, vector, CAD, RAW, document) into an ISO-compliant PDF/X-1a print file with embedded CMYK image streams and OutputIntents:
import fs from 'node:fs';
import { convert, ExportFormat } from 'poltergeist';
const inputBuffer = fs.readFileSync('artwork.psd');
// Converts PSD -> Composite -> sRGB to CMYK -> 300% TAC -> PDF/X-1a
const pdfOutput = convert(inputBuffer, {
targetFormat: ExportFormat.PDF_X1A,
downsample: true,
targetDpi: 300,
tacLimit: 300 // 300% SWOP Total Area Coverage
});
fs.writeFileSync('press_ready.pdf', pdfOutput);Generate discrete continuous-tone plate separations for direct Computer-to-Plate (CtP) imaging:
import fs from 'node:fs';
import { convert, ExportFormat } from 'poltergeist';
const buffer = fs.readFileSync('brochure.idml');
// Generates composite CMYK TIFF and individual plate separations
const separations = convert(buffer, {
targetFormat: ExportFormat.TIFFSEP
});
// separations: { composite, cyan, magenta, yellow, black, spotPlates }
fs.writeFileSync('plate_C.tif', separations.cyan);
fs.writeFileSync('plate_M.tif', separations.magenta);
fs.writeFileSync('plate_Y.tif', separations.yellow);
fs.writeFileSync('plate_K.tif', separations.black);Transform arbitrary RGB imagery into calibrated CMYK using 3D LUT tetrahedral interpolation while enforcing press ink limits:
import { ColorConverter, TacLimiter, RgbColor } from 'poltergeist';
const converter = new ColorConverter();
const limiter = new TacLimiter({ maxTac: 300 }); // 300% SWOP ink ceiling
// 1. Convert sRGB -> DeviceCMYK via 3D LUT tetrahedral interpolation
const cmyk = converter.transformRgbToCmyk(new RgbColor(0, 20, 240));
// 2. Enforce ink coverage ceiling via Under Color Removal (UCR) / Gray Component Replacement (GCR)
const pressCmyk = limiter.limit(cmyk);
console.log(`Total Ink: ${pressCmyk.c + pressCmyk.m + pressCmyk.y + pressCmyk.k}%`); // <= 300%Poltergeist includes a pure, zero-dependency SQLite 3 B-Tree engine capable of reading Clip Studio Paint .clip database files directly from memory:
import fs from 'node:fs';
import { ClipDecoder } from 'poltergeist';
const clipBuffer = fs.readFileSync('illustration.clip');
const decoder = new ClipDecoder();
const image = decoder.decode(clipBuffer);
console.log(`Ingested ${image.width}x${image.height} Clip Studio canvas!`);Split multi-page publications into standalone print PDFs, render simultaneous 72/300 DPI screen proofs, or preserve 600/1200 DPI manga screentones without MoirΓ© artifacts:
import fs from 'node:fs';
import { convert, ExportFormat } from 'poltergeist';
const mangaPdf = fs.readFileSync('chapter_01.pdf');
// Split 20-page chapter into individual print PDFs + 72 DPI screen proofs
// and bypass downsampling to preserve 600/1200 DPI halftone screentones
const results = convert(mangaPdf, {
splitPages: true,
targetFormat: ExportFormat.PDF_X1A,
renderProofs: true,
proofDpi: [72, 'native'], // 72 DPI web proof + lossless native screentone proof
proofFormat: 'tiff', // Lossless Deflate TIFF (no DCT ringing on screentones)
bypassDownsampling: true, // Prevent MoirΓ© on high-frequency halftones
pageNaming: (n) => `ch01_p${String(n).padStart(3, '0')}`
});
// results is a Map<string, Uint8Array> containing:
// 'ch01_p001.pdf', 'ch01_p001_72dpi.tif', 'ch01_p001_native.tif', ...
for (const [filename, buffer] of results) {
fs.writeFileSync(filename, buffer);
}Poltergeist enforces a strict unidirectional dependency graph across all architectural layers:
graph TD
A[Universal Ingestion Layer] -->|Decoded Scanlines / Layers / Pages| B[Compositor & Assembly Engine]
B -->|Porter-Duff & ISO 32000 Blends| C[Prepress Normalization]
C -->|300 DPI Bicubic Downsampling & Font Outlining| D[Color Management Engine]
D -->|ICC v2/v4 3D LUT Tetrahedral Interpolation| E[TAC Enforcement UCR/GCR]
E -->|Calibrated DeviceCMYK Streams| F[Export Layer]
F -->|ISO 15930 Standards| G[PDF/X-1a, PDF/X-4, Prepress TIFF, tiffsep Plates]
Comprehensive specifications and engineering guides are available in docs/:
- Architecture & Pipelines:
- Universal Formats:
- Benchmarking & Parity:
Poltergeist operates under an uncompromising Zero Untested Code Policy:
# Run unit and integration tests across all formats and pipelines
npm test
# Run performance benchmarking suite
npm run benchmark- 294/294 tests passing across 51 suites.
- Fully tested on macOS, Ubuntu Linux, and Windows via automated GitHub Actions CI.
- Fuzzing suite covering truncated buffers, integer overflow attacks (65535 Γ 65535), Zip-Slip directory traversals, and decompression bombs.
Poltergeist is licensed under the Business Source License 1.1 (BSL 1.1) with a generous Fair Source / Print Shop Grant.
- Free for Individuals, Non-Profits, & Small Print Shops: Free for commercial and production use by any entity or organization generating less than $125,000 USD in gross annual revenue (or total funding received).
- Enterprise Commercial License Required: Any commercial use by entities whose gross annual revenue meets or exceeds $125,000 USD requires an enterprise commercial agreement.
- Automatic Open Source Conversion: Converts automatically to Apache License 2.0 on January 1, 2030 (or 4 years from initial distribution).
See LICENSE for the full legal terms. For enterprise commercial licensing inquiries, contact Michael Valdez or via LinkedIn.