Skip to content

Film negative conversion: non-destructive & in-library (replaces the modal/TIFF flow)#1349

Open
SandeepSubba wants to merge 3 commits into
CyberTimon:mainfrom
SandeepSubba:upstream-negative-conversion
Open

Film negative conversion: non-destructive & in-library (replaces the modal/TIFF flow)#1349
SandeepSubba wants to merge 3 commits into
CyberTimon:mainfrom
SandeepSubba:upstream-negative-conversion

Conversation

@SandeepSubba

Copy link
Copy Markdown

Summary

Reworks the Film Negative Converter from a modal that bakes a separate _Positive.tiff into a non-destructive, in-library conversion that fits RapidRAW's sidecar model.

You right-click a negative → Convert Negative. It inverts to a neutral positive in place (no new file, no duplicate library entry), and you do all the tuning — exposure, white balance, contrast, curves, masks — in the normal Develop module on top. Right-click → Revert to Negative turns it back off.

Why

The old flow was self-contained because it was destructive: once you exported the TIFF there was no going back, so the modal carried its own exposure / contrast / white-balance sliders. Those duplicate what Develop already does. The only genuinely negative-specific step is the density inversion + per-channel auto-bounds — everything else belongs in Develop. Making it non-destructive removes the duplication and the duplicate files, and makes the conversion re-tunable and reversible.

What changed

Behaviour

  • Right-click Convert Negative / Revert to Negative in both the editor and the library/filmstrip context menus. The label toggles based on whether the image(s) are already converted; batch selection works.
  • The conversion (density inversion + per-channel auto-bounds) is stored in the image's .rrdata sidecar as negativeConversion: { enabled, bounds } and applied on load, so the editor, thumbnails and export all render the positive. The original raw is never touched.
  • The Convert Negative modal is removed.

Backend

  • Replaces preview_negative_conversion / convert_negatives with a single set_negative_conversion(paths, enabled).
  • maybe_apply_negative inverts a flagged negative at the single decode chokepoint (load_base_image_from_bytes), so every consumer agrees.
  • Auto-bounds are still computed at convert time (same NegPy-derived analysis) for a good neutral starting point.
  • Adjustment saves preserve the backend-owned negativeConversion block, so a normal edit or navigation can't strip it; thumbnails regenerate on convert/revert.

Notes

  • Backward compatible — existing sidecar conversions still render.
  • The inversion math is unchanged (still the NegPy-derived pipeline, GPL-3.0, credited as before).

🤖 Generated with Claude Code

@SandeepSubba
SandeepSubba requested a review from CyberTimon as a code owner July 7, 2026 16:21
@CyberTimon

Copy link
Copy Markdown
Owner

Great PR!

My notes from a quick testing:

  • Batch negative conversion works but batch reverting doesn't do anything
  • Too many AI generated code comments. Please remove these code comments.

Thanks a lot, looks good otherwise :)

subbajeu and others added 2 commits July 8, 2026 21:57
…/TIFF flow)

Reworks the Film Negative Converter from a modal that bakes a separate
_Positive.tiff into a non-destructive, in-library conversion that fits the
sidecar model.

- Right-click 'Convert Negative' inverts a negative to a neutral positive in
  place (density inversion + per-channel auto-bounds), stored in the raw's
  .rrdata sidecar as negativeConversion { enabled, bounds } and applied on load
  (single decode chokepoint, load_base_image_from_bytes), so the editor,
  thumbnails and export all render the positive. The original raw is untouched.
- All further tuning (exposure, white balance, contrast, curves, masks) happens
  in the normal Develop module on top. 'Revert to Negative' removes it; the
  editor + library/filmstrip menus toggle Convert/Revert based on state.
- Backend: replaces preview_negative_conversion/convert_negatives with a single
  set_negative_conversion(paths, enabled). Adjustment saves preserve the
  backend-owned negativeConversion block; thumbnails regenerate on convert/revert.
- Removes the Convert Negative modal.

Inversion math unchanged (NegPy-derived, GPL-3.0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Batch revert was a no-op: the context-menu toggle keys off each item's
  is_negative flag, which only refreshed via the async folder re-list, so a
  freshly-converted batch still read is_negative=false and the toggle kept
  re-converting instead of reverting. Update the affected list items optimistically
  right after the command so Convert/Revert flips immediately.
- Trim the verbose doc/inline comments across the negative-conversion files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@SandeepSubba
SandeepSubba force-pushed the upstream-negative-conversion branch from 4ac81df to 8952181 Compare July 8, 2026 13:58
These two files are left unformatted on upstream/main (from the CyberTimon#1339 Android LUT
fix) and fail `cargo fmt --check` in CI; `cargo fmt` collapses three multi-line
calls that fit on one line. Not part of the negative-conversion feature — included
only so this PR's lint job passes. main needs the same fix independently.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants