npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@theprogrammingiantpanda/xcfreader

v1.1.0

Published

Reads in GIMP xcf files

Downloads

521

Readme

xcfreader

Parses files generated by GIMP (.xcf) and exposes a TypeScript/JavaScript API to read metadata, layers and render images.

CI Coverage Status

Highlights

  • TypeScript source: Full type safety with strict mode, types for ColorRGBA, XCFParser, GimpLayer, IXCFImage, and compositing modes via the CompositerMode enum
  • CompositerMode enum: All compositing/blend modes are now type-safe and referenced via the CompositerMode enum for improved reliability and maintainability
  • Native ESM: package.json sets type: "module" with proper exports
  • Promise-based API: XCFParser.parseFileAsync(path) returns a Promise
  • Browser support: Dedicated browser bundle with XCFDataImage for canvas rendering
  • Node.js support: XCFPNGImage for PNG file output using pngjs
  • GIMP 2.10+ support: Full XCF v011 64-bit pointer format compatibility
  • Grayscale support: Parse and render grayscale XCF images
  • High performance: Optimized rendering with 27% improvement through zero-allocation compositing, bulk copy operations, and specialized fast paths. Latest benchmark: ~357ms total rendering time across test suite (fullColour: 136ms, grey: 133ms, indexed: 88ms).

Installation

npm install @theprogrammingiantpanda/xcfreader

For Node.js usage with PNG file output, also install pngjs:

npm install @theprogrammingiantpanda/xcfreader pngjs

Note: pngjs is an optional peer dependency. Browser-only users don't need it.

Quick Start

Node.js Usage

import { XCFParser, XCFPNGImage } from "@theprogrammingiantpanda/xcfreader/node";

const parser = await XCFParser.parseFileAsync("./image.xcf");
console.log(`Size: ${parser.width}x${parser.height}`);
console.log(`Layers: ${parser.layers.length}`);

// Render to PNG file
const image = new XCFPNGImage(parser.width, parser.height);
parser.createImage(image);
await image.writeImage("./output.png");

Browser Usage

import { XCFParser, XCFDataImage } from "@theprogrammingiantpanda/xcfreader/browser";

// Parse from ArrayBuffer (e.g., from file input or fetch)
const arrayBuffer = await file.arrayBuffer();
const parser = XCFParser.parseBuffer(arrayBuffer);

// Render to canvas
const image = new XCFDataImage(parser.width, parser.height);
parser.createImage(image);

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.width = parser.width;
canvas.height = parser.height;
ctx.putImageData(image.imageData, 0, 0);

Debugging in the Browser Demo

The browser demo (examples/browser-demo.html) includes advanced diagnostics for XCF parsing and file loading. To enable raw header/byte/version debug output, add ?debug=1 to the URL:

examples/browser-demo.html?debug=1

This will show:

  • Raw bytes 0–20 (hex and ASCII)
  • Parsed version string and version number
  • Internal header and layer info

By default, this debug output is hidden for normal users.

Script Tag (IIFE)

<script src="node_modules/@theprogrammingiantpanda/xcfreader/dist/xcfreader.browser.js"></script>
<script>
  const { XCFParser, XCFDataImage } = XCFReader;

  async function parseXCF(file) {
    const arrayBuffer = await file.arrayBuffer();
    const parser = XCFParser.parseBuffer(arrayBuffer);

    const image = new XCFDataImage(parser.width, parser.height);
    parser.createImage(image);
    return image;
  }
</script>

Entry Points

| Entry Point | Image Class | Use Case | | -------------------------------------------- | ---------------------- | ------------------------------------ | | @theprogrammingiantpanda/xcfreader/node | XCFPNGImage | Node.js with PNG file output | | @theprogrammingiantpanda/xcfreader/browser | XCFDataImage | Browser with canvas rendering | | @theprogrammingiantpanda/xcfreader | None (base types only) | Advanced: bring your own IXCFImage |

API Reference

XCFParser

The main parser class for XCF files.

// Node.js - parse from file path
const parser = await XCFParser.parseFileAsync("./image.xcf");

// Browser - parse from ArrayBuffer
const parser = XCFParser.parseBuffer(arrayBuffer);

