28const QRgb QgsRasterBlock::NO_DATA_COLOR = qRgba( 0, 0, 0, 0 );
 
   31  : mNoDataValue( std::numeric_limits<double>::quiet_NaN() )
 
   36  : mDataType( dataType )
 
   39  , mNoDataValue( std::numeric_limits<double>::quiet_NaN() )
 
   41  ( void )
reset( mDataType, mWidth, mHeight );
 
   46  QgsDebugMsgLevel( QStringLiteral( 
"mData = %1" ).arg( 
reinterpret_cast< quint64 
>( mData ) ), 4 );
 
   61  mNoDataBitmap = 
nullptr;
 
   66  mHasNoDataValue = 
false;
 
   67  mNoDataValue = std::numeric_limits<double>::quiet_NaN();
 
   85    const QImage::Format format = imageFormat( 
dataType );
 
   99  QgsDebugMsgLevel( QStringLiteral( 
"mWidth= %1 mHeight = %2 mDataType = %3 mData = %4 mImage = %5" ).arg( mWidth ).arg( mHeight ).arg( 
static_cast< int>( mDataType ) )
 
  100                    .arg( 
reinterpret_cast< quint64 
>( mData ) ).arg( 
reinterpret_cast< quint64 
>( mImage ) ), 4 );
 
  104QImage::Format QgsRasterBlock::imageFormat( 
Qgis::DataType dataType )
 
  108    return QImage::Format_ARGB32;
 
  112    return QImage::Format_ARGB32_Premultiplied;
 
  114  return QImage::Format_Invalid;
 
  119  if ( format == QImage::Format_ARGB32 )
 
  123  else if ( format == QImage::Format_ARGB32_Premultiplied )
 
  132  QgsDebugMsgLevel( QStringLiteral( 
"mWidth= %1 mHeight = %2 mDataType = %3 mData = %4 mImage = %5" ).arg( mWidth ).arg( mHeight ).arg( 
qgsEnumValueToKey( mDataType ) )
 
  133                    .arg( 
reinterpret_cast< quint64 
>( mData ) ).arg( 
reinterpret_cast< quint64 
>( mImage ) ), 4 );
 
  134  return mWidth == 0 || mHeight == 0 ||
 
  214      *
noDataValue = std::numeric_limits<double>::max() * -1.0;
 
  227  QgsDebugMsgLevel( QStringLiteral( 
"newDataType = %1 noDataValue = %2" ).arg( qgsEnumValueToKey< Qgis::DataType >( newDataType ) ).arg( *
noDataValue ), 4 );
 
  233  mHasNoDataValue = 
true;
 
  239  mHasNoDataValue = 
false;
 
  240  mNoDataValue = std::numeric_limits<double>::quiet_NaN();
 
  249    if ( mHasNoDataValue )
 
  253        QgsDebugError( QStringLiteral( 
"Data block not allocated" ) );
 
  258      QByteArray noDataByteArray = 
valueBytes( mDataType, mNoDataValue );
 
  259      if ( mNoDataValue == 0 )
 
  265        const char *nodata = noDataByteArray.data();
 
  266        for ( 
qgssize i = 0; i < static_cast< qgssize >( mWidth )*mHeight; i++ )
 
  275      if ( !mNoDataBitmap )
 
  277        if ( !createNoDataBitmap() )
 
  283      memset( mNoDataBitmap, 0xff, mNoDataBitmapSize );
 
  300    mImage->fill( NO_DATA_COLOR );
 
  307  int top = exceptRect.top();
 
  308  int bottom = exceptRect.bottom();
 
  309  int left = exceptRect.left();
 
  310  int right = exceptRect.right();
 
  311  top = std::min( std::max( top, 0 ), mHeight - 1 );
 
  312  left = std::min( std::max( left, 0 ), mWidth - 1 );
 
  313  bottom = std::max( 0, std::min( bottom, mHeight - 1 ) );
 
  314  right = std::max( 0, std::min( right, mWidth - 1 ) );
 
  320    if ( mHasNoDataValue )
 
  324        QgsDebugError( QStringLiteral( 
"Data block not allocated" ) );
 
  329      QByteArray noDataByteArray = 
