Skip to main content

High-performance tool for improving AI-generated pixel art

Project description

unfake

Improve AI-generated pixel art through scale detection, color quantization, and smart downscaling. Features Rust acceleration for critical operations, achieving a 10-20% speedup over the original JavaScript implementation.

Based on the excellent work by:

Examples

Click each image to view the original, processed result, and results of two different naïve fixed-size-nearest-neighbor methods. comparison_grid comparison_grid comparison_grid comparison_grid comparison_grid

Images taken from examples for AI pixel art models like Pixel Art XL, FLUX.1-Dev Pixel LoRA, and FLUX.1-Kontext Pixel LoRA.

Features

  • Automatic Scale Detection: Detects the inherent scale of pixel art using both runs-based and edge-aware methods
  • Advanced Color Quantization: Wu color quantization algorithm with Rust acceleration
  • Smart Downscaling: Multiple methods including dominant color, median, mode, and content-adaptive
  • Image Cleanup: Alpha binarization, morphological operations, and jaggy edge removal
  • Transparent Background: Automatic background removal using edge-based flood fill
  • Grid Snapping: Automatic alignment to pixel grid for clean results
  • Flexible API: Both synchronous and asynchronous interfaces
  • Fast: Process a 1-megapixel image in as fast as half a second.

Upcoming

  • Vectorization

Installation

From PyPI (recommended)

pip install unfake

From Source

# Clone the repository
git clone https://github.com/painebenjamin/unfake.py.git
cd unfake

# Install with pip (includes Rust compilation)
pip install .

# Or for development
pip install -e .

Requirements

  • Python 3.8+
  • Rust toolchain (for building from source)
  • OpenCV Python bindings
  • Pillow
  • NumPy

Usage

Command Line

# Basic usage with auto-detection
unfake input.png

# Specify output file
unfake input.png -o output.png

# Control color palette size
unfake input.png -c 16                    # Maximum 16 colors
unfake input.png --auto-colors            # Auto-detect optimal color count

# Force specific scale
unfake input.png --scale 4                # Force 4x downscaling

# Choose downscaling method
unfake input.png -m dominant              # Dominant color (default, best for pixel art)
unfake input.png -m median                # Median color
unfake input.png -m content-adaptive      # High quality but slower

# Enable cleanup operations
unfake input.png --cleanup morph,jaggy    # Morphological + jaggy edge cleanup

# Use fixed color palette
unfake input.png --palette palette.txt    # File with hex colors, one per line

# Adjust processing parameters
unfake input.png --alpha-threshold 200    # Higher threshold for alpha binarization
unfake input.png --threshold 0.1          # Dominant color threshold (0.0-1.0)
unfake input.png --no-snap                # Disable grid snapping

# Make background transparent
unfake input.png --transparent-background # Flood-fill background from edges

# Verbose output
unfake input.png -v                       # Show detailed processing info

Python API

import unfake

# Basic processing with defaults
result = unfake.process_image_sync(
    "input.png",
    max_colors=32,                       # Maximum colors in output
    detect_method="auto",                # Scale detection: "auto", "runs", "edge"
    downscale_method="dominant",         # Method: "dominant", "median", "mode", "mean", "content-adaptive"
    cleanup={"morph": False, "jaggy": False},
    snap_grid=True                       # Align to pixel grid
)

# Access results
processed_image = result['image']        # PIL Image
palette = result['palette']              # List of hex colors
manifest = result['manifest']            # Processing metadata

# Auto-detect optimal colors
result = unfake.process_image_sync(
    "input.png",
    max_colors=None,                     # Auto-detect
    auto_color_detect=True
)

# Use fixed palette
fixed_colors = ['#000000', '#ffffff', '#ff0000', '#00ff00', '#0000ff']
result = unfake.process_image_sync(
    "input.png",
    fixed_palette=fixed_colors
)

# Make background transparent
result = unfake.process_image_sync(
    "input.png",
    transparent_background=True          # Flood-fill background from edges
)

Asynchronous API

import asyncio
import unfake

async def process_image_async():
    result = await unfake.process_image(
        "input.png",
        max_colors=16,
        detect_method="runs",
        downscale_method="median",
        cleanup={"morph": True, "jaggy": False},
        snap_grid=True,
        transparent_background=True          # Optional: make background transparent
    )
    result["image"].save("output.png")

asyncio.run(process_image_async())

