chalk

kis_histogram.cpp
1/*
2 * Copyright (c) 2004 Boudewijn Rempt
3 * (c) 2005 Bart Coppens <kde@bartcoppens.be>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20#include <kdebug.h>
21#include <tqdatetime.h> // ### Debug
22
23#include "kis_types.h"
24#include "kis_histogram.h"
25#include "kis_paint_layer.h"
26#include "kis_iterators_pixel.h"
27#include "kis_colorspace.h"
28#include "kis_debug_areas.h"
29
30KisHistogram::KisHistogram(KisPaintLayerSP layer,
31 KisHistogramProducerSP producer,
32 const enumHistogramType type)
33{
34 m_dev = layer->paintDevice();
35 m_type = type;
36 m_producer = producer;
37 m_selection = false;
38 m_channel = 0;
39
41}
42
43KisHistogram::KisHistogram(KisPaintDeviceSP paintdev,
44 KisHistogramProducerSP producer,
45 const enumHistogramType type)
46{
47 m_dev = paintdev;
48 m_type = type;
49 m_producer = producer;
50 m_selection = false;
51 m_channel = 0;
52
54}
55
56KisHistogram::~KisHistogram()
57{
58}
59
61{
62 TQ_INT32 x,y,w,h;
63 m_dev->exactBounds(x,y,w,h);
64 KisRectIteratorPixel srcIt = m_dev->createRectIterator(x,y,w,h, false);
65 KisColorSpace* cs = m_dev->colorSpace();
66
67 TQTime t;
68 t.start();
69
70 // Let the producer do it's work
71 m_producer->clear();
72 int i;
73 // Handle degenerate case (this happens with the accumulating histogram,
74 // which has an empty device)
75 if (srcIt.isDone()) {
76 m_producer->addRegionToBin(0, 0, 0, cs);
77 } else {
78 while ( !srcIt.isDone() ) {
79 i = srcIt.nConseqPixels();
80 m_producer->addRegionToBin(srcIt.rawData(), srcIt.selectionMask(), i, cs);
81 srcIt += i;
82 }
83 }
84
86}
87
89{
90 m_completeCalculations = calculateForRange(m_producer->viewFrom(),
91 m_producer->viewFrom() + m_producer->viewWidth());
92
93 if (m_selection) {
94 m_selectionCalculations = calculateForRange(m_selFrom, m_selTo);
95 } else {
96 m_selectionCalculations.clear();
97 }
98
99#if 1
100 dump();
101#endif
102}
103
105 return m_completeCalculations.at(m_channel);
106}
107
109 return m_selectionCalculations.at(m_channel);
110}
111
112TQValueVector<KisHistogram::Calculations> KisHistogram::calculateForRange(double from, double to) {
113 TQValueVector<Calculations> calculations;
114 uint count = m_producer->channels().count();
115
116 for (uint i = 0; i < count; i++) {
117 calculations.append(calculateSingleRange(i, from, to));
118 }
119
120 return calculations;
121}
122
123KisHistogram::Calculations KisHistogram::calculateSingleRange(int channel, double from, double to) {
124 Calculations c;
125
126 // XXX If from == to, we only want a specific bin, handle that properly!
127
128 double max = from, min = to, total = 0.0, mean = 0.0; //, median = 0.0, stddev = 0.0;
129 TQ_UINT32 high = 0, low = (TQ_UINT32) -1, count = 0;
130
131 if (m_producer->count() == 0) {
132 // We won't get anything, even if a range is specified
133 // XXX make sure all initial '0' values are correct here!
134 return c;
135 }
136
137 TQ_INT32 totbins = m_producer->numberOfBins();
138 TQ_UINT32 current;
139
140 // convert the double range into actual bins:
141 double factor = static_cast<double>(totbins) / m_producer->viewWidth();
142
143 TQ_INT32 fromBin = static_cast<TQ_INT32>((from - m_producer->viewFrom()) * factor);
144 TQ_INT32 toBin = fromBin + static_cast<TQ_INT32>((to - from) * factor);
145
146 // Min, max, count, low, high
147 for (TQ_INT32 i = fromBin; i < toBin; i++) {
148 current = m_producer->getBinAt(channel, i);
149 double pos = static_cast<double>(i) / factor + from;
150 if (current > high)
151 high = current;
152 if (current < low)
153 low = current;
154 if (current > 0) {
155 if (pos < min)
156 min = pos;
157 if (pos > max)
158 max = pos;
159 }
160 // We do the count here as well.
161 // we can't use m_producer->count() for this, because of the range
162 count += current;
163 total += current * pos;
164 }
165
166 if (count > 0)
167 mean = total / count;
168
169 c.m_high = high;
170 c.m_low = low;
171 c.m_count = count;
172 c.m_min = min;
173 c.m_max = max;
174 c.m_mean = mean;
175 c.m_total = total;
176
177 return c;
178}
179
180
181void KisHistogram::dump() {
182 kdDebug(DBG_AREA_MATH) << "Histogram\n";
183
184 switch (m_type) {
185 case LINEAR:
186 kdDebug(DBG_AREA_MATH) << "Linear histogram\n";
187 break;
188 case LOGARITHMIC:
189 kdDebug(DBG_AREA_MATH) << "Logarithmic histogram\n";
190 }
191
192 kdDebug(DBG_AREA_MATH) << "Dumping channel " << m_channel << endl;
193 Calculations c = calculations();
194
195/* for( int i = 0; i <256; ++i ) {
196 kdDebug(DBG_AREA_MATH) << "Value "
197 << TQString().setNum(i)
198 << ": "
199 << TQString().setNum(m_values[i])
200 << "\n";
201 }*/
202 kdDebug(DBG_AREA_MATH) << "\n";
203
204 kdDebug(DBG_AREA_MATH) << "Max: " << TQString(TQString().setNum(c.getMax())) << "\n";
205 kdDebug(DBG_AREA_MATH) << "Min: " << TQString(TQString().setNum(c.getMin())) << "\n";
206 kdDebug(DBG_AREA_MATH) << "High: " << TQString(TQString().setNum(c.getHighest())) << "\n";
207 kdDebug(DBG_AREA_MATH) << "Low: " << TQString(TQString().setNum(c.getLowest())) << "\n";
208 kdDebug(DBG_AREA_MATH) << "Mean: " << TQString(m_producer->positionToString(c.getMean())) << "\n";
209 kdDebug(DBG_AREA_MATH) << "Total: " << TQString(TQString().setNum(c.getTotal())) << "\n";
210// kdDebug(DBG_AREA_MATH) << "Median: " << TQString().setNum(m_median) << "\n";
211// kdDebug(DBG_AREA_MATH) << "Stddev: " << TQString().setNum(m_stddev) << "\n";
212// kdDebug(DBG_AREA_MATH) << "percentile: " << TQString().setNum(m_percentile) << "\n";
213
214 kdDebug(DBG_AREA_MATH) << "\n";
215}
A colorspace is the definition of a certain color model in Chalk.
Class that stores the result of histogram calculations.
Calculations selectionCalculations()
The information on the current selection for the current channel.
void computeHistogram()
(Re)computes the mathematical information from the information currently in the producer.
Calculations calculations()
The information on the entire view for the current channel.
void updateHistogram()
Updates the information in the producer.