Skip to main content

FE8 palette tool: PNG -> 16-colour JASC .pal extraction & apply (fireemblem8u; inspired by Loxed's Porypal)

Project description

porypal-fe8

A small, FE8-oriented palette CLI for the fireemblem8u decomp graphics pipeline. It does two things:

  • extract — quantize a PNG down to ≤16 colours and write a GBA-style JASC .pal palette.
  • apply — remap every pixel of a PNG to its nearest colour in a given .pal and save an indexed PNG, ready for gbagfx.

It is a focused, clean reimplementation of the reusable core of Loxed's Porypal — k-means colour quantization in a perceptual colour space (Oklab) plus JASC .pal I/O — with all the Pokémon-specific and UI parts dropped. See Credits & license.

Why this exists (honest note)

For day-to-day FE8 graphics work you usually do not need this tool:

  • Usenti handles palette editing, reduction, and indexed-PNG export interactively.
  • The decomp's own gbagfx already converts between .png, .pal, .gbapal, and .4bpp.

porypal-fe8 is for batch / automated quantization — e.g. scripting the reduction of many full-colour PNGs to 16-colour palettes in a build or asset pipeline, where a headless CLI is more convenient than a GUI.

Install

Requires Python 3.9+.

python3 -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt
# optional: install the `porypal-fe8` console command
pip install .

Without installing, you can run the module directly:

python3 palette_tool.py extract IN.png -o OUT.pal

Install / Releases

Once published to PyPI:

pip install porypal-fe8

Each v* tag also produces a GitHub Release with the built wheel and sdist attached (under Releases), so you can pip install a downloaded artifact even without PyPI.

Note: PyPI publishing uses OIDC trusted publishing (no API token). It requires a trusted publisher to be configured on PyPI for project porypal-fe8, owner laqieer, workflow release.yml, environment pypi. The GitHub Release job is independent and succeeds even before that is set up.

Usage

Extract a palette

porypal-fe8 extract IN.png -o OUT.pal [-n 16]

Quantizes IN.png to at most -n colours (default 16, the GBA 4bpp limit) and writes a JASC .pal:

JASC-PAL
0100
16
115 131 164
255 255 255
...

Apply a palette

porypal-fe8 apply IN.png PALETTE.pal -o OUT.png

Remaps every pixel of IN.png to the nearest colour in PALETTE.pal (nearest in Oklab) and saves an indexed (P-mode) PNG whose colours are exactly the palette.

How it fits the FE8 pipeline

The decomp stores graphics as PNGs and JASC .pal palettes, and its Makefile drives gbagfx to turn those into the GBA's native formats:

            porypal-fe8 extract              gbagfx (pal2gbapal)
   IN.png ───────────────────────▶  OUT.pal ───────────────────▶  .gbapal   (32 bytes for 16 colours)

            porypal-fe8 apply                gbagfx (png2gbagfx)
   IN.png ───────────────────────▶  OUT.png ───────────────────▶  .4bpp
   (+ .pal)                         (indexed)

Relevant Makefile rules in the decomp:

%.gbapal: %.pal ; $(PAL2GBAPAL) $< $@
%.gbapal: %.png ; $(GBAGFX) $< $@

A 16-colour JASC .pal converts to exactly 32 bytes of .gbapal (16 colours × 2 bytes, the GBA's 15-bit BGR555 format). Palettes are written with CRLF line endings to match the decomp's .pal files — gbagfx rejects LF-only palettes. See the fireemblem8u repo and gbagfx for the full graphics flow.

How it works

  • Quantization clusters the image's pixels with k-means++ in Oklab, a perceptually uniform colour space, so the chosen colours match how the eye groups them. Each cluster centre is then snapped to the nearest actual colour in the source image, so every palette entry really occurs in the PNG. If the image already has ≤ N colours, they are kept verbatim.
  • Apply assigns each pixel to the nearest palette colour, again measured in Oklab.

Credits & license

The colour-quantization approach and JASC .pal round-trip are inspired by Loxed's Porypal. Porypal is licensed under the GPL-3.0, which is incompatible with this project's MIT license, so no Porypal source code was copied — this is an independent reimplementation of the high-level idea only. Credit and thanks to Loxed.

porypal-fe8 itself is released under the MIT License.

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

porypal_fe8-0.1.2.tar.gz (11.8 kB view details)

Uploaded Source

Built Distribution

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

porypal_fe8-0.1.2-py3-none-any.whl (10.4 kB view details)

Uploaded Python 3

File details

Details for the file porypal_fe8-0.1.2.tar.gz.

File metadata

  • Download URL: porypal_fe8-0.1.2.tar.gz
  • Upload date:
  • Size: 11.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for porypal_fe8-0.1.2.tar.gz
Algorithm Hash digest
SHA256 c0e575bbbd6c14e9c17777773c6ab31a803f3f02ff03cd3000b1c82e5989b0b9
MD5 e93622fcdd12720b64c2063a960f6382
BLAKE2b-256 8670b9d6a473eaeed3f0a7414cd4dee6421e7875853bd8a6997d97c71f569db4

See more details on using hashes here.

Provenance

The following attestation bundles were made for porypal_fe8-0.1.2.tar.gz:

Publisher: release.yml on laqieer/porypal-fe8

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file porypal_fe8-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: porypal_fe8-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 10.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for porypal_fe8-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 3bb2b20d66984cf28e682aba7ea1d85495a25a3d61c2627262dd148c3fffdd80
MD5 9db8203f14272597fcb9607e4e8b8239
BLAKE2b-256 4425cbb596507e44ebee99dcc5207cd69972c63fdf28cdc5f6151757e9b4b527

See more details on using hashes here.

Provenance

The following attestation bundles were made for porypal_fe8-0.1.2-py3-none-any.whl:

Publisher: release.yml on laqieer/porypal-fe8

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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