Skip to content

Commit

Permalink
Slightly optimize raster pseudo color rendering
Browse files Browse the repository at this point in the history
This brought rendering time per raster tile from ~80ms to ~50ms
(this is with debug version so the timing may be skewed)
  • Loading branch information
wonder-sk committed Jul 12, 2018
1 parent 1ac5ca0 commit 39ac58b
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 21 deletions.
31 changes: 17 additions & 14 deletions src/core/raster/qgscolorrampshader.cpp
Expand Up @@ -325,17 +325,18 @@ bool QgsColorRampShader::shade( double value, int *returnRedValue, int *returnGr
return false; return false;


int colorRampItemListCount = mColorRampItemList.count(); int colorRampItemListCount = mColorRampItemList.count();
const QgsColorRampShader::ColorRampItem *colorRampItems = mColorRampItemList.constData();
int idx; int idx;
if ( !mLUTInitialized ) if ( !mLUTInitialized )
{ {
// calculate LUT for faster index recovery // calculate LUT for faster index recovery
mLUTFactor = 1.0; mLUTFactor = 1.0;
double minimumValue = mColorRampItemList.first().value; double minimumValue = colorRampItems[0].value;
mLUTOffset = minimumValue + DOUBLE_DIFF_THRESHOLD; mLUTOffset = minimumValue + DOUBLE_DIFF_THRESHOLD;
// Only make lut if at least 3 items, with 2 items the low and high cases handle both // Only make lut if at least 3 items, with 2 items the low and high cases handle both
if ( colorRampItemListCount >= 3 ) if ( colorRampItemListCount >= 3 )
{ {
double rangeValue = mColorRampItemList.at( colorRampItemListCount - 2 ).value - minimumValue; double rangeValue = colorRampItems[colorRampItemListCount - 2].value - minimumValue;
if ( rangeValue > 0 ) if ( rangeValue > 0 )
{ {
int lutSize = 256; // TODO: test if speed can be increased with a different LUT size int lutSize = 256; // TODO: test if speed can be increased with a different LUT size
Expand All @@ -347,7 +348,7 @@ bool QgsColorRampShader::shade( double value, int *returnRedValue, int *returnGr
{ {
val = ( i / mLUTFactor ) + mLUTOffset; val = ( i / mLUTFactor ) + mLUTOffset;
while ( idx < colorRampItemListCount while ( idx < colorRampItemListCount
&& mColorRampItemList.at( idx ).value - DOUBLE_DIFF_THRESHOLD < val ) && colorRampItems[idx].value - DOUBLE_DIFF_THRESHOLD < val )
{ {
idx++; idx++;
} }
Expand All @@ -371,7 +372,7 @@ bool QgsColorRampShader::shade( double value, int *returnRedValue, int *returnGr
else if ( lutIndex >= mLUT.count() ) else if ( lutIndex >= mLUT.count() )
{ {
idx = colorRampItemListCount - 1; idx = colorRampItemListCount - 1;
if ( mColorRampItemList.at( idx ).value + DOUBLE_DIFF_THRESHOLD < value ) if ( colorRampItems[idx].value + DOUBLE_DIFF_THRESHOLD < value )
{ {
overflow = true; overflow = true;
} }
Expand All @@ -383,7 +384,7 @@ bool QgsColorRampShader::shade( double value, int *returnRedValue, int *returnGr


// check if it's correct and if not increase until correct // check if it's correct and if not increase until correct
// the LUT is made in such a way the index is always correct or too low, never too high // the LUT is made in such a way the index is always correct or too low, never too high
while ( idx < colorRampItemListCount && mColorRampItemList.at( idx ).value + DOUBLE_DIFF_THRESHOLD < value ) while ( idx < colorRampItemListCount && colorRampItems[idx].value + DOUBLE_DIFF_THRESHOLD < value )
{ {
idx++; idx++;
} }
Expand All @@ -394,7 +395,7 @@ bool QgsColorRampShader::shade( double value, int *returnRedValue, int *returnGr
} }
} }


const QgsColorRampShader::ColorRampItem &currentColorRampItem = mColorRampItemList.at( idx ); const QgsColorRampShader::ColorRampItem &currentColorRampItem = colorRampItems[idx];


if ( colorRampType() == Interpolated ) if ( colorRampType() == Interpolated )
{ {
Expand All @@ -413,16 +414,18 @@ bool QgsColorRampShader::shade( double value, int *returnRedValue, int *returnGr
return true; return true;
} }


const QgsColorRampShader::ColorRampItem &previousColorRampItem = mColorRampItemList.at( idx - 1 ); const QgsColorRampShader::ColorRampItem &previousColorRampItem = colorRampItems[idx - 1];


double currentRampRange = currentColorRampItem.value - previousColorRampItem.value; float currentRampRange = currentColorRampItem.value - previousColorRampItem.value;
double offsetInRange = value - previousColorRampItem.value; float offsetInRange = value - previousColorRampItem.value;
double scale = offsetInRange / currentRampRange; float scale = offsetInRange / currentRampRange;
const QRgb c1 = previousColorRampItem.color.rgba();
const QRgb c2 = currentColorRampItem.color.rgba();


*returnRedValue = static_cast< int >( static_cast< double >( previousColorRampItem.color.red() ) + ( static_cast< double >( currentColorRampItem.color.red() - previousColorRampItem.color.red() ) * scale ) ); *returnRedValue = qRed( c1 ) + static_cast< int >( ( qRed( c2 ) - qRed( c1 ) ) * scale );
*returnGreenValue = static_cast< int >( static_cast< double >( previousColorRampItem.color.green() ) + ( static_cast< double >( currentColorRampItem.color.green() - previousColorRampItem.color.green() ) * scale ) ); *returnGreenValue = qGreen( c1 ) + static_cast< int >( ( qGreen( c2 ) - qGreen( c1 ) ) * scale );
*returnBlueValue = static_cast< int >( static_cast< double >( previousColorRampItem.color.blue() ) + ( static_cast< double >( currentColorRampItem.color.blue() - previousColorRampItem.color.blue() ) * scale ) ); *returnBlueValue = qBlue( c1 ) + static_cast< int >( ( qBlue( c2 ) - qBlue( c1 ) ) * scale );
*returnAlphaValue = static_cast< int >( static_cast< double >( previousColorRampItem.color.alpha() ) + ( static_cast< double >( currentColorRampItem.color.alpha() - previousColorRampItem.color.alpha() ) * scale ) ); *returnAlphaValue = qAlpha( c1 ) + static_cast< int >( ( qAlpha( c2 ) - qAlpha( c1 ) ) * scale );
return true; return true;
} }
else if ( colorRampType() == Discrete ) else if ( colorRampType() == Discrete )
Expand Down
17 changes: 10 additions & 7 deletions src/core/raster/qgssinglebandpseudocolorrenderer.cpp
Expand Up @@ -198,7 +198,7 @@ QgsRasterBlock *QgsSingleBandPseudoColorRenderer::block( int bandNo, QgsRectangl
Q_UNUSED( bandNo ); Q_UNUSED( bandNo );


std::unique_ptr< QgsRasterBlock > outputBlock( new QgsRasterBlock() ); std::unique_ptr< QgsRasterBlock > outputBlock( new QgsRasterBlock() );
if ( !mInput || !mShader ) if ( !mInput || !mShader || !mShader->rasterShaderFunction() )
{ {
return outputBlock.release(); return outputBlock.release();
} }
Expand Down Expand Up @@ -234,19 +234,22 @@ QgsRasterBlock *QgsSingleBandPseudoColorRenderer::block( int bandNo, QgsRectangl
} }


QRgb myDefaultColor = NODATA_COLOR; QRgb myDefaultColor = NODATA_COLOR;
QRgb *outputBlockData = outputBlock->colorData();
QgsRasterShaderFunction *fcn = const_cast<QgsRasterShaderFunction *>( mShader->rasterShaderFunction() );


for ( qgssize i = 0; i < ( qgssize )width * height; i++ ) qgssize count = ( qgssize )width * height;
for ( qgssize i = 0; i < count; i++ )
{ {
if ( inputBlock->isNoData( i ) ) if ( inputBlock->isNoData( i ) )
{ {
outputBlock->setColor( i, myDefaultColor ); outputBlockData[i] = myDefaultColor;
continue; continue;
} }
double val = inputBlock->value( i ); double val = inputBlock->value( i );
int red, green, blue, alpha; int red, green, blue, alpha;
if ( !mShader->shade( val, &red, &green, &blue, &alpha ) ) if ( !fcn->shade( val, &red, &green, &blue, &alpha ) )
{ {
outputBlock->setColor( i, myDefaultColor ); outputBlockData[i] = myDefaultColor;
continue; continue;
} }


Expand All @@ -260,7 +263,7 @@ QgsRasterBlock *QgsSingleBandPseudoColorRenderer::block( int bandNo, QgsRectangl


if ( !hasTransparency ) if ( !hasTransparency )
{ {
outputBlock->setColor( i, qRgba( red, green, blue, alpha ) ); outputBlockData[i] = qRgba( red, green, blue, alpha );
} }
else else
{ {
Expand All @@ -275,7 +278,7 @@ QgsRasterBlock *QgsSingleBandPseudoColorRenderer::block( int bandNo, QgsRectangl
currentOpacity *= alphaBlock->value( i ) / 255.0; currentOpacity *= alphaBlock->value( i ) / 255.0;
} }


outputBlock->setColor( i, qRgba( currentOpacity * red, currentOpacity * green, currentOpacity * blue, currentOpacity * alpha ) ); outputBlockData[i] = qRgba( currentOpacity * red, currentOpacity * green, currentOpacity * blue, currentOpacity * alpha );
} }
} }


Expand Down

0 comments on commit 39ac58b

Please sign in to comment.