valueBytes( mDataType, mNoDataValue );
 
  331      char *nodata = noDataByteArray.data();
 
  333      for ( 
int c = 0; 
c < mWidth; 
c++ )
 
  339      for ( 
int r = 0; r < mHeight; r++ )
 
  341        if ( r >= top && r <= bottom ) 
continue; 
 
  346      for ( 
int r = top; r <= bottom; r++ )
 
  353        const int w = mWidth - right - 1;
 
  361      if ( !mNoDataBitmap )
 
  363        if ( !createNoDataBitmap() )
 
  375      char *nodataRow = 
new char[mNoDataBitmapWidth]; 
 
  377      memset( nodataRow, 0, mNoDataBitmapWidth );
 
  378      for ( 
int c = 0; 
c < mWidth; 
c ++ )
 
  380        const int byte = 
c / 8;
 
  381        const int bit = 
c % 8;
 
  382        const char nodata = 0x80 >> bit;
 
  383        memset( nodataRow + 
byte, nodataRow[
byte] | nodata, 1 );
 
  387      for ( 
int r = 0; r < mHeight; r++ )
 
  389        if ( r >= top && r <= bottom ) 
continue; 
 
  390        const qgssize i = 
static_cast< qgssize >( r ) * mNoDataBitmapWidth;
 
  391        memcpy( mNoDataBitmap + i, nodataRow, mNoDataBitmapWidth );
 
  394      memset( nodataRow, 0, mNoDataBitmapWidth );
 
  395      for ( 
int c = 0; 
c < mWidth; 
c ++ )
 
  397        if ( 
c >= left && 
c <= right ) 
continue; 
 
  398        const int byte = 
c / 8;
 
  399        const int bit = 
c % 8;
 
  400        const char nodata = 0x80 >> bit;
 
  401        memset( nodataRow + 
byte, nodataRow[
byte] | nodata, 1 );
 
  403      for ( 
int r = top; r <= bottom; r++ )
 
  405        const qgssize i = 
static_cast< qgssize >( r ) * mNoDataBitmapWidth;
 
  406        memcpy( mNoDataBitmap + i, nodataRow, mNoDataBitmapWidth );
 
  421    if ( mImage->width() != mWidth ||  mImage->height() != mHeight )
 
  423      QgsDebugError( QStringLiteral( 
"Image and block size differ" ) );
 
  427    QgsDebugMsgLevel( QStringLiteral( 
"Fill image depth = %1" ).arg( mImage->depth() ), 4 );
 
  430    if ( mImage->depth() != 32 )
 
  432      QgsDebugError( QStringLiteral( 
"Unsupported image depth" ) );
 
  436    const QRgb nodataRgba = NO_DATA_COLOR;
 
  437    QRgb *nodataRow = 
new QRgb[mWidth]; 
 
  438    const int rgbSize = 
sizeof( QRgb );
 
  439    for ( 
int c = 0; 
c < mWidth; 
c ++ )
 
  441      nodataRow[
c] = nodataRgba;
 
  445    for ( 
int r = 0; r < mHeight; r++ )
 
  447      if ( r >= top && r <= bottom ) 
