krita

kis_histogram.cc

00001 /*
00002  *  Copyright (c) 2004 Boudewijn Rempt
00003  *            (c) 2005 Bart Coppens <kde@bartcoppens.be>
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  */
00019 
00020 #include <kdebug.h>
00021 #include <qdatetime.h> // ### Debug
00022 
00023 #include "kis_types.h"
00024 #include "kis_histogram.h"
00025 #include "kis_paint_layer.h"
00026 #include "kis_iterators_pixel.h"
00027 #include "kis_colorspace.h"
00028 #include "kis_debug_areas.h"
00029 
00030 KisHistogram::KisHistogram(KisPaintLayerSP layer,
00031                            KisHistogramProducerSP producer,
00032                            const enumHistogramType type)
00033 {
00034     m_dev = layer->paintDevice();
00035     m_type = type;
00036     m_producer = producer;
00037     m_selection = false;
00038     m_channel = 0;
00039 
00040     updateHistogram();
00041 }
00042 
00043 KisHistogram::KisHistogram(KisPaintDeviceSP paintdev,
00044                            KisHistogramProducerSP producer,
00045                            const enumHistogramType type)
00046 {
00047     m_dev = paintdev;
00048     m_type = type;
00049     m_producer = producer;
00050     m_selection = false;
00051     m_channel = 0;
00052 
00053     updateHistogram();
00054 }
00055 
00056 KisHistogram::~KisHistogram()
00057 {
00058 }
00059 
00060 void KisHistogram::updateHistogram()
00061 {
00062     Q_INT32 x,y,w,h;
00063     m_dev->exactBounds(x,y,w,h);
00064     KisRectIteratorPixel srcIt = m_dev->createRectIterator(x,y,w,h, false);
00065     KisColorSpace* cs = m_dev->colorSpace();
00066 
00067     QTime t;
00068     t.start();
00069 
00070     // Let the producer do it's work
00071     m_producer->clear();
00072     int i;
00073     // Handle degenerate case (this happens with the accumulating histogram,
00074     // which has an empty device)
00075     if (srcIt.isDone()) {
00076         m_producer->addRegionToBin(0, 0, 0, cs);
00077     } else {
00078         while ( !srcIt.isDone() ) {
00079             i = srcIt.nConseqPixels();
00080             m_producer->addRegionToBin(srcIt.rawData(), srcIt.selectionMask(), i, cs);
00081             srcIt += i;
00082         }
00083     }
00084 
00085     computeHistogram();
00086 }
00087 
00088 void KisHistogram::computeHistogram()
00089 {
00090     m_completeCalculations = calculateForRange(m_producer->viewFrom(),
00091             m_producer->viewFrom() + m_producer->viewWidth());
00092 
00093     if (m_selection) {
00094         m_selectionCalculations = calculateForRange(m_selFrom, m_selTo);
00095     } else {
00096         m_selectionCalculations.clear();
00097     }
00098 
00099 #if 1
00100     dump();
00101 #endif
00102 }
00103 
00104 KisHistogram::Calculations KisHistogram::calculations() {
00105     return m_completeCalculations.at(m_channel);
00106 }
00107 
00108 KisHistogram::Calculations KisHistogram::selectionCalculations() {
00109     return m_selectionCalculations.at(m_channel);
00110 }
00111 
00112 QValueVector<KisHistogram::Calculations> KisHistogram::calculateForRange(double from, double to) {
00113     QValueVector<Calculations> calculations;
00114     uint count = m_producer->channels().count();
00115 
00116     for (uint i = 0; i < count; i++) {
00117         calculations.append(calculateSingleRange(i, from, to));
00118     }
00119 
00120     return calculations;
00121 }
00122 
00123 KisHistogram::Calculations KisHistogram::calculateSingleRange(int channel, double from, double to) {
00124     Calculations c;
00125 
00126     // XXX If from == to, we only want a specific bin, handle that properly!
00127 
00128     double max = from, min = to, total = 0.0, mean = 0.0; //, median = 0.0, stddev = 0.0;
00129     Q_UINT32 high = 0, low = (Q_UINT32) -1, count = 0;
00130 
00131     if (m_producer->count() == 0) {
00132         // We won't get anything, even if a range is specified
00133         // XXX make sure all initial '0' values are correct here!
00134         return c;
00135     }
00136 
00137     Q_INT32 totbins = m_producer->numberOfBins();
00138     Q_UINT32 current;
00139 
00140     // convert the double range into actual bins:
00141     double factor = static_cast<double>(totbins) / m_producer->viewWidth();
00142 
00143     Q_INT32 fromBin = static_cast<Q_INT32>((from - m_producer->viewFrom()) * factor);
00144     Q_INT32 toBin = fromBin + static_cast<Q_INT32>((to - from) * factor);
00145 
00146     // Min, max, count, low, high
00147     for (Q_INT32 i = fromBin; i < toBin; i++) {
00148         current = m_producer->getBinAt(channel, i);
00149         double pos = static_cast<double>(i) / factor + from;
00150         if (current > high)
00151             high = current;
00152         if (current < low)
00153             low = current;
00154         if (current > 0) {
00155             if (pos < min)
00156                 min = pos;
00157             if (pos > max)
00158                 max = pos;
00159         }
00160         // We do the count here as well.
00161         // we can't use m_producer->count() for this, because of the range
00162         count += current;
00163         total += current * pos;
00164     }
00165 
00166     if (count > 0)
00167         mean = total / count;
00168 
00169     c.m_high = high;
00170     c.m_low = low;
00171     c.m_count = count;
00172     c.m_min = min;
00173     c.m_max = max;
00174     c.m_mean = mean;
00175     c.m_total = total;
00176 
00177     return c;
00178 }
00179 
00180 
00181 void KisHistogram::dump() {
00182     kdDebug(DBG_AREA_MATH) << "Histogram\n";
00183 
00184     switch (m_type) {
00185     case LINEAR:
00186         kdDebug(DBG_AREA_MATH) << "Linear histogram\n";
00187         break;
00188     case LOGARITHMIC:
00189         kdDebug(DBG_AREA_MATH) << "Logarithmic histogram\n";
00190     }
00191 
00192     kdDebug(DBG_AREA_MATH) << "Dumping channel " << m_channel << endl;
00193     Calculations c = calculations();
00194 
00195 /*        for( int i = 0; i <256; ++i ) {
00196         kdDebug(DBG_AREA_MATH) << "Value "
00197               << QString().setNum(i)
00198               << ": "
00199               <<  QString().setNum(m_values[i])
00200               << "\n";
00201         }*/
00202     kdDebug(DBG_AREA_MATH) << "\n";
00203 
00204     kdDebug(DBG_AREA_MATH) << "Max: " << QString().setNum(c.getMax()) << "\n";
00205     kdDebug(DBG_AREA_MATH) << "Min: " << QString().setNum(c.getMin()) << "\n";
00206     kdDebug(DBG_AREA_MATH) << "High: " << QString().setNum(c.getHighest()) << "\n";
00207     kdDebug(DBG_AREA_MATH) << "Low: " << QString().setNum(c.getLowest()) << "\n";
00208     kdDebug(DBG_AREA_MATH) << "Mean: " << m_producer->positionToString(c.getMean()) << "\n";
00209     kdDebug(DBG_AREA_MATH) << "Total: " << QString().setNum(c.getTotal()) << "\n";
00210 //    kdDebug(DBG_AREA_MATH) << "Median: " << QString().setNum(m_median) << "\n";
00211 //    kdDebug(DBG_AREA_MATH) << "Stddev: " << QString().setNum(m_stddev) << "\n";
00212 //    kdDebug(DBG_AREA_MATH) << "percentile: " << QString().setNum(m_percentile) << "\n";
00213 
00214     kdDebug(DBG_AREA_MATH) << "\n";
00215 }
KDE Home | KDE Accessibility Home | Description of Access Keys