Python SDK for reading and writing PixTXT documents
Project description
PixTXT Python SDK
Python SDK for parsing, validating, optimizing, and exporting PixTXT documents.
What is PixTXT?
PixTXT is a text format for pixel art designed for human readability, low token cost, and reliable LLM generation.
- Readable:
rowsencoding is easy to inspect and edit by eye. - Token-efficient:
rleencoding compresses repeated runs. - Structured: supports
@meta,@palette,@image,@anim, and@sheet. - Engineering-friendly: works well with git diff, CI validation, and automation.
Minimal example:
PixTXT 1
@palette global
A:#111111
B:#22AAFF
@image dot 2x2 rows
AB
B.
Documentation
- PixTXT text format (English):
docs/pixtxt-format.md - PixTXT text format (中文):
docs/pixtxt-format.zh-CN.md - PyPI release guide:
docs/pypi-release-guide.md
Install
python -m pip install -e .
For local development and tests:
python -m pip install -e .[dev]
Quickstart
from pixtxt import loads, validate
doc = loads("""PixTXT 1
@palette global
A:#111111
@image dot 1x1 rows
A
""")
issues = validate(doc)
print(f"images={len(doc.images)} issues={len(issues)}")
Typical Workflow
- Parse/load PixTXT.
- Validate for issues.
- Optimize (
rows/rle) if needed. - Dump
.pxtoutput. - Export PNG/GIF assets.
Print PixTXT in Code
Use dumps(doc) when you want PixTXT text in memory (for logging, prompting an LLM, or sending over an API).
from pixtxt import dumps, from_image
doc = from_image("assets/source.png")
text = dumps(doc)
print(text)
Use dump(doc, path) when you want to save a .pxt file.
from pixtxt import dump, from_image
doc = from_image("assets/source.png")
dump(doc, "out/source.pxt")
Print optimized PixTXT:
from pixtxt import dumps, from_image, optimize
doc = from_image("assets/source.png")
optimized = optimize(doc, mode="token")
print(dumps(optimized))
SDK Guide
Core Data Model
Main objects in pixtxt.models:
PixTXTDocumentmeta: dict[str, str]palettes: list[PaletteDef]images: list[ImageDef]anims: list[AnimDef]sheets: list[SheetDef]extensions: list[tuple[str, list[str]]]
PaletteDef(name, colors)ImageDef(image_id, width, height, encoding, payload, pixels, palette_name)AnimDef(anim_id, fps, loop, frames)SheetDef(sheet_id, cell_width, cell_height, grid_width, grid_height, items)SheetItem(image_id, x, y)
ImageDef.pixels is the canonical internal matrix representation.
Parse and Validate
from pixtxt import loads, validate
text = """PixTXT 1
@palette global
A:#000000
@image dot 1x1 rows
A
"""
doc = loads(text, strict=False)
issues = validate(doc, strict=False)
if issues:
for issue in issues:
print(issue.code, issue.location, issue.message)
Strict mode behavior:
loads(..., strict=True): rejects unknown sections and unknown@metakeys.validate(..., strict=True): reports strict-only semantic issues.
Read and Write Files
from pixtxt import load, dump
doc = load("assets/hero.pxt", strict=False)
dump(doc, "out/hero_copy.pxt", encoding_preference="auto")
encoding_preference:
"auto": preserve image encoding preference per image."rows": force rows output."rle": force rle output.
Optimize for Token Cost
from pixtxt import load, optimize, dump
doc = load("assets/anim.pxt")
optimized = optimize(doc, mode="token")
dump(optimized, "out/anim_optimized.pxt")
Optimizer guarantees matrix-equivalent output.
Render and Export Assets
Single image to PNG:
from pixtxt import load, to_png
doc = load("assets/hero.pxt")
to_png(doc, "hero_idle", "out/hero_idle.png")
Sheet to PNG:
from pixtxt import load, sheet_to_png
doc = load("assets/hero.pxt")
sheet_to_png(doc, "atlas", "out/atlas.png")
Animation to GIF:
from pixtxt import load, anim_to_gif
doc = load("assets/hero.pxt")
anim_to_gif(doc, "walk", "out/walk.gif")
Import Existing Images
Single static image:
from pixtxt import from_image, dump
doc = from_image("assets/source.png", palette_mode="global")
dump(doc, "out/source.pxt")
Animated GIF/APNG (import all frames and auto-create @anim):
from pixtxt import from_image, dump
doc = from_image(
"assets/blink.gif",
frame_mode="all",
anim_id="blink",
frame_fps=12, # fallback when source timing is unavailable
frame_loop=1,
use_source_timing=True,
)
dump(doc, "out/blink_anim.pxt")
Sprite sheet slicing (grid -> images + @sheet):
from pixtxt import from_image, dump
doc = from_image(
"assets/atlas.png",
cell=(16, 16),
grid=(8, 4),
sheet_id="actors",
naming="rowcol", # or "index"
)
dump(doc, "out/atlas_sheet.pxt")
Create @anim in code (common after sheet slicing):
from pixtxt import AnimDef, anim_to_gif, dump, from_image
doc = from_image(
"assets/run-Sheet.png",
cell=(34, 50),
grid=(8, 1),
sheet_id="actors",
naming="rowcol", # run-Sheet_r0_c0 ... run-Sheet_r0_c7
)
doc.anims.append(
AnimDef(
anim_id="walk",
fps=12,
loop=1,
frames=[
"run-Sheet_r0_c0",
"run-Sheet_r0_c1",
"run-Sheet_r0_c2",
"run-Sheet_r0_c3",
"run-Sheet_r0_c4",
"run-Sheet_r0_c5",
"run-Sheet_r0_c6",
"run-Sheet_r0_c7",
],
)
)
dump(doc, "out/run_sheet_with_anim.pxt")
anim_to_gif(doc, "walk", "out/walk.gif")
Errors
The SDK exposes typed errors:
PixTXTParseError: text parsing errors.PixTXTSemanticError: semantic consistency errors.PixTXTValidationError: validation aggregation category.
For reporting-style checks, prefer validate(doc) which returns list[Issue].
End-to-End Recipes
A) Static image -> PixTXT -> PNG
from pixtxt import from_image, dump, load, to_png
doc = from_image("assets/hero.png")
dump(doc, "out/hero.pxt")
doc2 = load("out/hero.pxt")
to_png(doc2, doc2.images[0].image_id, "out/hero_roundtrip.png")
B) Animated GIF -> PixTXT anim -> GIF
from pixtxt import from_image, dump, anim_to_gif
doc = from_image(
"assets/run.gif",
frame_mode="all",
anim_id="run",
use_source_timing=True,
frame_fps=12,
frame_loop=1,
)
dump(doc, "out/run_anim.pxt")
anim_to_gif(doc, "run", "out/run_rebuilt.gif")
C) Sprite sheet -> Images + Sheet -> Manual Anim -> GIF
from pixtxt import AnimDef, anim_to_gif, dump, from_image
doc = from_image(
"assets/run-Sheet.png",
cell=(34, 50),
grid=(8, 1),
sheet_id="actors",
naming="rowcol",
)
doc.anims.append(
AnimDef(
anim_id="walk",
fps=12,
loop=1,
frames=[
"run-Sheet_r0_c0",
"run-Sheet_r0_c1",
"run-Sheet_r0_c2",
"run-Sheet_r0_c3",
"run-Sheet_r0_c4",
"run-Sheet_r0_c5",
"run-Sheet_r0_c6",
"run-Sheet_r0_c7",
],
)
)
dump(doc, "out/run_sheet_with_anim.pxt")
anim_to_gif(doc, "walk", "out/walk.gif")
Troubleshooting
Animation '<id>' not found
Reason: your document does not contain a matching @anim section.
Fix:
- Inspect available animation IDs:
print([a.anim_id for a in doc.anims])
- Add
AnimDef(...)programmatically if needed (see recipe C).
image size WxH does not match cell*grid size ...
Reason: cell[0] * grid[0] != image_width or cell[1] * grid[1] != image_height.
Fix: adjust cell and grid so they multiply exactly to source image dimensions.
TestPyPI install fails with dependency resolution
Use both indexes so dependencies can come from PyPI:
uv add --index https://test.pypi.org/simple/ --index https://pypi.org/simple pixtxt
Upload fails: filename was previously used
Bump package version (pyproject.toml) and re-build/re-upload.
Parse / Validate / Dump
from pathlib import Path
from pixtxt import dump, dumps, loads, validate
text = """PixTXT 1
@meta
title: Demo
@palette global
A:#111111
B:#22AAFF
@image hero 2x2 rows
AB
B.
"""
doc = loads(text)
issues = validate(doc, strict=True)
assert issues == []
serialized = dumps(doc)
Path("out").mkdir(parents=True, exist_ok=True)
dump(doc, "out/demo.pxt", encoding_preference="auto")
print(serialized.splitlines()[0]) # PixTXT 1
PNG / GIF Export
from pathlib import Path
from pixtxt import anim_to_gif, loads, sheet_to_png, to_png
doc = loads("""PixTXT 1
@palette global
A:#111111
B:#22AAFF
@image hero_idle 2x2 rows
AB
B.
@image hero_blink 2x2 rows
BA
.A
@anim blink fps=8 loop=1
use: hero_idle, hero_blink
@sheet atlas
cell:2x2
grid:2x1
item: hero_idle at 0,0
item: hero_blink at 1,0
""")
Path("out").mkdir(parents=True, exist_ok=True)
to_png(doc, "hero_idle", "out/hero_idle.png")
sheet_to_png(doc, "atlas", "out/atlas.png")
anim_to_gif(doc, "blink", "out/blink.gif")
Strict Mode Notes
loads(..., strict=True)rejects unknown section headers and unknown@metakeys.validate(..., strict=True)reportsMETA_UNKNOWN_KEYfor non-standard@metakeys.- In non-strict mode, unknown sections are preserved as
doc.extensions.
API Signatures
| Function | Signature |
|---|---|
load |
`load(path: str |
loads |
loads(text: str, strict: bool = False) -> PixTXTDocument |
dump |
`dump(doc: PixTXTDocument, path: str |
dumps |
dumps(doc: PixTXTDocument, encoding_preference: str = "auto") -> str |
validate |
validate(doc: PixTXTDocument, strict: bool = False) -> list[Issue] |
optimize |
optimize(doc: PixTXTDocument, mode: str = "token") -> PixTXTDocument |
from_image |
from_image(path, palette_mode="global", frame_mode="first", cell=None, grid=None, sheet_id=None, anim_id=None, frame_fps=8, frame_loop=1, naming="index", use_source_timing=False) -> PixTXTDocument |
to_png |
`to_png(doc: PixTXTDocument, image_id: str, out_path: str |
sheet_to_png |
`sheet_to_png(doc: PixTXTDocument, sheet_id: str, out_path: str |
anim_to_gif |
`anim_to_gif(doc: PixTXTDocument, anim_id: str, out_path: str |
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pixtxt-0.1.4.tar.gz.
File metadata
- Download URL: pixtxt-0.1.4.tar.gz
- Upload date:
- Size: 29.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e667980c6d0deb10615ee95d7ca23841d951be238bc86b17ac13d3f3e5752cc6
|
|
| MD5 |
024866528c605303c7a15611e092bf83
|
|
| BLAKE2b-256 |
ff59e4b472b4f0a6551dc6391ce6dee8d51685cea4360f042ddb8a4d5d94b928
|
File details
Details for the file pixtxt-0.1.4-py3-none-any.whl.
File metadata
- Download URL: pixtxt-0.1.4-py3-none-any.whl
- Upload date:
- Size: 19.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
74631931ce7cbc3ac2699948d349344ad4ad520c9abee909ad4577a29c9f43ae
|
|
| MD5 |
1de3d361c1a8be627e458f7b70cd4d83
|
|
| BLAKE2b-256 |
0865222781c01f2f46750c7f04f7b36a8bb82621bf4a482c8450584a66e7db9a
|