|
QGIS API Documentation
master-6227475
|
00001 /*************************************************************************** 00002 qgsrasterblock.h - Class representing a block of raster data 00003 -------------------------------------- 00004 Date : Oct 9, 2012 00005 Copyright : (C) 2012 by Radim Blazek 00006 email : radim dot blazek at gmail dot com 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #ifndef QGSRASTERBLOCK_H 00019 #define QGSRASTERBLOCK_H 00020 00021 #include <limits> 00022 #include <QImage> 00023 #include "qgis.h" 00024 #include "qgserror.h" 00025 #include "qgslogger.h" 00026 #include "qgsrasterrange.h" 00027 #include "qgsrectangle.h" 00028 00032 class CORE_EXPORT QgsRasterBlock 00033 { 00034 public: 00035 QgsRasterBlock(); 00036 00042 QgsRasterBlock( QGis::DataType theDataType, int theWidth, int theHeight ); 00043 00050 QgsRasterBlock( QGis::DataType theDataType, int theWidth, int theHeight, double theNoDataValue ); 00051 00052 virtual ~QgsRasterBlock(); 00053 00060 bool reset( QGis::DataType theDataType, int theWidth, int theHeight ); 00061 00069 bool reset( QGis::DataType theDataType, int theWidth, int theHeight, double theNoDataValue ); 00070 00071 // TODO: consider if use isValid() at all, isEmpty() should be sufficient 00072 // and works also if block is valid but empty - difference between valid and empty? 00077 bool isValid() const { return mValid; } 00078 00080 void setValid( bool valid ) { mValid = valid; } 00081 00086 bool isEmpty() const; 00087 00088 // Return data type size in bytes 00089 static int typeSize( int dataType ) 00090 { 00091 // Modified and extended copy from GDAL 00092 switch ( dataType ) 00093 { 00094 case QGis::Byte: 00095 return 1; 00096 00097 case QGis::UInt16: 00098 case QGis::Int16: 00099 return 2; 00100 00101 case QGis::UInt32: 00102 case QGis::Int32: 00103 case QGis::Float32: 00104 case QGis::CInt16: 00105 return 4; 00106 00107 case QGis::Float64: 00108 case QGis::CInt32: 00109 case QGis::CFloat32: 00110 return 8; 00111 00112 case QGis::CFloat64: 00113 return 16; 00114 00115 case QGis::ARGB32: 00116 case QGis::ARGB32_Premultiplied: 00117 return 4; 00118 00119 default: 00120 return 0; 00121 } 00122 } 00123 00124 // Data type in bytes 00125 int dataTypeSize( ) const 00126 { 00127 return typeSize( mDataType ); 00128 } 00129 00131 static bool typeIsNumeric( QGis::DataType type ); 00132 00134 static bool typeIsColor( QGis::DataType type ); 00135 00137 QGis::DataType dataType() const { return mDataType; } 00138 00140 static QGis::DataType typeWithNoDataValue( QGis::DataType dataType, double *noDataValue ); 00141 00144 bool hasNoDataValue() const { return mHasNoDataValue; } 00145 00150 bool hasNoData() const; 00151 00155 double noDataValue() const { return mNoDataValue; } 00156 00161 static QByteArray valueBytes( QGis::DataType theDataType, double theValue ); 00162 00168 double value( int row, int column ) const; 00169 00174 double value( size_t index ) const; 00175 00180 QRgb color( int row, int column ) const; 00181 00185 QRgb color( size_t index ) const; 00186 00191 bool isNoData( int row, int column ); 00192 00196 bool isNoData( size_t index ); 00197 00203 bool setValue( int row, int column, double value ); 00204 00209 bool setValue( size_t index, double value ); 00210 00216 bool setColor( int row, int column, QRgb color ); 00217 00222 bool setColor( size_t index, QRgb color ); 00223 00228 bool setIsNoData( int row, int column ); 00229 00233 bool setIsNoData( size_t index ); 00234 00237 bool setIsNoData( ); 00238 00241 bool setIsNoDataExcept( const QRect & theExceptRect ); 00242 00248 char * bits( int row, int column ); 00249 00253 char * bits( size_t index ); 00254 00257 char * bits(); 00258 00263 static QString printValue( double value ); 00264 00268 bool convert( QGis::DataType destDataType ); 00269 00272 QImage image() const; 00273 00277 bool setImage( const QImage * image ); 00278 00279 inline static double readValue( void *data, QGis::DataType type, size_t index ); 00280 00281 inline static void writeValue( void *data, QGis::DataType type, size_t index, double value ); 00282 00283 void applyNoDataValues( const QgsRasterRangeList & rangeList ); 00284 00286 QgsError error() const { return mError; } 00287 00289 void setError( const QgsError & theError ) { mError = theError;} 00290 00300 static QRect subRect( const QgsRectangle & theExtent, int theWidth, int theHeight, const QgsRectangle & theSubExtent ); 00301 00302 private: 00303 static QImage::Format imageFormat( QGis::DataType theDataType ); 00304 static QGis::DataType dataType( QImage::Format theFormat ); 00305 00310 static bool isNoDataValue( double value, double noDataValue ); 00311 00315 bool isNoDataValue( double value ) const; 00316 00319 bool createNoDataBitmap(); 00320 00328 static void * convert( void *srcData, QGis::DataType srcDataType, QGis::DataType destDataType, size_t size ); 00329 00330 // Valid 00331 bool mValid; 00332 00333 // Data type 00334 QGis::DataType mDataType; 00335 00336 // Data type size in bytes, to make bits() fast 00337 int mTypeSize; 00338 00339 // Width 00340 int mWidth; 00341 00342 // Height 00343 int mHeight; 00344 00345 // Has no data value 00346 bool mHasNoDataValue; 00347 00348 // No data value 00349 double mNoDataValue; 00350 00351 // Data block for numerical data types, not used with image data types 00352 // QByteArray does not seem to be intended for large data blocks, does it? 00353 void * mData; 00354 00355 // Image for image data types, not used with numerical data types 00356 QImage *mImage; 00357 00358 // Bitmap of no data. One bit for each pixel. Bit is 1 if a pixels is no data. 00359 // Each row is represented by whole number of bytes (last bits may be unused) 00360 // to make processing rows easy. 00361 char *mNoDataBitmap; 00362 00363 // number of bytes in mNoDataBitmap row 00364 int mNoDataBitmapWidth; 00365 00366 // total size in bytes of mNoDataBitmap 00367 size_t mNoDataBitmapSize; 00368 00369 // Error 00370 QgsError mError; 00371 }; 00372 00373 inline double QgsRasterBlock::readValue( void *data, QGis::DataType type, size_t index ) 00374 { 00375 if ( !data ) 00376 { 00377 return std::numeric_limits<double>::quiet_NaN(); 00378 } 00379 00380 switch ( type ) 00381 { 00382 case QGis::Byte: 00383 return ( double )(( quint8 * )data )[index]; 00384 break; 00385 case QGis::UInt16: 00386 return ( double )(( quint16 * )data )[index]; 00387 break; 00388 case QGis::Int16: 00389 return ( double )(( qint16 * )data )[index]; 00390 break; 00391 case QGis::UInt32: 00392 return ( double )(( quint32 * )data )[index]; 00393 break; 00394 case QGis::Int32: 00395 return ( double )(( qint32 * )data )[index]; 00396 break; 00397 case QGis::Float32: 00398 return ( double )(( float * )data )[index]; 00399 break; 00400 case QGis::Float64: 00401 return ( double )(( double * )data )[index]; 00402 break; 00403 default: 00404 QgsDebugMsg( QString( "Data type %1 is not supported" ).arg( type ) ); 00405 break; 00406 } 00407 00408 return std::numeric_limits<double>::quiet_NaN(); 00409 } 00410 00411 inline void QgsRasterBlock::writeValue( void *data, QGis::DataType type, size_t index, double value ) 00412 { 00413 if ( !data ) return; 00414 00415 switch ( type ) 00416 { 00417 case QGis::Byte: 00418 (( quint8 * )data )[index] = ( quint8 ) value; 00419 break; 00420 case QGis::UInt16: 00421 (( quint16 * )data )[index] = ( quint16 ) value; 00422 break; 00423 case QGis::Int16: 00424 (( qint16 * )data )[index] = ( qint16 ) value; 00425 break; 00426 case QGis::UInt32: 00427 (( quint32 * )data )[index] = ( quint32 ) value; 00428 break; 00429 case QGis::Int32: 00430 (( qint32 * )data )[index] = ( qint32 ) value; 00431 break; 00432 case QGis::Float32: 00433 (( float * )data )[index] = ( float ) value; 00434 break; 00435 case QGis::Float64: 00436 (( double * )data )[index] = value; 00437 break; 00438 default: 00439 QgsDebugMsg( QString( "Data type %1 is not supported" ).arg( type ) ); 00440 break; 00441 } 00442 } 00443 00444 inline double QgsRasterBlock::value( size_t index ) const 00445 { 00446 if ( !mData ) 00447 { 00448 QgsDebugMsg( "Data block not allocated" ); 00449 return std::numeric_limits<double>::quiet_NaN(); 00450 } 00451 return readValue( mData, mDataType, index ); 00452 } 00453 00454 inline bool QgsRasterBlock::isNoDataValue( double value ) const 00455 { 00456 return qIsNaN( value ) || qgsDoubleNear( value, mNoDataValue ); 00457 } 00458 00459 #endif 00460 00461