Converts pixel-art-style images such as those from generative models or low-quality sprite web uploads to true resolution usable assets.
Project description
Proper Pixel Art
|
Noisy, high resolution |
→ |
Clean, true-resolution pixel art |
Summary
Converts noisy, high-resolution pixel-art-style images (from generative models or low-quality web uploads) into clean, true-resolution assets. Such images often have a non-uniform grid and random artifacts, so standard downsampling fails — the usual alternatives are naive downscaling or redrawing the asset pixel by pixel. This tool automates the recovery instead.
Contents
Installation
Install From PyPI
pip install proper-pixel-art # CLI and Python API
pip install "proper-pixel-art[web]" # Include the local web UI
Or with uv:
uv add proper-pixel-art # CLI and Python API
uv add proper-pixel-art --extra web # Include the local web UI
Install from source
git clone git@github.com:KennethJAllen/proper-pixel-art.git
cd proper-pixel-art
uv sync --extra web
Usage
First, obtain a source pixel-art-style image (e.g. from a generative model such as OpenAI's gpt-image-2, or a web upload of pixel art).
The examples below assume you installed via
pip installoruv add(commands are on yourPATH). If you installed from source withuv sync, prefix each command withuv run(e.g.uv run ppa ...).
Web Interface
Try it live in your browser, no install required, on Hugging Face Spaces.
To run the same interface locally:
ppa-web
# Opens http://127.0.0.1:7860
CLI
ppa <input_path> -o <output_path> -c <num_colors> -s <result_scale> [-t]
Options
| Option | Description |
|---|---|
| INPUT (positional) | Source file in pixel-art-style |
-o, --output <path> |
Output directory or file path for result. (default: '.') |
-c, --colors <int> |
Number of colors for output (1-256). Use 0 to skip quantization and preserve all colors. May need to try a few different values. (default 0) |
-s, --scale-result <int> |
Width/height of each "pixel" in the output. 1 = no scaling. (default: 1) |
-t, --transparent <bool> |
Output with transparent background. (default: off) |
-u, --initial-upscale <int> |
Initial image upscale factor. Increasing this may help detect pixel edges. (default 2) |
-w, --pixel-width <int> |
Width of the pixels in the input image. Use 0 to determine it automatically. (default: 0) |
--config <path> |
YAML config file of pixelation parameters. Flags passed explicitly override values in the file. (default: none) |
--intermediate-dir <path> |
Directory to save images visualizing intermediate algorithm steps. Useful for development. (default: none) |
Example
ppa assets/blob/blob.png -c 16 -s 25
Note: --colors is the parameter most likely to need tuning. See the option table above.
Use Without Cloning
Web Interface (without cloning)
uvx --from "proper-pixel-art[web]" ppa-web
CLI (without cloning)
uvx --from "proper-pixel-art" ppa <input_path>
Python API
For Python developers who want to integrate this tool into their own code.
from PIL import Image
from proper_pixel_art import pixelate
image = Image.open('path/to/input.png')
result = pixelate(image, num_colors=16)
result.save('path/to/output.png')
Parameters
These mirror the CLI options above.
image:PIL.Image.Image— the image to pixelate.num_colors:int— colors in result (1-256), or 0 to skip quantization. Most likely to need tuning.initial_upscale_factor:int— upscale the input first; may help detect lines.scale_result:int— upscale the result; 1 = no scaling.transparent_background:bool— if True, flood-fill each corner with transparent alpha.intermediate_dir:Path | None— save visualizations of intermediate steps (for development).pixel_width:int— pixel width in the input, or 0 to detect automatically.config:PixelateConfig | None— a bundle of every tunable parameter, including the deeper mesh-detection (Canny, Hough, line clustering) and color (alpha/transparency thresholds, quantization method, color binning) settings not exposed as direct arguments. Load one withPixelateConfig.from_yaml(path). Explicit arguments override matching values inconfig.
Returns
A PIL image with true pixel resolution and quantized colors.
Configuration file
All tunable parameters can be collected in a YAML file so you can fine-tune the algorithm without changing code. See config.example.yaml for the full list of keys with their defaults. Any key you omit falls back to the default, so partial files are fine.
from PIL import Image
from proper_pixel_art import pixelate
from proper_pixel_art.config import PixelateConfig
config = PixelateConfig.from_yaml('config.yaml')
result = pixelate(Image.open('input.png'), config=config)
From the CLI, pass --config. Flags given explicitly override values from the file:
ppa input.png --config config.yaml # use the file
ppa input.png --config config.yaml -c 8 # but override num_colors to 8
Examples
The algorithm is robust. It performs well for images that are already approximately aligned to a grid.
Here are a few examples. A mesh is computed, where each cell corresponds to one pixel.
Bat
- Generated by GPT-4o.
|
Noisy, High Resolution |
Mesh |
True Pixel Resolution |
Ash
- Screenshot from Google images of Pokemon asset.
|
Noisy, High Resolution |
Mesh |
True Pixel Resolution |
Demon
- Original image generated by GPT-4o.
|
Noisy, High Resolution |
Mesh |
True Pixel Resolution |
Pumpkin
- Screenshot from Google Images of Stardew Valley asset. This is an adversarial example as the source image is both low quality and the object is round.
|
Noisy, High Resolution |
Mesh |
True Pixel Resolution |
Real Images To Pixel Art
-
This tool can also be used to convert real images to pixel art by first requesting a pixelated version of the original image from GPT-4o, then using the tool to get the true pixel-resolution image.
-
Consider this image of a mountain
- Here are the results of first requesting a pixelated version of the mountain, then using the tool to get a true resolution pixel art version.
|
Noisy, High Resolution |
Mesh |
True Pixel Resolution |
Algorithm
Here's a step-by-step overview, applied to this GPT-4o-generated blob:
- Note that this image is high resolution and noisy.
-
Trim the edges of the image and zero out pixels with more than 50% alpha.
- This is to work around some issues with models such as GPT-4o not giving a perfectly transparent background.
-
Upscale by a factor of 2 using nearest neighbor.
- This can help identify the correct pixel mesh.
-
Find edges of the pixel art using Canny edge detection.
- Close small gaps in edges with a morphological closing.
- Take the probabilistic Hough transform to get the coordinates of lines in the detected edges. Only keep lines that are close to vertical or horizontal giving some grid coordinates. Cluster lines that are closeby together.
- Find the grid spacing by filtering outliers and taking the median of the spacings, then complete the mesh.
-
Quantize the original image to a small number of colors (see the
num_colorstuning note above). -
In each cell specified by the mesh, choose the most common color in the cell as the color for the pixel. Recreate the original image with one pixel per cell.
- Result upscaled by a factor of $20 \times$ using nearest neighbor.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file proper_pixel_art-1.5.2.tar.gz.
File metadata
- Download URL: proper_pixel_art-1.5.2.tar.gz
- Upload date:
- Size: 162.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
abd12cae1db81ad3f6512761a0b6995f45fdc6e51a1f66cd628464f87a19b74d
|
|
| MD5 |
dc4bf95f3445a574ff5acaccaddf6c35
|
|
| BLAKE2b-256 |
4c4097f491657b5e63ee952be345e5c441fe0425d07f433167498efaf00f41a6
|
Provenance
The following attestation bundles were made for proper_pixel_art-1.5.2.tar.gz:
Publisher:
release.yml on KennethJAllen/proper-pixel-art
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
proper_pixel_art-1.5.2.tar.gz -
Subject digest:
abd12cae1db81ad3f6512761a0b6995f45fdc6e51a1f66cd628464f87a19b74d - Sigstore transparency entry: 1786959338
- Sigstore integration time:
-
Permalink:
KennethJAllen/proper-pixel-art@464509679b48ae647a545d270aa8a1817fecc5a8 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/KennethJAllen
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@464509679b48ae647a545d270aa8a1817fecc5a8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file proper_pixel_art-1.5.2-py3-none-any.whl.
File metadata
- Download URL: proper_pixel_art-1.5.2-py3-none-any.whl
- Upload date:
- Size: 23.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c2a6f39412b24dc836b6d091ab661356f30747e7cc70df77eb2321a4c15a788b
|
|
| MD5 |
9cc50519df1967d654cd8ff3262c6628
|
|
| BLAKE2b-256 |
eb2b41003ca2f31e72da963428997a56d0f02e3afae693ccf2fe72573d20554a
|
Provenance
The following attestation bundles were made for proper_pixel_art-1.5.2-py3-none-any.whl:
Publisher:
release.yml on KennethJAllen/proper-pixel-art
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
proper_pixel_art-1.5.2-py3-none-any.whl -
Subject digest:
c2a6f39412b24dc836b6d091ab661356f30747e7cc70df77eb2321a4c15a788b - Sigstore transparency entry: 1786959385
- Sigstore integration time:
-
Permalink:
KennethJAllen/proper-pixel-art@464509679b48ae647a545d270aa8a1817fecc5a8 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/KennethJAllen
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@464509679b48ae647a545d270aa8a1817fecc5a8 -
Trigger Event:
push
-
Statement type: