29const QRgb QgsRasterBlock::NO_DATA_COLOR = qRgba( 0, 0, 0, 0 );
 
   32  : mNoDataValue( std::numeric_limits<double>::quiet_NaN() )
 
 
   37  : mDataType( dataType )
 
   40  , mNoDataValue( std::numeric_limits<double>::quiet_NaN() )
 
   42  ( void )
reset( mDataType, mWidth, mHeight );
 
 
   47  QgsDebugMsgLevel( QStringLiteral( 
"mData = %1" ).arg( 
reinterpret_cast< quint64 
>( mData ) ), 4 );
 
 
   62  mNoDataBitmap = 
nullptr;
 
   67  mHasNoDataValue = 
false;
 
   68  mNoDataValue = std::numeric_limits<double>::quiet_NaN();
 
   86    const QImage::Format format = imageFormat( 
dataType );
 
  100  QgsDebugMsgLevel( QStringLiteral( 
"mWidth= %1 mHeight = %2 mDataType = %3 mData = %4 mImage = %5" ).arg( mWidth ).arg( mHeight ).arg( 
static_cast< int>( mDataType ) )
 
  101                    .arg( 
reinterpret_cast< quint64 
>( mData ) ).arg( 
reinterpret_cast< quint64 
>( mImage ) ), 4 );
 
 
  105QImage::Format QgsRasterBlock::imageFormat( 
Qgis::DataType dataType )
 
  109    return QImage::Format_ARGB32;
 
  113    return QImage::Format_ARGB32_Premultiplied;
 
  115  return QImage::Format_Invalid;
 
  120  if ( format == QImage::Format_ARGB32 )
 
  124  else if ( format == QImage::Format_ARGB32_Premultiplied )
 
  133  QgsDebugMsgLevel( QStringLiteral( 
"mWidth= %1 mHeight = %2 mDataType = %3 mData = %4 mImage = %5" ).arg( mWidth ).arg( mHeight ).arg( 
qgsEnumValueToKey( mDataType ) )
 
  134                    .arg( 
reinterpret_cast< quint64 
>( mData ) ).arg( 
reinterpret_cast< quint64 
>( mImage ) ), 4 );
 
  135  return mWidth == 0 || mHeight == 0 ||
 
 
  215      *
noDataValue = std::numeric_limits<double>::max() * -1.0;
 
  228  QgsDebugMsgLevel( QStringLiteral( 
"newDataType = %1 noDataValue = %2" ).arg( qgsEnumValueToKey< Qgis::DataType >( newDataType ) ).arg( *
noDataValue ), 4 );
 
 
  234  mHasNoDataValue = 
true;
 
 
  240  mHasNoDataValue = 
false;
 
  241  mNoDataValue = std::numeric_limits<double>::quiet_NaN();
 
 
  250    if ( mHasNoDataValue )
 
  254        QgsDebugError( QStringLiteral( 
"Data block not allocated" ) );
 
  259      QByteArray noDataByteArray = 
valueBytes( mDataType, mNoDataValue );
 
  260      if ( mNoDataValue == 0 )
 
  266        const char *nodata = noDataByteArray.data();
 
  267        for ( 
qgssize i = 0; i < static_cast< qgssize >( mWidth )*mHeight; i++ )
 
  276      if ( !mNoDataBitmap )
 
  278        if ( !createNoDataBitmap() )
 
  284      memset( mNoDataBitmap, 0xff, mNoDataBitmapSize );
 
  301    mImage->fill( NO_DATA_COLOR );
 
 
  308  int top = exceptRect.top();
 
  309  int bottom = exceptRect.bottom();
 
  310  int left = exceptRect.left();
 
  311  int right = exceptRect.right();
 
  312  top = std::min( std::max( top, 0 ), mHeight - 1 );
 
  313  left = std::min( std::max( left, 0 ), mWidth - 1 );
 
  314  bottom = std::max( 0, std::min( bottom, mHeight - 1 ) );
 
  315  right = std::max( 0, std::min( right, mWidth - 1 ) );
 
  321    if ( mHasNoDataValue )
 
  325        QgsDebugError( QStringLiteral( 
"Data block not allocated" ) );
 
  330      QByteArray noDataByteArray = 
valueBytes( mDataType, mNoDataValue );
 
  332      char *nodata = noDataByteArray.data();
 
  334      for ( 
int c = 0; 
c < mWidth; 
c++ )
 
  340      for ( 
int r = 0; r < mHeight; r++ )
 
  342        if ( r >= top && r <= bottom ) 
continue; 
 
  347      for ( 
int r = top; r <= bottom; r++ )
 
  354        const int w = mWidth - right - 1;
 
  362      if ( !mNoDataBitmap )
 
  364        if ( !createNoDataBitmap() )
 
  376      char *nodataRow = 
