Skip to content

feat(iv): comparison modes (wipe/absdiff/FLIP) and --compare flag - #5584

Open
linsen458-spec wants to merge 2 commits into
AcademySoftwareFoundation:mainfrom
linsen458-spec:feat/iv-compare-modes
Open

linsen458-spec wants to merge 2 commits into
AcademySoftwareFoundation:mainfrom
linsen458-spec:feat/iv-compare-modes

Conversation

@linsen458-spec

@linsen458-spec linsen458-spec commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Closes #4711.

Motivation

#4711 asks for difference visualizations in iv. The wipe comparison from #5480 (two-texture-slot renderer) provides the groundwork; this adds a difference view on top of it, kept separate from the wipe in the UI (per review feedback below).

What changed

  • Wipe (W) is unchanged from feat(iv): image wipe compare #5480.
  • Difference view (View > Difference): Off (default) / Absolute difference / FLIP, with D cycling through them. Entering it pairs the current image with the last one displayed (same rule as the wipe) and shows the result immediately. Wipe and difference view are mutually exclusive.
  • AbsDiff in the fragment shader: per-pixel absolute difference, shown as the grayscale magnitude of the most-differing channel; no CPU cost, interactive at any zoom.
  • FLIP on a background thread: ImageBufAlgo::FLIP_diff on a worker, uploaded as a third texture when ready; error map through color_map() (inferno by default, toggleable in the Difference submenu); a signature cache skips recomputes for the same pair. While it runs: busy cursor + "Computing FLIP difference..." in the status bar.
  • --compare wipe|absdiff|flipdiff starts iv directly in the wipe or the chosen difference view.

Verification

Manual end-to-end on Linux (X11, Qt 6): D cycles Off → absdiff → FLIP → Off; W/D switch each other off; paging to another image re-pairs; absdiff of identical images is black; FLIP output matches the offline fliptest reference; the computing indicator shows and clears on a 4k pair; --compare with a single image prints a diagnostic and shows the plain image.

Packaging

The FLIP part (background thread + color map) is separable if you'd rather land wipe-independent absdiff first.

Assisted-by: glm-5.3-flash

Extend iv's image comparison (AcademySoftwareFoundation#4711), building on the two-texture-slot
architecture from AcademySoftwareFoundation#5480:

