Skip to content

Improve levels filter

Deif Lou requested to merge deiflou/krita:deiflou/improve_levels_filter into master

This MR improve the levels filter. It makes the following changes:

  • Separates the functionality of the filter in different files (config, widget, plugin, filter)
  • Implements per channel adjustments, like the curves filter. In fact they now share some code related to the multichannel features that I put outside the multichannel/perchannel classes.
  • It has two modes: "lightness" and "per channel". In the lightness mode the user can only change the levels for the lightness, just like in the old filter. This mode is the default and is simple and straightforward, like the old one. In the "per channel" mode you can set the levels for the independent channels, just like in the curves filter.
  • You can also change the lightness levels in the "per channel" mode but I implemented the "lightness" mode mainly for retro compatibility reasons. You can still load "old" files that use the old levels filter and the parameters will be put in this mode's levels. Likewise, if you save a file with the new filter, the lightness parameters should be recognized in an "old" krita. Even if you use the new "per channel" mode the filter will be loaded in an "old" krita with the "lightness" mode parameters.
  • Added to the gui some "reset levels" buttons.
  • There is a new and more powerful auto levels functionality. It is more similar to the PS one. You can apply the auto levels to a single channel or to all color channels in general (only rgb). You can select if you want to apply the same levels to all the channels (monochromatic contrast enhancement) or to single channels (per channel contrast enhancement). If you are applying the autolevels to a single channel only the monochromatic method is available.
    You can also enhance the midtones by selecting what point should be taken as neutral (taken automaticaly from the median or the mean of the histogram). Finally you can select what output colors to use. Normally they would be black for the shadows, mid-gray for the midtones and white for the highlights (the default), but you can choose others.
  • New facilities to show histograms were added:
    • KisHistogramPainter is an utility class that can paint nice histograms. It uses a polygon internally instead of a pixmap so it can be painted using any QPainter in any size without loss of quality or ugly smoothing. Its function is to take some KisHistogram and generate the shapes for the required channels. The histograms themselves are not stored. The shape is smoothed a bit (to remove super high frequency peaks) and also simplified (to reduce the number of points in the polygon). It also can display multiple histograms at once (for different channels for example). The rgb, cmyk, and xyz channels are colored with the respective channel color, and the rest are displayed as gray. The histogram is painted on a given rect (or it also can be retrieved as a QImage) but it can be scaled vertically. 1.0 scale means that all the histogram is shown in the rect. Also the histogram can be drawn in a logarithmic scale.
    • KisHistogramView is a widget that takes some KisHistograms and desired channel indices and uses KisHistogramPainter to paint them. It is a convenience class and it has all the features that KisHistogramPainter has. The histogram can be scaled by click & dragging vertically or by double clicking: if the scale is greater than one, double clicking will set the scale to 1 and if the scale is 1 it will try to set a scale factor that favors "normal" values over big peaks (outliers).
  • I also removed the KisGradientSlider and replaced it with a new KisLevelsSlider (and subclasses). I was asked by @kamathraghavendra to improve the widget a bit, mostly putting bigger handles, but the widget looked to me a bit messy code-wise, handling corner cases in a intrincate way. It also had some bad painting on the right extreme of the gradient. Now there is a generic base class that handles a collection of handles, the painting and the input (mostly similar to the gradient widgets). It is simple. Then there are subclasses (currently KisInputLevelsSlider, KisInputLevelsSliderWithGamma, KisOutputLevelsSlider, KisThresholdSlider) that basically just tell the base class the number of handles required and how the gradient area should be painted. This way it will be very simple to add a new levels-like slider without messing the code.
    Also the handles now can have an associated color that is used to color them and the slider. For example, in this new levels filter if the color space is cmyk, the levels slider shows white on the left and c/m/y/k on the right, since the highlights are represented with low values.

levels filter test

NOTE 1: This is marked as draft because I want to add one more functionality: the ability to click on a eyedrop button to select the black/gray/white points directly from the image. I don't know if that is possible at the moment. For example for a filter layer/mask the filter dialog is modal so it seems one can not interact with the canvas.

NOTE 2: The computation of the histogram still blocks krita when the image is big. That happened before also. I didn't change the KisHistogram, but it would be nice in the future to be able to compute the histograms in a multithreaded fashion.

Formalities Checklist

  • I confirmed this builds.
  • I confirmed Krita ran and the relevant functions work.
  • I tested the relevant unit tests and can confirm they are not broken. (If not possible, don't hesitate to ask for help!)
  • I made sure my commits build individually and have good descriptions as per KDE guidelines.
  • I made sure my code conforms to the standards set in the HACKING file.
  • I can confirm the code is licensed and attributed appropriately, and that unattributed code is mine, as per KDE Licensing Policy.
Edited by Deif Lou

Merge request reports