new char[mNoDataBitmapWidth]; 
 
  378      memset( nodataRow, 0, mNoDataBitmapWidth );
 
  379      for ( 
int c = 0; 
c < mWidth; 
c ++ )
 
  381        const int byte = 
c / 8;
 
  382        const int bit = 
c % 8;
 
  383        const char nodata = 0x80 >> bit;
 
  384        memset( nodataRow + 
byte, nodataRow[
byte] | nodata, 1 );
 
  388      for ( 
int r = 0; r < mHeight; r++ )
 
  390        if ( r >= top && r <= bottom ) 
continue; 
 
  391        const qgssize i = 
static_cast< qgssize >( r ) * mNoDataBitmapWidth;
 
  392        memcpy( mNoDataBitmap + i, nodataRow, mNoDataBitmapWidth );
 
  395      memset( nodataRow, 0, mNoDataBitmapWidth );
 
  396      for ( 
int c = 0; 
c < mWidth; 
c ++ )
 
  398        if ( 
c >= left && 
c <= right ) 
continue; 
 
  399        const int byte = 
c / 8;
 
  400        const int bit = 
c % 8;
 
  401        const char nodata = 0x80 >> bit;
 
  402        memset( nodataRow + 
byte, nodataRow[
byte] | nodata, 1 );
 
  404      for ( 
int r = top; r <= bottom; r++ )
 
  406        const qgssize i = 
static_cast< qgssize >( r ) * mNoDataBitmapWidth;
 
  407        memcpy( mNoDataBitmap + i, nodataRow, mNoDataBitmapWidth );
 
  422    if ( mImage->width() != mWidth ||  mImage->height() != mHeight )
 
  424      QgsDebugError( QStringLiteral( 
"Image and block size differ" ) );
 
  428    QgsDebugMsgLevel( QStringLiteral( 
"Fill image depth = %1" ).arg( mImage->depth() ), 4 );
 
  431    if ( mImage->depth() != 32 )
 
  433      QgsDebugError( QStringLiteral( 
"Unsupported image depth" ) );
 
  437    const QRgb nodataRgba = NO_DATA_COLOR;
 
  438    QRgb *nodataRow = 
new QRgb[mWidth]; 
 
  439    const int rgbSize = 
sizeof( QRgb );
 
  440    for ( 
int c = 0; 
c < mWidth; 
c ++ )
 
  442      nodataRow[
c] = nodataRgba;
 
  446    for ( 
int r = 0; r < mHeight; r++ )
 
  448      if ( r >= top && r <= bottom ) 
continue; 
 
  450      memcpy( 
reinterpret_cast< void * 
>( mImage->bits() + rgbSize * i ), nodataRow, rgbSize * 
static_cast< qgssize >( mWidth ) );
 
  453    for ( 
int r = top; r <= bottom; r++ )
 
  459        memcpy( 
reinterpret_cast< void * 
>( mImage->bits() + rgbSize * i ), nodataRow, rgbSize * 
static_cast< qgssize >( left - 1 ) );
 
  463      const int w = mWidth - right - 1;
 
  464      memcpy( 
reinterpret_cast< void * 
>( mImage->bits() + rgbSize * i ), nodataRow, rgbSize * 
static_cast< qgssize >( w ) );
 
 
  474    return QByteArray::fromRawData( 
static_cast<const char *
>( mData ), 
typeSize( mDataType ) * mWidth * mHeight );
 
  475  else if ( mImage && mImage->constBits() )
 
  476    return QByteArray::fromRawData( 
reinterpret_cast<const char *
>( mImage->constBits() ), mImage->sizeInBytes() );
 
 
  488    const int len = std::min( 
static_cast<int>( 
data.size() ), 
typeSize( mDataType ) * mWidth * mHeight - offset );
 
  489    ::memcpy( 
static_cast<char *
>( mData ) + offset, 
data.constData(), len );
 
  491  else if ( mImage && mImage->constBits() )
 
  493    const qsizetype len = std::min( 
static_cast< qsizetype 
>( 
data.size() ), mImage->sizeInBytes() - offset );
 
  494    ::memcpy( mImage->bits() + offset, 
data.constData(), len );
 
 
  501  if ( index >= 
static_cast< qgssize >( mWidth )*mHeight )
 
  503    QgsDebugMsgLevel( QStringLiteral( 
"Index %1 out of range (%2 x %3)" ).arg( index ).arg( mWidth ).arg( mHeight ), 4 );
 
  508    return reinterpret_cast< char * 
>( mData ) + index * mTypeSize;
 
  512    if ( uchar *
data = mImage->bits() )
 
  514      return reinterpret_cast< char * 
