emf-converter

A zero-dependency TypeScript library that converts EMF (Enhanced Metafile) and WMF (Windows Metafile) binaries into PNG data URLs — entirely in the browser, by replaying their GDI/GDI+ drawing records onto a Canvas.

zero dependencies Canvas 2D EMF · EMF+ · WMF Apache-2.0

Install

npm install emf-converter

No runtime dependencies. Requires a Canvas API — OffscreenCanvas (Web Workers) or HTMLCanvasElement.

Usage

import { convertEmfToDataUrl, convertWmfToDataUrl } from 'emf-converter';

// `buffer` is an ArrayBuffer loaded from a file, fetch(), or an Office doc.
const pngDataUrl = await convertEmfToDataUrl(buffer);
// => "data:image/png;base64,iVBORw0KGgo…"  (or null on failure)

const wmfPng = await convertWmfToDataUrl(wmfBuffer);

// Optional: clamp output dimensions (aspect ratio preserved).
const scaled = await convertEmfToDataUrl(buffer, 1024, 768);

Both functions are async and return Promise<string | null> — the PNG data URL, or null when the buffer is invalid or no Canvas API is available.

Interactive demo

Everything below runs client-side in your browser — no upload, no server. Pick or drop an .emf or .wmf file and it is converted to a PNG on the spot.

Loading demo…

The rasterised PNG appears here.

How it works

A three-phase pipeline: parse → replay → export. The header parser extracts the drawing bounds, a Canvas is created (clamped to 4096×4096), then records are scanned sequentially and dispatched to GDI, EMF+, or WMF handlers that drive the Canvas 2D context. Embedded bitmaps (DIB and GDI+ pixel formats) and recursively embedded metafiles are resolved asynchronously after the synchronous replay completes, then the canvas is exported as a data:image/png;base64,… URL.

WMF
Windows Metafile (16-bit) — window/viewport mapping.
EMF
Enhanced Metafile (32-bit GDI) — bounds-based scaling.
EMF+
GDI+ extension embedded in EMF — world transform matrix.

Limitations