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

0001 /*
0002  *  SPDX-FileCopyrightText: 2004 Boudewijn Rempt
0003  *  SPDX-FileCopyrightText: 2005 Bart Coppens <kde@bartcoppens.be>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 #ifndef KIS_HISTOGRAM_
0008 #define KIS_HISTOGRAM_
0009 
0010 #include <QVector>
0011 #include <QRect>
0012 
0013 #include "KoHistogramProducer.h"
0014 
0015 #include "kis_shared.h"
0016 #include "kis_types.h"
0017 #include "kritaimage_export.h"
0018 
0019 enum enumHistogramType {
0020     LINEAR,
0021     LOGARITHMIC
0022 };
0023 /**
0024  * The histogram class computes the histogram data from the specified layer
0025  * for the specified channel, through the use of a KoHistogramProducer.
0026  * This class is only for layers and paintdevices. KisImages are not supported,
0027  * but you can use the mergedImage function to create a paintdevice and feed that to this class.
0028  *
0029  * A Histogram also can have a selection: this is a specific range in the current histogram
0030  * that will get calculations done on it as well. If the range's begin and end are the same,
0031  * it is supposed to specify a single bin in the histogram.
0032  *
0033  * The calculations are done in the range 0 - 1, instead of the native range that a pixel
0034  * might have, so it's not always as precise as it could be. But you can't have it all...
0035  */
0036 class KRITAIMAGE_EXPORT KisHistogram : public KisShared
0037 {
0038 
0039 public:
0040     /**
0041      * Class that stores the result of histogram calculations.
0042      * Doubles are in the 0-1 range, use the producer's positionToString function to display it.
0043      **/
0044     class Calculations
0045     {
0046 
0047         double m_max {0.0};
0048         double m_min {0.0};
0049         double m_mean {0.0};
0050         double m_total {0.0};
0051 
0052         quint32 m_high {0};
0053         quint32 m_low {0};
0054         quint32 m_count {0};
0055 
0056         friend class KisHistogram;
0057 
0058     public:
0059 
0060         Calculations()
0061         {
0062         }
0063         /**
0064          * This function return the maximum bound of the histogram
0065          * (values at greater position than the maximum are null)
0066          */
0067         inline double getMax() {
0068             return m_max;
0069         }
0070         /**
0071          * This function return the minimum bound of the histogram
0072          * (values at smaller position than the minimum are null)
0073          */
0074         inline double getMin() {
0075             return m_min;
0076         }
0077         /// This function return the highest value of the histogram
0078         inline quint32 getHighest() {
0079             return m_high;
0080         }
0081         /// This function return the lowest value of the histogram
0082         inline quint32 getLowest() {
0083             return m_low;
0084         }
0085         /// This function return the mean of value of the histogram
0086         inline double getMean() {
0087             return m_mean;
0088         }
0089         //double getMedian() { return m_median; }
0090         //double getStandardDeviation() { return m_stddev; }
0091         /// This function return the number of pixels used by the histogram
0092         inline quint32 getCount() {
0093             return m_count;
0094         }
0095         /** The sum of (the contents of every bin * the double value of that bin)*/
0096         inline double getTotal() {
0097             return m_total;
0098         }
0099         //quint8 getPercentile() { return m_percentile; } // What is this exactly? XXX
0100     };
0101 
0102     KisHistogram(KisPaintLayerSP layer,
0103                  KoHistogramProducer *producer,
0104                  const enumHistogramType type);
0105 
0106     KisHistogram(KisPaintDeviceSP paintdev,
0107                  const QRect &bounds,
0108                  KoHistogramProducer *producer,
0109                  const enumHistogramType type);
0110 
0111     virtual ~KisHistogram();
0112 
0113     /** Updates the information in the producer */
0114     void updateHistogram();
0115 
0116     /**
0117      * (Re)computes the mathematical information from the information currently in the producer.
0118      * Needs to be called when you change the selection and want to get that information
0119      **/
0120     void computeHistogram();
0121 
0122     /** The information on the entire view for the current channel */
0123     Calculations calculations();
0124     /** The information on the current selection for the current channel */
0125     Calculations selectionCalculations();
0126 
0127     inline quint32 getValue(quint8 i) {
0128         return m_producer->getBinAt(m_channel, i);
0129     }
0130 
0131     inline enumHistogramType getHistogramType() {
0132         return m_type;
0133     }
0134     inline void setHistogramType(enumHistogramType type) {
0135         m_type = type;
0136     }
0137     inline void setProducer(KoHistogramProducer *producer) {
0138         m_channel = 0;
0139         m_producer = producer;
0140     }
0141     inline void setChannel(qint32 channel) {
0142         Q_ASSERT(m_channel < m_completeCalculations.size());
0143         m_channel = channel;
0144     }
0145     inline KoHistogramProducer *producer() {
0146         return m_producer;
0147     }
0148     inline qint32 channel() {
0149         return m_channel;
0150     }
0151 
0152     inline bool hasSelection() {
0153         return m_selection;
0154     }
0155     inline double selectionFrom() {
0156         return m_selFrom;
0157     }
0158     inline double selectionTo() {
0159         return m_selTo;
0160     }
0161     inline void setNoSelection() {
0162         m_selection = false;
0163     }
0164     /** Sets the current selection */
0165     inline void setSelection(double from, double to) {
0166         m_selection = true; m_selFrom = from; m_selTo = to;
0167     }
0168 
0169 
0170 private:
0171     // Dump the histogram to debug.
0172     void dump();
0173     QVector<Calculations> calculateForRange(double from, double to);
0174     Calculations calculateSingleRange(int channel, double from, double to);
0175 
0176     const KisPaintDeviceSP m_paintDevice;
0177     QRect m_bounds;
0178     KoHistogramProducer *m_producer {nullptr};
0179     enumHistogramType m_type {LINEAR};
0180 
0181     qint32 m_channel {0};
0182     double m_selFrom {0.0};
0183     double m_selTo {0.0};
0184     bool m_selection {false};
0185 
0186     QVector<Calculations> m_completeCalculations, m_selectionCalculations;
0187 };
0188 
0189 
0190 #endif // KIS_HISTOGRAM_WIDGET_