/
qgsrasterinterface.h
343 lines (287 loc) · 11.1 KB
/
qgsrasterinterface.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
/***************************************************************************
qgsrasterface.h - Internal raster processing modules interface
--------------------------------------
Date : Jun 21, 2012
Copyright : (C) 2012 by Radim Blazek
email : radim dot blazek at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSRASTERINTERFACE_H
#define QGSRASTERINTERFACE_H
#include <limits>
#include <QImage>
#include "qgslogger.h"
#include "qgsrectangle.h"
#include "gdal.h"
/** \ingroup core
* Base class for processing modules.
*/
// TODO: inherit from QObject? It would be probably better but QgsDataProvider inherits already from QObject and multiple inheritance from QObject is not allowed
class CORE_EXPORT QgsRasterInterface
{
public:
/** Data types.
* This is modified and extended copy of GDALDataType.
*/
enum DataType
{
/*! Unknown or unspecified type */ UnknownDataType = 0,
/*! Eight bit unsigned integer */ Byte = 1,
/*! Sixteen bit unsigned integer */ UInt16 = 2,
/*! Sixteen bit signed integer */ Int16 = 3,
/*! Thirty two bit unsigned integer */ UInt32 = 4,
/*! Thirty two bit signed integer */ Int32 = 5,
/*! Thirty two bit floating point */ Float32 = 6,
/*! Sixty four bit floating point */ Float64 = 7,
/*! Complex Int16 */ CInt16 = 8,
/*! Complex Int32 */ CInt32 = 9,
/*! Complex Float32 */ CFloat32 = 10,
/*! Complex Float64 */ CFloat64 = 11,
/*! Color, alpha, red, green, blue, 4 bytes the same as
QImage::Format_ARGB32 */ ARGB32 = 12,
/*! Color, alpha, red, green, blue, 4 bytes the same as
QImage::Format_ARGB32_Premultiplied */ ARGB32_Premultiplied = 13,
TypeCount = 14 /* maximum type # + 1 */
};
struct Range
{
double min;
double max;
inline bool operator==( const Range &o ) const
{
return min == o.min && max == o.max;
}
};
QgsRasterInterface( QgsRasterInterface * input = 0 );
virtual ~QgsRasterInterface();
static int typeSize( int dataType )
{
// Modified and extended copy from GDAL
switch ( dataType )
{
case Byte:
return 8;
case UInt16:
case Int16:
return 16;
case UInt32:
case Int32:
case Float32:
case CInt16:
return 32;
case Float64:
case CInt32:
case CFloat32:
return 64;
case CFloat64:
return 128;
case ARGB32:
case ARGB32_Premultiplied:
return 32;
default:
return 0;
}
}
/** Clone itself, create deep copy */
virtual QgsRasterInterface *clone() const = 0;
int dataTypeSize( int bandNo ) const
{
return typeSize( dataType( bandNo ) );
}
/** Returns true if data type is numeric */
bool typeIsNumeric( DataType type ) const;
/** Returns true if data type is color */
bool typeIsColor( DataType type ) const;
/** Returns data type for the band specified by number */
virtual DataType dataType( int bandNo ) const
{
Q_UNUSED( bandNo );
QgsDebugMsg( "Entered" );
return UnknownDataType;
}
/** For given data type returns wider type and sets no data value */
static DataType typeWithNoDataValue( DataType dataType, double *noDataValue );
/** Get number of bands */
virtual int bandCount() const
{
return 1;
}
/** Retruns value representing 'no data' (NULL) */
// TODO: Q_DECL_DEPRECATED
virtual double noDataValue() const { return 0; }
/** Return no data value for specific band. Each band/provider must have
* no data value, if there is no one set in original data, provider decides one
* possibly using wider data type.
* @param bandNo band number
* @return No data value */
virtual double noDataValue( int bandNo ) const { Q_UNUSED( bandNo ); return noDataValue(); }
/** Test if value is nodata for specific band
* @param bandNo band number
* @param value tested value
* @return true if value is nodata */
virtual bool isNoDataValue( int bandNo, double value ) const ;
/** Read block of data using given extent and size.
* Returns pointer to data.
* Caller is responsible to free the memory returned.
*/
void * block( int bandNo, QgsRectangle const & extent, int width, int height );
/** Read block of data using given extent and size.
* Method to be implemented by subclasses.
* Returns pointer to data.
* Caller is responsible to free the memory returned.
*/
virtual void * readBlock( int bandNo, QgsRectangle const & extent, int width, int height )
{
Q_UNUSED( bandNo ); Q_UNUSED( extent ); Q_UNUSED( width ); Q_UNUSED( height );
return 0;
}
/** Set input.
* Returns true if set correctly, false if cannot use that input */
virtual bool setInput( QgsRasterInterface* input ) { mInput = input; return true; }
/** Is on/off */
virtual bool on( ) { return mOn; }
/** Set on/off */
virtual void setOn( bool on ) { mOn = on; }
/** Get source / raw input, the first in pipe, usually provider.
* It may be used to get info about original data, e.g. resolution to decide
* resampling etc.
*/
virtual const QgsRasterInterface * srcInput() const { return mInput ? mInput->srcInput() : this; }
virtual QgsRasterInterface * srcInput() { return mInput ? mInput->srcInput() : this; }
/** Create a new image with extraneous data, such data may be used
* after the image is destroyed. The memory is not initialized.
*/
QImage * createImage( int width, int height, QImage::Format format );
/** Switch on (and clear old statistics) or off collection of statistics */
void setStatsOn( bool on );
/** Last total time (for allbands) consumed by this interface for call to block()
* If cumulative is true, the result includes also time spent in all preceding
* interfaces. If cumulative is false, only time consumed by this interface is
* returned. */
double time( bool cumulative = false );
/** \brief Print double value with all necessary significant digits.
* It is ensured that conversion back to double gives the same number.
* @param value the value to be printed
* @return string representing the value*/
static QString printValue( double value );
/** \brief Convert block of data from one type to another. Original block memory
* is not release.
* @param srcData source data
* @param srcDataType source data type
* @param destDataType dest data type
* @param size block size (width * height)
* @return block of data in destDataType */
static void * convert( void *srcData, QgsRasterInterface::DataType srcDataType, QgsRasterInterface::DataType destDataType, int size );
protected:
// QgsRasterInterface used as input
QgsRasterInterface* mInput;
// On/off state, if off, it does not do anything, replicates input
bool mOn;
inline static double readValue( void *data, QgsRasterInterface::DataType type, int index );
inline static void writeValue( void *data, QgsRasterInterface::DataType type, int index, double value );
/** \brief Test if value is within the list of ranges
* @param value value
* @param rangeList list of ranges
* @return true if value is in at least one of ranges */
inline static bool valueInRange( double value, QList<QgsRasterInterface::Range> rangeList );
private:
// Last rendering cumulative (this and all preceding interfaces) times, from index 1
QVector<double> mTime;
// Collect statistics
int mStatsOn;
};
inline double QgsRasterInterface::readValue( void *data, QgsRasterInterface::DataType type, int index )
{
#if 0
if ( !mInput )
{
return 0;
}
if ( !data )
{
return mInput->noDataValue();
}
#endif
switch ( type )
{
case QgsRasterInterface::Byte:
return ( double )(( GByte * )data )[index];
break;
case QgsRasterInterface::UInt16:
return ( double )(( GUInt16 * )data )[index];
break;
case QgsRasterInterface::Int16:
return ( double )(( GInt16 * )data )[index];
break;
case QgsRasterInterface::UInt32:
return ( double )(( GUInt32 * )data )[index];
break;
case QgsRasterInterface::Int32:
return ( double )(( GInt32 * )data )[index];
break;
case QgsRasterInterface::Float32:
return ( double )(( float * )data )[index];
break;
case QgsRasterInterface::Float64:
return ( double )(( double * )data )[index];
break;
default:
//QgsMessageLog::logMessage( tr( "GDAL data type %1 is not supported" ).arg( type ), tr( "Raster" ) );
break;
}
// TODO: noDataValue is per band
//return mInput->noDataValue();
return std::numeric_limits<double>::quiet_NaN();
}
inline void QgsRasterInterface::writeValue( void *data, QgsRasterInterface::DataType type, int index, double value )
{
if ( !data ) return;
switch ( type )
{
case QgsRasterInterface::Byte:
(( GByte * )data )[index] = ( GByte ) value;
break;
case QgsRasterInterface::UInt16:
(( GUInt16 * )data )[index] = ( GUInt16 ) value;
break;
case QgsRasterInterface::Int16:
(( GInt16 * )data )[index] = ( GInt16 ) value;
break;
case QgsRasterInterface::UInt32:
(( GUInt32 * )data )[index] = ( GUInt32 ) value;
break;
case QgsRasterInterface::Int32:
(( GInt32 * )data )[index] = ( GInt32 ) value;
break;
case QgsRasterInterface::Float32:
(( float * )data )[index] = ( float ) value;
break;
case QgsRasterInterface::Float64:
(( double * )data )[index] = value;
break;
default:
//QgsMessageLog::logMessage( tr( "GDAL data type %1 is not supported" ).arg( type ), tr( "Raster" ) );
break;
}
}
inline bool QgsRasterInterface::valueInRange( double value, QList<QgsRasterInterface::Range> rangeList )
{
foreach ( QgsRasterInterface::Range range, rangeList )
{
if (( value >= range.min && value <= range.max ) ||
doubleNear( value, range.min ) ||
doubleNear( value, range.max ) )
{
return true;
}
}
return false;
}
#endif