File indexing completed on 2024-12-22 04:13:16

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_HISTOGRAM_VIEW_H
0010 #define KIS_HISTOGRAM_VIEW_H
0011 
0012 #include <QScopedPointer>
0013 #include <QWidget>
0014 
0015 #include "kritaui_export.h"
0016 
0017 class KisHistogram;
0018 class KoColorSpace;
0019 
0020 /**
0021  * @brief A widget that can display different KisHistograms. It renders a
0022  * somewhat smooth shape with different colors (for rgb, cmyk and xyz channels).
0023  * It can also display the different channels of a colorspace overlapped.
0024  */
0025 class KRITAUI_EXPORT KisHistogramView : public QWidget
0026 {
0027     Q_OBJECT
0028 
0029 public:
0030     KisHistogramView(QWidget *parent);
0031     ~KisHistogramView();
0032 
0033     /**
0034      * @brief Sets up the widget by passing a collection of KisHistograms, the
0035      * color space for each histogram and the channels that must be set up for
0036      * each histogram
0037      * @param histograms A collection of KisHistogram pointers to take the info
0038      * from. You can add several histograms and later select which histogram is
0039      * used at any given moment. This prevents calling multiple times the setup
0040      * function with different histograms. That way the shaped to draw are
0041      * computed only once. The histogram pointers are not stored or owned
0042      * internally, so you can safely delete them if you don't need them
0043      * @param colorSpaces The collection of color spaces associated with each
0044      * histogram. They are used to color different channels. For example, the
0045      * histogram for the red channel of a rgb histogram will be painted as a red
0046      * shape
0047      * @param channels A collection of vectors that contain the channel number
0048      * for the channels that must be used to compute the histograms. For example,
0049      * if the second histogram is a Lab histogram, and you are interested only
0050      * in the lightness channel, the second vector in the collection should have
0051      * only one element, the number 0 (index of the lightness channel). If the
0052      * collection is empty or if the vector of channels for any given histogram
0053      * is empty, then all the channels will be used
0054      */
0055     void setup(const QVector<KisHistogram*> &histograms,
0056                const QVector<const KoColorSpace*> &colorSpaces,
0057                const QVector<QVector<int>> &channels = {});
0058     /**
0059      * @brief Returns the channels that are available for the currently selected
0060      * histogram
0061      * @see setChannel
0062      * @see setChannels
0063      */
0064     const QVector<int>& channels() const;
0065     /**
0066      * @brief Returns the color that is being used to paint a generic histogram. 
0067      * All the histogram channels will use this color with the exception of the
0068      * red, green and blue channels in a rgba histogram; the cyan, magenta,
0069      * yellow and black channels in a cmyka histogram; and the x, y, and z
0070      * channels in a xyz histogram
0071      * @see setDefaultColor
0072      */
0073     QColor defaultColor() const;
0074     /**
0075      * @brief Return the vertical scale that is used to paint the histogram
0076      * shape. A scale of 1 will show all the histogram in the widget area.
0077      * Scales less that 1 are not allowed
0078      * @see setScale
0079      * @see setScaleToFit
0080      * @see setScaleToCutLongPeaks
0081      */
0082     qreal scale() const;
0083     /**
0084      * @brief Returns true if the histogram shape being shown is formed by the
0085      * logarithmic mapping of the original histogram values instead of the values
0086      * themselves
0087      * @see setLogarithmic
0088      */
0089     bool isLogarithmic() const;
0090 
0091 public Q_SLOTS:
0092     /**
0093      * @brief Activates the given channel of the given histogram. This allows to
0094      * change the view between the different histograms and channels passed to
0095      * the setup function
0096      * @see channel
0097      * @see setChannels
0098      * @see setup
0099      */
0100     void setChannel(int channel, int histogramIndex = 0);
0101     /**
0102      * @brief Activates the given channels of the given histogram. This allows to
0103      * change the view between the different histograms and channels passed to
0104      * the setup function. This function activates multiple channels that will be
0105      * displayed at once in the widget
0106      * @see channel
0107      * @see setChannel
0108      * @see setup
0109      */
0110     void setChannels(const QVector<int> &channels, int histogramIndex = 0);
0111     /**
0112      * @brief This clears the channel selection. The widget will show a null
0113      * symbol in it's center when there are no activated channels
0114      */
0115     void clearChannels();
0116     /**
0117      * @brief Set the default color used when there is no preference to color
0118      * the selected histogram
0119      * @see defaultColor
0120      */
0121     void setDefaultColor(const QColor &newDefaultColor);
0122     /**
0123      * @brief Set the scale used to paint the widget. The scale can also be
0124      * changed by clicking and dragging up/down in the widget
0125      * @see scale 
0126      * @see setScaleToFit
0127      * @see setScaleToCutLongPeaks
0128      */
0129     void setScale(qreal newScale);
0130     /**
0131      * @brief Set the scale used to paint the widget to 1. You can also return
0132      * to a scale of 1 by double clicking on the widget if the current scale is
0133      * other than 1. If you double click when the scale is one the effect will
0134      * be the same as calling setScaleToCutLongPeaks
0135      * @see scale
0136      * @see setScale
0137      * @see setScaleToCutLongPeaks
0138      */
0139     void setScaleToFit();
0140     /**
0141      * @brief Sometimes there can be some outliers in the histogram that show in
0142      * the widget as long vertical peaks. Since a scale of 1 will show all the
0143      * histogram, this can make its interesting parts too small to take any
0144      * valuable information from them. This function will try to come up with a
0145      * scale value that favors those interesting parts over the long peaks,
0146      * which will be pushed and will look cutted
0147      * @see scale
0148      * @see setScale
0149      * @see setScaleToFit
0150      */
0151     void setScaleToCutLongPeaks();
0152     /**
0153      * @brief Set if the histogram shape being shown is formed by the
0154      * logarithmic mapping of the original histogram values instead of the
0155      * values themselves
0156      * @see isLogarithmic 
0157      */
0158     void setLogarithmic(bool logarithmic);
0159 
0160 protected:
0161     void paintEvent(QPaintEvent *e) override;
0162     void mouseDoubleClickEvent(QMouseEvent *e) override;
0163     void mousePressEvent(QMouseEvent *e) override;
0164     void mouseMoveEvent(QMouseEvent *e) override;
0165 
0166 private:
0167     class Private;
0168     QScopedPointer<Private> m_d;
0169 };
0170 
0171 #endif