continue; 
 
  449      memcpy( 
reinterpret_cast< void * 
>( mImage->bits() + rgbSize * i ), nodataRow, rgbSize * 
static_cast< qgssize >( mWidth ) );
 
  452    for ( 
int r = top; r <= bottom; r++ )
 
  458        memcpy( 
reinterpret_cast< void * 
>( mImage->bits() + rgbSize * i ), nodataRow, rgbSize * 
static_cast< qgssize >( left - 1 ) );
 
  462      const int w = mWidth - right - 1;
 
  463      memcpy( 
reinterpret_cast< void * 
>( mImage->bits() + rgbSize * i ), nodataRow, rgbSize * 
static_cast< qgssize >( w ) );
 
  473    return QByteArray::fromRawData( 
static_cast<const char *
>( mData ), 
typeSize( mDataType ) * mWidth * mHeight );
 
  474  else if ( mImage && mImage->constBits() )
 
  475    return QByteArray::fromRawData( 
reinterpret_cast<const char *
>( mImage->constBits() ), mImage->sizeInBytes() );
 
  487    const int len = std::min( 
static_cast<int>( 
data.size() ), 
typeSize( mDataType ) * mWidth * mHeight - offset );
 
  488    ::memcpy( 
static_cast<char *
>( mData ) + offset, 
data.constData(), len );
 
  490  else if ( mImage && mImage->constBits() )
 
  492    const qsizetype len = std::min( 
static_cast< qsizetype 
>( 
data.size() ), mImage->sizeInBytes() - offset );
 
  493    ::memcpy( mImage->bits() + offset, 
data.constData(), len );
 
  500  if ( index >= 
static_cast< qgssize >( mWidth )*mHeight )
 
  502    QgsDebugMsgLevel( QStringLiteral( 
"Index %1 out of range (%2 x %3)" ).arg( index ).arg( mWidth ).arg( mHeight ), 4 );
 
  507    return reinterpret_cast< char * 
>( mData ) + index * mTypeSize;
 
  509  if ( mImage && mImage->bits() )
 
  511    return reinterpret_cast< char * 
>( mImage->bits() + index * 4 );
 
  519  return bits( 
static_cast< qgssize >( row ) * mWidth + column );
 
  526    return reinterpret_cast< char * 
>( mData );
 
  528  if ( mImage && mImage->bits() )
 
  530    return reinterpret_cast< char * 
>( mImage->bits() );
 
  539  if ( destDataType == mDataType ) 
return true;
 
  543    void *
data = 
convert( mData, mDataType, destDataType, 
static_cast< qgssize >( mWidth ) * 
static_cast< qgssize >( mHeight ) );
 
  547      QgsDebugError( QStringLiteral( 
"Cannot convert raster block" ) );
 
  552    mDataType = destDataType;
 
  557    const QImage::Format format = imageFormat( destDataType );
 
  558    const QImage 
image = mImage->convertToFormat( format );
 
  560    mDataType = destDataType;
 
  575  if ( scale == 1.0 && offset == 0.0 ) 
return;
 
  578  for ( 
qgssize i = 0; i < size; ++i )
 
  586  if ( rangeList.isEmpty() )
 
  592  for ( 
qgssize i = 0; i < size; ++i )
 
  594    const double val = 
value( i );
 
  607    return QImage( *mImage );
 
  618  mImage = 
new QImage( *
image );
 
  619  mWidth = mImage->width();
 
  620  mHeight = mImage->height();
 
  621  mDataType = 
dataType( mImage->format() );
 
  623  mNoDataValue = std::numeric_limits<double>::quiet_NaN();
 
  653  for ( 
int i = 15; i <= 17; i++ )
 
  655    s.setNum( 
value, 
'g', i );
 
  662  QgsDebugError( QStringLiteral( 
"Cannot correctly parse printed value" ) );
 
  674  for ( 
int i = 6; i <= 9; i++ )
 
  676    s.setNum( 
value, 
'g', i );
 
  683  QgsDebugError( QStringLiteral( 
"Cannot correctly parse printed value" ) );
 
  689  const int destDataTypeSize = 
typeSize( destDataType );
 
  690  void *destData = 
qgsMalloc( destDataTypeSize * size );
 
  691  for ( 
qgssize i = 0; i < size; i++ )
 
  705  ba.resize( 
static_cast< int >( size ) );
 
  706  char *
data = ba.data();
 
  717      uc = 
static_cast< quint8 
>( 
value );
 
  718      memcpy( 
data, &uc, size );
 
  722      const qint8 myint8 = 
static_cast< qint8 
>( 
value );
 
  723      memcpy( 
data, &myint8, size );
 
  727      us = 
static_cast< quint16 
>( 
value );
 
  728      memcpy( 
data, &us, size );
 
  731      s = 
static_cast< qint16 
>( 
value );
 
  732      memcpy( 
data, &s, size );
 
  735      ui = 
