Isis 3 Programmer Reference
ImageHistogram.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "ImageHistogram.h"
8
9#include "Brick.h"
10#include "ControlNet.h"
11#include "ControlMeasure.h"
12
13#include <iostream>
14#include <math.h>
15#include <stdio.h>
16#include <string>
17
18using namespace std;
19
20namespace Isis {
21
30 ImageHistogram::ImageHistogram(double minimum, double maximum, int nbins) :
31 Histogram(minimum, maximum, nbins) {
32 }
33
34
56 ImageHistogram::ImageHistogram(Cube &cube, int statsBand, Progress *progress,
57 double startSample, double startLine,
58 double endSample, double endLine,
59 int bins, bool addCubeData) {
60 InitializeFromCube(cube, statsBand, progress, bins, startSample, startLine,
61 endSample, endLine);
62
63 if (addCubeData) {
64 Brick cubeDataBrick((int)(endSample - startSample + 1),
65 1, 1, cube.pixelType());
66
67 // if band == 0, then we're gathering data for all bands.
68 int startBand = statsBand;
69 int endBand = statsBand;
70
71 if (statsBand == 0) {
72 startBand = 1;
73 endBand = cube.bandCount();
74 }
75
76 if (progress != NULL) {
77 progress->SetText("Gathering histogram");
78 progress->SetMaximumSteps(
79 (int)(endLine - startLine + 1) * (int)(endBand - startBand + 1));
80 progress->CheckStatus();
81 }
82
83 for (int band = startBand; band <= endBand; band++) {
84 for (int line = (int)startLine; line <= endLine; line++) {
85 cubeDataBrick.SetBasePosition(qRound(startSample), line, band);
86 cube.read(cubeDataBrick);
87 AddData(cubeDataBrick.DoubleBuffer(), cubeDataBrick.size());
88 if (progress != NULL) {
89 progress->CheckStatus();
90 }
91 }
92 }
93 }
94 }
95
96 void ImageHistogram::InitializeFromCube(Cube &cube, int statsBand,
97 Progress *progress, int nbins, double startSample, double startLine,
98 double endSample, double endLine) {
99 // Make sure band is valid, 0 is valid (means all bands)
100 if ( (statsBand < 0) || (statsBand > cube.bandCount() ) ) {
101 string msg = "Cannot gather histogram for band [" + IString(statsBand) +
102 "]";
103 throw IException(IException::Programmer, msg, _FILEINFO_);
104 }
105
106 // We need to find the min/max DN value for our histogram bins to be the
107 // correct size.
108 double minDnValue = Null;
109 double maxDnValue = Null;
110
111 if (cube.pixelType() == UnsignedByte) {
112 // If we can discretely store every data point, then we can use the
113 // possible extent of the data range as our min/max dn values.
114 if (nbins == 0) {
115 minDnValue = 0.0 * cube.multiplier() + cube.base();
116 maxDnValue = 255.0 * cube.multiplier() + cube.base();
117 nbins = 256;
118 }
119 }
120 else if (cube.pixelType() == UnsignedWord) {
121 if (nbins == 0) {
122 minDnValue = 0.0 * cube.multiplier() + cube.base();
123 maxDnValue = 65535.0 * cube.multiplier() + cube.base();
124 nbins = 65536;
125 }
126 }
127 else if (cube.pixelType() == SignedWord) {
128 if (nbins == 0) {
129 minDnValue = -32768.0 * cube.multiplier() + cube.base();
130 maxDnValue = 32767.0 * cube.multiplier() + cube.base();
131 nbins = 65536;
132 }
133 }
134 // 32-bit data covers too big of a range of values to use
135 // the min and max possible values to set our value range.
136 // So, just set the number of bins and then later we will
137 // compute the min and max value in the actual cube.
138 else if (cube.pixelType() == UnsignedInteger ||
139 cube.pixelType() == SignedInteger ||
140 cube.pixelType() == Real) {
141 if (nbins == 0) {
142 nbins = 65536;
143 }
144 }
145 else {
146 IString msg = "Unsupported pixel type";
147 throw IException(IException::Programmer, msg, _FILEINFO_);
148 }
149
150 if (startSample == Null)
151 startSample = 1.0;
152
153 if (endSample == Null)
154 endSample = cube.sampleCount();
155
156 if (startLine == Null)
157 startLine = 1.0;
158
159 if (endLine == Null)
160 endLine = cube.lineCount();
161
162 // If we still need our min/max DN values, find them.
163 if (minDnValue == Null || maxDnValue == Null) {
164
165 Brick cubeDataBrick((int)(endSample - startSample + 1),
166 1, 1, cube.pixelType() );
167 Statistics stats;
168
169 // if band == 0, then we're gathering stats for all bands. I'm really
170 // not sure that this is correct, a good idea or called from anywhere...
171 // but I don't have time to track down the use case.
172 int startBand = statsBand;
173 int endBand = statsBand;
174
175 if (statsBand == 0) {
176 startBand = 1;
177 endBand = cube.bandCount();
178 }
179
180 if (progress != NULL) {
181
182 progress->SetText("Computing min/max for histogram");
183 progress->SetMaximumSteps(
184 (int)(endLine - startLine + 1) * (int)(endBand - startBand + 1) );
185 progress->CheckStatus();
186 }
187
188 for (int band = startBand; band <= endBand; band++) {
189 for (int line = (int)startLine; line <= endLine; line++) {
190
191 cubeDataBrick.SetBasePosition(qRound(startSample), line, band);
192 cube.read(cubeDataBrick);
193 stats.AddData(cubeDataBrick.DoubleBuffer(), cubeDataBrick.size());
194
195 if (progress != NULL) {
196 progress->CheckStatus();
197 }
198 }
199 }
200
201 if (stats.ValidPixels() == 0) {
202 minDnValue = 0.0;
203 maxDnValue = 1.0;
204 }
205 else {
206 minDnValue = stats.Minimum();
207 maxDnValue = stats.Maximum();
208 }
209 }
210
211 // Set the bins and range
212 SetValidRange(minDnValue, maxDnValue);
213 SetBins(nbins);
214 }
215
219
228 void ImageHistogram::AddData(const double *data,
229 const unsigned int count) {
230 Statistics::AddData(data, count);
231
232 int nbins = p_bins.size();
233 int index;
234 for (unsigned int i = 0; i < count; i++) {
235 if (IsValidPixel(data[i]) && InRange(data[i]) ) {
236 if (BinRangeStart() == BinRangeEnd() ) {
237 index = 0;
238 }
239 else {
240 index = (int) floor((double)(nbins - 1) / (BinRangeEnd() - BinRangeStart()) *
241 (data[i] - BinRangeStart() ) + 0.5);
242 }
243 if (index < 0) index = 0;
244 if (index >= nbins) index = nbins - 1;
245 p_bins[index] += 1;
246 }
247 }
248 }
249
256 void ImageHistogram::AddData(const double data) {
258
259 int nbins = p_bins.size();
260 int index;
261 if (IsValidPixel(data) && InRange(data) ) {
262 if (BinRangeStart() == BinRangeEnd() ) {
263 index = 0;
264 }
265 else {
266 index = (int) floor((double)(nbins - 1) / (BinRangeEnd() - BinRangeStart() ) *
267 (data - BinRangeStart() ) + 0.5);
268 }
269 if (index < 0) index = 0;
270 if (index >= nbins) index = nbins - 1;
271 p_bins[index] += 1;
272 }
273 }
274
284 void ImageHistogram::RemoveData(const double *data,
285 const unsigned int count) {
286 Statistics::RemoveData(data, count);
287
288 int nbins = p_bins.size();
289 int index;
290 for (unsigned int i = 0; i < count; i++) {
291 if (IsValidPixel(data[i]) ) {
292
293 if (BinRangeStart() == BinRangeEnd() ) {
294 index = 0;
295 }
296 else {
297 index = (int) floor((double)(nbins - 1) / (BinRangeEnd() - BinRangeStart()) *
298 (data[i] - BinRangeStart()) + 0.5);
299 }
300 if (index < 0) index = 0;
301 if (index >= nbins) index = nbins - 1;
302 p_bins[index] -= 1;
303 }
304 }
305 }
306
318 void ImageHistogram::BinRange(const int index,
319 double &low, double &high) const {
320 if ( (index < 0) || (index >= (int)p_bins.size() ) ) {
321
322 QString message = Message::ArraySubscriptNotInRange(index);
323 throw IException(IException::Programmer, message, _FILEINFO_);
324 }
325
326 double binSize = (BinRangeEnd() - BinRangeStart()) / (double)(p_bins.size() - 1);
327 low = BinRangeStart() - binSize / 2.0 + binSize * (double) index;
328 high = low + binSize;
329 }
330}
Buffer for containing a three dimensional section of an image.
Definition Brick.h:45
IO Handler for Isis Cubes.
Definition Cube.h:168
int lineCount() const
Definition Cube.cpp:1740
double multiplier() const
Returns the multiplier value for converting 8-bit/16-bit pixels to 32-bit.
Definition Cube.cpp:1754
int sampleCount() const
Definition Cube.cpp:1813
double base() const
Returns the base value for converting 8-bit/16-bit pixels to 32-bit.
Definition Cube.cpp:1433
PixelType pixelType() const
Definition Cube.cpp:1764
void read(Blob &blob, const std::vector< PvlKeyword > keywords=std::vector< PvlKeyword >()) const
This method will read data from the specified Blob object.
Definition Cube.cpp:813
virtual int bandCount() const
Returns the number of virtual bands for the cube.
Definition Cube.cpp:1416
Container of a cube histogram.
Definition Histogram.h:74
void SetBins(const int bins)
Change the number of bins in the histogram and reset counters.
std::vector< BigInt > p_bins
The array of counts.
Definition Histogram.h:121
void SetValidRange(const double minimum=Isis::ValidMinimum, const double maximum=Isis::ValidMaximum)
Changes the range of the bins.
Isis exception class.
Definition IException.h:91
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
Adds specific functionality to C++ strings.
Definition IString.h:165
ImageHistogram(double minimum, double maximum, int bins=1024)
Constructs a histogram object.
virtual void AddData(const double *data, const unsigned int count)
Add an array of doubles to the histogram counters.
virtual void RemoveData(const double *data, const unsigned int count)
Remove an array of doubles from the histogram counters.
~ImageHistogram()
Destructs a histogram object.
virtual void BinRange(const int index, double &low, double &high) const
Returns the left edge and right edge values of a bin.
Program progress reporter.
Definition Progress.h:42
void SetMaximumSteps(const int steps)
This sets the maximum number of steps in the process.
Definition Progress.cpp:85
void SetText(const QString &text)
Changes the value of the text string reported just before 0% processed.
Definition Progress.cpp:61
void CheckStatus()
Checks and updates the status.
Definition Progress.cpp:105
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the accumulators and counters.
void RemoveData(const double *data, const unsigned int count)
Remove an array of doubles from the accumulators and counters.
Statistics(QObject *parent=0)
Constructs an IsisStats object with accumulators and counters set to zero.
QString ArraySubscriptNotInRange(int index)
This error should be used when an Isis object or application is checking array bounds and the legal r...
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
bool IsValidPixel(const double d)
Returns if the input pixel is valid.
const double Null
Value for an Isis Null pixel.
Namespace for the standard library.