@theprogrammingiantpanda/xcfreader
v1.1.0
Published
Reads in GIMP xcf files
Downloads
521
Maintainers
Readme
xcfreader
Parses files generated by GIMP (.xcf) and exposes a TypeScript/JavaScript API to read metadata, layers and render images.
Highlights
- TypeScript source: Full type safety with strict mode, types for
ColorRGBA,XCFParser,GimpLayer,IXCFImage, and compositing modes via theCompositerModeenum - CompositerMode enum: All compositing/blend modes are now type-safe and referenced via the
CompositerModeenum for improved reliability and maintainability - Native ESM:
package.jsonsetstype: "module"with proper exports - Promise-based API:
XCFParser.parseFileAsync(path)returns aPromise - Browser support: Dedicated browser bundle with
XCFDataImagefor canvas rendering - Node.js support:
XCFPNGImagefor PNG file output usingpngjs - 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/xcfreaderFor Node.js usage with PNG file output, also install pngjs:
npm install @theprogrammingiantpanda/xcfreader pngjsNote:
pngjsis 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=1This 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 nameGimpLayer
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 fileXCFDataImage (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 URLIXCFImage 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) exampleTroubleshooting
- "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
- CHANGELOG.md - Version history
- ../../example-xcf/browser-demo.html - Interactive browser demo
- ../../.github/copilot-instructions.md - Architecture documentation
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.
