Skip to content

Latest commit

 

History

25 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

stitch

Combine 2+ images into one composite from the command line — horizontal or vertical strips. Single binary, no runtime dependencies.

What is stitching?

Give it two (or more) images; you get back one image with them side by side, heights normalized so the top and bottom edges line up:

examples/red.png (240×160) examples/blue.png (120×80)
red gradient input blue gradient input
stitch examples/red.png examples/blue.png -o examples/montage.png

resulting montage: both gradients side by side

The result is a single 240×80 PNG: the taller red image was downscaled to 120×80 to match the smallest input height (the default --fit min, which never upscales; --fit 160 would have upscaled the blue one instead). Add --vertical to stack instead, --gap/--bg for spacing and background, --cols 2 for grids — full option list below.

Install

cargo install --path .

Usage

# Side by side, heights auto-normalized (default: downscale to the smallest)
stitch a.png b.png c.png -o out.png

# Stack vertically, 10px gap, white background, JPEG output
stitch *.jpg -o out.jpg --vertical --gap 10 --bg white

# Normalize all tile heights to exactly 480px
stitch a.png b.png -o out.png --fit 480

# 2x2 grid with gaps on a white background
stitch *.png -o grid.png --cols 2 --gap 8 --bg white

# Fixed 1200x630 canvas, every tile fills its cell (crop overflow)
stitch a.jpg b.jpg c.jpg -o banner.jpg --width 1200 --height 630 --mode cover

# Contact sheet: rounded corners, borders, labels
stitch *.jpg -o wall.png --cols 4 --radius 12 --border 2 --label "a,b,c,d"

# Compose in a pipe
cat cover.jpg | stitch - hero.jpg -o - --format jpg > banner.jpg

Options

Option Default Meaning
-o, --output PATH required output file; format from extension (png, jpg, webp); - writes stdout (needs --format)
--format FMT png/jpg/webp; overrides the extension, required for -o -
-d, --direction horizontal horizontal/h or vertical/v
-g, --gap N 0 gap between images: single value or WxH (e.g. 4x8)
-m, --margin N 0 outer margin in px
-b, --bg COLOR transparent named color or hex (#rgb, #rgba, #rrggbb, #rrggbbaa); JPEG output flattens transparent onto white
--fit FIT min tile size along the cross axis: min (never upscales), max, first, or exact px (e.g. 480); in grids, normalizes tile heights (ignored by --mode none)
--grid RxC grid layout like 2x3; unfilled cells stay empty
--cols N / --rows N grid with the other axis flowing automatically
--align A center tile position in grid cells (start/center/end); also the crop anchor for --mode cover
--mode M contain how images fill grid cells: contain (fit fully), cover (fill and crop), none (no cell-based scaling)
--width/--height PX fixed canvas size; without grid flags, the strip becomes a single-row/column grid
--quality N 90 JPEG quality, 1–100
--border N 0 border thickness in px, drawn over tile edges
--border-color C white border color (syntax as --bg)
--radius N 0 rounded-corner radius; keep alpha with PNG/WebP output
--label TEXTS comma-separated caption per tile (final, sorted order)
--label-size N 24 label font size in px
--label-color C white label color
--font PATH system font font file for labels (.ttf/.ttc/.otf)
--sort KEY argument order name, size, or time
--shuffle off randomize input order
-v, --verbose off print the computed layout to stderr

Notes:

  • JPEGs are auto-rotated per their EXIF orientation.
  • Transparent PNGs are alpha-blended over --bg; PNG output keeps alpha.
  • Grids flow row-major by default; --vertical switches to column-major (down first, then across).
  • Grid cells are the bounding box of the (height-normalized) images, or equal divisions of a fixed --width/--height canvas.
  • Labels use a system font when --font is not given (macOS: Helvetica, Linux: DejaVu/Liberation). Label strips are reserved space under each tile (strips) or at the bottom of each grid cell.
  • - as an input path reads one image from stdin.
  • HEIC input is not supported yet (convert first, e.g. sips -s format jpeg).

License

MIT — see LICENSE. The bundled test font (Silkscreen, tests/fixtures/fonts/) is separately licensed under the SIL Open Font License 1.1; it is not compiled into the binary.

Development

cargo test        # unit + CLI smoke + golden-image tests
cargo run -- a.png b.png -o out.png --verbose

Golden-image tests

tests/golden.rs renders fixed gradient inputs and compares pixel-exact against references in tests/fixtures/goldens/ (tolerance: 2 per channel). Label goldens bundle the Silkscreen font (SIL OFL, tests/fixtures/fonts/) so text renders identically on every platform. After an intentional rendering change, regenerate and commit the references:

UPDATE_GOLDENS=1 cargo test --test golden

About

Combine 2+ images into one composite from the command line

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages