Skip to main content

Python SDK for reading and writing PixTXT documents

Project description

PixTXT Python SDK

PixTXT Logo

Python SDK for parsing, validating, optimizing, and exporting PixTXT documents.

🇨🇳 中文 | 🇺🇸 English


What is PixTXT?

PixTXT is a text format for pixel art designed for human readability, low token cost, and reliable LLM generation.

  • Readable: rows encoding is easy to inspect and edit by eye.
  • Token-efficient: rle encoding 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

  1. Parse/load PixTXT.
  2. Validate for issues.
  3. Optimize (rows/rle) if needed.
  4. Dump .pxt output.
  5. 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:

  • PixTXTDocument
    • meta: 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 @meta keys.
  • 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 @meta keys.
  • validate(..., strict=True) reports META_UNKNOWN_KEY for non-standard @meta keys.
  • 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pixtxt-0.1.4.tar.gz (29.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pixtxt-0.1.4-py3-none-any.whl (19.6 kB view details)

Uploaded Python 3

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

Hashes for pixtxt-0.1.4.tar.gz
Algorithm Hash digest
SHA256 e667980c6d0deb10615ee95d7ca23841d951be238bc86b17ac13d3f3e5752cc6
MD5 024866528c605303c7a15611e092bf83
BLAKE2b-256 ff59e4b472b4f0a6551dc6391ce6dee8d51685cea4360f042ddb8a4d5d94b928

See more details on using hashes here.

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

Hashes for pixtxt-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 74631931ce7cbc3ac2699948d349344ad4ad520c9abee909ad4577a29c9f43ae
MD5 1de3d361c1a8be627e458f7b70cd4d83
BLAKE2b-256 0865222781c01f2f46750c7f04f7b36a8bb82621bf4a482c8450584a66e7db9a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page