Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Speed up rendering of RGB images
In my simple test case this made map rendering of RGB satellite image tiles
go down by ~50% from ~40ms per tile to ~20ms per tile (in debug version, ahem)
  • Loading branch information
wonder-sk committed Jul 9, 2018
1 parent c4b9106 commit 0a35d43
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 5 deletions.
2 changes: 2 additions & 0 deletions python/core/auto_generated/raster/qgsrasterblock.sip.in
Expand Up @@ -166,6 +166,7 @@ returned value is undefined.
:return: value *
%End


QRgb color( int row, int column ) const;
%Docstring
Read a single color
Expand Down Expand Up @@ -246,6 +247,7 @@ Set color on index (indexed line by line)
:return: true on success *
%End


bool setIsNoData( int row, int column );
%Docstring
Set no data on pixel
Expand Down
30 changes: 25 additions & 5 deletions src/core/raster/qgsmultibandcolorrenderer.cpp
Expand Up @@ -225,9 +225,22 @@ QgsRasterBlock *QgsMultiBandColorRenderer::block( int bandNo, QgsRectangle cons
return outputBlock.release();
}

QRgb *outputBlockColorData = outputBlock->colorData();

// faster data access to data for the common case that input data are coming from RGB image with 8-bit bands
bool hasByteRgb = ( redBlock->dataType() == Qgis::Byte && greenBlock->dataType() == Qgis::Byte && blueBlock->dataType() == Qgis::Byte );
const quint8 *redData = nullptr, *greenData = nullptr, *blueData = nullptr;
if ( hasByteRgb )
{
redData = redBlock->byteData();
greenData = greenBlock->byteData();
blueData = blueBlock->byteData();
}

QRgb myDefaultColor = NODATA_COLOR;

for ( qgssize i = 0; i < ( qgssize )width * height; i++ )
qgssize count = ( qgssize )width * height;
for ( qgssize i = 0; i < count; i++ )
{
if ( fastDraw ) //fast rendering if no transparency, stretching, color inversion, etc.
{
Expand All @@ -239,10 +252,17 @@ QgsRasterBlock *QgsMultiBandColorRenderer::block( int bandNo, QgsRectangle cons
}
else
{
int redVal = ( int )redBlock->value( i );
int greenVal = ( int )greenBlock->value( i );
int blueVal = ( int )blueBlock->value( i );
outputBlock->setColor( i, qRgba( redVal, greenVal, blueVal, 255 ) );
if ( hasByteRgb )
{
outputBlockColorData[i] = qRgb( redData[i], greenData[i], blueData[i] );
}
else
{
int redVal = ( int )redBlock->value( i );
int greenVal = ( int )greenBlock->value( i );
int blueVal = ( int )blueBlock->value( i );
outputBlockColorData[i] = qRgb( redVal, greenVal, blueVal );
}
}
continue;
}
Expand Down
28 changes: 28 additions & 0 deletions src/core/raster/qgsrasterblock.h
Expand Up @@ -196,6 +196,20 @@ class CORE_EXPORT QgsRasterBlock
* \returns value */
double value( qgssize index ) const;

/**
* Gives direct access to the raster block data.
* The data type of the block must be Qgis::Byte otherwise it returns null pointer.
* Useful for most efficient read access.
* \note not available in Python bindings
* \since QGIS 3.4
*/
const quint8 *byteData() const SIP_SKIP
{
if ( mDataType != Qgis::Byte )
return nullptr;
return static_cast< const quint8 * >( mData );
}

/**
* \brief Read a single color
* \param row row index
Expand Down Expand Up @@ -332,6 +346,20 @@ class CORE_EXPORT QgsRasterBlock
return true;
}

/**
* Gives direct read/write access to the raster RGB data.
* The data type of the block must be Qgis::ARGB32 or Qgis::ARGB32_Premultiplied otherwise it returns null pointer.
* Useful for most efficient read/write access to RGB blocks.
* \note not available in Python bindings
* \since QGIS 3.4
*/
QRgb *colorData() SIP_SKIP
{
if ( !mImage )
return nullptr;
return reinterpret_cast< QRgb * >( mImage->bits() );
}

/**
* \brief Set no data on pixel
* \param row row index
Expand Down

0 comments on commit 0a35d43

Please sign in to comment.