// Properties
parser.width; // Image width in pixels
parser.height; // Image height in pixels
parser.layers; // Array of GimpLayer objects
parser.baseType; // Color mode: XCF_BaseType.RGB, GRAYSCALE, or INDEXED
parser.isV11; // True if XCF v011 format (GIMP 2.10+ with 64-bit pointers)
parser.colormap; // Color palette for indexed images (array of RGB), or null
parser.precision; // Bit depth: XCF_Precision enum (U8_GAMMA, U16_LINEAR, U32_GAMMA, etc.)
parser.bytesPerChannel; // Bytes per color channel (1, 2, 4, or 8)
parser.isFloatingPoint; // True if floating point precision

// Methods
parser.createImage(image); // Render all visible layers into image
parser.getLayerByName(name); // Find layer by name

GimpLayer

Represents a layer in the XCF file.

layer.name // Layer name
layer.width // Layer width
layer.height // Layer height
layer.x // X offset
layer.y // Y offset
layer.isVisible // Visibility flag
layer.isGroup // True if layer group
layer.opacity // Opacity (0-255)
layer.parasites // Layer parasites (metadata)

// Render single layer
layer.makeImage(image, useOffset?)

XCFPNGImage (Node.js only)

PNG-based image class using pngjs. Import from @theprogrammingiantpanda/xcfreader/node.

import { XCFPNGImage } from "@theprogrammingiantpanda/xcfreader/node";

const image = new XCFPNGImage(width, height);
image.setAt(x, y, { red: 255, green: 0, blue: 0, alpha: 255 });
image.getAt(x, y); // Returns ColorRGBA
image.fillRect(x, y, w, h, color);
image.getPixelData(); // Returns Uint8Array
await image.writeImage("output.png"); // Write to file

XCFDataImage (Browser)

ImageData-based image class for canvas rendering. Import from @theprogrammingiantpanda/xcfreader/browser.

import { XCFDataImage } from "@theprogrammingiantpanda/xcfreader/browser";

const image = new XCFDataImage(width, height);
image.setAt(x, y, { red: 255, green: 0, blue: 0, alpha: 255 });
image.getAt(x, y); // Returns ColorRGBA
image.fillRect(x, y, w, h, color);
image.getPixelData(); // Returns Uint8Array
image.imageData; // Returns ImageData-compatible object

// Export methods (browser only)
const blob = await image.toBlob(); // Returns Promise<Blob>
const blob = await image.toBlob("image/jpeg", 0.9); // JPEG with quality
const dataUrl = image.toDataURL(); // Returns data URL string
const dataUrl = image.toDataURL("image/jpeg", 0.8); // JPEG data URL

IXCFImage Interface

Both image classes implement this interface. Create custom implementations for other rendering targets.

interface IXCFImage {
  readonly width: number;
  readonly height: number;
  setAt(x: number, y: number, colour: ColorRGBA): void;
  getAt(x: number, y: number): ColorRGBA;
  fillRect(x: number, y: number, w: number, h: number, colour: ColorRGBA): void;
  getPixelData(): Uint8Array;
}

Supported Formats

  • GIMP versions: 2.10.x (v011 64-bit), 2.8.x (v010 32-bit), and earlier
  • XCF versions: v010 (32-bit pointers), v011 (64-bit pointers), and v012
  • Color modes: RGB/RGBA, Grayscale, and Indexed (paletted) images
  • Bit depths: 8-bit, 16-bit, 32-bit integer; 16-bit (half), 32-bit, 64-bit float
  • Limitations: Text and path layers have limited support

Development

# Install dependencies
npm install

# Build TypeScript
npm run build

# Build browser bundles
npm run build:browser

# Build all
npm run build:all

# Run tests
npm test

# Run examples
npm run single
npm run multi
npm run map
npm run text
npm run grey # grayscale v011 example
npm run indexed # indexed color example
npm run fullColour # full color RGB v011 example
npm run int32 # 32-bit integer precision example
npm run float32 # 32-bit float precision example
npm run icon # 512x512 icon example
npm run pipe # indexed color pipe example
npm run boardpieces # game asset sprites example
npm run nhl-marlow # large image (2480×3507) example

Troubleshooting

  • "Invalid XCF file ... missing GIMP magic bytes" - Verify the file is a valid GIMP XCF
  • Unsupported layer types - Try flattening or exporting as standard RGB in GIMP
  • Blank/corrupted output - Check layer visibility and opacity in GIMP

See Also

API Documentation

Full API documentation is available in the docs/index.html file generated by TypeDoc. Open this file in your browser to explore all classes, interfaces, enums, and functions.

License

MIT License. See LICENSE for details.