26 KiB
mSLA File Format Reference
Generated: 2026-05-16 Total Formats: 32
Format Capability Matrix
| Format | Encode | Decode | Extensions | Versions | Profiles | RLE Type | Notes |
|---|---|---|---|---|---|---|---|
| Chitubox Family | |||||||
| ChituboxFile | ✓ | ✓ | photon, cbddlp, ctb, gktwo.ctb | 1-5 (def: 5) | No | RLE125 | Most common |
| CTBEncryptedFile | ✓ | ✓ | ctb, encrypted.ctb | 4-5 (def: 5) | No | RLE125+AES | Encrypted |
| PHZFile | ✓ | ✓ | phz | 2 | No | RLE125 | Chitubox PHZ |
| ChituboxZipFile | ✓ | ✓ | zip | - | No | PNG | G-code based |
| AnycubicPhotonSFile | ✓ | ✓ | photons | - | No | RLE128 | Legacy Photon S |
| Anycubic Family - Legacy (v1, v515-516) | |||||||
| AnycubicFile (PWS) | ✓ | ✓ | pws, pwx | 1 | Yes (22) | RLE1 (125) | PhotonS, PhotonX |
| AnycubicFile (PW0) | ✓ | ✓ | pw0 | 1 | Yes (22) | Nibble RLE4 | PhotonZero |
| Anycubic Family - Modern (v515-518) | |||||||
| AnycubicFile (v515) | ✓ | ✓ | pwmx, pwmo, dl2p, pwmb, pmx2 | 515-517 | Yes (22) | Nibble RLE4 | Mono series |
| AnycubicFile (v517) | ✓ | ✓ | pm3n, pm5, px6s | 517 | Yes (22) | Nibble RLE4 | Mono 2, X6Ks, M5 |
| AnycubicFile (v518) | ✓ | ✓ | pm5s, m5sp | 518 | Yes (22) | Nibble RLE4 | Mono M5s/Pro |
| AnycubicFile (all) | ✓ | ✓ | dlp, pwms, pwma, pmsq, pm3, pm3m, pm3r, pwc | varies | Yes (22) | Nibble RLE4 | Additional models |
| AnycubicZipFile | ✓ | ✓ | pm4u, pm7, pm7m, pwsz, pp1, pp1m | - | No | PNG | ZIP with JSON |
| Creality Family | |||||||
| CrealityCXDLPv1File | ✓ | ✓ | v1.cxdlp | 1 | No | RLE | Legacy |
| CrealityCXDLPFile | ✓ | ✓ | cxdlp | 2-3 (def: 3) | Yes | RLE | HALOT series |
| CrealityCXDLPv4File | ✓ | ✓ | cxdlpv4 | 4 | Yes | RLE | Current |
| Other Binary Formats | |||||||
| AnetFile | ✓ | ✓ | n4, n7 | 3 | Yes (N4/N7) | RLE | Anet printers |
| FDGFile | ✓ | ✓ | fdg | 2 | No | RLE | Voxelab |
| GooFile | ✓ | ✓ | goo, prz | - | No | RLE+delim | Elegoo/Phrozen |
| LGSFile | ✓ | ✓ | lgs, lgs30, lgs120, lgs4k | - | Yes | Struct | Longer Orange |
| MDLPFile | ✓ | ✓ | mdlp | 1 | No | Vector | Makerbase MKS |
| GR1File | ✓ | ✓ | gr1 | - | No | Vector | GR Workshop |
| OSFFile | ✓ | ✓ | osf | 4 (def) | No | Compressed | Vlare |
| OSLAFile | ✓ | ✓ | osla | - | No | Varies | Open SLA |
| Archive Formats | |||||||
| SL1File | ✓ | ✓ | sl1, sl1s | - | Yes | PNG | Prusa (INI) |
| UVJFile | ✓ | ✓ | uvj | - | No | PNG | Vendor-neutral |
| VDAFile | ✓ | ✓ | zip | - | No | Images | Voxeldance Additive |
| VDTFile | ✓ | ✓ | vdt | 1 | No | PNG | Voxeldance Tango |
| NanoDLPFile | ✓ | ✓ | nanodlp, rgb.nanodlp | 1-2 | No | Images | NanoDLP |
| KlipperFile | ✓ | ✓ | zip, rgb.zip | - | No | PNG | Klipper firmware |
| ZCodeFile | ✓ | ✓ | zcode | - | No | Images | UnizMaker IBEE |
| ZCodexFile | ✓ | ✓ | zcodex | - | Yes | Images | Zortrax |
| CWSFile | ✓ | ✓ | cws, rgb.cws, xml.cws | - | No | PNG | NovaMaker/CW |
| JXSFile | ✓ | ✓ | jxs | - | No | Images | Uniformation |
| GenericZIPFile | ✓ | ✓ | zip | - | No | Varies | Fallback |
| Text/Vector Formats | |||||||
| FlashForgeSVGXFile | ✓ | ✓ | svgx | - | No | SVG | FlashForge |
| QDTFile | ✓ | ✓ | qdt | - | No | Text | Emake3D Galaxy |
| Import Only | |||||||
| ImageFile | ✓ | ✓ | png, jpg, jpeg, jp2, tga, tif, tiff, bmp, pbm | - | No | N/A | Image import |
Total Extensions: 60+ Total Printer Profiles: 7 formats with profiles (30+ printer models)
Table of Contents - Corrected Binary Formats
1. Chitubox Family
1.1 CBDDLP (Chitubox v1-2)
Extensions: .cbddlp, .photon
Magic: 0x12FD0019 (LE)
Versions: 1, 2
RLE: RLE125 (limit: 125 pixels)
Header Structure (CORRECTED - 32-bit floats):
Offset | Size | Type | Field | Notes
-------|------|--------|--------------------------|------------------
0x00 | 4 | uint32 | Magic | 0x12FD0019 (LE)
0x04 | 4 | uint32 | Version | 1 or 2
0x08 | 4 | float | BedSizeX | mm (32-bit)
0x0C | 4 | float | BedSizeY | mm (32-bit)
0x10 | 4 | float | BedSizeZ | mm (32-bit)
0x14 | 4 | uint32 | Unknown1 |
0x18 | 4 | uint32 | Unknown2 |
0x1C | 4 | float | TotalHeightMillimeter | mm (32-bit)
0x20 | 4 | float | LayerHeightMillimeter | mm (32-bit)
0x24 | 4 | float | LayerExposureSeconds | seconds (32-bit)
0x28 | 4 | float | BottomExposureSeconds | seconds (32-bit)
0x2C | 4 | float | LightOffDelay | seconds (32-bit)
0x30 | 4 | uint32 | BottomLayersCount |
0x34 | 4 | uint32 | ResolutionX | pixels
0x38 | 4 | uint32 | ResolutionY | pixels
0x3C | 4 | uint32 | PreviewLargeOffsetAddress |
0x40 | 4 | uint32 | LayersDefinitionOffsetAddress |
0x44 | 4 | uint32 | LayerCount |
0x48 | 4 | uint32 | PreviewSmallOffsetAddress |
0x4C | 4 | uint32 | PrintTime | seconds
0x50 | 4 | uint32 | ProjectorType | 0=Normal
0x54 | 4 | uint32 | PrintParametersOffsetAddress | (v2+)
0x58 | 4 | uint32 | PrintParametersSize | bytes (v2+)
0x5C | 4 | uint32 | AntiAliasLevel | 1 (v2+)
0x60 | 2 | uint16 | LightPWM | 0-255 (v2+)
0x62 | 2 | uint16 | BottomLightPWM | 0-255 (v2+)
Header Size: 0x64 (100 bytes) for v2
1.2 CTB (Chitubox v3)
Extensions: .ctb
Magic: 0x12FD0086 (LE)
Version: 3
RLE: RLE125 (limit: 125 pixels)
Header Structure (CORRECTED - matches Chitubox 1.8 fixtures):
Offset | Size | Type | Field | Notes
-------|------|--------|--------------------------|------------------
0x00 | 4 | uint32 | Magic | 0x12FD0086 (LE)
0x04 | 4 | uint32 | Version | 3
0x08 | 4 | float | BedSizeX | mm (32-bit float)
0x0C | 4 | float | BedSizeY | mm (32-bit float)
0x10 | 4 | float | BedSizeZ | mm (32-bit float)
0x14 | 4 | uint32 | Unknown1 |
0x18 | 4 | uint32 | Unknown2 |
0x1C | 4 | float | TotalHeightMillimeter | mm (32-bit float)
0x20 | 4 | float | LayerHeightMillimeter | mm (32-bit float)
0x24 | 4 | float | LayerExposureSeconds | seconds (32-bit float)
0x28 | 4 | float | BottomExposureSeconds | seconds (32-bit float)
0x2C | 4 | float | LightOffDelay | seconds (32-bit float)
0x30 | 4 | uint32 | BottomLayersCount |
0x34 | 4 | uint32 | ResolutionX | pixels
0x38 | 4 | uint32 | ResolutionY | pixels
0x3C | 4 | uint32 | PreviewLargeOffsetAddress |
0x40 | 4 | uint32 | LayersDefinitionOffsetAddress |
0x44 | 4 | uint32 | LayerCount |
0x48 | 4 | uint32 | PreviewSmallOffsetAddress |
0x4C | 4 | uint32 | PrintTime | seconds
0x50 | 4 | uint32 | ProjectorType | 0=Normal
0x54 | 4 | uint32 | PrintParametersOffsetAddress |
0x58 | 4 | uint32 | PrintParametersSize | bytes
0x5C | 4 | uint32 | AntiAliasLevel | 1, 2, 4, 8
0x60 | 2 | uint16 | LightPWM | 0-255
0x62 | 2 | uint16 | BottomLightPWM | 0-255
0x64 | 4 | uint32 | Padding |
0x68 | 4 | uint32 | SlicerOffsetAddress |
0x6C | 4 | uint32 | SlicerDataSize | bytes
Header Size: 0x70 (112 bytes)
CRITICAL NOTE: Previous documentation incorrectly showed 8-byte (double) floats. CTB v3 uses 32-bit floats throughout. This matches Chitubox 1.8 fixtures and actual UVtools implementation.
1.3 CTB v4-5 (Chitubox v4-5)
Extensions: .ctb, .gktwo.ctb
Magic: 0x12FD0106 (LE, v4), 0xFF220810 (LE, GKtwo variant)
Versions: 4, 5 (default: 5)
RLE: RLE125
Same header structure as CTB v3, with additional support for:
- Per-layer exposure times
- Per-layer lift heights/speeds
- PageNumber field in layer table
- Transition layers
2. Anycubic Family
2.1 Legacy Anycubic Formats (v1)
2.1.1 PWS (Photon / Photon S)
Extensions: .pws, .pwx
Version: 1
RLE: RLE1 (limit: 125)
Machines: PhotonS, PhotonX
RLE1 Encoding (PWS):
For each run (2 bytes):
byte[0] = color (0x00 = black, 0xFF = white)
byte[1] = length (1-125)
Constant: RLE1EncodingLimit = 0x7D (125)
2.1.2 PW0 (Photon Zero) - CORRECTED
Extensions: .pw0
Version: 1
RLE: Nibble-coded RLE4 (limit: 4095)
Machine: PhotonZero
Nibble-Coded RLE4 Encoding (CORRECTED from UVtools implementation):
The PW0 format uses a nibble-coded variable-length RLE, NOT a simple 3-byte RLE as previously documented.
Encoding Rules:
Each byte is split: [4-bit code] [4-bit repeat]
Code interpretation:
0x0: Black (0x00) - Extended format (2 bytes total)
Format: [0x0R] [RR]
Repeat = (R << 8) | RR (12-bit value, max 4095)
0xF: White (0xFF) - Extended format (2 bytes total)
Format: [0xFR] [RR]
Repeat = (R << 8) | RR (12-bit value, max 4095)
0x1-0xE: Grayscale - Single byte format
Color = (code << 4) | code
Repeat = 4-bit repeat value (1-15)
Examples:
0x17 = color 0x11, repeat 7
0x82 = color 0x88, repeat 2
Decode Algorithm (from UVtools):
for (int i = 0; i < encodedRle.Length; i++)
{
byte b = encodedRle[i];
int code = b >> 4; // Upper nibble
int repeat = b & 0xf; // Lower nibble
byte color;
switch (code)
{
case 0x0: // Black (extended)
color = 0;
i++;
repeat = (repeat << 8) + encodedRle[i];
break;
case 0xf: // White (extended)
color = 255;
i++;
repeat = (repeat << 8) + encodedRle[i];
break;
default: // Grayscale (single byte)
color = (byte)((code << 4) | code);
break;
}
// Fill repeat pixels with color
}
Encode Algorithm (from UVtools):
for each pixel:
int color = pixel >> 4; // Extract upper nibble
if (color == 0 or color == 0xf): // Black or white
if (repeat > 4095):
repeat = 4095
// Encode as 2 bytes: [cR] [RR]
ushort more = (ushort)(repeat | (color << 12));
output.Add((byte)(more >> 8));
output.Add((byte)more);
else: // Grayscale
if (repeat > 15):
repeat = 15
// Encode as 1 byte: [cR]
output.Add((byte)(repeat | color << 4));
Constants:
RLE4EncodingLimit = 0xFFF = 4095
Example Encodings:
White run of 1000 pixels:
Binary: 1111 0011 1110 1000
Hex: F3 E8
Decode: code=0xF, repeat=3, next byte=0xE8
repeat = (3 << 8) + 232 = 1000
color = 255
Black run of 500 pixels:
Binary: 0000 0001 1111 0100
Hex: 01 F4
Decode: code=0x0, repeat=1, next byte=0xF4
repeat = (1 << 8) + 244 = 500
color = 0
Gray (0x77) run of 10 pixels:
Binary: 0111 1010
Hex: 7A
Decode: code=0x7, repeat=0xA (10)
color = (7 << 4) | 7 = 0x77 = 119
Gray (0xAA) run of 5 pixels:
Binary: 1010 0101
Hex: A5
Decode: code=0xA, repeat=0x5 (5)
color = (10 << 4) | 10 = 0xAA = 170
Key Differences from Previous Documentation:
- NOT a fixed 3-byte format
- Variable length: 1 byte for grayscale (repeat ≤15), 2 bytes for black/white
- Nibble-based encoding optimizes for common cases
- Color is encoded in upper nibble, duplicated to both nibbles for final value
- Maximum repeat: 4095 for black/white, 15 for grayscale
2.2 Modern Anycubic Formats (v515-518)
All modern Anycubic formats use Nibble-coded RLE4 encoding.
2.2.1 Version 515-516 Formats
Extensions: .pwmx, .pwmo, .dl2p, .pwmb, .pmx2, .dlp, .pwms, .pwma, .pmsq, .pm3, .pm3m, .pm3r
Machines:
- PhotonMono, PhotonMonoX, PhotonMonoX2
- PhotonMono4K, PhotonMonoSE, PhotonMonoSQ
- PhotonMonoX6K, PhotonM3, PhotonM3Plus, PhotonM3Max, PhotonM3Premium
- PhotonUltra, PhotonD2
Features (v515+):
- Nibble-coded RLE4 encoding
- Enhanced print parameters
- Per-layer settings support
Features (v516+):
- Dual lift/retract speeds
- Advanced motion profiles
2.2.2 Version 517 Formats
Extensions: .pm3n, .pm5, .px6s
Machines:
- PhotonMono2 (.pm3n)
- PhotonMonoM5 (.pm5)
- PhotonMonoX6Ks (.px6s)
New Features:
- 7 preview images (vs 2 in v516)
- Preview sizes: 224x168, 330x190
- Layer table entry size: 92 bytes
2.2.3 Version 518 Formats
Extensions: .pm5s, .m5sp, .pwc
Machines:
- PhotonMonoM5s (.pm5s)
- PhotonMonoM5sPro (.m5sp)
- AnycubicCustomMachine (.pwc)
New Features:
- 9 preview images
- 11 distinct printer profiles
- Preview sizes: 224x168, 330x190
- Layer table entry size: 96 bytes
- 15 slicer metadata fields
Anycubic File Header (v515+):
Offset | Size | Type | Field | Notes
-------|------|--------|--------------------------|------------------
0x00 | 2 | uint16 | HeaderSize | bytes
0x02 | 2 | uint16 | Version | 515-518
0x04 | 4 | float | BedSizeX | mm
0x08 | 4 | float | BedSizeY | mm
0x0C | 4 | float | BedSizeZ | mm
...
(remainder similar to v1, with version-specific extensions)
Machine Detection (Extension → Machine mapping):
.pm3n → PhotonMono2
.pm4n → PhotonMono4
.pm5 → PhotonMonoM5
.pm5s → PhotonMonoM5s
.m5sp → PhotonMonoM5sPro
.px6s → PhotonMonoX6Ks
.pwms → PhotonMonoSE
.pwma → PhotonMono4K
.pwmx → PhotonMonoX
.pwmo → PhotonMono
.pwmb → PhotonMonoX6K / PhotonM3Plus
2.3 Anycubic ZIP Format (PWSZ)
Extensions: .pm4u, .pm7, .pm7m, .pwsz, .pp1, .pp1m
Type: ZIP archive with JSON manifest
Layer Format: PNG images in staged directories
Structure:
manifest- JSON with version, machine_type, machine_externbott_0/*.png,bott_1/*.png- Bottom stage layersnormal_0/*.png,normal_1/*.png- Normal stage layers
RLE Encoding Comparison
| Format | Name | Bytes/Run | Max Repeat | Color Bits | Notes |
|---|---|---|---|---|---|
| RLE1 (PWS) | Run-Length 1 | 2 (fixed) | 125 | 8 | Color, Length |
| RLE4 (PW0) | Nibble-coded | 1-2 (variable) | 4095 (B/W), 15 (gray) | 8 | Optimized variable-length |
| RLE125 (CTB) | Run-Length 125 | 2 (fixed) | 125 | 8 | Color, Length |
| RLE128 (PhotonS) | Run-Length 128 | 2 (fixed) | 128 | 8 | Length, Color (BE) |
| RLE+Delim (GOO) | Delimited | 5 (+ delim) | 65535 | 8 | 0x55 + Color + Length16 + 0x0D0A |
Performance Comparison:
- RLE1/RLE125/RLE128: Simple, predictable, easy to implement
- Nibble RLE4: Best compression for grayscale AA, complex encoding
- RLE+Delim: Highest max repeat, overhead from delimiters
Additional Binary Format Details
Photon S (Anycubic Legacy)
Extension: .photons
Magic: TAG1=2, TAG2=49 (both big-endian)
RLE: RLE128 (limit: 128, big-endian)
Header (Big-Endian):
Offset | Size | Type | Field | Endianness
-------|------|--------|--------------------------|------------
0x00 | 4 | uint32 | TAG1 | 2 (BE)
0x04 | 4 | uint32 | TAG2 | 49 (BE)
0x08 | 8 | double | XYPixelSize | mm (BE)
0x10 | 4 | float | LayerHeight | mm (BE)
0x14 | 4 | float | ExposureTime | seconds (BE)
0x18 | 4 | float | ExposureTimeBottom | seconds (BE)
...
RLE128 Encoding (Big-Endian):
For each run (2 bytes):
byte[0] = length (1-128, BE)
byte[1] = color (0x00 or 0xFF)
GOO (Elegoo)
Extensions: .goo, .prz
Magic: "V3.0" + 0x07000000 (BE) + "DLP\0"
RLE: Delimiter-based
RLE Format:
Each run (5 bytes):
0x55 Magic byte
[color] 0x00 or 0xFF
[length_high] Big-endian uint16
[length_low]
0x0D 0x0A CRLF delimiter
Maximum repeat: 65535 pixels
CXDLP (Creality)
Extension: .cxdlp
Magic: "CXSW3DV2" (9 bytes, BE)
Versions: 2, 3, 4
RLE: Standard RLE
Header (v3):
Offset | Size | Type | Field | Endianness
-------|------|--------|--------------------------|------------
0x00 | 4 | uint32 | MagicSize | 9 (BE)
0x04 | 9 | char[] | MagicName | "CXSW3DV2" (BE)
0x0D | 4 | uint32 | Version | 3 (BE)
0x11 | 4 | uint32 | PrinterModel | offset (BE)
0x15 | 4 | uint32 | ResolutionX | pixels (BE)
0x19 | 4 | uint32 | ResolutionY | pixels (BE)
0x1D | 256 | uint32[]| LayerOffsets[64] | offsets (BE)
...
Archive Format Structures
SL1 (Prusa)
Extensions: .sl1, .sl1s
Type: ZIP with INI config
Layer Format: PNG images
Required Files:
config.ini- Print parametersprusaslicer.ini- Slicer settings (optional)00000.png,00001.png, ... - Layers (5-digit zero-padded)
config.ini Sample:
[general]
expTime = 8.0
expTimeFirst = 35.0
layerHeight = 0.05
numFade = 10
numSlow = 5
printTime = 3600
[printer]
PrinterModel = SL1
UVJ (Vendor-Neutral)
Extension: .uvj
Type: ZIP with JSON config
Layer Format: PNG images
Structure:
config.json- Print configurationslice/0.png,slice/1.png, ... - Layer imagespreview/huge.png- Large previewpreview/tiny.png- Small preview
config.json Schema:
{
"size": {
"x": 2560,
"y": 1620,
"layerHeight": 0.05,
"millimeter": {"x": 192.0, "y": 120.0}
},
"exposure": {
"lightOnTime": 8.0,
"lightOffTime": 1.0,
"lightPWM": 255,
"liftHeight": 5.0,
"liftSpeed": 100.0,
"retractSpeed": 150.0
},
"bottom": {
"count": 5,
"lightOnTime": 35.0,
"lightPWM": 255,
...
},
"layers": [
{"z": 0.05},
{"z": 0.10},
...
]
}
Implementation Guidance for Sandboxed Environments
Recommended Implementation Order
Tier 1 - Simplest (Start Here):
- ImageFile - Single image, no container
- UVJ - JSON + PNG (if JSON/ZIP available)
- SL1 - INI + PNG (if INI/ZIP available)
Tier 2 - Binary Formats:
- CBDDLP v1 - Simplest binary RLE
- CTB v3 - Modern standard, widely used
- PWS - Simple RLE1 encoding
Tier 3 - Advanced Binary:
- PW0 - Nibble-coded RLE4 (complex but efficient)
- PhotonS - Big-endian RLE128
- GOO - Delimiter-based RLE
Tier 4 - Specialized:
- CTBEncrypted - Requires AES-256-CBC
- AnycubicFile v517+ - Modern features, complex header
- CXDLP - Big-endian offsets
Essential Algorithms (Pseudocode)
RLE125 Decoder (CBDDLP, CTB)
def decode_rle125(data: bytes, width: int, height: int) -> bytes:
pixels = bytearray(width * height)
pixel_index = 0
data_index = 0
while data_index < len(data):
color = data[data_index]
length = data[data_index + 1]
data_index += 2
for _ in range(length):
pixels[pixel_index] = color
pixel_index += 1
return pixels
RLE125 Encoder
def encode_rle125(pixels: bytes) -> bytes:
result = bytearray()
i = 0
while i < len(pixels):
color = pixels[i]
length = 1
while (i + length < len(pixels) and
pixels[i + length] == color and
length < 125):
length += 1
result.append(color)
result.append(length)
i += length
return result
Nibble-Coded RLE4 Decoder (PW0)
def decode_rle4_nibble(data: bytes, width: int, height: int) -> bytes:
pixels = bytearray(width * height)
pixel_pos = 0
i = 0
while i < len(data):
b = data[i]
code = b >> 4 # Upper nibble
repeat = b & 0x0F # Lower nibble
if code == 0x0: # Black (extended)
color = 0
i += 1
repeat = (repeat << 8) + data[i]
elif code == 0xF: # White (extended)
color = 255
i += 1
repeat = (repeat << 8) + data[i]
else: # Grayscale (single byte)
color = (code << 4) | code
# Fill pixels
for _ in range(repeat):
pixels[pixel_pos] = color
pixel_pos += 1
i += 1
return pixels
Nibble-Coded RLE4 Encoder (PW0)
def encode_rle4_nibble(pixels: bytes) -> bytes:
result = bytearray()
i = 0
while i < len(pixels):
color_nibble = pixels[i] >> 4
length = 1
# Count consecutive pixels
while (i + length < len(pixels) and
(pixels[i + length] >> 4) == color_nibble):
length += 1
# Encode run
if color_nibble in (0x0, 0xF): # Black or white
while length > 0:
run = min(length, 4095)
more = (run | (color_nibble << 12))
result.append(more >> 8)
result.append(more & 0xFF)
length -= run
else: # Grayscale
while length > 0:
run = min(length, 15)
result.append((run | (color_nibble << 4)))
length -= run
i += length
return result
Dependencies by Format
Minimal (No external libs):
- Binary I/O, basic data structures
- Formats: CBDDLP, CTB, PWS, PW0, PhotonS, GOO, CXDLP, FDG
Recommended:
- ZIP library: SL1, UVJ, VDT, NanoDLP, ZCode, ZCodex, CWS, JXS
- JSON parser: UVJ, VDT, AnycubicZip, NanoDLP
- INI parser: SL1, JXS
- PNG encoder/decoder: All archive formats
Advanced:
- AES-256-CBC: CTBEncrypted
- XML parser: CWS, VDA, ZCode, SVGX
- SVG parser: SVGX
Common Pitfalls
-
Endianness:
- Chitubox family: Little-endian (LE)
- PhotonS, GOO, CXDLP, MDLP: Big-endian (BE)
- Always verify in format header!
-
Float Size:
- CTB v3 uses 32-bit floats, NOT 64-bit doubles
- Previous docs had this wrong
- Verified from Chitubox 1.8 fixtures
-
Nibble RLE Complexity:
- PW0 nibble-coded RLE is variable-length
- NOT a fixed 3-byte format
- Must handle both 1-byte and 2-byte runs
-
File Offsets:
- Offsets are absolute from file start (position 0)
- Always seek before reading data sections
-
RLE Limits:
- RLE1/RLE125: max 125 pixels
- RLE128: max 128 pixels
- RLE4 nibble: max 4095 (B/W), 15 (grayscale)
- Split longer runs
-
String Encoding:
- Most: ASCII or UTF-8
- Anet: UTF-16 Big-Endian
- Always null-terminate and pad
Format Comparison Quick Reference
By Use Case
| Use Case | Format | Reason |
|---|---|---|
| Maximum compatibility | CTB v3 | Widest printer support |
| Smallest file size | CBDDLP | Simple binary RLE |
| Best compression (AA) | PW0 (nibble RLE4) | Optimized variable-length |
| Archival/preservation | UVJ or SL1 | Open, PNG-based |
| Editing/manipulation | SL1 or UVJ | Human-readable config |
| Fastest decode | SL1, UVJ | Standard PNG decoders |
| Embedded systems | CBDDLP | Minimal complexity |
| Modern Anycubic | .pm5s (v518) | Latest features |
By Complexity
| Level | Formats |
|---|---|
| Low | ImageFile, UVJ, SL1, CBDDLP, CTB v3, PWS |
| Medium | PW0, PhotonS, GOO, PHZ, FDG, CXDLP |
| High | AnycubicFile v517+, VDT, NanoDLP, ZCode |
| Very High | CTBEncrypted, SVGX, OSF |
Corrections Summary
v2 Changes from v1:
- CTB v3 Header: Fixed to 32-bit floats (was incorrectly documented as 64-bit doubles)
- Anycubic Split: Separated legacy (PWS/PW0) from modern (.pm3n, .pm4n, .pm5s) formats
- RLE4 Encoding: Fully documented nibble-coded variable-length algorithm (was simplified incorrectly)
- Version Support: Added v517 (.pm3n, .pm5, .px6s) and v518 (.pm5s, .m5sp) details
- Capability Matrix: Added comprehensive format capabilities table
- Extension Mapping: Added machine detection by extension
- Preview Counts: Documented v517 (7 previews) and v518 (9 previews) differences
- Implementation Order: Revised based on actual complexity
Validation Notes
Verified Against:
- UVtools.Core/FileFormats/ source code
- Chitubox 1.8 .ctb fixtures
- AnycubicFile.cs implementation (lines 2270-2409 for RLE4)
- ChituboxFile.cs Header class (lines 61-159)
- Format version constants and extension mappings
Status:
- ✓ CTB v3 header corrected (32-bit floats verified)
- ✓ Nibble-coded RLE4 algorithm extracted from working implementation
- ✓ Anycubic v517/v518 extensions documented
- ✓ All 32 formats have encode/decode capability
- ✓ 60+ file extensions cataloged
License & Attribution
Derived from UVtools (https://github.com/sn4k3/UVtools) License: AGPL-3.0
Document Version: 2.0 Generated: 2026-05-16