# Pixel art research and implemented pipeline

26 September 2026. Built-in image-generation tool; no paid external image service.

The previous sheet started as a detailed illustration. Shrinking with nearest-neighbor preserved noisy highlights and uneven outlines. Palette reduction alone did not fix the structure.

## What changed

1. Generated four new deliberately coarse character candidates (`assets/pixel-candidates-v4.png`). Selected bottom right: big head, squat wrestler silhouette, red sash.
2. Generated the animation atlas from that reference with explicit logical pixels, simple clusters, sparse facial details, and a limited palette (`assets/rock-atlas-v5-source.png`). Prompts are in `ART-PROMPTS.md`.
3. Compared automatic grid recovery with a calibrated grid. The generated file is 1254×1254, **not** the requested 1280×1280; the rows are not evenly spaced. Auto-detection returned 164×190 for the atlas and distorted proportions, so it was rejected. Requested image dimensions are not proof of a correct grid.
4. Used Pixel Art Fixer's two-stage reconstruction at a common scale for the entire atlas. It votes on structural colour labels inside each cell, then recovers that label's colour. This avoids blended outline/skin boundary colours.
5. Quantized the whole atlas to one shared palette: 15 opaque colours, including three skin shades, plus transparent index 0. No dithering; binary alpha. Reconstructed at 208×208, calibrated transparent row gutters, then translated each pose into a 48×52 canvas with the same foot anchor. **No independent frame scaling.** Compared larger grids too; those exceeded the engine's sprite box and were rejected.
6. Encoded the exact pixels as native SCUMM costume RLE. All sixteen frames round-trip exactly against their PNGs. Browser enlargement uses nearest-neighbor/pixelated display.

`reconstruct-sprites.py` performs reconstruction; `build-sprites.mjs` only validates palette/alpha and encodes the resulting pixels. The prior converter is retained as `build-sprites-legacy.mjs` for comparison. `assets/rock-sprites-preview.png` is the exact production atlas; `assets/rock-v5-preview-52.png` is its enlarged inspection preview.

## Sources and alternatives

- [Retro Diffusion Pixel Art Fixer](https://github.com/Retro-Diffusion/pixel-art-fixer): grid detection and two-stage reconstruction. Used Python API at commit `ef376e57e1c272633ca2dbf5f29ec3fcf6596465`, MIT. Local checkout under `~/src/github.com/Retro-Diffusion/pixel-art-fixer`. Its CLI has a stale `detector` import at this revision; the documented Python import works. Vendor benchmark claims were not treated as independent evidence; our actual atlas was tested.
- [Aseprite indexed colour mode](https://aseprite.com/docs/color-mode/): explicit palette indices and transparency. [CLI](https://www.aseprite.org/docs/cli/) supports repeatable palette conversion.
- [ImageMagick filter documentation](https://usage.imagemagick.org/filter/): nearest/point sampling copies individual samples; area reduction combines samples. Neither can invent deliberate pixel clusters in a painted input. Grid reconstruction is the better fit here.
- [PixelLab native sprite tools](https://www.pixellab.ai/pixellab-api): specialist generation/rotation/animation, including small sprites. Promising alternative; not used or quality-verified for this project.
- [Cloudflare FLUX.2 dev](https://developers.cloudflare.com/workers-ai/models/flux-2-dev/): reference-image editing is available, but it does not by itself guarantee a native pixel grid. The same reconstruction and palette validation would still be needed. No reason to add an AI binding to the production game just to generate static build-time art.
- [Pixel Game Kit](https://github.com/kenyonxu/pixel-game-kit): fixed-size grid reconstruction and shared palette options; considered, not used.

This is a substantially cleaner game-sized sprite, not a claim that prompting alone produces perfect hand-authored animation. Orientation-specific anatomy and contact/passing poses still benefit from pixel-level art direction. Inspect it in the actual scene, not only as a large attractive contact sheet.

## Reproduce

Create `.venv-pixels`, install the pinned Pixel Art Fixer checkout's `python/requirements.txt`, then:

```sh
.venv-pixels/bin/python reconstruct-sprites.py
node build-sprites.mjs
node verify-assets.mjs
```

The script expects the checkout at the path above. Copy `rock-sprites.h` to `engines/scumm/`, rebuild ScummVM, and run `python3 package-engine.py` to publish a matched, content-hashed JS/WASM pair.

The title received the same structure-preserving conversion at 320×200, with a 64-colour palette and no dithering. The site splash and social preview are nearest-neighbor enlargements of those actual title pixels, replacing the earlier high-resolution faux-pixel presentation.
