pixa 🖼️
A fast Rust image processing CLI — optimize AI-generated images for the web in one command, split sprite/expression sheets into individual avatars, generate favicon sets from a logo, remove Gemini AI watermarks, and more.
Features
| Command | Description |
|---|---|
compress |
Compress, resize, and convert formats (MozJPEG / OxiPNG / WebP) |
convert |
Convert between JPEG ↔ PNG ↔ WebP ↔ BMP ↔ GIF ↔ TIFF |
info |
Show dimensions, color, EXIF, SHA-256, and other metadata |
favicon |
Generate a web-ready icon set (ICO + PNGs) from any image |
split |
Auto-detect and crop individual objects from a sheet image |
transparent |
Key out a solid background color (chroma-key) to produce an RGBA PNG |
remove-watermark |
Remove the Gemini AI watermark via Reverse Alpha Blending |
detect |
Score whether a Gemini watermark is present in an image |
install |
Install the Claude Code skill so coding agents can use pixa |
compress, convert, transparent, and remove-watermark accept
either a file or a directory — pass -r/--recursive to walk into
subdirectories.
The watermark removal algorithm is adapted from GeminiWatermarkTool by Allen Kuo (MIT License).
Installation
Homebrew (macOS / Linux)
Subsequent updates: brew upgrade pixa.
Prebuilt binary installer — no Rust toolchain required
macOS / Linux:
|
Windows (PowerShell):
powershell -ExecutionPolicy ByPass -c "irm https://github.com/techarm/pixa/releases/latest/download/pixa-installer.ps1 | iex"
The installer downloads the right binary for your platform, places it
on your $PATH, and prints the install location. Supported platforms:
macOS (Intel + Apple Silicon), Linux (x86_64 + ARM64), Windows (x86_64).
You can also grab the archive directly from the Releases page.
From crates.io
Builds the latest published version from source. Requires a Rust
toolchain plus the system dependencies for mozjpeg (see below).
From source
Requirements:
- Rust 1.87+
- CMake, NASM, pkg-config (needed by
mozjpeg)
# Ubuntu / Debian
# macOS
# Build
The binary lands at target/release/pixa. Put it on your $PATH:
Setup (one-time)
After installing pixa, run this once to enable shell tab-completion and AI coding agent integration:
This installs:
- Shell completions — auto-detected (zsh/bash/fish) and placed in
the standard directory (same as
brew-installed tools) - Claude Code skill —
~/.claude/skills/pixa/SKILL.mdso AI coding agents can call pixa automatically
Re-run with --force to update after a pixa upgrade.
Quick start
Web-optimize an AI-generated image (one command)
# Source PNG → 1920px WebP (resize + format convert + compress)
# ✓ docs/images/hero.png → hero.webp
# 6.3 MB → 145.0 KB -97.7%
--max is the longest edge in pixels. Aspect ratio is preserved, and
the same flag works for both landscape and portrait inputs. You can
reproduce the numbers above against docs/images/hero.png,
which is kept in this repo as evidence.
Compress
When -o is omitted, pixa writes to <input>.min.<ext> (file) or
<input>.min/ (directory) — it never overwrites the original. If the
optimizer would make a file larger (already-minified assets), the
original bytes are written to the destination instead.
Split a sheet image into individual files
Input — a single sprite sheet:
One command:
Output — 5 individual avatars, text labels automatically excluded, all padded to the same size so they drop straight into UI components:
Add --preview to see exactly what pixa detected — each box shows the
uniform frame the crops were centered on:
How it works:
- Background color is auto-detected from corner samples
- Each object's bounding box is detected; text labels printed below characters are excluded automatically
- All output PNGs are uniformly sized — smaller crops are centered on a max-sized canvas filled with the detected background color
- When
--namesprovides a count, the algorithm re-splits the widest blob if the initial detection finds fewer objects than expected (handles near-touching or variable-width characters)
Useful flags:
--previewwrites<basename>-preview.pngshowing the detection--preview-style detected|output|bothcontrols what the preview draws--padding 10adds extra breathing room around each object--transparentalso keys out the detected background color per crop, producing RGBA outputs ready to drop onto any UI background
Make an AI-generated icon transparent
For AI-generated icons, the most reliable way to get a clean transparent
PNG is: ask the model to render the subject on a solid magenta
(#FF00FF) (or chroma-green) background, then key it out:
# Chroma-key-friendly prompt (no pink/purple on subject) — defaults
# are tuned for this, no flags needed
# Softer / prettier AI prompt (any hue, soft shadows) — the
# "high-quality" combo: narrower flood + edge despill + 1 px erode
# Override the detected background / pick a specific key colour
# Batch a whole directory
For sheets of multiple icons, combine with split — it accepts the
same --tolerance / --despill / --shrink flags:
| Flag | Default | Purpose |
|---|---|---|
--bg <#RRGGBB> |
auto | Override the detected background colour |
--tolerance <N> |
200 | RGB distance threshold for flood-fill |
--despill |
off | Channel-based spill suppression on edge band |
--despill-band <N> |
3 | Edge-band radius (pixels) for --despill |
--shrink <N> |
0 | Morphological erosion of the opaque region |
The algorithm is a connectivity-based flood fill from the four corners
through pixels within --tolerance RGB-distance of the detected
background colour. Flooded pixels become alpha 0; everything else is
left exactly as-is — no colour shifting, no soft alpha halo. A near-bg
pixel buried inside the subject (e.g. a designed pink sparkle) is not
reachable from the corners and survives. Raise --tolerance if a halo
remains, lower it and add --despill --shrink 1 if pastel subject
regions dissolve.
For best results, use a chroma-key-friendly generator prompt that
forbids purple/pink/violet hues on the subject — see
assets/skills/pixa/SKILL.md for a copy-paste template.
Generate a favicon set
Outputs:
favicon.ico(multi-resolution: 16×16, 32×32, 48×48)favicon-16x16.png,favicon-32x32.pngapple-touch-icon.png(180×180)android-chrome-192x192.png,android-chrome-512x512.png- HTML
<link>snippet to paste into<head>
Convert format only
For most cases, prefer compress -o foo.webp since that also re-encodes
the output for size.
Inspect image
Remove or detect Gemini watermark
--if-detected skips images that don't actually contain a watermark.
Project layout
pixa/
├── Cargo.toml
├── assets/
│ ├── watermark_48x48.png # embedded chromakey alpha maps
│ ├── watermark_96x96.png
│ └── skills/pixa/SKILL.md # bundled into the binary by `install`
└── src/
├── main.rs # CLI entry point
├── lib.rs # public library API
├── compress.rs # JPEG / PNG / WebP encode + resize
├── convert.rs # format conversion
├── favicon.rs # favicon set generation
├── info.rs # metadata extraction
├── split.rs # sheet auto-cropping
├── transparent.rs # chroma-key / color-to-alpha
├── watermark.rs # Reverse Alpha Blending
└── commands/ # one file per subcommand
├── mod.rs # shared utilities (walk, format, mirror)
├── style.rs # ANSI color / symbol helpers
├── compress.rs
├── convert.rs
├── detect.rs
├── favicon.rs
├── info.rs
├── install.rs
├── remove_watermark.rs
└── split.rs
How watermark removal works
Gemini composites its visible watermark using:
watermarked = α × logo + (1 - α) × original
pixa solves for the original pixel values:
original = (watermarked - α × logo) / (1 - α)
Pre-calibrated 48×48 / 96×96 alpha maps (embedded in the binary) are used directly, so no AI inference is required. Detection runs in three stages: Spatial NCC + Gradient NCC + Variance Analysis.
License
MIT