Automatic frame detection and crop sidecar generation for scanned film negatives.
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.
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.
- Scans a folder of RAW files.
- Detects each frame boundary with lightweight signal-processing heuristics.
- Writes Lightroom-compatible
.xmpcrop sidecars next to each RAW. - Optionally writes preview JPEGs to inspect results.
Croppy does not modify, delete, or rewrite your RAW files.
- Bulk import your scanned RAW negatives into Lightroom Classic.
- Run Croppy on the scan directory.
- In Croppy, select files and enable
XMP Sidecars. - Back in Lightroom, select the files and use
Metadata > Read Metadata from Files(or right-click equivalent) to apply crops. - Do any needed flips/inversion/WB adjustments in Lightroom.
- Run Negative Lab Pro in bulk, usually roll by roll.
- Open the latest release page.
- 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
- Extract the archive.
- 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"Requires libclang (needed by rsraw-sys for LibRaw bindings). On Debian/Ubuntu:
sudo apt install libclang-devThen build:
cargo build --releaseBinary path:
target/release/croppy
croppy /path/to/raw/folderRun croppy --help for all options. Key flags:
--max-edge <N>downscale long edge before detection (default1000)--out-dir <PATH>where preview output folder is created (default current directory)--recursiverecursive scan flag (scan is recursive in normal use)
Supported RAW extensions include: ARW, CR2, CR3, NEF, NRW, RAF, ORF, RW2, DNG, PEF.
- File selection:
Up/Downmove cursorSpacetoggle one fileaselect alluselect all files without existing.xmpnclear selection
- Outputs and preview mode:
xtoggle XMP sidecarsvtoggle preview JPEGspcycle preview mode (Overlay,Final Crop,Crop + Frame)
- Crop tuning:
-/=adjustFinal Crop Scaleby0.25%0reset crop scale,/.adjust horizontal trim;/'adjust vertical trim9reset trim defaults
- Run/cancel:
Enterstarty/nconfirm/cancel XMP overwrite promptccancel active runqquit
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.
- XMP output:
<raw_basename>.xmpnext 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.
- 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:2aspect ratio. - You should still do a quick manual review pass.
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.
- Decode the RAW file, preferring the embedded JPEG preview for speed.
- Preprocess to grayscale, invert, level-stretch, and optionally flip 180 degrees.
- Detect frame boundaries by building 1D brightness profiles, taking their derivatives, and finding the first strong peak from each side.
- Refine rotation by fitting lines to edge points and applying a skew correction (capped at 3 degrees).
- Write Lightroom crop metadata (
CropLeft,CropTop,CropRight,CropBottom,CropAngle) to XMP sidecars.
For the full technical details, see the blog post.
Contributions are welcome. See CONTRIBUTING.md.

