Files
craft-libs/crates/pdn/README.md
Dylan M. Taylor fa26a2a4c6 Add craft-pdn: Paint.NET PDN3 reader and a data-only MS-NRBF reader, from PhotoCraft (#968)
The format half of PhotoCraft's Paint.NET import (crates/io/src/pdn.rs and pdn/nrbf.rs at
abeb16c96): the PDN3 header, the .NET binary serialization graph, the layer list and blend
modes, and the chunked gzip pixel blocks. Surfaces, blend-mode mapping and warnings stay in
the app.
2026-11-11 19:30:55 -05:00

1.7 KiB

craft-pdn

Paint.NET documents (.pdn), read. Only the PDN3 layout (Paint.NET 3 and 4): the PDN3 signature, an XML header (skipped), a .NET binary serialization stream holding a PaintDotNet.Document, then one block of pixels per surface in numbered chunks, each a gzip stream or raw bytes. The layout follows the reader of the pypdn project (MIT); the serialization records follow Microsoft's public MS-NRBF specification.

  • is_pdn: the signature.
  • Document::parse: canvas size, bitmap layers (name, visibility, opacity 0 to 255, Paint.NET's own BlendMode, from the current blendMode field or the older UserBlendOps class names) and which surface each layer shows. Every allocation the pixels need is checked first.
  • Document::read_surfaces: decodes the pixel blocks in file order, one Surface (rows of B, G, R, A bytes, straight alpha) at a time, with a keep_going callback.
  • nrbf: the data-only MS-NRBF reader on its own: a Graph of Values with references kept as ids. No .NET type is instantiated or run.

Paint.NET's Color Burn and Color Dodge are its own formulas; what an application maps them to is its own choice. There is no writer.

Limits

Limit Value
Canvas, and all pixel blocks together 1 GiB (MAX_PIXEL_BYTES)
Layers 1 to 1024 (MAX_LAYERS)
A layer name; all names 64 KiB (MAX_NAME_BYTES); 4 MiB (MAX_TOTAL_NAME_BYTES)
Pixel chunks in one block 1,000,000
NRBF records, items and members 1,000,000 (nrbf::MAX_ITEMS)
NRBF string bytes 64 MiB (nrbf::MAX_STRINGS)
NRBF nesting and reference chains 64 (nrbf::MAX_DEPTH)

A raw pixel block shorter than it declares is refused before its buffer is allocated.