QGIS API Documentation  2.8.2-Wien
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups 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 
251  char * bits( int row, int column );
252 
258  char * bits( qgssize index );
259 
264  char * bits();
265 
270  static QString printValue( double value );
271 
275  bool convert( QGis::DataType destDataType );
276 
279  QImage image() const;
280 
284  bool setImage( const QImage * image );
285 
286  // @note not available in python bindings
287  inline static double readValue( void *data, QGis::DataType type, qgssize index );
288 
289  // @note not available in python bindings
290  inline static void writeValue( void *data, QGis::DataType type, qgssize index, double value );
291 
292  void applyNoDataValues( const QgsRasterRangeList & rangeList );
293 
296  void applyScaleOffset( double scale, double offset );
297 
299  QgsError error() const { return mError; }
300 
302  void setError( const QgsError & theError ) { mError = theError;}
303 
313  static QRect subRect( const QgsRectangle &theExtent, int theWidth, int theHeight, const QgsRectangle &theSubExtent );
314 
315  private:
316  static QImage::Format imageFormat( QGis::DataType theDataType );
317  static QGis::DataType dataType( QImage::Format theFormat );
318 
323  static bool isNoDataValue( double value, double noDataValue );
324 
328  bool isNoDataValue( double value ) const;
329 
332  bool createNoDataBitmap();
333 
341  static void * convert( void *srcData, QGis::DataType srcDataType, QGis::DataType destDataType, qgssize size );
342 
343  // Valid
344  bool mValid;
345 
346  // Data type
347  QGis::DataType mDataType;
348 
349  // Data type size in bytes, to make bits() fast
350  int mTypeSize;
351 
352  // Width
353  int mWidth;
354 
355  // Height
356  int mHeight;
357 
358  // Has no data value
359  bool mHasNoDataValue;
360 
361  // No data value
362  double mNoDataValue;
363 
364  static const QRgb mNoDataColor;
365 
366  // Data block for numerical data types, not used with image data types
367  // QByteArray does not seem to be intended for large data blocks, does it?
368  void * mData;
369 
370  // Image for image data types, not used with numerical data types
371  QImage *mImage;
372 
373  // Bitmap of no data. One bit for each pixel. Bit is 1 if a pixels is no data.
374  // Each row is represented by whole number of bytes (last bits may be unused)
375  // to make processing rows easy.
376  char *mNoDataBitmap;
377 
378  // number of bytes in mNoDataBitmap row
379  int mNoDataBitmapWidth;
380 
381  // total size in bytes of mNoDataBitmap
382  qgssize mNoDataBitmapSize;
383 
384  // Error
385  QgsError mError;
386 };
387 
388 inline double QgsRasterBlock::readValue( void *data, QGis::DataType type, qgssize index )
389 {
390  if ( !data )
391  {
392  return std::numeric_limits<double>::quiet_NaN();
393  }
394 
395  switch ( type )
396  {
397  case QGis::Byte:
398  return ( double )(( quint8 * )data )[index];
399  break;
400  case QGis::UInt16:
401  return ( double )(( quint16 * )data )[index];
402  break;
403  case QGis::Int16:
404  return ( double )(( qint16 * )data )[index];
405  break;
406  case QGis::UInt32:
407  return ( double )(( quint32 * )data )[index];
408  break;
409  case QGis::Int32:
410  return ( double )(( qint32 * )data )[index];
411  break;
412  case QGis::Float32:
413  return ( double )(( float * )data )[index];
414  break;
415  case QGis::Float64:
416  return ( double )(( double * )data )[index];
417  break;
418  default:
419  QgsDebugMsg( QString( "Data type %1 is not supported" ).arg( type ) );
420  break;
421  }
422 
423  return std::numeric_limits<double>::quiet_NaN();
424 }
425 
426 inline void QgsRasterBlock::writeValue( void *data, QGis::DataType type, qgssize index, double value )
427 {
428  if ( !data ) return;
429 
430  switch ( type )
431  {
432  case QGis::Byte:
433  (( quint8 * )data )[index] = ( quint8 ) value;
434  break;
435  case QGis::UInt16:
436  (( quint16 * )data )[index] = ( quint16 ) value;
437  break;
438  case QGis::Int16:
439  (( qint16 * )data )[index] = ( qint16 ) value;
440  break;
441  case QGis::UInt32:
442  (( quint32 * )data )[index] = ( quint32 ) value;
443  break;
444  case QGis::Int32:
445  (( qint32 * )data )[index] = ( qint32 ) value;
446  break;
447  case QGis::Float32:
448  (( float * )data )[index] = ( float ) value;
449  break;
450  case QGis::Float64:
451  (( double * )data )[index] = value;
452  break;
453  default:
454  QgsDebugMsg( QString( "Data type %1 is not supported" ).arg( type ) );
455  break;
456  }
457 }
458 
459 inline double QgsRasterBlock::value( qgssize index ) const
460 {
461  if ( !mData )
462  {
463  QgsDebugMsg( "Data block not allocated" );
464  return std::numeric_limits<double>::quiet_NaN();
465  }
466  return readValue( mData, mDataType, index );
467 }
468 
469 inline bool QgsRasterBlock::isNoDataValue( double value ) const
470 {
471  return qIsNaN( value ) || qgsDoubleNear( value, mNoDataValue );
472 }
473 
474 #endif
475 
476