- A unified "comparison mode": the existing W toggle turns comparison
  on, and a View > Comparison Mode submenu selects Wipe (default,
  identical to AcademySoftwareFoundation#5480), Absolute difference, or FLIP difference.
- Absdiff is computed in the fragment shader (grayscale magnitude of
  the most-differing channel per pixel), so it has no CPU cost or
  latency even for large images.
- FLIP diff is computed on a background worker thread with
  ImageBufAlgo::FLIP_diff and uploaded as a third texture when ready;
  the error map is run through color_map() (inferno by default,
  toggleable) for readability, and a signature-based cache skips
  recomputation while the same image pair is displayed.
- New --compare wipe|absdiff|flipdiff command line flag starts iv
  directly in the chosen comparison mode.

Assisted-by: Claude Code / glm-5.3-flash

Signed-off-by: linsen <251731047+linsen458-spec@users.noreply.github.com>
@lgritz

lgritz commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator

This is super cool!

I do have some UX feedback, though.

I found it a little difficult to grok that you could have two images loaded, select "absolute difference" or "FLIP" mode, and then... nothing happens. You have to ALSO be in "wipe" mode to see the difference image, which is also a little odd because you're not able to wipe anything in those modes?

I do see what you were getting at conceptionally: there are three ways to compare two images -- wipe between them, diff them, or FLIP compare them. It sounds good on paper, but it wasn't until I tried it that it was clear that in practice, that's an awkward experience.

I think the utilization of some of the infrastructure we used to implement wipe mode may be helpful, but from a UI standpoint, they should probably be separate features. Maybe wipe wipes only, and some other comparison mode toggles between plain view, absdiff, and FLIP?

The only other thing was that because it takes a bit of time to compute the FLIP image (the image I tried was 4k, so kinda big), there was a moment of "is it going to so something?" not sure if I did the command right. Then it switches. Maybe it would be helpful to have a spinning clock or whatever icon means things are loading, so you can tell that something is in progress?

@linsen458-spec

Copy link
Copy Markdown
Contributor Author

Thanks for trying it out, and for the feedback. You're right, that's a flaw in my design.

Everything currently hangs off the #5480 toggle: W turns comparison on and off, and the Comparison Mode submenu only picks which comparison runs, so unless W is on, selecting absolute difference or FLIP does nothing. Looking back, piling the three comparisons into one mode with three states doesn't work well in practice. I'll split them the way you suggest:

  • Wipe stays as it is in feat(iv): image wipe compare #5480. W toggles the split, nothing else.
  • A separate Difference submenu under View: Off (default) / Absolute difference / FLIP, with D cycling through the three. The color map toggle moves in there too.
  • Entering the difference view shows something right away. It pairs the current image with the last one displayed, same rule as wipe, so no second toggle is needed. Wipe and the difference view are mutually exclusive; turning one on turns the other off, since a difference image is a single image with nothing to wipe.
  • --compare keeps its meaning: wipe for the wipe, absdiff/flipdiff for the difference view.

For the FLIP wait, I'll show a busy cursor and a status bar message ("Computing FLIP difference...") while the background worker runs, and clear them when it's done. Absdiff runs in the shader so it's instant and doesn't need one.

What do you think of this approach? I'll start on it right away and push once it's done.

@lgritz

lgritz commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator

What do you think of this approach? I'll start on it right away and push once it's done.

That all sounds great to me.

Maybe somebody with more UI imagination than me could have been more specific from the start, but in this case, I think I had to experience it myself to know what was working smoothly and what was not. Thanks for being so receptive to the feedback.

As a note: I'd only used the FLIP myself in oiiotool, and in that context, even if it takes 3-4 seconds for a big image, who cares? But in iv, you really feel the delay, even with the busy cursor. It inspires me to take another look at my FLIP code and see what I can optimize to shorten that time. I'm sure there's lots of easy optimizations I just never got to in the initial implementation. Now I'll go take another look.

Per review feedback on AcademySoftwareFoundation#5584: choosing absdiff or FLIP did nothing
unless the wipe was also on, and a difference image has nothing to wipe.

- Wipe (W) is back to exactly the AcademySoftwareFoundation#5480 behavior.
- New View > Difference submenu: Off (default) / Absolute difference /
  FLIP, with D cycling through them; the FLIP colormap toggle moves
  there. Entering a difference view pairs the current image with the
  last one displayed and shows the result right away.
- Wipe and the difference view are mutually exclusive.
- While FLIP is computing: busy cursor plus a "Computing FLIP
  difference..." status bar note; the view shows the current image
  (not a split) until the error map is ready.
- --compare keeps its values: wipe for the wipe, absdiff/flipdiff for
  the difference view.

Assisted-by: glm-5.3-flash
Signed-off-by: linsen <251731047+linsen458-spec@users.noreply.github.com>
@linsen458-spec

Copy link
Copy Markdown
Contributor Author

Sorry for the slow follow-up. Some things came up on my end over the past week and I didn't get back to this as quickly as I'd said I would.

The rework is pushed now (576b379), following the plan above:

  • W is the feat(iv): image wipe compare #5480 wipe again, nothing else.
  • View > Difference: Off / Absolute difference / FLIP, D cycles through them, and the FLIP colormap toggle lives there now. Turning it on shows the difference straight away, using the same pairing as the wipe (current image vs. the last one displayed).
  • Wipe and difference view switch each other off.
  • While FLIP runs you get a busy cursor and "Computing FLIP difference..." in the status bar, and the view stays on the current image until the result is ready.
  • --compare wipe|absdiff|flipdiff works as before.

Thanks for looking into the FLIP speed, too. On a 4k pair it's the one place where you still notice the wait.

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.

iv: make a difference mode: shows you the absdiff between the current image and the last image.

2 participants