Skip to content
Permalink
Browse files

Slightly optimize raster pseudo color rendering

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 10, 2018
1 parent 1ac5ca0 commit 39ac58b9aa85f38f31eef6c2a807f00f9dfb7453
Showing with 27 additions and 21 deletions.
  1. +17 −14 src/core/raster/qgscolorrampshader.cpp
  2. +10 −7 src/core/raster/qgssinglebandpseudocolorrenderer.cpp
@@ -325,17 +325,18 @@ bool QgsColorRampShader::shade( double value, int *returnRedValue, int *returnGr
return false;

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

// 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
while ( idx < colorRampItemListCount && mColorRampItemList.at( idx ).value + DOUBLE_DIFF_THRESHOLD < value )
while ( idx < colorRampItemListCount && colorRampItems[idx].value + DOUBLE_DIFF_THRESHOLD < value )
{
idx++;
}
@@ -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 )
{
@@ -413,16 +414,18 @@ bool QgsColorRampShader::shade( double value, int *returnRedValue, int *returnGr
return true;
}

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

double currentRampRange = currentColorRampItem.value - previousColorRampItem.value;
double offsetInRange = value - previousColorRampItem.value;
double scale = offsetInRange / currentRampRange;
float currentRampRange = currentColorRampItem.value - previousColorRampItem.value;
float offsetInRange = value - previousColorRampItem.value;
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 ) );
*returnGreenValue = static_cast< int >( static_cast< double >( previousColorRampItem.color.green() ) + ( static_cast< double >( currentColorRampItem.color.green() - previousColorRampItem.color.green() ) * scale ) );
*returnBlueValue = static_cast< int >( static_cast< double >( previousColorRampItem.color.blue() ) + ( static_cast< double >( currentColorRampItem.color.blue() - previousColorRampItem.color.blue() ) * scale ) );
*returnAlphaValue = static_cast< int >( static_cast< double >( previousColorRampItem.color.alpha() ) + ( static_cast< double >( currentColorRampItem.color.alpha() - previousColorRampItem.color.alpha() ) * scale ) );
*returnRedValue = qRed( c1 ) + static_cast< int >( ( qRed( c2 ) - qRed( c1 ) ) * scale );
*returnGreenValue = qGreen( c1 ) + static_cast< int >( ( qGreen( c2 ) - qGreen( c1 ) ) * scale );
*returnBlueValue = qBlue( c1 ) + static_cast< int >( ( qBlue( c2 ) - qBlue( c1 ) ) * scale );
*returnAlphaValue = qAlpha( c1 ) + static_cast< int >( ( qAlpha( c2 ) - qAlpha( c1 ) ) * scale );
return true;
}
else if ( colorRampType() == Discrete )
@@ -198,7 +198,7 @@ QgsRasterBlock *QgsSingleBandPseudoColorRenderer::block( int bandNo, QgsRectangl
Q_UNUSED( bandNo );

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

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 ) )
{
outputBlock->setColor( i, myDefaultColor );
outputBlockData[i] = myDefaultColor;
continue;
}
double val = inputBlock->value( i );
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;
}

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

if ( !hasTransparency )
{
outputBlock->setColor( i, qRgba( red, green, blue, alpha ) );
outputBlockData[i] = qRgba( red, green, blue, alpha );
}
else
{
@@ -275,7 +278,7 @@ QgsRasterBlock *QgsSingleBandPseudoColorRenderer::block( int bandNo, QgsRectangl
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 );
}
}

0 comments on commit 39ac58b

Please sign in to comment.
You can’t perform that action at this time.