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() )
39 , mNoDataBitmap( nullptr )
40 , mNoDataBitmapWidth( 0 )
41 , mNoDataBitmapSize( 0 )
47 , mDataType( theDataType )
50 , mHeight( theHeight )
51 , mHasNoDataValue( false )
52 , mNoDataValue( std::numeric_limits<double>::quiet_NaN() )
55 , mNoDataBitmap( nullptr )
56 , mNoDataBitmapWidth( 0 )
57 , mNoDataBitmapSize( 0 )
59 ( void )
reset( mDataType, mWidth, mHeight );
64 , mDataType( theDataType )
67 , mHeight( theHeight )
68 , mHasNoDataValue( true )
69 , mNoDataValue( theNoDataValue )
72 , mNoDataBitmap( nullptr )
73 , mNoDataBitmapWidth( 0 )
74 , mNoDataBitmapSize( 0 )
76 ( void )
reset( mDataType, mWidth, mHeight, mNoDataValue );
89 QgsDebugMsgLevel(
QString(
"theWidth= %1 theHeight = %2 theDataType = %3" ).arg( theWidth ).arg( theHeight ).arg( theDataType ), 4 );
90 if ( !
reset( theDataType, theWidth, theHeight, std::numeric_limits<double>::quiet_NaN() ) )
94 mHasNoDataValue =
false;
101 QgsDebugMsgLevel(
QString(
"theWidth= %1 theHeight = %2 theDataType = %3 theNoDataValue = %4" ).arg( theWidth ).arg( theHeight ).arg( theDataType ).arg( theNoDataValue ), 4 );
108 mNoDataBitmap =
nullptr;
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 QgsDebugMsgLevel(
QString(
"mWidth= %1 mHeight = %2 mDataType = %3 mData = %4 mImage = %5" ).arg( mWidth ).arg( mHeight ).arg( mDataType )
149 .arg( reinterpret_cast< ulong >( mData ) ).arg( reinterpret_cast< ulong >( mImage ) ), 4 );
153 QImage::Format QgsRasterBlock::imageFormat(
QGis::DataType theDataType )
157 return QImage::Format_ARGB32;
161 return QImage::Format_ARGB32_Premultiplied;
163 return QImage::Format_Invalid;
168 if ( theFormat == QImage::Format_ARGB32 )
172 else if ( theFormat == QImage::Format_ARGB32_Premultiplied )
181 QgsDebugMsgLevel(
QString(
"mWidth= %1 mHeight = %2 mDataType = %3 mData = %4 mImage = %5" ).arg( mWidth ).arg( mHeight ).arg( mDataType )
182 .arg( reinterpret_cast< ulong >( mData ) ).arg( reinterpret_cast< ulong >( mImage ) ), 4 );
183 if ( mWidth == 0 || mHeight == 0 ||
249 *noDataValue = -32768.0;
253 *noDataValue = -2147483648.0;
257 *noDataValue = -2147483648.0;
277 return mHasNoDataValue || mNoDataBitmap;
285 if ( qIsNaN(
value ) ||
295 return value( static_cast< qgssize >( row ) *mWidth + column );
300 int row = floor( static_cast< double >( index ) / mWidth );
301 int column = index % mWidth;
302 return color( row, column );
307 if ( !mImage )
return mNoDataColor;
309 return mImage->
pixel( column, row );
314 if ( !mHasNoDataValue && !mNoDataBitmap )
return false;
315 if ( index >= static_cast< qgssize >( mWidth )*mHeight )
317 QgsDebugMsg(
QString(
"Index %1 out of range (%2 x %3)" ).arg( index ).arg( mWidth ).arg( mHeight ) );
320 if ( mHasNoDataValue )
323 return isNoDataValue( value );
326 if ( !mNoDataBitmap )
332 int row =
static_cast< int >(
index ) / mWidth;
333 int column = index % mWidth;
334 qgssize byte =
static_cast< qgssize >( row ) * mNoDataBitmapWidth + column / 8;
335 int bit = column % 8;
336 int mask = 0x80 >> bit;
339 return mNoDataBitmap[byte] & mask;
344 return isNoData( static_cast< qgssize >( row )*mWidth + column );
354 if ( index >= static_cast< qgssize >( mWidth ) *mHeight )
356 QgsDebugMsg(
QString(
"Index %1 out of range (%2 x %3)" ).arg( index ).arg( mWidth ).arg( mHeight ) );
365 return setValue( static_cast< qgssize >( row )*mWidth + column, value );
370 return setColor( static_cast< qgssize >( row ) *mWidth + column, color );
381 if ( index >= static_cast< qgssize >( mImage->
width() ) * mImage->
height() )
388 QRgb*
bits =
reinterpret_cast< QRgb*
>( mImage->
bits() );
395 return setIsNoData( static_cast< qgssize >( row )*mWidth + column );
400 if ( mHasNoDataValue )
402 return setValue( index, mNoDataValue );
406 if ( !mNoDataBitmap )
408 if ( !createNoDataBitmap() )
414 int row =
static_cast< int >(
index ) / mWidth;
415 int column = index % mWidth;
416 qgssize byte =
static_cast< qgssize >( row ) * mNoDataBitmapWidth + column / 8;
417 int bit = column % 8;
418 int nodata = 0x80 >> bit;
420 mNoDataBitmap[byte] = mNoDataBitmap[byte] | nodata;
430 if ( mHasNoDataValue )
442 char *nodata = noDataByteArray.
data();
443 for (
qgssize i = 0; i < static_cast< qgssize >( mWidth )*mHeight; i++ )
445 memcpy( reinterpret_cast< char* >( mData ) + i*dataTypeSize, nodata, dataTypeSize );
451 if ( !mNoDataBitmap )
453 if ( !createNoDataBitmap() )
459 memset( mNoDataBitmap, 0xff, mNoDataBitmapSize );
472 mImage->
fill( mNoDataColor );
479 int top = theExceptRect.
top();
480 int bottom = theExceptRect.
bottom();
481 int left = theExceptRect.
left();
482 int right = theExceptRect.
right();
483 top = qMin( qMax( top, 0 ), mHeight - 1 );
484 left = qMin( qMax( left, 0 ), mWidth - 1 );
485 bottom = qMax( 0, qMin( bottom, mHeight - 1 ) );
486 right = qMax( 0, qMin( right, mWidth - 1 ) );
491 if ( mHasNoDataValue )
503 char *nodata = noDataByteArray.
data();
505 for (
int c = 0; c < mWidth; c++ )
507 memcpy( nodataRow + c*dataTypeSize, nodata, dataTypeSize );
511 for (
int r = 0; r < mHeight; r++ )
513 if ( r >= top && r <= bottom )
continue;
515 memcpy( reinterpret_cast< char* >( mData ) + i*dataTypeSize, nodataRow, dataTypeSize*mWidth );
518 for (
int r = top; r <= bottom; r++ )
522 memcpy( reinterpret_cast< char* >( mData ) + i*dataTypeSize, nodataRow, dataTypeSize*left );
525 int w = mWidth - right - 1;
526 memcpy( reinterpret_cast< char* >( mData ) + i*dataTypeSize, nodataRow, dataTypeSize*w );
533 if ( !mNoDataBitmap )
535 if ( !createNoDataBitmap() )
542 char *nodataRow =
new char[mNoDataBitmapWidth];
544 memset( nodataRow, 0, mNoDataBitmapWidth );
545 for (
int c = 0; c < mWidth; c ++ )
549 char nodata = 0x80 >> bit;
550 memset( nodataRow + byte, nodataRow[byte] | nodata, 1 );
554 for (
int r = 0; r < mHeight; r++ )
556 if ( r >= top && r <= bottom )
continue;
558 memcpy( mNoDataBitmap + i, nodataRow, mNoDataBitmapWidth );
561 memset( nodataRow, 0, mNoDataBitmapWidth );
562 for (
int c = 0; c < mWidth; c ++ )
564 if ( c >= left && c <= right )
continue;
567 char nodata = 0x80 >> bit;
568 memset( nodataRow + byte, nodataRow[byte] | nodata, 1 );
570 for (
int r = top; r <= bottom; r++ )
573 memcpy( mNoDataBitmap + i, nodataRow, mNoDataBitmapWidth );
588 if ( mImage->
width() != mWidth || mImage->
height() != mHeight )
597 if ( mImage->
depth() != 32 )
603 QRgb nodataRgba = mNoDataColor;
604 QRgb *nodataRow =
new QRgb[mWidth];
605 int rgbSize =
sizeof( QRgb );
606 for (
int c = 0; c < mWidth; c ++ )
608 nodataRow[c] = nodataRgba;
612 for (
int r = 0; r < mHeight; r++ )
614 if ( r >= top && r <= bottom )
continue;
616 memcpy( reinterpret_cast< void * >( mImage->
bits() + rgbSize*i ), nodataRow, rgbSize*mWidth );
619 for (
int r = top; r <= bottom; r++ )
625 memcpy( reinterpret_cast< void * >( mImage->
bits() + rgbSize*i ), nodataRow, rgbSize*( left - 1 ) );
629 int w = mWidth - right - 1;
630 memcpy( reinterpret_cast< void * >( mImage->
bits() + rgbSize*i ), nodataRow, rgbSize*w );
639 setIsData( static_cast< qgssize >( row )*mWidth + column );
644 if ( mHasNoDataValue )
650 if ( !mNoDataBitmap )
656 int row =
static_cast< int >(
index ) / mWidth;
657 int column = index % mWidth;
658 qgssize byte =
static_cast< qgssize >( row ) * mNoDataBitmapWidth + column / 8;
659 int bit = column % 8;
660 int nodata = 0x80 >> bit;
661 mNoDataBitmap[byte] = mNoDataBitmap[byte] & ~nodata;
667 if ( index >= static_cast< qgssize >( mWidth )*mHeight )
674 return reinterpret_cast< char*
>( mData ) + index * mTypeSize;
676 if ( mImage && mImage->
bits() )
678 return reinterpret_cast< char*
>( mImage->
bits() + index * 4 );
686 return bits( static_cast< qgssize >( row )*mWidth + column );
693 return reinterpret_cast< char*
>( mData );
695 if ( mImage && mImage->
bits() )
697 return reinterpret_cast< char*
>( mImage->
bits() );
706 if ( destDataType == mDataType )
return true;
710 void *data =
convert( mData, mDataType, destDataType, static_cast< qgssize >( mWidth ) * static_cast< qgssize >( mHeight ) );
719 mDataType = destDataType;
724 QImage::Format format = imageFormat( destDataType );
727 mDataType = destDataType;
742 if ( scale == 1.0 && offset == 0.0 )
return;
745 for (
qgssize i = 0; i < size; ++i )
759 qgssize size =
static_cast< qgssize >( mWidth ) * static_cast< qgssize >( mHeight );
760 for (
qgssize i = 0; i < size; ++i )
762 double val =
value( i );
786 mImage =
new QImage( *image );
787 mWidth = mImage->
width();
788 mHeight = mImage->
height();
791 mNoDataValue = std::numeric_limits<double>::quiet_NaN();
821 for (
int i = 15; i <= 17; i++ )
823 s.
setNum( value,
'g', i );
830 QgsDebugMsg(
"Cannot correctly parse printed value" );
842 for (
int i = 6; i <= 9; i++ )
844 s.
setNum( value,
'g', i );
851 QgsDebugMsg(
"Cannot correctly parse printed value" );
857 int destDataTypeSize =
typeSize( destDataType );
858 void *destData =
qgsMalloc( destDataTypeSize * size );
859 for (
qgssize i = 0; i < size; i++ )
862 writeValue( destData, destDataType, i, value );
873 ba.
resize( static_cast< int >( size ) );
874 char * data = ba.
data();
882 switch ( theDataType )
885 uc =
static_cast< quint8
>( theValue );
886 memcpy( data, &uc, size );
889 us =
static_cast< quint16
>( theValue );
890 memcpy( data, &us, size );
893 s =
static_cast< qint16
>( theValue );
894 memcpy( data, &s, size );
897 ui =
static_cast< quint32
>( theValue );
898 memcpy( data, &ui, size );
901 i =
static_cast< qint32
>( theValue );
902 memcpy( data, &i, size );
905 f =
static_cast< float >( theValue );
906 memcpy( data, &f, size );
909 d =
static_cast< double >( theValue );
910 memcpy( data, &d, size );
918 bool QgsRasterBlock::createNoDataBitmap()
920 mNoDataBitmapWidth = mWidth / 8 + 1;
921 mNoDataBitmapSize =
static_cast< qgssize >( mNoDataBitmapWidth ) * mHeight;
923 mNoDataBitmap =
reinterpret_cast< char*
>(
qgsMalloc( mNoDataBitmapSize ) );
924 if ( !mNoDataBitmap )
926 QgsDebugMsg(
QString(
"Couldn't allocate no data memory of %1 bytes" ).arg( mNoDataBitmapSize ) );
929 memset( mNoDataBitmap, 0, mNoDataBitmapSize );
935 return QString(
"dataType = %1 width = %2 height = %3" )
936 .
arg( mDataType ).
arg( mWidth ).
arg( mHeight );
943 double xRes = theExtent.
width() / theWidth;
944 double yRes = theExtent.
height() / theHeight;
946 QgsDebugMsgLevel(
QString(
"theWidth = %1 theHeight = %2 xRes = %3 yRes = %4" ).arg( theWidth ).arg( theHeight ).arg( xRes ).arg( yRes ), 4 );
949 int bottom = theHeight - 1;
951 int right = theWidth - 1;
959 bottom = qRound(( theExtent.
yMaximum() - theSubExtent.
yMinimum() ) / yRes ) - 1;
968 right = qRound(( theSubExtent.
xMaximum() - theExtent.
xMinimum() ) / xRes ) - 1;
Eight bit unsigned integer (quint8)
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.
Unknown or unspecified type.
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.
bool qgsFloatNear(float a, float b, float epsilon=4 *FLT_EPSILON)
Compare two floats (but allow some difference)
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.
Thirty two bit floating point (float)
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)
Compare two doubles (but allow some difference)
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.
QString toString(bool automaticPrecision=false) const
returns string representation of form xmin,ymin xmax,ymax
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
Sixteen bit unsigned integer (quint16)
Sixty four bit floating point (double)
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
void fill(uint pixelValue)
bool setImage(const QImage *image)
set image.
#define QgsDebugMsgLevel(str, level)
Thirty two bit signed integer (qint32)
double width() const
Width of the rectangle.
static bool typeIsColor(QGis::DataType type)
Returns true if data type is color.
Thirty two bit unsigned integer (quint32)
QRgb color(int row, int column) const
Read a single color.
bool setIsNoDataExcept(QRect theExceptRect)
Set the whole block to no data except specified rectangle.
void setIsData(int row, int column)
Remove no data flag on pixel.
char * bits()
Get pointer to data.
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
static int typeSize(int dataType)
bool isEmpty() const
Returns true if block is empty, i.e.
Sixteen bit signed integer (qint16)
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.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
QImage image() const
Get image if type is color.
double xMaximum() const
Get the x maximum value (right side of rectangle)
static void writeValue(void *data, QGis::DataType type, qgssize index, double value)
QGis::DataType dataType() const
Returns data type.
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)
float toFloat(bool *ok) const
static QByteArray valueBytes(QGis::DataType theDataType, double theValue)
Get byte array representing a value.
DataType
Raster data types.
double value(int row, int column) const
Read a single value if type of block is numeric.
double xMinimum() const
Get the x minimum value (left side of rectangle)
double yMaximum() const
Get the y maximum value (top side of rectangle)
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.
bool hasNoData() const
Returns true if the block may contain no data.
double noDataValue() const
Return no data value.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
void qgsFree(void *ptr)
Frees the memory space pointed to by ptr.
double height() const
Height of the rectangle.