18#ifndef QGSRASTERBLOCK_H
19#define QGSRASTERBLOCK_H
33using namespace Qt::StringLiterals;
186 return mHasNoDataValue || mNoDataBitmap;
195 void setNoDataValue(
double noDataValue )
SIP_HOLDGIL;
222 static QByteArray valueBytes(
Qgis::DataType dataType,
double value );
234 return value(
static_cast< qgssize >( row ) * mWidth + column );
275 inline double valueAndNoData(
qgssize index,
bool &isNoData )
const SIP_SKIP;
288 return static_cast< const quint8 *
>( mData );
299 if ( !mImage )
return NO_DATA_COLOR;
301 return mImage->pixel( column, row );
311 const int row =
static_cast< int >( std::floor(
static_cast< double >( index ) / mWidth ) );
312 const int column = index % mWidth;
313 return color( row, column );
348 if ( !mHasNoDataValue && !mNoDataBitmap )
350 if ( index >=
static_cast< qgssize >( mWidth )*mHeight )
352 QgsDebugError( u
"Index %1 out of range (%2 x %3)"_s.arg( index ).arg( mWidth ).arg( mHeight ) );
355 if ( mHasNoDataValue )
358 return isNoDataValue(
value );
361 if ( !mNoDataBitmap )
367 const int row =
static_cast< int >( index ) / mWidth;
368 const int column = index % mWidth;
369 const qgssize byte =
static_cast< qgssize >( row ) * mNoDataBitmapWidth + column / 8;
370 const int bit = column % 8;
371 const int mask = 0x80 >> bit;
374 return mNoDataBitmap[byte] & mask;
402 if ( index >=
static_cast< qgssize >( mWidth ) *mHeight )
404 QgsDebugError( u
"Index %1 out of range (%2 x %3)"_s.arg( index ).arg( mWidth ).arg( mHeight ) );
437 if ( index >=
static_cast< qgssize >( mImage->width() ) * mImage->height() )
444 QRgb *
bits =
reinterpret_cast< QRgb *
>( mImage->bits() );
460 return reinterpret_cast< QRgb *
>( mImage->bits() );
481 if ( mHasNoDataValue )
483 return setValue( index, mNoDataValue );
487 if ( !mNoDataBitmap )
489 if ( !createNoDataBitmap() )
495 const int row =
static_cast< int >( index ) / mWidth;
496 const int column = index % mWidth;
497 const qgssize byte =
static_cast< qgssize >( row ) * mNoDataBitmapWidth + column / 8;
498 const int bit = column % 8;
499 const int nodata = 0x80 >> bit;
501 mNoDataBitmap[byte] = mNoDataBitmap[byte] | nodata;
516 bool setIsNoDataExcept( QRect exceptRect );
540 if ( mHasNoDataValue )
546 if ( !mNoDataBitmap )
552 const int row =
static_cast< int >( index ) / mWidth;
553 const int column = index % mWidth;
554 const qgssize byte =
static_cast< qgssize >( row ) * mNoDataBitmapWidth + column / 8;
555 const int bit = column % 8;
556 const int nodata = 0x80 >> bit;
557 mNoDataBitmap[byte] = mNoDataBitmap[byte] & ~nodata;
569 bool fill(
double value );
581 void fill(
double value );
585 PyErr_SetString( PyExc_ValueError, u
"Cannot fill a block with %1 data type"_s.arg(
qgsEnumValueToKey( sipCpp->dataType() ) ).toUtf8().constData() );
590 PyErr_SetString( PyExc_ValueError, u
"Cannot fill a block with %1 complex data type"_s.arg(
qgsEnumValueToKey( sipCpp->dataType() ) ).toUtf8().constData() );
593 else if ( sipCpp->isEmpty() )
595 PyErr_SetString( PyExc_ValueError, u
"Cannot fill an empty block"_s.toUtf8().constData() );
614 QByteArray data()
const;
624 void setData(
const QByteArray &data,
int offset = 0 );
632 char *bits(
int row,
int column )
SIP_SKIP;
669 const
char *constBits() const
SIP_SKIP;
678 static QString printValue(
double value,
bool localized = false );
688 static QString printValue(
float value,
bool localized = false )
SIP_SKIP;
695 bool convert( Qgis::DataType destDataType );
700 QImage image() const;
706 bool setImage( const QImage *image );
709 inline static
double readValue(
void *data, Qgis::DataType type,
qgssize index )
SIP_SKIP;
712 inline static
void writeValue(
void *data, Qgis::DataType type,
qgssize index,
double value )
SIP_SKIP;
719 void applyScaleOffset(
double scale,
double offset );
727 QString toString()
const;
830 static bool isNoDataValue(
double value,
double noDataValue )
835 return std::isnan( value ) ||
844 inline bool isNoDataValue(
double value )
const;
850 bool createNoDataBitmap();
879 bool mHasNoDataValue =
false;
884 static const QRgb NO_DATA_COLOR;
888 void *mData =
nullptr;
891 std::unique_ptr<QImage> mImage;
896 char *mNoDataBitmap =
nullptr;
899 int mNoDataBitmapWidth = 0;
912 return std::numeric_limits<double>::quiet_NaN();
918 return static_cast< double >( (
static_cast< quint8 *
>(
data ) )[index] );
920 return static_cast< double >( (
static_cast< qint8 *
>(
data ) )[index] );
922 return static_cast< double >( (
static_cast< quint16 *
>(
data ) )[index] );
924 return static_cast< double >( (
static_cast< qint16 *
>(
data ) )[index] );
926 return static_cast< double >( (
static_cast< quint32 *
>(
data ) )[index] );
928 return static_cast< double >( (
static_cast< qint32 *
>(
data ) )[index] );
930 return static_cast< double >( (
static_cast< float *
>(
data ) )[index] );
932 return static_cast< double >( (
static_cast< double *
>(
data ) )[index] );
944 return std::numeric_limits<double>::quiet_NaN();
954 (
static_cast< quint8 *
>(
data ) )[index] =
static_cast< quint8
>(
value );
957 (
static_cast< qint8 *
>(
data ) )[index] =
static_cast< qint8
>(
value );
960 (
static_cast< quint16 *
>(
data ) )[index] =
static_cast< quint16
>(
value );
963 (
static_cast< qint16 *
>(
data ) )[index] =
static_cast< qint16
>(
value );
966 (
static_cast< quint32 *
>(
data ) )[index] =
static_cast< quint32
>(
value );
969 (
static_cast< qint32 *
>(
data ) )[index] =
static_cast< qint32
>(
value );
972 (
static_cast< float *
>(
data ) )[index] =
static_cast< float >(
value );
975 (
static_cast< double *
>(
data ) )[index] =
value;
994 return std::numeric_limits<double>::quiet_NaN();
996 return readValue( mData, mDataType, index );
1005 return std::numeric_limits<double>::quiet_NaN();
1007 if ( index >=
static_cast< qgssize >( mWidth )*mHeight )
1009 QgsDebugError( u
"Index %1 out of range (%2 x %3)"_s.arg( index ).arg( mWidth ).arg( mHeight ) );
1011 return std::numeric_limits<double>::quiet_NaN();
1014 const double val =
readValue( mData, mDataType, index );
1016 if ( !mHasNoDataValue && !mNoDataBitmap )
1022 if ( mHasNoDataValue )
1028 if ( !mNoDataBitmap )
1040inline bool QgsRasterBlock::isNoDataValue(
double value )
const SIP_SKIP
1042 return std::isnan( value ) ||
qgsDoubleNear( value, mNoDataValue );
DataType
Raster data types.
@ Float32
Thirty two bit floating point (float).
@ CFloat64
Complex Float64.
@ Int16
Sixteen bit signed integer (qint16).
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
@ Int8
Eight bit signed integer (qint8) (added in QGIS 3.30).
@ UInt16
Sixteen bit unsigned integer (quint16).
@ Byte
Eight bit unsigned integer (quint8).
@ UnknownDataType
Unknown or unspecified type.
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
@ Int32
Thirty two bit signed integer (qint32).
@ Float64
Sixty four bit floating point (double).
@ CFloat32
Complex Float32.
@ UInt32
Thirty two bit unsigned integer (quint32).
A container for error messages.
bool isValid() const
Returns true if the block is valid (correctly filled with data).
QRgb color(int row, int column) const
Read a single color.
QgsRasterBlock(const QgsRasterBlock &rh)=delete
double value(int row, int column) const
Read a single value if type of block is numeric.
static bool typeIsNumeric(Qgis::DataType type)
Returns true if a data type is numeric.
void setValid(bool valid)
Mark block as valid or invalid.
int height() const
Returns the height (number of rows) of the raster block.
bool isNoData(qgssize row, qgssize column) const
Check if value at position is no data.
bool isNoData(qgssize index) const
Check if value at position is no data.
bool setColor(qgssize index, QRgb color)
Set color on index (indexed line by line).
int dataTypeSize() const
Data type size in bytes.
bool hasNoData() const
Returns true if the block may contain no data.
char * bits(int row, int column)
Returns a pointer to block data.
double valueAndNoData(int row, int column, bool &isNoData) const
Reads a single value from the pixel at row and column, if type of block is numeric.
QgsRasterBlock & operator=(const QgsRasterBlock &rh)=delete
static int typeSize(Qgis::DataType dataType)
Returns the size in bytes for the specified dataType.
QByteArray data() const
Gets access to raw data.
bool setIsNoData(qgssize index)
Set no data on pixel.
bool setValue(qgssize index, double value)
Set value on index (indexed line by line).
double noDataValue() const
Returns no data value.
QRgb * colorData()
Gives direct read/write access to the raster RGB data.
void setIsData(qgssize index)
Remove no data flag on pixel.
bool setValue(int row, int column, double value)
Set value on position.
bool setColor(int row, int column, QRgb color)
Set color on position.
bool isNoData(int row, int column) const
Checks if value at position is no data.
void setIsData(int row, int column)
Remove no data flag on pixel.
Qgis::DataType dataType() const
Returns data type.
bool hasNoDataValue() const
true if the block has no data value.
static bool typeIsComplex(Qgis::DataType type)
Returns true if a data type is a complex number type.
const quint8 * byteData() const
Gives direct access to the raster block data.
static void writeValue(void *data, Qgis::DataType type, qgssize index, double value)
int width() const
Returns the width (number of columns) of the raster block.
QgsError error() const
Returns the last error.
void setError(const QgsError &error)
Sets the last error.
static double readValue(void *data, Qgis::DataType type, qgssize index)
bool setIsNoData(int row, int column)
Set no data on pixel.
QRgb color(qgssize index) const
Read a single value.
bool reset(Qgis::DataType dataType, int width, int height)
Reset block.
A rectangle specified with double values.
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
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 qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
#define QgsDebugError(str)
QList< QgsRasterRange > QgsRasterRangeList