Processing Options

Scale Detection Methods

  • auto (default): Tries runs-based first, falls back to edge-aware
  • runs: Analyzes color run lengths (fast, works well for clean pixel art)
  • edge: Uses edge detection (slower but handles anti-aliased images)

Downscaling Methods

  • dominant (default): Uses most frequent color in each block (best for pixel art)
  • median: Median color value (good for photos)
  • mode: Most common color (similar to dominant)
  • mean: Average color (can create new colors)
  • content-adaptive: Advanced algorithm based on Kopf & Lischinski 2011

Cleanup Options

  • morph: Morphological operations to remove noise
  • jaggy: Removes isolated diagonal pixels

Transparent Background

When enabled (transparent_background=True or --transparent-background), the tool automatically removes the background by flood-filling from the image edges. This feature:

  • Uses edge-based flood fill to detect background regions
  • Converts background pixels to transparent
  • Uses a configurable tolerance for color matching (default: 10)
  • Works with both RGB and RGBA images
  • Includes Rust acceleration for better performance

Performance

Example processing times for a 1024x1024 image on a high-end Intel desktop CPU using defaults:

  • Pure Python: ~71 seconds
  • With Rust Acceleration: ~700 milliseconds (about 100x speedup!)

Algorithm Details

Scale Detection

The tool uses two methods to detect the inherent scale of pixel art:

  1. Runs-based: Analyzes horizontal and vertical color runs to find the GCD
  2. Edge-aware: Uses Sobel edge detection to find regular grid patterns

Color Quantization

Implements the Wu color quantization algorithm (1992) which:

  • Builds a 3D color histogram
  • Recursively subdivides color space
  • Minimizes variance within each partition
  • Produces high-quality palettes

Downscaling

The dominant color method:

  • Divides image into scale×scale blocks
  • Finds most frequent color in each block
  • Falls back to mean if no color is dominant
  • Preserves original palette colors

Credits

This Python/Rust implementation is based on:

  • unfake.js by Eugeniy Smirnov - The original JavaScript implementation that inspired this project
  • image-quantization by Igor Bezkrovnyi - TypeScript implementation of various color quantization algorithms

Additional references:

  • Wu, Xiaolin. "Efficient Statistical Computations for Optimal Color Quantization" (1992)
  • Kopf, Johannes and Dani Lischinski. "Depixelizing Pixel Art" (2011)

License

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 Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

unfake-1.0.6-cp38-abi3-win_amd64.whl (278.4 kB view details)

Uploaded CPython 3.8+Windows x86-64

unfake-1.0.6-cp38-abi3-manylinux_2_34_x86_64.whl (360.1 kB view details)

Uploaded CPython 3.8+manylinux: glibc 2.34+ x86-64

unfake-1.0.6-cp38-abi3-macosx_11_0_arm64.whl (314.4 kB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

File details

Details for the file unfake-1.0.6-cp38-abi3-win_amd64.whl.

File metadata

  • Download URL: unfake-1.0.6-cp38-abi3-win_amd64.whl
  • Upload date:
  • Size: 278.4 kB
  • Tags: CPython 3.8+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.12

File hashes

Hashes for unfake-1.0.6-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 ee7be1f79675422d9ba9094a6c789f2bd96e568517d52a2323cded6b230f2756
MD5 a698ad151097d372e6a4089b959e3405
BLAKE2b-256 fa47c0e8232918a6864386fedb9637cf4337d0e45f296bc612452bc55d523386

See more details on using hashes here.

File details

Details for the file unfake-1.0.6-cp38-abi3-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for unfake-1.0.6-cp38-abi3-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 f97ffb0c6e7ee4a603fa5e95050f39c5d7292b03f144121e9fc5af4458e860db
MD5 ca2fd9d7bc4cab771d536ef3929a8722
BLAKE2b-256 2db94d6c33ec37e313b793ea554df3260964b50c4da7a2cb1cca25e7751ae450

See more details on using hashes here.

File details

Details for the file unfake-1.0.6-cp38-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for unfake-1.0.6-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 60fa9a841b9ed49ec99cef2b5b99f7b50e309ccf3684cbffacb99777100d26ad
MD5 925d4adb4b2206c555b07bd1c8344a97
BLAKE2b-256 c22c606dbd6cc9239629613e869df7bc7812b3d5d15b1777368a953d997dab53

See more details on using hashes here.

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