# crapify
Deep-fry your images, and other crimes against pixels.
`crapify` is the evil twin of [`mogrify`](https://imagemagick.org/script/mogrify.php). Same CLI ergonomics as ImageMagick's batch image-transform tool, opposite goal: take a perfectly fine image and make it look like total dogshit. The crapification is pluggable — each transform is a named **crapifier** you can stack, parameterize, and chain into a pipeline.
## What it does
The flagship crapifier is `deep-fry`, which reproduces the mid-2010s "this meme has been forwarded so many times it's become a hot mess" aesthetic. The recipe:
1. Re-save the image as a low-quality JPEG several times in a row, so the compression damage compounds with every round-trip.
2. Push saturation and contrast past where a sane image editor would let you go.
3. Sharpen edges hard so the blocky JPEG patches grow visible halos around everything.
4. Sprinkle grainy speckle on top so even the smooth areas look gritty.
Five preset doneness levels ship out of the box — `raw`, `pan-seared`, `chicken-fried`, `deep-fried` (the default), `forwarded-by-your-dad` — each one bundling all seven knobs (quality, passes, saturation, contrast, brightness, sharpen-radius, noise) into a single named ramp. Pass `--preset <slug>` to pick one; pass individual knobs to override.
The second crapifier is `palettecrush`: snap every pixel to a tiny fixed palette (web-safe 16, GameBoy green, CGA, NES, C64, Atari 2600 — twelve catalogs ship in the box) with optional dithering, for the "saved-from-a-1997-GeoCities-page" look. Three named presets — `geocities` (16-color CSS palette + 8×8 Bayer crosshatch, the default), `gameboy-pocket` (4 swamp greens, no dither), `cga-eyestrain` (CGA cyan/magenta, no dither). Adaptive quantization via `--colors N` is the escape hatch when you want a custom-tuned palette.
Other crapifiers are sketched (xerox-machine simulation, format-rotting through pointless conversions, aspect-ratio mangling), but v0.1.0 shipped `deep-fry` and `palettecrush` landed in the next release.
## Try it
```
# Default ("deep-fried") preset:
crapify deep-fry in.png out.png
# Maximum doneness:
crapify deep-fry --preset forwarded-by-your-dad in.png out.png
# Preset + targeted override:
crapify deep-fry --preset deep-fried --saturation 2.0 in.jpg out.png
# Raw knobs, no preset:
crapify deep-fry --quality 32 --passes 5 in.png out.png
# Palette-quantize to the geocities preset (web-safe 16 + bayer-8):
crapify palettecrush in.png out.png
# Pick a different palette + dither:
crapify palettecrush --palette nes-54 --dither floyd-steinberg in.png out.png
# Adaptive 4-color palette, no dither:
crapify palettecrush --colors 4 --dither none in.png out.png
# Pipeline: deep-fry first, then palettecrush:
crapify deep-fry --preset chicken-fried + palettecrush --preset geocities in.png out.png
```
## Doneness presets
`crapify deep-fry --help` ends with this preset table. Each row is a complete recipe — pick a doneness level and you get all seven knobs at once. Override individual knobs alongside `--preset` to mix-and-match.
```
PRESETS (via --preset <slug>):
raw "Raw" q=95, 1 pass. Barely touched.
pan-seared "Pan seared" q=78, 1 pass. Light crunch.
chicken-fried "Chicken fried" q=60, 2 passes. Visible JPEG mess.
deep-fried "Deep fried" q=50, 3 passes. The canonical look (also the default).
forwarded-by-your-dad "Forwarded by your dad" q=32, 5 passes. Maximum doneness.
```
Full per-knob docs with units and value ranges:
```
crapify --help # top-level: pipeline grammar + registered stages
crapify deep-fry --help # per-stage: every knob + the preset table
crapify palettecrush --help # palette catalog + dither options + preset bindings
```
## Pipeline grammar
Stages are composed in a single command, separated by `+`. The last two positional arguments are always input and output:
```
crapify <stage> [args] + <stage> [args] ... <input> <output>
```
Each crapifier between `+`s gets its own argument parser, so flag names don't collide across stages. v0.1.0 shipped `deep-fry` alone; subsequent releases add more crapifiers (starting with `palettecrush`) that drop straight into the pipeline. Reproducible-randomness (a global `--seed`) is deferred to a later release; for now, `deep-fry`'s grain pattern is fresh per invocation. `palettecrush` is fully deterministic — same input + same flags = identical output every time, no seed needed.
## Install
```
cargo install crapify
```
Or grab a pre-built binary from the [latest release](https://github.com/bojanrajkovic/crapify/releases/latest) (Linux x86_64, macOS Apple Silicon, Windows x86_64).
Or build from source:
```
git clone https://github.com/bojanrajkovic/crapify.git
cd crapify
cargo build --release
./target/release/crapify --help
```
Requires Rust 1.95 or later; the pinned toolchain lives in `mise.toml`.
## Why does this exist?
The deep-fried-meme aesthetic was a defining visual of mid-2010s internet culture, and there's no good CLI tool for reproducing it. ImageMagick can do it in four lines of shell, but the *bit* is having a dedicated, lovingly-named binary. A small Rust CLI is also a fine shape for hands-on time with the `image` and `imageproc` crates. And if anyone needs a practical excuse: thumbnailers, OCR, and vision models all have to survive degraded inputs in the wild, and `crapify` is a convenient fuzz/torture input generator. Mostly, though, it's funny, which is enough.
## License
WTFPL. See [`LICENSE`](./LICENSE).