Skip to content

0.1.0 - 2026-07-03

Choose a tag to compare

@github-actions github-actions released this 04 Jul 02:44

Release Notes

This is the initial MVP release: a single static Rust binary that turns image
prep from guess-a-quality-knob to declare-an-intent. Zero system dependencies
by default; all formats handled in pure Rust.

Added

Inspect and view

  • view <INPUT> — display an image directly in the terminal via viuer (the
    display feature is on by default; headless builds omit it with
    --no-default-features).
  • info <INPUT> [--exif] [--json] — print dimensions, format, file size on disk,
    color type, bit depth, alpha presence, and ICC/EXIF presence. --exif dumps EXIF
    tags; --json emits machine-readable output to stdout.

Geometry / transform

  • resize <INPUT...> — resize with a SIMD backend in six modes: --max (long-edge
    bound, never upscales), --exact WxH, --percent P, --fit WxH (letterbox,
    never upscales), --cover WxH (fill box, may upscale), --fill WxH
    (cover + center-crop to exact dimensions). Batch-ready with --out-dir.
  • thumbnail <INPUT...> [--size N] [--square] — convenience resize: bounds the
    longest edge to N (default 256), or produces an exact N×N square via cover +
    center-crop.
  • shrink <INPUT...> — optimize for web: resize to a long-edge bound (default 1600),
    re-encode at quality 80, drop metadata. Accepts --target visually-lossless|high|medium or --ssim <0-100> for perceptual auto-quality
    (binary-searches SSIMULACRA2; see below), or --max-size <KB/MB> for a byte
    budget with automatic dimension-reduction fallback.
  • convert <INPUT...> --format FMT — pure re-encode to another format with no pixel
    transform. Supports all core formats plus WebP (default build) and AVIF (opt-in
    feature). --max-size <SIZE> fits the output under a byte budget for every format.
  • auto-orient <INPUT...> — bake the EXIF orientation into pixels and clear the tag,
    fixing the common silent-rotation bug. A no-op when no orientation tag is present.

Optimize, diff, and responsive web delivery (STAGE-009)

  • optimize <INPUT...> — one-command web prep: auto-orient + strip metadata +
    perceptual visually-lossless re-encode in a single pass. The "just make this
    web-good" default.
  • diff <A> <B> [--fail-under N] [--json] — compute an SSIMULACRA2 perceptual
    similarity score between two images. --fail-under N turns it into a CI
    visual-regression gate: a score below N exits with code 7 (distinct from a
    runtime error), so CI can tell "regression detected" from "couldn't run".
  • responsive <INPUT> --widths W1,W2,… --out-dir DIR [--formats …] — generate a
    width × format responsive image set and print a paste-ready <picture>/srcset
    HTML snippet to stdout.

Perceptual auto-quality and byte budgets (STAGE-008)

  • SSIMULACRA2-driven quality search: binary-searches the encoder quality against a
    perceptual target — the smallest file that still clears a visual quality level.
    Available via --target visually-lossless|high|medium or --ssim <score> on
    shrink and optimize.
  • Byte-budget mode (--max-size <SIZE>) on shrink and convert: lowers quality
    first, then progressively downscales dimensions as a fallback when quality alone
    cannot meet the budget. Works for every output format, including lossless ones.
  • Modern formats: WebP is the pure-Rust default (lossless; lossy via opt-in
    webp-lossy feature); AVIF is a pure-Rust opt-in feature (--features avif,
    via ravif). Both are available as output targets for all quality/budget modes.

Compositing and text overlays (STAGE-004 / SPEC-029-030)

  • watermark <INPUT...> --image LOGO [--gravity G] [--opacity O] [--scale S] [--margin M] [--tile] — overlay an image watermark at a compass gravity anchor
    (default southeast); supports tiling, opacity, and proportional scaling.
  • watermark <INPUT...> --text STRING [--font PATH] [--size N] [--color HEX]
    rasterize text (via ab_glyph) and composite it as an overlay. Default font is
    the bundled BSD-3 Go font.

