27 const QRgb QgsRasterBlock::mNoDataColor = qRgba( 0, 0, 0, 0 );
31 , mDataType(
QGis::UnknownDataType )
35 , mHasNoDataValue( false )
36 , mNoDataValue( std::numeric_limits<double>::quiet_NaN() )
40 , mNoDataBitmapWidth( 0 )
41 , mNoDataBitmapSize( 0 )
47 , mDataType( theDataType )
50 , mHeight( theHeight )
51 , mHasNoDataValue( false )
52 , mNoDataValue( std::numeric_limits<double>::quiet_NaN() )
56 , mNoDataBitmapWidth( 0 )
57 , mNoDataBitmapSize( 0 )
59 ( void )
reset( mDataType, mWidth, mHeight );
64 , mDataType( theDataType )
67 , mHeight( theHeight )
68 , mHasNoDataValue( true )
69 , mNoDataValue( theNoDataValue )
73 , mNoDataBitmapWidth( 0 )
74 , mNoDataBitmapSize( 0 )
76 ( void )
reset( mDataType, mWidth, mHeight, mNoDataValue );
81 QgsDebugMsg( QString(
"mData = %1" ).arg(( ulong )mData ) );
89 QgsDebugMsg( QString(
"theWidth= %1 theHeight = %2 theDataType = %3" ).arg( theWidth ).arg( theHeight ).arg( theDataType ) );
90 if ( !
reset( theDataType, theWidth, theHeight, std::numeric_limits<double>::quiet_NaN() ) )
94 mHasNoDataValue =
false;
101 QgsDebugMsg( QString(
"theWidth= %1 theHeight = %2 theDataType = %3 theNoDataValue = %4" ).arg( theWidth ).arg( theHeight ).arg( theDataType ).arg( theNoDataValue ) );
113 mHasNoDataValue =
false;
114 mNoDataValue = std::numeric_limits<double>::quiet_NaN();
121 QgsDebugMsg( QString(
"allocate %1 bytes" ).arg( tSize * theWidth * theHeight ) );
122 mData =
qgsMalloc( tSize * theWidth * theHeight );
125 QgsDebugMsg( QString(
"Couldn't allocate data memory of %1 bytes" ).arg( tSize * theWidth * theHeight ) );
132 QImage::Format format = imageFormat( theDataType );
133 mImage =
new QImage( theWidth, theHeight, format );
142 mDataType = theDataType;
146 mHasNoDataValue =
true;
147 mNoDataValue = theNoDataValue;
148 QgsDebugMsg( QString(
"mWidth= %1 mHeight = %2 mDataType = %3 mData = %4 mImage = %5" ).arg( mWidth ).arg( mHeight ).arg( mDataType ).arg(( ulong )mData ).arg(( ulong )mImage ) );
152 QImage::Format QgsRasterBlock::imageFormat(
QGis::DataType theDataType )
156 return QImage::Format_ARGB32;
160 return QImage::Format_ARGB32_Premultiplied;
162 return QImage::Format_Invalid;
167 if ( theFormat == QImage::Format_ARGB32 )
171 else if ( theFormat == QImage::Format_ARGB32_Premultiplied )
180 QgsDebugMsg( QString(
"mWidth= %1 mHeight = %2 mDataType = %3 mData = %4 mImage = %5" ).arg( mWidth ).arg( mHeight ).arg( mDataType ).arg(( ulong )mData ).arg(( ulong )mImage ) );
181 if ( mWidth == 0 || mHeight == 0 ||
247 *noDataValue = -32768.0;
251 *noDataValue = -2147483648.0;
255 *noDataValue = -2147483648.0;
266 QgsDebugMsg( QString(
"Unknow data type %1" ).arg( dataType ) );
270 QgsDebugMsg( QString(
"newDataType = %1 noDataValue = %2" ).arg( newDataType ).arg( *noDataValue ) );
276 return mHasNoDataValue || mNoDataBitmap != 0;
284 if ( qIsNaN(
value ) ||
299 int row = floor((
double )index / mWidth );
300 int column = index % mWidth;
301 return color( row, column );
306 if ( !mImage )
return mNoDataColor;
308 return mImage->pixel( column, row );
313 if ( !mHasNoDataValue && !mNoDataBitmap )
return false;
314 if ( index >= (
qgssize )mWidth*mHeight )
316 QgsDebugMsg( QString(
"Index %1 out of range (%2 x %3)" ).arg( index ).arg( mWidth ).arg( mHeight ) );
319 if ( mHasNoDataValue )
322 return isNoDataValue( value );
325 if ( mNoDataBitmap == 0 )
331 int row = ( int ) index / mWidth;
332 int column = index % mWidth;
334 int bit = column % 8;
335 int mask = 0x80 >> bit;
338 return mNoDataBitmap[byte] & mask;
353 if ( index >= (
qgssize )mWidth*mHeight )
355 QgsDebugMsg( QString(
"Index %1 out of range (%2 x %3)" ).arg( index ).arg( mWidth ).arg( mHeight ) );
380 if ( index >= (
qgssize )mImage->width()* mImage->height() )
382 QgsDebugMsg( QString(
"index %1 out of range" ).arg( index ) );
387 QRgb*
bits = ( QRgb* )mImage->bits();
399 if ( mHasNoDataValue )
401 return setValue( index, mNoDataValue );
405 if ( mNoDataBitmap == 0 )
407 if ( !createNoDataBitmap() )
413 int row = ( int ) index / mWidth;
414 int column = index % mWidth;
416 int bit = column % 8;
417 int nodata = 0x80 >> bit;
419 mNoDataBitmap[byte] = mNoDataBitmap[byte] | nodata;
429 if ( mHasNoDataValue )
439 QByteArray noDataByteArray =
valueBytes( mDataType, mNoDataValue );
441 char *nodata = noDataByteArray.data();
444 memcpy((
char* )mData + i*dataTypeSize, nodata, dataTypeSize );
450 if ( mNoDataBitmap == 0 )
452 if ( !createNoDataBitmap() )
458 memset( mNoDataBitmap, 0xff, mNoDataBitmapSize );
471 mImage->fill( mNoDataColor );
478 int top = theExceptRect.top();
479 int bottom = theExceptRect.bottom();
480 int left = theExceptRect.left();
481 int right = theExceptRect.right();
482 top = qMin( qMax( top, 0 ), mHeight - 1 );
483 left = qMin( qMax( left, 0 ), mWidth - 1 );
484 bottom = qMax( 0, qMin( bottom, mHeight - 1 ) );
485 right = qMax( 0, qMin( right, mWidth - 1 ) );
490 if ( mHasNoDataValue )
500 QByteArray noDataByteArray =
valueBytes( mDataType, mNoDataValue );
502 char *nodata = noDataByteArray.data();
504 for (
int c = 0; c < mWidth; c++ )
506 memcpy( nodataRow + c*dataTypeSize, nodata, dataTypeSize );
510 for (
int r = 0; r < mHeight; r++ )
512 if ( r >= top && r <= bottom )
continue;
514 memcpy((
char* )mData + i*dataTypeSize, nodataRow, dataTypeSize*mWidth );
517 for (
int r = top; r <= bottom; r++ )
521 memcpy((
char* )mData + i*dataTypeSize, nodataRow, dataTypeSize*left );
524 int w = mWidth - right - 1;
525 memcpy((
char* )mData + i*dataTypeSize, nodataRow, dataTypeSize*w );
532 if ( mNoDataBitmap == 0 )
534 if ( !createNoDataBitmap() )
541 char *nodataRow =
new char[mNoDataBitmapWidth];
543 memset( nodataRow, 0, mNoDataBitmapWidth );
544 for (
int c = 0; c < mWidth; c ++ )
548 char nodata = 0x80 >> bit;
549 memset( nodataRow + byte, nodataRow[byte] | nodata, 1 );
553 for (
int r = 0; r < mHeight; r++ )
555 if ( r >= top && r <= bottom )
continue;
557 memcpy( mNoDataBitmap + i, nodataRow, mNoDataBitmapWidth );
560 memset( nodataRow, 0, mNoDataBitmapWidth );
561 for (
int c = 0; c < mWidth; c ++ )
563 if ( c >= left && c <= right )
continue;
566 char nodata = 0x80 >> bit;
567 memset( nodataRow + byte, nodataRow[byte] | nodata, 1 );
569 for (
int r = top; r <= bottom; r++ )
572 memcpy( mNoDataBitmap + i, nodataRow, mNoDataBitmapWidth );
587 if ( mImage->width() != mWidth || mImage->height() != mHeight )
593 QgsDebugMsg( QString(
"Fill image depth = %1" ).arg( mImage->depth() ) );
596 if ( mImage->depth() != 32 )
602 QRgb nodataRgba = mNoDataColor;
603 QRgb *nodataRow =
new QRgb[mWidth];
604 int rgbSize =
sizeof( QRgb );
605 for (
int c = 0; c < mWidth; c ++ )
607 nodataRow[c] = nodataRgba;
611 for (
int r = 0; r < mHeight; r++ )
613 if ( r >= top && r <= bottom )
continue;
615 memcpy((
void * )( mImage->bits() + rgbSize*i ), nodataRow, rgbSize*mWidth );
618 for (
int r = top; r <= bottom; r++ )
624 memcpy((
void * )( mImage->bits() + rgbSize*i ), nodataRow, rgbSize*( left - 1 ) );
628 int w = mWidth - right - 1;
629 memcpy((
void * )( mImage->bits() + rgbSize*i ), nodataRow, rgbSize*w );
643 if ( mHasNoDataValue )
649 if ( mNoDataBitmap == 0 )
655 int row = ( int ) index / mWidth;
656 int column = index % mWidth;
658 int bit = column % 8;
659 int nodata = 0x80 >> bit;
660 mNoDataBitmap[byte] = mNoDataBitmap[byte] & ~nodata;
666 if ( index >= (
qgssize )mWidth*mHeight )
668 QgsDebugMsg( QString(
"Index %1 out of range (%2 x %3)" ).arg( index ).arg( mWidth ).arg( mHeight ) );
673 return (
char* )mData + index * mTypeSize;
675 if ( mImage && mImage->bits() )
677 return (
char* )( mImage->bits() + index * 4 );
692 return (
char* )mData;
694 if ( mImage && mImage->bits() )
696 return (
char* )( mImage->bits() );
705 if ( destDataType == mDataType )
return true;
718 mDataType = destDataType;
723 QImage::Format format = imageFormat( destDataType );
724 QImage
image = mImage->convertToFormat( format );
726 mDataType = destDataType;
741 if ( scale == 1.0 && offset == 0.0 )
return;
744 for (
qgssize i = 0; i < size; ++i )
753 if ( rangeList.isEmpty() )
759 for (
qgssize i = 0; i < size; ++i )
761 double val =
value( i );
774 return QImage( *mImage );
785 mImage =
new QImage( *image );
786 mWidth = mImage->width();
787 mHeight = mImage->height();
788 mDataType =
dataType( mImage->format() );
790 mNoDataValue = std::numeric_limits<double>::quiet_NaN();
820 for (
int i = 15; i <= 17; i++ )
822 s.setNum( value,
'g', i );
823 if ( s.toDouble() ==
value )
829 QgsDebugMsg(
"Cannot correctly parse printed value" );
835 int destDataTypeSize =
typeSize( destDataType );
836 void *destData =
qgsMalloc( destDataTypeSize * size );
837 for (
qgssize i = 0; i < size; i++ )
840 writeValue( destData, destDataType, i, value );
851 ba.resize((
int )size );
852 char * data = ba.data();
860 switch ( theDataType )
863 uc = ( quint8 )theValue;
864 memcpy( data, &uc, size );
867 us = ( quint16 )theValue;
868 memcpy( data, &us, size );
871 s = ( qint16 )theValue;
872 memcpy( data, &s, size );
875 ui = ( quint32 )theValue;
876 memcpy( data, &ui, size );
879 i = ( qint32 )theValue;
880 memcpy( data, &i, size );
883 f = ( float )theValue;
884 memcpy( data, &f, size );
887 d = ( double )theValue;
888 memcpy( data, &d, size );
896 bool QgsRasterBlock::createNoDataBitmap()
898 mNoDataBitmapWidth = mWidth / 8 + 1;
899 mNoDataBitmapSize = (
qgssize )mNoDataBitmapWidth * mHeight;
900 QgsDebugMsg( QString(
"allocate %1 bytes" ).arg( mNoDataBitmapSize ) );
901 mNoDataBitmap = (
char* )
qgsMalloc( mNoDataBitmapSize );
902 if ( mNoDataBitmap == 0 )
904 QgsDebugMsg( QString(
"Couldn't allocate no data memory of %1 bytes" ).arg( mNoDataBitmapSize ) );
907 memset( mNoDataBitmap, 0, mNoDataBitmapSize );
915 double xRes = theExtent.
width() / theWidth;
916 double yRes = theExtent.
height() / theHeight;
918 QgsDebugMsg( QString(
"theWidth = %1 theHeight = %2 xRes = %3 yRes = %4" ).arg( theWidth ).arg( theHeight ).arg( xRes ).arg( yRes ) );
921 int bottom = theHeight - 1;
923 int right = theWidth - 1;
931 bottom = qRound(( theExtent.
yMaximum() - theSubExtent.
yMinimum() ) / yRes ) - 1;
940 right = qRound(( theSubExtent.
xMaximum() - theExtent.
xMinimum() ) / xRes ) - 1;
942 QRect
subRect = QRect( left, top, right - left + 1, bottom - top + 1 );
943 QgsDebugMsg( QString(
"subRect: %1 %2 %3 %4" ).arg( subRect.x() ).arg( subRect.y() ).arg( subRect.width() ).arg( subRect.height() ) );
A rectangle specified with double values.
bool convert(QGis::DataType destDataType)
Convert data to different type.
static QString printValue(double value)
Print double value with all necessary significant digits.
void * qgsMalloc(size_t size)
Allocates size bytes and returns a pointer to the allocated memory.
bool setIsNoData()
Set the whole block to no data.
static bool contains(double value, const QgsRasterRangeList &rangeList)
Test if value is within the list of ranges.
double yMaximum() const
Get the y maximum value (top side of rectangle)
static bool typeIsNumeric(QGis::DataType type)
Returns true if data type is numeric.
void applyNoDataValues(const QgsRasterRangeList &rangeList)
bool setValue(int row, int column, double value)
Set value on position.
double noDataValue() const
Return no data value.
QGis::DataType dataType() const
Returns data type.
The QGis class provides global constants for use throughout the application.
bool isNoData(int row, int column)
Check if value at position is no data.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
bool setColor(int row, int column, QRgb color)
Set color on position.
virtual ~QgsRasterBlock()
static QGis::DataType typeWithNoDataValue(QGis::DataType dataType, double *noDataValue)
For given data type returns wider type and sets no data value.
bool setIsNoDataExcept(const QRect &theExceptRect)
Set the whole block to no data except specified rectangle.
bool hasNoData() const
Returns true if the block may contain no data.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
double xMaximum() const
Get the x maximum value (right side of rectangle)
bool setImage(const QImage *image)
set image.
double value(int row, int column) const
Read a single value if type of block is numeric.
static bool typeIsColor(QGis::DataType type)
Returns true if data type is color.
void setIsData(int row, int column)
Remove no data flag on pixel.
char * bits()
Get pointer to data.
static int typeSize(int dataType)
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...
bool reset(QGis::DataType theDataType, int theWidth, int theHeight)
Reset block.
static void writeValue(void *data, QGis::DataType type, qgssize index, double value)
QList< QgsRasterRange > QgsRasterRangeList
void applyScaleOffset(double scale, double offset)
apply band scale and offset to raster block values @note added in 2.3
static QByteArray valueBytes(QGis::DataType theDataType, double theValue)
Get byte array representing a value.
DataType
Raster data types.
QImage image() const
Get image if type is color.
QRgb color(int row, int column) const
Read a single color.
static double readValue(void *data, QGis::DataType type, qgssize index)
static QRect subRect(const QgsRectangle &theExtent, int theWidth, int theHeight, const QgsRectangle &theSubExtent)
For theExtent and theWidht, theHeight find rectangle covered by subextent.
double width() const
Width of the rectangle.
QString toString(bool automaticPrecision=false) const
returns string representation of form xmin,ymin xmax,ymax
double xMinimum() const
Get the x minimum value (left side of rectangle)
void qgsFree(void *ptr)
Frees the memory space pointed to by ptr.
double height() const
Height of the rectangle.
bool isEmpty() const
Returns true if block is empty, i.e.