Pixilart project guide
How the Pixilart 2.7 project importer works
Learn how this project reads the observed genuine Pixilart 2.7 project structure, reconstructs layers across frames, and rejects uncertain data.
This importer is based on engineering work performed against an observed genuine Pixilart 2.7.0 saved-project structure. It is not a claim that every Pixilart version, feature, or historical file is compatible. The committed fixtures reproduce only the verified container shape with freshly generated 2×2 test pixels; no user's file or embedded artwork is part of the repository.
Why the importer had to change
An earlier implementation used a repository-defined synthetic object shaped like { pixil: { schemaVersion: 1, ... } }. Compatibility testing with a genuine 2.7 save showed that this model was not the application's actual file contract. It failed on the real top-level application field before reaching pixels.
Task 103 replaced that fixture-only assumption with a conservative parser for the observed structure. The old synthetic schema is now intentionally rejected with a migration diagnostic instead of being mistaken for a real Pixilart project.
The accepted 2.7 container
{
"application": "pixil",
"type": ".pixil",
"version": "2.7.0",
"website": "pixilart.com",
"width": "2",
"height": "2",
"frames": [
{ "width": "2", "height": "2", "speed": 120, "layers": [...] }
]
}
Canvas dimensions may be safe integers or canonical non-negative integer strings. Each frame must repeat those dimensions, provide a positive integer speed in milliseconds, and contain a non-empty layer array. The implementation accepts version 2.7.0 only.
Per-frame layers and embedded PNGs
Each observed layer record has a non-empty name, opacity from 0 through 1, options.blend: "source-over", stable identity, and an embedded PNG payload in src. The parser finds the base64, marker, strictly decodes what follows, verifies the PNG signature, then uses browser image decoding to obtain full-canvas RGBA pixels.
The layer payload for every frame is a complete canvas-sized PNG, not a raw RGBA array and not a remote URL. Decoded dimensions must match the project canvas exactly.
Reconstructing logical layers across frames
Pixilart repeats layers inside every frame. Aseprite and SpriteProject instead describe a logical layer once and attach cels to it over time. The importer joins repeated records using a non-empty unqid when available. If it is absent, a validated non-negative numeric id is the only fallback.
Names, opacity, identity, and order must remain consistent across frames. A missing, duplicated, reordered, or conflicting logical layer is rejected rather than merged by position. Each resulting cel is placed at (0, 0).
What the conversion preserves
- Canvas width and height within the documented limits.
- Frame-array order.
- Each frame's positive millisecond
speed, normalized to 1–65,535 ms. - Supported layer names, order, opacity, and full-canvas RGBA pixels.
- Normal source-over behavior, represented by normal Aseprite layers.
Opacity is converted to the 0–255 integer range. Layer IDs in the output are deterministic converter IDs; the source identity is used to reconstruct layers, not advertised as preserved editor metadata.
What remains uncertain or unsupported
The optional active boolean is type-checked but not mapped to visibility because its editor-state meaning was not established. Imported layers remain visible. Palettes, previews, selection state, locks, filters, frame names, contact fields, effects, groups, external data, non-PNG payloads, and non-normal blend modes are not preserved.
A different Pixilart version or a valid 2.7 file using unobserved metadata may be rejected. Strict rejection is a compatibility safeguard, not evidence that the source is corrupt.
Validation and privacy boundaries
The parser limits dimensions to 1–1024, frames to 512, layers per frame to 64, cels to 4,096, and both embedded PNG bytes and decoded cel allocation to documented totals. Malformed base64, non-PNG data, mismatched dimensions, ambiguous identity, and unsupported blends produce content-safe diagnostics without echoing source JSON or embedded pixels.
How to verify a conversion
- Keep the genuine file outside the repository and choose Pixil/Pixilart project in the converter.
- Compare canvas size and frame timing with the source project.
- Check layer count, order, names, opacity, and representative pixels on at least two frames.
- Confirm layers expected to be visible remain visible; do not interpret Pixilart's
activestate as visibility. - Keep the original file because the output intentionally omits uncertain editor metadata.
For the underlying layer/cel relationship, read Frames, layers, and cels explained. If the file is rejected, use project-file troubleshooting and report only a newly created minimal reproduction that is safe to disclose.