Skip to content

cgbur/croppy

Repository files navigation

Croppy

Automatic frame detection and crop sidecar generation for scanned film negatives.

Croppy TUI and detection preview

Left: file selection and run options. Right: preview overlay showing detected crop boundaries. Yellow is the initial detection, cyan is the rotation-aligned refinement, and green is the final crop written to the XMP sidecar.

Why this exists

After scanning negatives (with holders like the VALOI easy35 or a custom camera scanning setup), frames are often slightly off-center, skewed, or inconsistent. Manually fixing the crop on every frame in Lightroom before running Negative Lab Pro is slow.

Croppy removes most of that manual first-pass crop work. For a deeper writeup on the motivation and how the detection works, see the blog post.

What it does

  • Scans a folder of RAW files.
  • Detects each frame boundary with lightweight signal-processing heuristics.
  • Writes Lightroom-compatible .xmp crop sidecars next to each RAW.
  • Optionally writes preview JPEGs to inspect results.

Croppy does not modify, delete, or rewrite your RAW files.

Typical Lightroom + Negative Lab Pro flow

  1. Bulk import your scanned RAW negatives into Lightroom Classic.
  2. Run Croppy on the scan directory.
  3. In Croppy, select files and enable XMP Sidecars.
  4. Back in Lightroom, select the files and use Metadata > Read Metadata from Files (or right-click equivalent) to apply crops.
  5. Do any needed flips/inversion/WB adjustments in Lightroom.
  6. Run Negative Lab Pro in bulk, usually roll by roll.

Install

Option 1: Download a prebuilt release (recommended)

  1. Open the latest release page.
  2. Download the asset for your platform:
  • Linux x86_64: croppy-vX.Y.Z-x86_64-unknown-linux-gnu.tar.gz
  • macOS (Apple Silicon): croppy-vX.Y.Z-aarch64-apple-darwin.tar.gz
  1. Extract the archive.
  2. Move the binary into a directory on your PATH.

Windows: Native Windows builds are not currently supported because LibRaw, the underlying RAW decoding library, does not build on Windows. If you're on a Windows machine, use WSL (Windows Subsystem for Linux) and run Croppy from there. This works well and is what I do on my own Windows desktop.

Linux / macOS example:

mkdir -p "$HOME/.local/bin"
cp croppy "$HOME/.local/bin/croppy"
chmod +x "$HOME/.local/bin/croppy"

If needed, add to shell profile (~/.bashrc or ~/.zshrc):

export PATH="$HOME/.local/bin:$PATH"

Option 2: Build from source

Requires libclang (needed by rsraw-sys for LibRaw bindings). On Debian/Ubuntu:

sudo apt install libclang-dev

Then build:

cargo build --release

Binary path:

target/release/croppy

Run

croppy /path/to/raw/folder

Run croppy --help for all options. Key flags:

  • --max-edge <N> downscale long edge before detection (default 1000)
  • --out-dir <PATH> where preview output folder is created (default current directory)
  • --recursive recursive scan flag (scan is recursive in normal use)

Supported RAW extensions include: ARW, CR2, CR3, NEF, NRW, RAF, ORF, RW2, DNG, PEF.

TUI controls

  • File selection:
    • Up/Down move cursor
    • Space toggle one file
    • a select all
    • u select all files without existing .xmp
    • n clear selection
  • Outputs and preview mode:
    • x toggle XMP sidecars
    • v toggle preview JPEGs
    • p cycle preview mode (Overlay, Final Crop, Crop + Frame)
  • Crop tuning:
    • - / = adjust Final Crop Scale by 0.25%
    • 0 reset crop scale
    • , / . adjust horizontal trim
    • ; / ' adjust vertical trim
    • 9 reset trim defaults
  • Run/cancel:
    • Enter start
    • y / n confirm/cancel XMP overwrite prompt
    • c cancel active run
    • q quit

Trim mode explained

XMP Trim is a normalized adjustment applied symmetrically on each axis:

  • Horizontal trim moves both left and right crop edges.
  • Vertical trim moves both top and bottom crop edges.
  • Positive trim shrinks the crop inward.
  • Negative trim expands it outward.

Defaults are:

  • Horizontal trim: +0.0000
  • Vertical trim: +0.0050

That default vertical trim is a small inward bias that often helps remove a little extra edge/border in real scans.

Output behavior and safety

  • XMP output: <raw_basename>.xmp next to each RAW.
  • Preview output: <out-dir>/previews/<raw_basename>.jpg.
  • If XMP already exists, Croppy prompts before overwriting.
  • RAW source files are never modified.

Limitations

  • Crops can be wrong on difficult frames, especially high-contrast black and white scans.
  • Crops are currently free-form and not constrained to a fixed 3:2 aspect ratio.
  • You should still do a quick manual review pass.

Example of an incorrect crop on a high-contrast B&W scan

An example where the crop aspect ratio is clearly wrong. The detection doesn't try to constrain to a particular aspect ratio. That said, even though the crop boundaries aren't correct, it still accurately selects the region of interest within the frame. Negative Lab Pro will do a good conversion from this selection; you'll just need to fix the crop manually afterwards.

How it works

  1. Decode the RAW file, preferring the embedded JPEG preview for speed.
  2. Preprocess to grayscale, invert, level-stretch, and optionally flip 180 degrees.
  3. Detect frame boundaries by building 1D brightness profiles, taking their derivatives, and finding the first strong peak from each side.
  4. Refine rotation by fitting lines to edge points and applying a skew correction (capped at 3 degrees).
  5. Write Lightroom crop metadata (CropLeft, CropTop, CropRight, CropBottom, CropAngle) to XMP sidecars.

For the full technical details, see the blog post.

License

MIT

Contributing

Contributions are welcome. See CONTRIBUTING.md.

About

Batch auto-crop tool for scanned film negatives in Lightroom

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Contributors