>( 
data + index * 4 );
 
 
  524  if ( index >= 
static_cast< qgssize >( mWidth )*mHeight )
 
  526    QgsDebugMsgLevel( QStringLiteral( 
"Index %1 out of range (%2 x %3)" ).arg( index ).arg( mWidth ).arg( mHeight ), 4 );
 
  531    return reinterpret_cast< const char * 
>( mData ) + index * mTypeSize;
 
  535    if ( 
const uchar *
data = mImage->constBits() )
 
  537      return reinterpret_cast< const char * 
>( 
data + index * 4 );
 
 
  546  return bits( 
static_cast< qgssize >( row ) * mWidth + column );
 
 
  553    return reinterpret_cast< char * 
>( mData );
 
  557    if ( uchar *
data = mImage->bits() )
 
  559      return reinterpret_cast< char * 
>( 
data );
 
 
  570    return reinterpret_cast< const char * 
>( mData );
 
  574    if ( 
const uchar *
data = mImage->constBits() )
 
  576      return reinterpret_cast< const char * 
>( 
data );
 
 
  586  if ( destDataType == mDataType ) 
return true;
 
  590    void *
data = 
convert( mData, mDataType, destDataType, 
static_cast< qgssize >( mWidth ) * 
static_cast< qgssize >( mHeight ) );
 
  594      QgsDebugError( QStringLiteral( 
"Cannot convert raster block" ) );
 
  599    mDataType = destDataType;
 
  604    const QImage::Format format = imageFormat( destDataType );
 
  605    const QImage 
image = mImage->convertToFormat( format );
 
  607    mDataType = destDataType;
 
 
  622  if ( scale == 1.0 && offset == 0.0 ) 
return;
 
  625  for ( 
qgssize i = 0; i < size; ++i )
 
 
  633  if ( rangeList.isEmpty() )
 
  639  for ( 
qgssize i = 0; i < size; ++i )
 
  641    const double val = 
value( i );
 
 
  654    return QImage( *mImage );
 
 
  665  mImage = 
new QImage( *
image );
 
  666  mWidth = mImage->width();
 
  667  mHeight = mImage->height();
 
  668  mDataType = 
dataType( mImage->format() );
 
  670  mNoDataValue = std::numeric_limits<double>::quiet_NaN();
 
 
  700  for ( 
int i = 15; i <= 17; i++ )
 
  702    s.setNum( 
value, 
'g', i );
 
  703    const double doubleValue { s.toDouble( ) };
 
  708        return QLocale().toString( doubleValue, 
'g', i );
 
  714  QgsDebugError( QStringLiteral( 
"Cannot correctly parse printed value" ) );
 
 
  726  for ( 
int i = 6; i <= 9; i++ )
 
  728    s.setNum( 
value, 
'g', i );
 
  729    const float floatValue { s.toFloat() };
 
  734        return QLocale().toString( floatValue, 
'g', i );
 
  740  QgsDebugError( QStringLiteral( 
"Cannot correctly parse printed value" ) );
 
 
  746  const int destDataTypeSize = 
typeSize( destDataType );
 
  747  void *destData = 
qgsMalloc( destDataTypeSize * size );
 
  748  for ( 
qgssize i = 0; i < size; i++ )
 
  762  ba.resize( 
static_cast< int >( size ) );
 
  763  char *
data = ba.data();
 
  774      uc = 
static_cast< quint8 
>( 
value );
 
  775      memcpy( 
data, &uc, size );
 
  779      const qint8 myint8 = 
static_cast< qint8 
>( 
value );
 
  780      memcpy( 
data, &myint8, size );
 
  784      us = 
static_cast< quint16 
>( 
value );
 
  785      memcpy( 
data, &us, size );
 
  788      s = 
static_cast< qint16 
>( 
value );
 
  789      memcpy( 
data, &s, size );
 
  792      ui = 
static_cast< quint32 
>( 
value );
 
  793      memcpy( 
data, &ui, size );
 
  796      i = 
static_cast< qint32 
>( 
value );
 
  797      memcpy( 
data, &i, size );
 
  800      f = 
static_cast< float >( 
value );
 
  801      memcpy( 
data, &f, size );
 
  804      d = 
static_cast< double >( 
value );
 
  805      memcpy( 
data, &d, size );
 
  814      QgsDebugError( QStringLiteral( 
"Data type is not supported" ) );
 
 
  819bool QgsRasterBlock::createNoDataBitmap()
 
  821  mNoDataBitmapWidth = mWidth / 8 + 1;
 
  822  mNoDataBitmapSize = 
static_cast< qgssize >( mNoDataBitmapWidth ) * mHeight;
 
  823  QgsDebugMsgLevel( QStringLiteral( 
"allocate %1 bytes" ).arg( mNoDataBitmapSize ), 4 );
 
  824  mNoDataBitmap = 
