_ __ _
_ __ (_)_ __/ _(_)_ __
| '_ \| \ \/ / |_| \ \/ /
| |_) | |> <| _| |> <
| .__/|_/_/\_\_| |_/_/\_\
|_|
Clean up AI-generated pixel art.
Snap to grid. Remove AA fuzz. Reduce to a palette. Remove backgrounds.
Docs (with an in-browser demo) · Download · Features · CLI Reference · How It Works
AI image generators produce "pixel art" riddled with mixels (mixed-resolution pixels), anti-aliasing artifacts, and colors that don't snap to any grid. pixfix takes that messy output and produces clean, uniform pixel art — while preserving the vibrancy and character of the original.
Available as a native desktop app (macOS, Windows, Linux) and a CLI tool for scripting and automation.
|
Desktop App
|
Processing Pipeline
|
Download the latest release for your platform:
| Platform | Download |
|---|---|
| macOS (Apple Silicon) | .dmg |
| macOS (Intel) | .dmg |
| Windows | .msi · .exe installer |
| Linux | .deb · .AppImage |
# From source (requires Rust 1.70+)
git clone https://github.com/lovelaced/pixfix.git
cd pixfix
cargo build --release
# Binary at target/release/pixfixPre-built CLI binaries for all platforms are also available on the Releases page.
| Key | Action |
|---|---|
| O | Open image |
| S | Save processed image |
| Space | Reprocess with current settings |
| R | Reset settings to defaults |
| Tab | Switch tabs |
| Esc | Back to Preview |
| Tab | What it does |
|---|---|
| Preview | Side-by-side original vs. processed |
| Settings | All pipeline parameters with live preview |
| Diagnostics | Grid detection scores, color histogram |
| Batch | Process multiple images at once |
| Sheet | Split sprite sheets, normalize tiles, export GIFs |
# Auto-detect grid, normalize
pixfix process input.png output.png
# Force grid size, snap to PICO-8 palette
pixfix process input.png output.png --grid-size 4 --palette pico-8
# Remove background
pixfix process input.png output.png --grid-size 4 --remove-bg
# Chroma key: make a color transparent everywhere (green-screen style)
pixfix process input.png output.png --chroma-key 00FF00
# Inspect without writing anything
pixfix analyze input.png --json
# Batch process a folder
pixfix batch sprites/ output/ --grid-size 4 --palette sweetie-16
# Auto-split an AI sprite sheet
pixfix sheet ai_sheet.png --output-dir sprites/
# Interactive terminal editor (Sixel/halfblock preview)
pixfix tui input.pngInput Image
│
▼
┌─────────────────┐
│ Grid Detection │ Find NxN pixel grid size and phase offset
└────────┬────────┘
▼
┌─────────────────┐
│ AA Removal │ Remove anti-aliasing artifacts (optional)
└────────┬────────┘
▼
┌─────────────────┐
│ Grid Normalize │ Snap/downscale pixels to the detected grid
└────────┬────────┘
▼
┌─────────────────┐
│ Quantize │ Snap colors to a palette (optional)
└────────┬────────┘
▼
┌─────────────────┐
│ Background Rm │ Remove solid backgrounds (optional)
└────────┬────────┘
▼
┌─────────────────┐
│ Final Resize │ Scale to output dimensions if needed
└────────┬────────┘
▼
Output Image
Grid Detection
For each candidate grid size (2..max), measures edge alignment — the ratio of color gradients at grid boundaries vs. non-boundary positions. The correct grid size maximizes this ratio because all real color transitions align to its grid lines. Phase detection scans all possible offsets to find where the grid starts, even when --grid-size is manually set.
Snap Mode (Default)
For each NxN block, finds the dominant color via center-weighted majority voting and paints every pixel in the block with that single color. Eliminates mixels and stray pixels while preserving dithering patterns across blocks (adjacent blocks can still have different colors). The output stays at the original resolution.
Color Quantization (OKLAB)
All color operations use OKLAB color space, which is perceptually uniform — Euclidean distance in OKLAB closely matches how humans see color differences. K-means clustering produces vibrant, meaningful centroids instead of muddy averages. Palette snapping picks the perceptually closest match.
Anti-Aliasing Removal
For each pixel, examines its 8-connected neighbors. If the pixel lies "between" the two most dominant neighbor colors in OKLAB space (triangle inequality test), it's identified as an AA artifact and snapped to the closer neighbor. Off by default — AI art has intentional edge detail that this can destroy.
-h shows a curated set of flags — the ones that change results, like
--grid-size and --coarsen. Tuning flags for detection thresholds and
edge cases only appear in --help, which is always complete.
pixfix process [OPTIONS] <INPUT> [OUTPUT]
Output defaults to <input>_normalized.png.
Animated GIFs. A GIF with more than one frame is normalized as one
animation, not as independent images: the grid is detected once on the first
frame, the background color is resolved once, and a single palette is
extracted from all frames together, so nothing drifts or flickers between
frames. Each frame is then snapped with those shared settings. Per-frame
timing is preserved and the output is always an animated GIF
(<input>_normalized.gif). Static GIFs take the normal single-image path.
All options
Grid
| Flag | Description |
|---|---|
--grid-size <N> |
Override auto-detected grid size (fractional values like 10.667 work) |
--grid-phase <X,Y> |
Override grid phase offset (requires --grid-size) |
--no-grid-detect |
Skip grid detection (requires --grid-size) |
--max-grid-candidate <N> |
Max pitch to test (default: scales with image size) |
--coarsen <N> |
Multiply the final grid pitch by an integer (see below) |
--min-confidence <0-1> |
Detection confidence floor (default: 0.35); below it the pipeline declines to snap and reports its best guess. Lower it for heavily anti-aliased images |
--coarsen, exactly: detection finds the render quantum — the grid the
generator physically painted on (often ~2px at 1024). The intended artistic
resolution is usually a multiple of that: a 1024px image at 2px pitch is a
512x512 sprite, nothing like 16-bit-era art, while --coarsen 2 snaps the
same image at 4px for an honest 256x256. The multiplier applies to the
auto-detected pitch or to --grid-size (so --grid-size 2.714 --coarsen 2
snaps at 5.428); phase is preserved, so coarse blocks stay aligned with the
fine grid; it does nothing when detection declines (there is no pitch to
multiply); and reported grid values (--json included) show the multiplied
pitch, while grid_best_guess diagnostics keep the raw detection.
Detection handles fractional pitch — AI upscales often render, say, 48 cells
across 512px (10.667px per cell), and the comb search finds that directly.
When confidence is too low to trust, the pipeline reports its best guess and
leaves the image unsnapped instead of inventing a grid; pass --grid-size
to force one.
Downscale
| Mode | Description |
|---|---|
snap |
Default. Clean grid at original resolution. Best for AI art. |
center-weighted |
Reduce to logical resolution, center pixels weighted more. |
majority-vote |
Reduce to logical resolution, most common color wins. |
center-pixel |
Reduce to logical resolution, center pixel only. Fastest. |
Color
| Flag | Description |
|---|---|
--palette <NAME> |
Built-in palette (pico-8, sweetie-16, endesga-32, endesga-64, gameboy, nes) |
--palette-file <PATH> |
Custom .hex palette file |
--lospec <SLUG> |
Fetch palette from Lospec by slug |
--colors <N> |
Auto-extract N colors via k-means |
--no-quantize |
Skip quantization |
--seed <N> |
RNG seed — same input and seed always produce identical bytes |
--flatten-dither |
Turn off dither preservation (detected dither pairs are normally pinned so quantization can't flatten them) |
The palette source flags are mutually exclusive. Extracted palettes use each cluster's most representative real color, never invented averages.
Anti-aliasing
| Flag | Description |
|---|---|
--aa-threshold <0-1> |
Enable AA removal; higher = more aggressive (off by default) |
--aa-passes <N> |
Max removal passes for wide AA ramps (default: 3) |
Background
| Flag | Description |
|---|---|
--remove-bg |
Enable background removal |
--bg-color <HEX> |
Explicit background color |
--bg-threshold <0-1> |
Border detection threshold (default: 0.4) |
--bg-tolerance <N> |
Color tolerance in OKLAB (default: 0.05) |
--no-flood-fill |
Global replacement instead of flood-fill |
--chroma-key <HEX> |
Green-screen removal: this color becomes transparent everywhere, interior regions included; repeat for multiple keys, combinable with --remove-bg |
--chroma-tolerance <N> |
Chroma key match tolerance in OKLAB (default: 0.05) |
Output
| Flag | Description |
|---|---|
--target-width <N> / --target-height <N> |
Explicit output size |
--logical-size |
Reduced modes: emit the true logical resolution instead of the default crisp integer re-upscale |
--keep-alpha |
Preserve per-pixel alpha instead of binarizing blocks to opaque/transparent |
--output-format <png|webp|bmp|gif> |
Output encoding; also sets the derived extension (default: png; animated inputs always produce gif) |
--overwrite / --no-overwrite |
Overwrite policy (no-clobber by default) |
--debug-overlay <PATH> |
Also write a diagnostic PNG: source dimmed, blocks tinted red by how contested their color vote was — a wrong pitch or phase lights up instantly |
Derived output names always get the output format's extension — a .jpg
input produces _normalized.png. Pass - as input to read from stdin, or as
output to write PNG to stdout for piping.
pixfix analyze input.png --jsonRuns grid detection, background detection, and color counting with zero
writes — pitch, phase, confidence, logical size, unique colors, detected
background. When a grid is found it also probes snapping at 1x/2x/4x of the
detected pitch and reports contested-block rates per factor, suggesting a
--coarsen value when the content reads cleanly at a coarser artistic
resolution. Add --sheet to preview the auto-split sprite count. Ideal for
scripts and agents that want to look before they process.
pixfix batch [OPTIONS] <INPUT> <OUTPUT_DIR>
INPUT can be a directory or glob pattern (extensions match
case-insensitively). Pipeline flags from process apply; --target-width/
--target-height are per-image and not available in batch.
| Flag | Description |
|---|---|
--suffix <S> |
Output name suffix (default: _normalized; '' for none) |
--preserve-dirs |
Recreate the input directory structure (recursive globs that would collide are rejected otherwise) |
--output-format <F> |
Output encoding for every file |
One bad file never aborts the run; every file's outcome is itemized, and a partial failure exits with code 6.
pixfix sheet [OPTIONS] <INPUT> [OUTPUT]
Fixed grid — specify --tile-width and --tile-height for known layouts.
Auto-split — omit tile dimensions to auto-detect sprite boundaries.
Sheet options
| Flag | Description |
|---|---|
--tile-width <N> / --tile-height <N> |
Fixed tile size (omit for auto-split) |
--spacing <N> |
Gap between tiles (default: 0) |
--margin <N> |
Sheet border (default: 0) |
--separator-threshold <0-1> |
Auto-split separator detection (default: 0.90) |
--min-sprite-size <N> |
Filter small artifacts (default: 8) |
--pad <N> |
Output padding per sprite (default: 0) |
--output-dir <PATH> |
Save individual tiles |
--no-normalize |
Split/reassemble only |
pixfix tui [INPUT]Terminal UI with live image preview (Sixel/halfblock). Requires building with
the tui feature (cargo install --features tui); it is not in the default
feature set.
pixfix palette list # Show built-in palettes
pixfix palette fetch endesga-32 # Download from Lospec
pixfix palette extract input.png -o p.hex # Extract from imageFetched palettes are cached in the platform cache directory; --refresh
bypasses the cache.
Every command takes a global --json flag that emits exactly one JSON
document on stdout (stable schema, fields always present); logs and progress
stay on stderr, as NDJSON events in JSON mode. --quiet silences everything
except errors. Results are deterministic: the same input and --seed
produce identical bytes.
For language models there's a plain-text version of the whole manual: llms.txt and llms-full.txt.
pixfix analyze sprite.png --json | jq .grid.pitch_x
pixfix process sprite.png out.png --json | jq .colors_afterExit codes:
| Code | Meaning |
|---|---|
| 0 | Success |
| 2 | Usage or config error |
| 3 | Input could not be read |
| 4 | Processing failed |
| 5 | Output already exists (pass --overwrite) |
| 6 | Batch finished with some files failed |
Save settings in .pixfix.toml — CLI arguments override config
values, which override the built-in defaults. An explicit --config path
that doesn't exist is an error; --no-config ignores config files entirely
(useful for scripted runs in arbitrary directories).
Example config
[grid]
size = 4
max_candidate = 16
[aa]
threshold = 0.3
[quantize]
palette = "pico-8"
[background]
enabled = true
color = "FF00FF"
flood_fill = true
[output]
overwrite = falsePerformance — parallelized via rayon. Grid detection, AA removal, batch mode, and sprite sheet tiles all process in parallel. A 1024x1024 image typically completes in under 1 second.
MIT License

