28 const 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();
78 QgsDebugMsg( QStringLiteral(
"Couldn't allocate data memory of %1 bytes" ).arg( tSize *
width *
height ) );
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 );
104 QImage::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 ||
211 *
noDataValue = std::numeric_limits<double>::max() * -1.0;
215 QgsDebugMsg( QStringLiteral(
"Unknown data type %1" ).arg(
static_cast< int >(
dataType ) ) );
218 QgsDebugMsgLevel( QStringLiteral(
"newDataType = %1 noDataValue = %2" ).arg( qgsEnumValueToKey< Qgis::DataType >( newDataType ) ).arg( *
noDataValue ), 4 );
224 mHasNoDataValue =
true;
230 mHasNoDataValue =
false;
231 mNoDataValue = std::numeric_limits<double>::quiet_NaN();
240 if ( mHasNoDataValue )
244 QgsDebugMsg( QStringLiteral(
"Data block not allocated" ) );
249 QByteArray noDataByteArray =
valueBytes( mDataType, mNoDataValue );
250 if ( mNoDataValue == 0 )
256 const char *nodata = noDataByteArray.data();
257 for (
qgssize i = 0; i < static_cast< qgssize >( mWidth )*mHeight; i++ )
266 if ( !mNoDataBitmap )
268 if ( !createNoDataBitmap() )
274 memset( mNoDataBitmap, 0xff, mNoDataBitmapSize );
287 QgsDebugMsg( QStringLiteral(
"Image not allocated" ) );
291 mImage->fill( NO_DATA_COLOR );
298 int top = exceptRect.top();
299 int bottom = exceptRect.bottom();
300 int left = exceptRect.left();
301 int right = exceptRect.right();
302 top = std::min( std::max( top, 0 ), mHeight - 1 );
303 left = std::min( std::max( left, 0 ), mWidth - 1 );
304 bottom = std::max( 0, std::min( bottom, mHeight - 1 ) );
305 right = std::max( 0, std::min( right, mWidth - 1 ) );
311 if ( mHasNoDataValue )
315 QgsDebugMsg( QStringLiteral(
"Data block not allocated" ) );
320 QByteArray noDataByteArray =
valueBytes( mDataType, mNoDataValue );
322 char *nodata = noDataByteArray.data();
324 for (
int c = 0;
c < mWidth;
c++ )
330 for (
int r = 0; r < mHeight; r++ )
332 if ( r >= top && r <= bottom )
continue;
337 for (
int r = top; r <= bottom; r++ )
344 const int w = mWidth - right - 1;
352 if ( !mNoDataBitmap )
354 if ( !createNoDataBitmap() )
366 char *nodataRow =
new char[mNoDataBitmapWidth];
368 memset( nodataRow, 0, mNoDataBitmapWidth );
369 for (
int c = 0;
c < mWidth;
c ++ )
371 const int byte =
c / 8;
372 const int bit =
c % 8;
373 const char nodata = 0x80 >> bit;
374 memset( nodataRow +
byte, nodataRow[
byte] | nodata, 1 );
378 for (
int r = 0; r < mHeight; r++ )
380 if ( r >= top && r <= bottom )
continue;
381 const qgssize i =
static_cast< qgssize >( r ) * mNoDataBitmapWidth;
382 memcpy( mNoDataBitmap + i, nodataRow, mNoDataBitmapWidth );
385 memset( nodataRow, 0, mNoDataBitmapWidth );
386 for (
int c = 0;
c < mWidth;
c ++ )
388 if (
c >= left &&
c <= right )
continue;
389 const int byte =
c / 8;
390 const int bit =
c % 8;
391 const char nodata = 0x80 >> bit;
392 memset( nodataRow +
byte, nodataRow[
byte] | nodata, 1 );
394 for (
int r = top; r <= bottom; r++ )
396 const qgssize i =
static_cast< qgssize >( r ) * mNoDataBitmapWidth;
397 memcpy( mNoDataBitmap + i, nodataRow, mNoDataBitmapWidth );
408 QgsDebugMsg( QStringLiteral(
"Image not allocated" ) );
412 if ( mImage->width() != mWidth || mImage->height() != mHeight )
414 QgsDebugMsg( QStringLiteral(
"Image and block size differ" ) );
418 QgsDebugMsgLevel( QStringLiteral(
"Fill image depth = %1" ).arg( mImage->depth() ), 4 );
421 if ( mImage->depth() != 32 )
423 QgsDebugMsg( QStringLiteral(
"Unsupported image depth" ) );
427 const QRgb nodataRgba = NO_DATA_COLOR;
428 QRgb *nodataRow =
new QRgb[mWidth];
429 const int rgbSize =
sizeof( QRgb );
430 for (
int c = 0;
c < mWidth;
c ++ )
432 nodataRow[
c] = nodataRgba;
436 for (
int r = 0; r < mHeight; r++ )
438 if ( r >= top && r <= bottom )
continue;
440 memcpy(
reinterpret_cast< void *
>( mImage->bits() + rgbSize * i ), nodataRow, rgbSize *
static_cast< qgssize >( mWidth ) );
443 for (
int r = top; r <= bottom; r++ )
449 memcpy(
reinterpret_cast< void *
>( mImage->bits() + rgbSize * i ), nodataRow, rgbSize *
static_cast< qgssize >( left - 1 ) );
453 const int w = mWidth - right - 1;
454 memcpy(
reinterpret_cast< void *
>( mImage->bits() + rgbSize * i ), nodataRow, rgbSize *
static_cast< qgssize >( w ) );
464 return QByteArray::fromRawData(
static_cast<const char *
>( mData ),
typeSize( mDataType ) * mWidth * mHeight );
465 else if ( mImage && mImage->constBits() )
466 return QByteArray::fromRawData(
reinterpret_cast<const char *
>( mImage->constBits() ), mImage->sizeInBytes() );
478 const int len = std::min(
static_cast<int>(
data.size() ),
typeSize( mDataType ) * mWidth * mHeight - offset );
479 ::memcpy(
static_cast<char *
>( mData ) + offset,
data.constData(), len );
481 else if ( mImage && mImage->constBits() )
483 const qsizetype len = std::min(
static_cast< qsizetype
>(
data.size() ), mImage->sizeInBytes() - offset );
484 ::memcpy( mImage->bits() + offset,
data.constData(), len );
491 if ( index >=
static_cast< qgssize >( mWidth )*mHeight )
493 QgsDebugMsgLevel( QStringLiteral(
"Index %1 out of range (%2 x %3)" ).arg( index ).arg( mWidth ).arg( mHeight ), 4 );
498 return reinterpret_cast< char *
>( mData ) + index * mTypeSize;
500 if ( mImage && mImage->bits() )
502 return reinterpret_cast< char *
>( mImage->bits() + index * 4 );
510 return bits(
static_cast< qgssize >( row ) * mWidth + column );
517 return reinterpret_cast< char *
>( mData );
519 if ( mImage && mImage->bits() )
521 return reinterpret_cast< char *
>( mImage->bits() );
530 if ( destDataType == mDataType )
return true;
534 void *
data =
convert( mData, mDataType, destDataType,
static_cast< qgssize >( mWidth ) *
static_cast< qgssize >( mHeight ) );
538 QgsDebugMsg( QStringLiteral(
"Cannot convert raster block" ) );
543 mDataType = destDataType;
548 const QImage::Format format = imageFormat( destDataType );
549 const QImage
image = mImage->convertToFormat( format );
551 mDataType = destDataType;
566 if ( scale == 1.0 && offset == 0.0 )
return;
569 for (
qgssize i = 0; i < size; ++i )
577 if ( rangeList.isEmpty() )
583 for (
qgssize i = 0; i < size; ++i )
585 const double val =
value( i );
598 return QImage( *mImage );
609 mImage =
new QImage( *
image );
610 mWidth = mImage->width();
611 mHeight = mImage->height();
612 mDataType =
dataType( mImage->format() );
614 mNoDataValue = std::numeric_limits<double>::quiet_NaN();
644 for (
int i = 15; i <= 17; i++ )
646 s.setNum(
value,
'g', i );
653 QgsDebugMsg( QStringLiteral(
"Cannot correctly parse printed value" ) );
665 for (
int i = 6; i <= 9; i++ )
667 s.setNum(
value,
'g', i );
674 QgsDebugMsg( QStringLiteral(
"Cannot correctly parse printed value" ) );
680 const int destDataTypeSize =
typeSize( destDataType );
681 void *destData =
qgsMalloc( destDataTypeSize * size );
682 for (
qgssize i = 0; i < size; i++ )
696 ba.resize(
static_cast< int >( size ) );
697 char *
data = ba.data();
708 uc =
static_cast< quint8
>(
value );
709 memcpy(
data, &uc, size );
712 us =
static_cast< quint16
>(
value );
713 memcpy(
data, &us, size );
716 s =
static_cast< qint16
>(
value );
717 memcpy(
data, &s, size );
720 ui =
static_cast< quint32
>(
value );
721 memcpy(
data, &ui, size );
724 i =
static_cast< qint32
>(
value );
725 memcpy(
data, &i, size );
728 f =
static_cast< float >(
value );
729 memcpy(
data, &f, size );
732 d =
static_cast< double >(
value );
733 memcpy(
data, &d, size );
736 QgsDebugMsg( QStringLiteral(
"Data type is not supported" ) );
741 bool QgsRasterBlock::createNoDataBitmap()
743 mNoDataBitmapWidth = mWidth / 8 + 1;
744 mNoDataBitmapSize =
static_cast< qgssize >( mNoDataBitmapWidth ) * mHeight;
745 QgsDebugMsgLevel( QStringLiteral(
"allocate %1 bytes" ).arg( mNoDataBitmapSize ), 4 );
746 mNoDataBitmap =
reinterpret_cast< char *
>(
qgsMalloc( mNoDataBitmapSize ) );
747 if ( !mNoDataBitmap )
749 QgsDebugMsg( QStringLiteral(
"Couldn't allocate no data memory of %1 bytes" ).arg( mNoDataBitmapSize ) );
752 memset( mNoDataBitmap, 0, mNoDataBitmapSize );
758 return QStringLiteral(
"dataType = %1 width = %2 height = %3" )
759 .arg( qgsEnumValueToKey< Qgis::DataType >( mDataType ) ).arg( mWidth ).arg( mHeight );
769 QgsDebugMsgLevel( QStringLiteral(
"theWidth = %1 height = %2 xRes = %3 yRes = %4" ).arg(
width ).arg(
height ).arg( xRes ).arg( yRes ), 4 );
774 int right =
width - 1;
782 bottom = std::round( ( extent.
yMaximum() - subExtent.
yMinimum() ) / yRes ) - 1;
791 right = std::round( ( subExtent.
xMaximum() - extent.
xMinimum() ) / xRes ) - 1;
793 QRect
subRect = QRect( left, top, right - left + 1, bottom - top + 1 );