reinterpret_cast< char * 
>( 
qgsMalloc( mNoDataBitmapSize ) );
 
  825  if ( !mNoDataBitmap )
 
  827    QgsDebugError( QStringLiteral( 
"Couldn't allocate no data memory of %1 bytes" ).arg( mNoDataBitmapSize ) );
 
  830  memset( mNoDataBitmap, 0, mNoDataBitmapSize );
 
  836  return QStringLiteral( 
"dataType = %1 width = %2 height = %3" )
 
  837         .arg( qgsEnumValueToKey< Qgis::DataType >( mDataType ) ).arg( mWidth ).arg( mHeight );
 
 
  847  QgsDebugMsgLevel( QStringLiteral( 
"theWidth = %1 height = %2 xRes = %3 yRes = %4" ).arg( 
width ).arg( 
height ).arg( xRes ).arg( yRes ), 4 );
 
  852  int right = 
width - 1;
 
  860    bottom = std::round( ( extent.
yMaximum() - subExtent.
yMinimum() ) / yRes ) - 1;
 
  869    right = std::round( ( subExtent.
xMaximum() - extent.
xMinimum() ) / xRes ) - 1;
 
  871  QRect 
subRect = QRect( left, top, right - left + 1, bottom - top + 1 );
 
 
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)
 
bool isEmpty() const
Returns true if block is empty, i.e.
 
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 data type is numeric.
 
int height() const
Returns the height (number of rows) of the raster block.
 
bool convert(Qgis::DataType destDataType)
Convert data to different type.
 
bool setIsNoData()
Set the whole block to no data.
 
void resetNoDataValue()
Reset no data value: if there was a no data value previously set, it will be discarded.
 
int dataTypeSize() const
Data type size in bytes.
 
static int typeSize(Qgis::DataType dataType)
Returns the size in bytes for the specified dataType.
 
bool setIsNoDataExcept(QRect exceptRect)
Set the whole block to no data except specified rectangle.
 
bool setImage(const QImage *image)
Sets the block data via an image.
 
QByteArray data() const
Gets access to raw data.
 
double noDataValue() const
Returns no data value.
 
const char * constBits() const
Returns a const pointer to block data.
 
void setData(const QByteArray &data, int offset=0)
Rewrite raw pixel data.
 
void applyNoDataValues(const QgsRasterRangeList &rangeList)
 
bool setValue(int row, int column, double value)
Set value on position.
 
bool isNoData(int row, int column) const
Checks if value at position is no data.
 
Qgis::DataType dataType() const
Returns data type.
 
char * bits()
Returns a pointer to block data.
 
static Qgis::DataType typeWithNoDataValue(Qgis::DataType dataType, double *noDataValue)
For given data type returns wider type and sets no data value.
 
QImage image() const
Returns an image containing the block data, if the block's data type is color.
 
void setNoDataValue(double noDataValue)
Sets cell value that will be considered as "no data".
 
virtual ~QgsRasterBlock()
 
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.
 
void applyScaleOffset(double scale, double offset)
Apply band scale and offset to raster block values.
 
static QString printValue(double value, bool localized=false)
Print double value with all necessary significant digits.
 
static QRect subRect(const QgsRectangle &extent, int width, int height, const QgsRectangle &subExtent)
For extent and width, height find rectangle covered by subextent.
 
static bool typeIsColor(Qgis::DataType type)
Returns true if data type is color.
 
static double readValue(void *data, Qgis::DataType type, qgssize index)
 
static QByteArray valueBytes(Qgis::DataType dataType, double value)
Gets byte array representing a value.
 
bool reset(Qgis::DataType dataType, int width, int height)
Reset block.
 
bool contains(double value) const
Returns true if this range contains the specified value.
 
A rectangle specified with double values.
 
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
 
double xMinimum() const
Returns the x minimum value (left side of rectangle).
 
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
 
double width() const
Returns the width of the rectangle.
 
double xMaximum() const
Returns the x maximum value (right side of rectangle).
 
double yMaximum() const
Returns the y maximum value (top side of rectangle).
 
double height() const
Returns the height of the rectangle.
 
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
 
void * qgsMalloc(size_t size)
Allocates size bytes and returns a pointer to the allocated memory.
 
void qgsFree(void *ptr)
Frees the memory space pointed to by ptr.
 
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 qgsFloatNear(float a, float b, float epsilon=4 *FLT_EPSILON)
Compare two floats (but allow some difference)
 
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
 
#define QgsDebugMsgLevel(str, level)
 
#define QgsDebugError(str)
 
QList< QgsRasterRange > QgsRasterRangeList