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

0001 /*
0002  * KDE. Krita Project.
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_LEVELS_CURVE_H
0010 #define KIS_LEVELS_CURVE_H
0011 
0012 #include <QtGlobal>
0013 #include <QVector>
0014 
0015 #include "kritaimage_export.h"
0016 
0017 /**
0018  * @brief This class holds the parameters for a levels adjustment. It is modeled
0019  * after KisCubicCurve and has similar interface and functionality
0020  */
0021 class KRITAIMAGE_EXPORT KisLevelsCurve
0022 {
0023 public:
0024     /**
0025      * @brief Default value for the input black point
0026      */
0027     static constexpr qreal defaultInputBlackPoint() { return 0.0; }
0028     /**
0029      * @brief Default value for the input white point
0030      */
0031     static constexpr qreal defaultInputWhitePoint() { return 1.0; }
0032     /**
0033      * @brief Default value for the input gamma
0034      */
0035     static constexpr qreal defaultInputGamma() { return 1.0; }
0036     /**
0037      * @brief Default value for the output black point
0038      */
0039     static constexpr qreal defaultOutputBlackPoint() { return 0.0; }
0040     /**
0041      * @brief Default value for the output white point
0042      */
0043     static constexpr qreal defaultOutputWhitePoint() { return 1.0; }
0044 
0045     KisLevelsCurve();
0046     KisLevelsCurve(qreal inputBlackPoint, qreal inputWhitePoint, qreal inputGamma,
0047                    qreal outputBlackPoint, qreal outputWhitePoint);
0048     KisLevelsCurve(const KisLevelsCurve &rhs) = default;
0049     KisLevelsCurve& operator=(const KisLevelsCurve &rhs) = default;
0050     bool operator==(const KisLevelsCurve& rhs) const;
0051 
0052     /**
0053      * @brief Evaluates the function formed by the levels parameters for a
0054      * given x. The input and output values are normalized
0055      */
0056     qreal value(qreal x) const;
0057     
0058     /**
0059      * @brief Get the input black point
0060      */
0061     qreal inputBlackPoint() const;
0062     /**
0063      * @brief Get the input white point
0064      */
0065     qreal inputWhitePoint() const;
0066     /**
0067      * @brief Get the gamma value
0068      */
0069     qreal inputGamma() const;
0070     /**
0071      * @brief Get the output black point
0072      */
0073     qreal outputBlackPoint() const;
0074     /**
0075      * @brief Get the output white point
0076      */
0077     qreal outputWhitePoint() const;
0078 
0079     /**
0080      * @brief Set the input black point
0081      */
0082     void setInputBlackPoint(qreal newInputBlackPoint);
0083     /**
0084      * @brief Set the input white point
0085      */
0086     void setInputWhitePoint(qreal newInputWhitePoint);
0087     /**
0088      * @brief Set the gamma value
0089      */
0090     void setInputGamma(qreal newInputGamma);
0091     /**
0092      * @brief Set the output black point
0093      */
0094     void setOutputBlackPoint(qreal newOutputBlackPoint);
0095     /**
0096      * @brief Set the output white point
0097      */
0098     void setOutputWhitePoint(qreal newOutputWhitePoint);
0099 
0100     /**
0101      * @brief Resets the input and output levels (and gamma)
0102      */
0103     void resetAll();
0104     /**
0105      * @brief Resets the input levels only (and gamma)
0106      */
0107     void resetInputLevels();
0108     /**
0109      * @brief Resets the output levels only
0110      */
0111     void resetOutputLevels();
0112 
0113     /**
0114      * @brief Check whether the level info maps all values to themselves.
0115      */
0116     bool isIdentity() const;
0117 
0118     /**
0119      * @brief Get the name associated with this levels info object
0120      */
0121     const QString& name() const;
0122     /**
0123      * @brief Set the name associated with this levels info object. This allows
0124      * us to carry around a display name for the level info internally. It could
0125      * potentially be useful anywhere level info are used in the UI
0126      */
0127     void setName(const QString &newName);
0128 
0129     /**
0130      * @brief Returns a vector of size @param size with values obtained by
0131      * evaluating the function formed by the levels parameters from 0.0 to 1.0.
0132      * The resulting values are scaled to the range [0, 0xFF]
0133      * @param size The size of the returned vector
0134      * @return const QVector<quint16>& The vector with the values
0135      * @see value()
0136      * @see floatTransfer()
0137      */
0138     const QVector<quint16>& uint16Transfer(int size = 256) const;
0139     /**
0140      * @brief Returns a vector of size @param size with values obtained by
0141      * evaluating the function formed by the levels parameters from 0.0 to 1.0.
0142      * The resulting values are in the range [0, 1]
0143      * @param size The size of the returned vector
0144      * @return const QVector<qreal>& The vector with the values
0145      * @see value()
0146      * @see uint16Transfer()
0147      */
0148     const QVector<qreal>& floatTransfer(int size = 256) const;
0149 
0150     /**
0151      * @brief Get a text representation of the parameters. The format is:
0152      * "input_black_point;input_white_point;input_gamma;output_black_point;output_white_point".
0153      * For example: "0;1;0.6;0;1", "0.2;0.8;1.2;0.25;0.75"
0154      * @see fromString()
0155      */
0156     QString toString() const;
0157     /**
0158      * @brief Parses the parameters from a given text
0159      * @see toString
0160      */
0161     void fromString(const QString &text, bool *ok = nullptr);
0162 
0163 private:
0164     qreal m_inputBlackPoint, m_inputWhitePoint, m_inputGamma;
0165     qreal m_outputBlackPoint, m_outputWhitePoint;
0166     qreal m_inputLevelsDelta, m_inverseInputGamma, m_outputLevelsDelta;
0167     QString m_name;
0168     mutable QVector<quint16> m_u16Transfer;
0169     mutable QVector<qreal> m_fTransfer;
0170     mutable bool m_mustRecomputeU16Transfer;
0171     mutable bool m_mustRecomputeFTransfer;
0172 
0173     void invalidate();
0174 };
0175 
0176 #endif