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;
Sixty four bit floating point (double)
Sixteen bit signed integer (qint16)
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.
Eight bit unsigned integer (quint8)
double yMaximum() const
Get the y maximum value (top side of rectangle)
Sixteen bit unsigned integer (quint16)
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)
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
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.
Thirty two bit floating point (float)
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)
DataType
Raster data types.
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)
Thirty two bit signed integer (qint32)
void applyScaleOffset(double scale, double offset)
Apply band scale and offset to raster block values @note added in 2.3.
Unknown or unspecified type.
QString & setNum(short n, int base)
static QByteArray valueBytes(QGis::DataType theDataType, double theValue)
Get byte array representing a value.
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.
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
double width() const
Width of the rectangle.
QString toString(bool automaticPrecision=false) const
returns string representation of form xmin,ymin xmax,ymax
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
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.
Thirty two bit unsigned integer (quint32)
double height() const
Height of the rectangle.
bool isEmpty() const
Returns true if block is empty, i.e.