QGIS API Documentation  2.11.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
qgsrasterblock.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrasterblock.h - Class representing a block of raster data
3  --------------------------------------
4  Date : Oct 9, 2012
5  Copyright : (C) 2012 by Radim Blazek
6  email : radim dot blazek at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #ifndef QGSRASTERBLOCK_H
19 #define QGSRASTERBLOCK_H
20 
21 #include <limits>
22 #include <QImage>
23 #include "qgis.h"
24 #include "qgserror.h"
25 #include "qgslogger.h"
26 #include "qgsrasterrange.h"
27 #include "qgsrectangle.h"
28 
32 class CORE_EXPORT QgsRasterBlock
33 {
34  public:
36 
43  QgsRasterBlock( QGis::DataType theDataType, int theWidth, int theHeight );
44 
51  QgsRasterBlock( QGis::DataType theDataType, int theWidth, int theHeight, double theNoDataValue );
52 
53  virtual ~QgsRasterBlock();
54 
62  bool reset( QGis::DataType theDataType, int theWidth, int theHeight );
63 
71  bool reset( QGis::DataType theDataType, int theWidth, int theHeight, double theNoDataValue );
72 
73  // TODO: consider if use isValid() at all, isEmpty() should be sufficient
74  // and works also if block is valid but empty - difference between valid and empty?
79  bool isValid() const { return mValid; }
80 
82  void setValid( bool valid ) { mValid = valid; }
83 
88  bool isEmpty() const;
89 
90  // Return data type size in bytes
91  static int typeSize( int dataType )
92  {
93  // Modified and extended copy from GDAL
94  switch ( dataType )
95  {
96  case QGis::Byte:
97  return 1;
98 
99  case QGis::UInt16:
100  case QGis::Int16:
101  return 2;
102 
103  case QGis::UInt32:
104  case QGis::Int32:
105  case QGis::Float32:
106  case QGis::CInt16:
107  return 4;
108 
109  case QGis::Float64:
110  case QGis::CInt32:
111  case QGis::CFloat32:
112  return 8;
113 
114  case QGis::CFloat64:
115  return 16;
116 
117  case QGis::ARGB32:
119  return 4;
120 
121  default:
122  return 0;
123  }
124  }
125 
126  // Data type in bytes
127  int dataTypeSize() const
128  {
129  return typeSize( mDataType );
130  }
131 
133  static bool typeIsNumeric( QGis::DataType type );
134 
136  static bool typeIsColor( QGis::DataType type );
137 
139  QGis::DataType dataType() const { return mDataType; }
140 
142  static QGis::DataType typeWithNoDataValue( QGis::DataType dataType, double *noDataValue );
143 
146  bool hasNoDataValue() const { return mHasNoDataValue; }
147 
152  bool hasNoData() const;
153 
157  double noDataValue() const { return mNoDataValue; }
158 
163  static QByteArray valueBytes( QGis::DataType theDataType, double theValue );
164 
170  double value( int row, int column ) const;
171 
176  double value( qgssize index ) const;
177 
182  QRgb color( int row, int column ) const;
183 
187  QRgb color( qgssize index ) const;
188 
193  bool isNoData( int row, int column );
194 
198  bool isNoData( qgssize index );
199 
205  bool setValue( int row, int column, double value );
206 
211  bool setValue( qgssize index, double value );
212 
218  bool setColor( int row, int column, QRgb color );
219 
224  bool setColor( qgssize index, QRgb color );
225 
230  bool setIsNoData( int row, int column );
231 
235  bool setIsNoData( qgssize index );
236 
239  bool setIsNoData();
240 
243  bool setIsNoDataExcept( const QRect & theExceptRect );
244 
252  void setIsData( int row, int column );
253 
260  void setIsData( qgssize index );
261 
268  char * bits( int row, int column );
269 
275  char * bits( qgssize index );
276 
281  char * bits();
282 
287  static QString printValue( double value );
288 
292  bool convert( QGis::DataType destDataType );
293 
296  QImage image() const;
297 
301  bool setImage( const QImage * image );
302 
303  // @note not available in python bindings
304  inline static double readValue( void *data, QGis::DataType type, qgssize index );
305 
306  // @note not available in python bindings
307  inline static void writeValue( void *data, QGis::DataType type, qgssize index, double value );
308 
309  void applyNoDataValues( const QgsRasterRangeList & rangeList );
310 
313  void applyScaleOffset( double scale, double offset );
314 
316  QgsError error() const { return mError; }
317 
319  void setError( const QgsError & theError ) { mError = theError;}
320 
321  QString toString() const;
322 
332  static QRect subRect( const QgsRectangle &theExtent, int theWidth, int theHeight, const QgsRectangle &theSubExtent );
333 
338  int width() const { return mWidth; }
339 
344  int height() const { return mHeight; }
345 
346  private:
347  static QImage::Format imageFormat( QGis::DataType theDataType );
348  static QGis::DataType dataType( QImage::Format theFormat );
349 
354  static bool isNoDataValue( double value, double noDataValue );
355 
359  bool isNoDataValue( double value ) const;
360 
363  bool createNoDataBitmap();
364 
372  static void * convert( void *srcData, QGis::DataType srcDataType, QGis::DataType destDataType, qgssize size );
373 
374  // Valid
375  bool mValid;
376 
377  // Data type
378  QGis::DataType mDataType;
379 
380  // Data type size in bytes, to make bits() fast
381  int mTypeSize;
382 
383  // Width
384  int mWidth;
385 
386  // Height
387  int mHeight;
388 
389  // Has no data value
390  bool mHasNoDataValue;
391 
392  // No data value
393  double mNoDataValue;
394 
395  static const QRgb mNoDataColor;
396 
397  // Data block for numerical data types, not used with image data types
398  // QByteArray does not seem to be intended for large data blocks, does it?
399  void * mData;
400 
401  // Image for image data types, not used with numerical data types
402  QImage *mImage;
403 
404  // Bitmap of no data. One bit for each pixel. Bit is 1 if a pixels is no data.
405  // Each row is represented by whole number of bytes (last bits may be unused)
406  // to make processing rows easy.
407  char *mNoDataBitmap;
408 
409  // number of bytes in mNoDataBitmap row
410  int mNoDataBitmapWidth;
411 
412  // total size in bytes of mNoDataBitmap
413  qgssize mNoDataBitmapSize;
414 
415  // Error
416  QgsError mError;
417 };
418 
419 inline double QgsRasterBlock::readValue( void *data, QGis::DataType type, qgssize index )
420 {
421  if ( !data )
422  {
423  return std::numeric_limits<double>::quiet_NaN();
424  }
425 
426  switch ( type )
427  {
428  case QGis::Byte:
429  return ( double )(( quint8 * )data )[index];
430  break;
431  case QGis::UInt16:
432  return ( double )(( quint16 * )data )[index];
433  break;
434  case QGis::Int16:
435  return ( double )(( qint16 * )data )[index];
436  break;
437  case QGis::UInt32:
438  return ( double )(( quint32 * )data )[index];
439  break;
440  case QGis::Int32:
441  return ( double )(( qint32 * )data )[index];
442  break;
443  case QGis::Float32:
444  return ( double )(( float * )data )[index];
445  break;
446  case QGis::Float64:
447  return ( double )(( double * )data )[index];
448  break;
449  default:
450  QgsDebugMsg( QString( "Data type %1 is not supported" ).arg( type ) );
451  break;
452  }
453 
454  return std::numeric_limits<double>::quiet_NaN();
455 }
456 
457 inline void QgsRasterBlock::writeValue( void *data, QGis::DataType type, qgssize index, double value )
458 {
459  if ( !data ) return;
460 
461  switch ( type )
462  {
463  case QGis::Byte:
464  (( quint8 * )data )[index] = ( quint8 ) value;
465  break;
466  case QGis::UInt16:
467  (( quint16 * )data )[index] = ( quint16 ) value;
468  break;
469  case QGis::Int16:
470  (( qint16 * )data )[index] = ( qint16 ) value;
471  break;
472  case QGis::UInt32:
473  (( quint32 * )data )[index] = ( quint32 ) value;
474  break;
475  case QGis::Int32:
476  (( qint32 * )data )[index] = ( qint32 ) value;
477  break;
478  case QGis::Float32:
479  (( float * )data )[index] = ( float ) value;
480  break;
481  case QGis::Float64:
482  (( double * )data )[index] = value;
483  break;
484  default:
485  QgsDebugMsg( QString( "Data type %1 is not supported" ).arg( type ) );
486  break;
487  }
488 }
489 
490 inline double QgsRasterBlock::value( qgssize index ) const
491 {
492  if ( !mData )
493  {
494  QgsDebugMsg( "Data block not allocated" );
495  return std::numeric_limits<double>::quiet_NaN();
496  }
497  return readValue( mData, mDataType, index );
498 }
499 
500 inline bool QgsRasterBlock::isNoDataValue( double value ) const
501 {
502  return qIsNaN( value ) || qgsDoubleNear( value, mNoDataValue );
503 }
504 
505 #endif
506 
507 
static unsigned index
A rectangle specified with double values.
Definition: qgsrectangle.h:35
int height() const
Returns the height (number of rows) of the raster block.
bool isValid() const
Returns true if the block is valid (correctly filled with data).
void setError(const QgsError &theError)
Set error.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
double noDataValue() const
Return no data value.
int width() const
Returns the width (number of columns) of the raster block.
QGis::DataType dataType() const
Returns data type.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:350
Raster data container.
double value(int row, int column) const
Read a single value if type of block is numeric.
static int typeSize(int dataType)
DataType
Raster data types.
Definition: qgis.h:204
unsigned long long qgssize
qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
Definition: qgis.h:449
int dataTypeSize() const
static void writeValue(void *data, QGis::DataType type, qgssize index, double value)
void setValid(bool valid)
Mark block as valid or invalid.
bool hasNoDataValue() const
True if the block has no data value.
QgsError is container for error messages (report).
Definition: qgserror.h:77
static double readValue(void *data, QGis::DataType type, qgssize index)
QgsError error() const
Get error.