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 );
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();
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;
270 QgsDebugMsg(
QString(
"newDataType = %1 noDataValue = %2" ).arg( newDataType ).arg( *noDataValue ) );
276 return mHasNoDataValue || mNoDataBitmap != 0;
279 bool QgsRasterBlock::isNoDataValue(
double value,
double noDataValue )
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 )
321 double value =
readValue( mData, mDataType, index );
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 ) );
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 )
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 )
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 )
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 );
726 mDataType = destDataType;
741 if ( scale == 1.0 && offset == 0.0 )
return;
744 for (
qgssize i = 0; i < size; ++i )
759 for (
qgssize i = 0; i < size; ++i )
761 double val =
value( i );
785 mImage =
new QImage( *image );
786 mWidth = mImage->
width();
787 mHeight = mImage->
height();
790 mNoDataValue = std::numeric_limits<double>::quiet_NaN();
820 for (
int i = 15; i <= 17; i++ )
822 s.
setNum( value,
'g', i );
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++ )
839 double value =
readValue( srcData, srcDataType, i );
840 writeValue( destData, destDataType, i, value );
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;
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 );
913 return QString(
"dataType = %1 width = %2 height = %3" )
914 .
arg( mDataType ).
arg( mWidth ).
arg( mHeight );
921 double xRes = theExtent.
width() / theWidth;
922 double yRes = theExtent.
height() / theHeight;
924 QgsDebugMsg(
QString(
"theWidth = %1 theHeight = %2 xRes = %3 yRes = %4" ).arg( theWidth ).arg( theHeight ).arg( xRes ).arg( yRes ) );
927 int bottom = theHeight - 1;
929 int right = theWidth - 1;
937 bottom = qRound(( theExtent.
yMaximum() - theSubExtent.
yMinimum() ) / yRes ) - 1;
946 right = qRound(( theSubExtent.
xMaximum() - theExtent.
xMinimum() ) / xRes ) - 1;
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.
QGis::DataType dataType() const
Returns data type.
The QGis class provides global constants for use throughout the application.
double toDouble(bool *ok) const
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.
QRgb pixel(int x, int y) const
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)
void fill(uint pixelValue)
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)
void applyScaleOffset(double scale, double offset)
apply band scale and offset to raster block values @note added in 2.3
QString & setNum(short n, int base)
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
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
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.