curves: add per-channel tab support using avfilter.curves

Closes #2187 (closed)

Adds per-channel tab support to the Curves effect by introducing a new avfilter.curves based effect with All/R/G/B tabs.

What changed

  • Each channel is a SEPARATE av_curve parameter in the XML (av.master, av.r, av.g, av.b), each with its own <name>. The first av_curve param creates the CurveParamWidget; subsequent ones add a tab to the existing widget via addAvCurveTab(). Each tab is bound to its own QPersistentModelIndex, so per-channel curve state lives in the model, not in a separate in-widget cache.
  • Added QTabBar (All, R, G, B) to KisCurveWidget; tabs only appear for avfilter.curves, frei0r.curves is completely untouched
  • New AvCurve param type handles per-parameter serialization; converts KisCubicCurve format to avfilter.curves MLT properties on write, and back on project load
  • New avfilter_curves.xml effect definition
  • Point coordinates within ~0.00266 x-distance of each other are snapped to a minimum safe distance rather than rejected, avoiding an avfilter/MLT crash on near-duplicate points
  • Each channel param supports an optional color attribute, used to draw that channel's curve line and distinguish it at a glance
  • Reset button resets only the currently active channel's curve to identity
  • Editable Input/Output spinboxes show the selected point's X/Y, updating live on selection/drag and writing back to the model on edit
  • When editing one channel, other channels' curves are drawn faintly (in their own colors) if they've been edited away from identity; similar to GIMP's curve overlay behavior. The active channel stays fully opaque and interactive on top.

Testing

  1. Apply "Curves (avfilter)" to a clip
  2. Pull the All tab curve; whole image affected
  3. Switch to R tab, pull curve up; red tint applied, R tab's curve line colored accordingly
  4. Switch back to All; curve preserved, R's edited curve appears as a faint ghost while editing All (if All has also been edited); actually ghosts show OTHER edited channels while one is active, so verify by editing R then switching to G: R should appear as a red ghost line
  5. Use the reset button on the active tab; only that channel resets, its ghost disappears if it was showing
  6. Select a point; confirm Input/Output spinboxes update and are editable
  7. Save and reopen project; all curves restore correctly, including edited-vs-default state
  8. Undo/redo curve edits; no crash, model and UI stay in sync

Notes

  • frei0r.bezier_curves and frei0r.curves behavior is unchanged
  • Backward compatibility with existing projects preserved
  • Unit tests added (tests/avcurvetest.cpp), 48 assertions covering parameter loading, format conversion, point snapping, per-channel independence, and default state; all passing
Edited by Yash Bavadiya

Merge request reports

Loading