File indexing completed on 2024-05-12 15:58:49

0001 /*
0002  * This file is part of Krita
0003  *
0004  * SPDX-FileCopyrightText: 2021 Deif Lou <ginoba@gmail.com>
0005  *
0006  * SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #ifndef KIS_AUTO_LEVELS_H
0010 #define KIS_AUTO_LEVELS_H
0011 
0012 #include <QVector>
0013 
0014 #include <KoColor.h>
0015 #include <kis_paint_device.h>
0016 #include <KisLevelsCurve.h>
0017 #include <kritaimage_export.h>
0018 
0019 class KisHistogram;
0020 
0021 /**
0022  * @brief This namespace contains functions to  compute the levels adjustment
0023  * parameters automatically from a histogram
0024  */
0025 namespace KisAutoLevels
0026 {
0027 
0028 /**
0029  * @brief The different methods to enhance the contrast
0030  */
0031 enum ShadowsAndHighlightsAdjustmentMethod {
0032     ShadowsAndHighlightsAdjustmentMethod_MonochromaticContrast,
0033     ShadowsAndHighlightsAdjustmentMethod_PerChannelContrast
0034 };
0035 
0036 /**
0037  * @brief The different methods to enhance the mid tones
0038  */
0039 enum MidtonesAdjustmentMethod {
0040     MidtonesAdjustmentMethod_None,
0041     MidtonesAdjustmentMethod_UseMedian,
0042     MidtonesAdjustmentMethod_UseMean
0043 };
0044 
0045 /**
0046  * @brief Convenience class that associates a KisHistogram and a channel index.
0047  * This is useful because setting a channel on the histogram mutates it. This
0048  * way the functions can change the histogram channel by looking at the
0049  * "channel" field
0050  * 
0051  */
0052 struct KRITAIMAGE_EXPORT ChannelHistogram
0053 {
0054     KisHistogram *histogram{nullptr};
0055     int channel{0};
0056 };
0057 
0058 /**
0059  * @brief Takes a reference histogram (luma, lightness) and computes the black
0060  *        and white points to maximize the contrast having into account
0061  *        the clipping.
0062  * @return A pair containing the black and white points indices
0063  */
0064 QPair<qreal, qreal> KRITAIMAGE_EXPORT getInputBlackAndWhitePoints(ChannelHistogram histogram,
0065                                                                   qreal shadowsClipping,
0066                                                                   qreal highlightsClipping);
0067 
0068 /**
0069  * @brief Finds the darkest and whitest colors in the device having into account
0070  *        the clipping
0071  * @return A pair containing the "darkest" and "lighter" colors 
0072  */
0073 QPair<KoColor, KoColor> KRITAIMAGE_EXPORT getDarkestAndWhitestColors(const KisPaintDeviceSP device,
0074                                                                      qreal shadowsClipping,
0075                                                                      qreal highlightsClipping);
0076 
0077 /**
0078  * @brief Computes a gamma value that "moves" the input midpoint towards
0079  *        the output midpoint
0080  * @param blackPoint If this gamma value will be part of a more complex levels
0081  *                   adjustment, set its black point here. Set it to 0
0082  *                   otherwhise. Since the gamma correction is applied after
0083  *                   the linear mapping given by the black and white points in a
0084  *                   levels adjustment, you have to provide those here to get
0085  *                   the correct gamma
0086  * @param whitePoint same as with blackPoint but for the white point
0087  * @param inputIntensity This is the intensity value that we want to map to the
0088  *                       output value. Sensible values are the mean and the median
0089  * @param outputIntensity This is the intensity value to which the input value
0090  *                        will be mapped to after the gamma correction. Use 0.5
0091  *                        to neutralize the midtones
0092  * @return the gamma value that, when applied after the lineat mapping given by
0093  *         the black and white points, will map the input intensity to the
0094  *         output intensity
0095  */
0096 qreal KRITAIMAGE_EXPORT getGamma(qreal blackPoint,
0097                                  qreal whitePoint,
0098                                  qreal inputIntensity,
0099                                  qreal outputIntensity);
0100 
0101 /**
0102  * @brief Creates a KisLevelsCurve for every channel in "channelsHistograms".
0103  *        Computes the input black and white points from the intensity histogram.
0104  *        Computes the gamma from each channels histogram and "outputMidtones"
0105  *        if the method is not "None". The output black and white points are
0106  *        computed from "outputBlackPoints" and "outputWhitePoints"
0107  * @param lightnessHistogram histogram to compute the input black and white
0108  *                           points from
0109  * @param channelsHistograms list of histograms to compute the gammas from. This
0110  *                           is also used to know the number of output levels infos
0111  * @param shadowsClipping A normalized perentage that is used to know how many
0112  *                        samples should be clipped on the shadows side of the
0113  *                        histogram by the input black point
0114  * @param highlightsClipping A normalized perentage that is used to know how
0115  *                           many samples should be clipped on the highlights
0116  *                           side of the histogram by the input white point
0117  * @param maximumInputBlackAndWhiteOffset A maximum value for the input black
0118  *                                        and white points. The black point won't
0119  *                                        be greater than this, and the white
0120  *                                        point won't be lesser than 1 - this
0121  * @param midtonesAdjustmentMethod The method used to get the gamma
0122  * @param midtonesAdjustmentAmount The strength of the midtone adjustment
0123  * @param outputBlackPoints The output black points used in each levels info
0124  * @param outputWhitePoints The output white points used in each levels info
0125  * @param outputMidtones The desired output midtone values for the gamma adjustment
0126  * @return A list of levels infos containing parameters for the levels adjustment
0127  */
0128 QVector<KisLevelsCurve> KRITAIMAGE_EXPORT adjustMonochromaticContrast(ChannelHistogram lightnessHistogram,
0129                                                                       QVector<ChannelHistogram> &channelsHistograms,
0130                                                                       qreal shadowsClipping,
0131                                                                       qreal highlightsClipping,
0132                                                                       qreal maximumInputBlackAndWhiteOffset,
0133                                                                       MidtonesAdjustmentMethod midtonesAdjustmentMethod,
0134                                                                       qreal midtonesAdjustmentAmount,
0135                                                                       const QVector<qreal> &outputBlackPoints,
0136                                                                       const QVector<qreal> &outputWhitePoints,
0137                                                                       const QVector<qreal> &outputMidtones);
0138 
0139 /**
0140  * @brief Creates a KisLevelsCurve for every channel in "channelsHistograms".
0141  *        Computes the input black and white points from each channels
0142  *        histogram separately. Computes the gamma from each channels histogram
0143  *        and "outputMidtones" if the method is not "None". The
0144  *        output black and white points are computed from "outputBlackPoints"
0145  *        and "outputWhitePoints"
0146  * @param channelsHistograms list of histograms to compute the gammas from. This
0147  *                           is also used to know the number of output levels infos
0148  * @param shadowsClipping A normalized perentage that is used to know how many
0149  *                        samples should be clipped on the shadows side of the
0150  *                        histogram by the input black point
0151  * @param highlightsClipping A normalized perentage that is used to know how
0152  *                           many samples should be clipped on the highlights
0153  *                           side of the histogram by the input white point
0154  * @param maximumInputBlackAndWhiteOffset A maximum value for the input black
0155  *                                        and white points. The black point won't
0156  *                                        be greater than this, and the white
0157  *                                        point won't be lesser than 1 - this
0158  * @param midtonesAdjustmentMethod The method used to get the gamma
0159  * @param midtonesAdjustmentAmount The strength of the midtone adjustment
0160  * @param outputBlackPoints The output black points used in each levels info
0161  * @param outputWhitePoints The output white points used in each levels info
0162  * @param outputMidtones The desired output midtone values for the gamma adjustment
0163  * @return A list of levels infos containing parameters for the levels adjustment
0164  */
0165 QVector<KisLevelsCurve> KRITAIMAGE_EXPORT adjustPerChannelContrast(QVector<ChannelHistogram> &channelsHistograms,
0166                                                                    qreal shadowsClipping,
0167                                                                    qreal highlightsClipping,
0168                                                                    qreal maximumInputBlackAndWhiteOffset,
0169                                                                    MidtonesAdjustmentMethod midtonesAdjustmentMethod,
0170                                                                    qreal midtonesAdjustmentAmount,
0171                                                                    const QVector<qreal> &outputBlackPoints,
0172                                                                    const QVector<qreal> &outputWhitePoints,
0173                                                                    const QVector<qreal> &outputMidtones);
0174 
0175 }
0176 
0177 #endif