Metadata lane — container-level ops, no pixel re-encode (STAGE-004)

All four commands operate on the image container directly — pixels are never
re-decoded, so privacy ops carry no quality cost and no recompression.

  • strip <INPUT...> — remove all container metadata (EXIF/IPTC/XMP/ICC). Supports
    JPEG and PNG.
  • clean <INPUT...> --gps — selectively remove GPS/location tags while preserving
    all other metadata (orientation, copyright, ICC). Supports JPEG and PNG.
  • set <INPUT...> [--artist S] [--copyright S] [--description S] — write named
    EXIF tags, creating a fresh EXIF block when the input has none.
  • copy-metadata --from SRC --to DST — copy EXIF + ICC from one image onto another
    without touching pixels or XMP. JPEG only in v1.
  • Default drop-GPS policy on all pixel-lane encodes (--keep-gps to opt out).

Recipes and parallel batch (STAGE-005)

  • edit <INPUT> [--auto-orient] [--resize-max N] [--invert] [--save-recipe FILE]
    chain an ordered op list on a single image in one decode→ops→encode pass. Ops
    apply in a fixed canonical order regardless of flag order, so the result is
    deterministic. --save-recipe FILE serializes the chain to a TOML recipe.
  • apply --recipe FILE <INPUT...> [--out-dir DIR] [-j N] — replay a saved recipe
    across a file, glob, or directory in parallel (rayon, -j N bounds workers) with
    an indicatif progress bar on stderr. The recipe that tuned one image runs
    unchanged across thousands. Per-input failures are summarized and exit with
    code 6; other inputs still write.
  • Recipe round-trip is byte-pinned: edit output equals apply-of-the-saved-recipe
    output on the same input.

Global options and exit-code contract

  • Global flags across all subcommands: --output / -o, --out-dir, --format,
    --quality / -q, --verbose / -v, --quiet / -Q, --yes / -y, --keep-gps,
    --jobs / -j.
  • Stdin/stdout piping: - as input or output keeps diagnostic output on stderr so
    pipes stay clean.
  • Typed exit codes: 0 success, 1 runtime error, 2 usage error, 3 input not found,
    4 unsupported format/codec not built, 5 output write refused, 6 partial batch
    failure, 7 check/gate not satisfied.
  • completions <bash|zsh|fish|powershell|elvish> — print a clap-generated shell
    completion script to stdout (e.g. crustyimg completions zsh > _crustyimg).

Security

  • Decode resource limits — every image load is bounded via image::Limits:
    per-dimension ≤ 65 535 px, decoded allocation ≤ 512 MiB. Decompression bombs and
    forged-dimension inputs are rejected with a typed error (exit 1) before pixels are
    produced; never a panic or OOM.
  • Recipe resource limits — untrusted recipe files over 64 KiB or with more than
    1024 steps are rejected before being read into memory.
  • Resize output cap — a resize whose output buffer would exceed 512 MiB (upscale
    bomb via exact/percent/cover/fill, from CLI or recipe) is rejected before
    allocation.
  • Path and symlink guards.., separator characters, and absolute paths in
    output names are rejected; symlinked destinations are refused even with --yes.
  • Supply-chain CIcargo deny check (advisories, bans, sources, licenses)
    runs in CI on every push.
  • A recorded threat model (SECURITY.md) maps each untrusted-input surface to its
    mitigation and the spec/decision that built it; an adversarial review over the
    cumulative diff found no unresolved finding.

Install crustyimg 0.1.0

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/jysf/crustyimg/releases/download/v0.1.0/crustyimg-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/jysf/crustyimg/releases/download/v0.1.0/crustyimg-installer.ps1 | iex"

Install prebuilt binaries via Homebrew

brew install jysf/tap/crustyimg

Download crustyimg 0.1.0

File Platform Checksum
crustyimg-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
crustyimg-x86_64-apple-darwin.tar.xz Intel macOS checksum
crustyimg-x86_64-pc-windows-msvc.zip x64 Windows checksum
crustyimg-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum