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.1.tar.gz (9.0 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.1-py3-none-any.whl (10.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: porypal_fe8-0.1.1.tar.gz
  • Upload date:
  • Size: 9.0 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.1.tar.gz
Algorithm Hash digest
SHA256 af2d15087e6018d4f589378fc02287f6c01ed14ff53be5dbbe822bca34560bf5
MD5 e459f6fd70c0eb8d14e318bd104ad9b6
BLAKE2b-256 2424eaf046c4d88c7d431e6c2eb609f5e49b970948ef3ada0f7baacec4cd57de

See more details on using hashes here.

Provenance

The following attestation bundles were made for porypal_fe8-0.1.1.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.1-py3-none-any.whl.

File metadata

  • Download URL: porypal_fe8-0.1.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 380cc93f4e51876f87dbed60494ebab544000392b0c32605da4cf0349226775a
MD5 bffe6b930cd8654a356d6690f0b0e3c1
BLAKE2b-256 66b25405da8c92fdc257691a31f38237b71ef174e77d6dd35881ee3ce358dded

See more details on using hashes here.

Provenance

The following attestation bundles were made for porypal_fe8-0.1.1-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