Magnific's SVG export is flat-shaded vector (~550 solid-fill paths, 6
gradients), which converts to pixel art cleanly. tools/svg2portrait.py
rasterises at 16x the target via qlmanage, then takes the most common
colour per 16x16 block — a true pixelate with no blending — and maps to
the 11-colour portrait palette.
Measured on Aki: 19 colours after pixelate, 10 after palette, visually
near-identical. So the portrait palette is sufficient for this art.
Contrast with the bitmap route this replaces: a 48x48 PNG resized in
Photoshop had 1330 unique colours in 2304 pixels, because bicubic
resampling turns flat regions into gradients. Quantising that speckled
badly across the blazer and background.
Also adds tools/pixtool.py — dependency-free PNG decode/encode (no Pillow
on this machine) plus the palette table shared with kissaten.c.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The palette constraint is not uniform across assets, so a single generic
line was not enough:
- Portraits list only the 11 non-sky colours, since a face never shows sky;
omitting the sky slots is safer than asking a generator to avoid them.
Adds the flat #492424 backdrop requirement (HMMM blits have no
transparency, so whatever surrounds the head gets copied literally).
- The background block is split by region: four sky colours inside the
window opening, eleven interior colours everywhere else, with the frame
and mullions counted as interior wood. Also reserves the top 16 and
bottom 64 rows the game draws over.
- Sprites take no palette at all — they are hardware sprites coloured at
runtime, so the art only defines shape.
Notes that the available clothing colours are few enough that characters
need distinct ones or they blur together in the dialogue box.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Resolves decision 8: art is generated in PixelLab from written prompts.
docs/ART.md carries the palette spec, the sky/wood slot rule, per-asset
sizes and return format, and prompts for Aki (needed for M3), the rest of
the cast, and the shop background.
art/palette.png (16x1, one pixel per entry) and art/palette_ref.png
(512x64 swatch strip) are generated from g_Palette so the generator and
the build cannot drift apart.
Flags a constraint the palette had hidden: only one literal skin entry, so
portraits use 6 -> 14 -> 4 as a hue-compatible skin ramp.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>