static_cast< quint32 
>( 
value );
 
  736      memcpy( 
data, &ui, size );
 
  739      i = 
static_cast< qint32 
>( 
value );
 
  740      memcpy( 
data, &i, size );
 
  743      f = 
static_cast< float >( 
value );
 
  744      memcpy( 
data, &f, size );
 
  747      d = 
static_cast< double >( 
value );
 
  748      memcpy( 
data, &d, size );
 
  757      QgsDebugError( QStringLiteral( 
"Data type is not supported" ) );
 
  762bool QgsRasterBlock::createNoDataBitmap()
 
  764  mNoDataBitmapWidth = mWidth / 8 + 1;
 
  765  mNoDataBitmapSize = 
static_cast< qgssize >( mNoDataBitmapWidth ) * mHeight;
 
  766  QgsDebugMsgLevel( QStringLiteral( 
"allocate %1 bytes" ).arg( mNoDataBitmapSize ), 4 );
 
  767  mNoDataBitmap = 
reinterpret_cast< char * 
>( 
qgsMalloc( mNoDataBitmapSize ) );
 
  768  if ( !mNoDataBitmap )
 
  770    QgsDebugError( QStringLiteral( 
"Couldn't allocate no data memory of %1 bytes" ).arg( mNoDataBitmapSize ) );
 
  773  memset( mNoDataBitmap, 0, mNoDataBitmapSize );
 
  779  return QStringLiteral( 
"dataType = %1 width = %2 height = %3" )
 
  780         .arg( qgsEnumValueToKey< Qgis::DataType >( mDataType ) ).arg( mWidth ).arg( mHeight );
 
  790  QgsDebugMsgLevel( QStringLiteral( 
"theWidth = %1 height = %2 xRes = %3 yRes = %4" ).arg( 
width ).arg( 
height ).arg( xRes ).arg( yRes ), 4 );
 
  795  int right = 
width - 1;
 
  803    bottom = std::round( ( extent.
yMaximum() - subExtent.
yMinimum() ) / yRes ) - 1;
 
  812    right = std::round( ( subExtent.
xMaximum() - extent.
xMinimum() ) / xRes ) - 1;
 
  814  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.
 
static bool typeIsNumeric(Qgis::DataType type)
Returns true if data type is numeric.
 
void setNoDataValue(double noDataValue) SIP_HOLDGIL
Sets cell value that will be considered as "no data".
 
bool convert(Qgis::DataType destDataType)
Convert data to different type.
 
bool setIsNoData()
Set the whole block to no data.
 
void resetNoDataValue() SIP_HOLDGIL
Reset no data value: if there was a no data value previously set, it will be discarded.
 
int width() const SIP_HOLDGIL
Returns the width (number of columns) of the raster block.
 
static int typeSize(Qgis::DataType dataType) SIP_HOLDGIL
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.
 
Qgis::DataType dataType() const SIP_HOLDGIL
Returns data type.
 
static QString printValue(double value)
Print double value with all necessary significant digits.
 
void setData(const QByteArray &data, int offset=0)
Rewrite raw pixel data.
 
void applyNoDataValues(const QgsRasterRangeList &rangeList)
 
double noDataValue() const SIP_HOLDGIL
Returns no data value.
 
char * bits()
Returns a pointer to block data.
 
double value(int row, int column) const SIP_HOLDGIL
Read a single value if type of block is numeric.
 
int dataTypeSize() const SIP_HOLDGIL
Data type size in bytes.
 
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.
 
virtual ~QgsRasterBlock()
 
static void writeValue(void *data, Qgis::DataType type, qgssize index, double value)
 
bool isNoData(int row, int column) const SIP_HOLDGIL
Checks if value at position is no data.
 
void applyScaleOffset(double scale, double offset)
Apply band scale and offset to raster block values.
 
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.
 
bool setValue(int row, int column, double value) SIP_HOLDGIL
Set value on position.
 
int height() const SIP_HOLDGIL
Returns the height (number of rows) of the raster block.
 
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 yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
 
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
 
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
 
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
 
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
 
double width() const SIP_HOLDGIL
Returns the width 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