Skip to content

Commit

Permalink
[feature] Transparency support for raster color ramps (fix #7847)
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed May 19, 2013
1 parent cf928a5 commit ff41a1d
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 43 deletions.
4 changes: 2 additions & 2 deletions python/core/raster/qgscolorrampshader.sip
Expand Up @@ -58,10 +58,10 @@ class QgsColorRampShader : QgsRasterShaderFunction
void setMaximumColorCacheSize( int theSize );

/** \brief Generates and new RGB value based on one input value */
bool shade( double, int* /Out/, int* /Out/, int* /Out/ );
bool shade( double, int* /Out/, int* /Out/, int* /Out/, int* /Out/ );

/** \brief Generates and new RGB value based on original RGB value */
bool shade( double, double, double, int* /Out/, int* /Out/, int* /Out/ );
bool shade( double, double, double, double, int* /Out/, int* /Out/, int* /Out/, int* /Out/);

void legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const;
};
4 changes: 2 additions & 2 deletions python/core/raster/qgsrastershader.sip
Expand Up @@ -29,10 +29,10 @@ class QgsRasterShader
*
*/
/** \brief generates and new RGB value based on one input value */
bool shade(double, int* /Out/, int* /Out/, int* /Out/);
bool shade(double, int* /Out/, int* /Out/, int* /Out/, int* /Out/);

/** \brief generates and new RGB value based on original RGB value */
bool shade(double, double, double, int* /Out/, int* /Out/, int* /Out/);
bool shade(double, double, double, double, int* /Out/, int* /Out/, int* /Out/, int* /Out/);

/** \brief A public method that allows the user to set their own shader function
\note Raster shader takes ownership of the shader function instance */
Expand Down
4 changes: 2 additions & 2 deletions python/core/raster/qgsrastershaderfunction.sip
Expand Up @@ -27,10 +27,10 @@ class QgsRasterShaderFunction
virtual void setMinimumValue( double );

/** \brief generates and new RGB value based on one input value */
virtual bool shade( double, int* /Out/, int* /Out/, int* /Out/ );
virtual bool shade( double, int* /Out/, int* /Out/, int* /Out/, int* /Out/ );

/** \brief generates and new RGB value based on original RGB value */
virtual bool shade( double, double, double, int* /Out/, int* /Out/, int* /Out/ );
virtual bool shade( double, double, double, double, int* /Out/, int* /Out/, int* /Out/, int* /Out/ );

double minimumMaximumRange() const;

Expand Down
29 changes: 18 additions & 11 deletions src/core/raster/qgscolorrampshader.cpp
Expand Up @@ -49,7 +49,7 @@ QString QgsColorRampShader::colorRampTypeAsQString()
return QString( "Unknown" );
}

bool QgsColorRampShader::discreteColor( double theValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue )
bool QgsColorRampShader::discreteColor( double theValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue, int* theReturnAlphaValue )
{
int myColorRampItemCount = mColorRampItemList.count();
if ( myColorRampItemCount <= 0 )
Expand All @@ -75,6 +75,7 @@ bool QgsColorRampShader::discreteColor( double theValue, int* theReturnRedValue,
*theReturnRedValue = myColorRampItem.color.red();
*theReturnGreenValue = myColorRampItem.color.green();
*theReturnBlueValue = myColorRampItem.color.blue();
*theReturnAlphaValue = myColorRampItem.color.alpha();
//Cache the shaded value
if ( mMaximumColorCacheSize >= mColorCache.size() )
{
Expand All @@ -92,7 +93,7 @@ bool QgsColorRampShader::discreteColor( double theValue, int* theReturnRedValue,
return false; // value not found
}

bool QgsColorRampShader::exactColor( double theValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue )
bool QgsColorRampShader::exactColor( double theValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue , int *theReturnAlphaValue )
{
int myColorRampItemCount = mColorRampItemList.count();
if ( myColorRampItemCount <= 0 )
Expand All @@ -112,6 +113,7 @@ bool QgsColorRampShader::exactColor( double theValue, int* theReturnRedValue, in
*theReturnRedValue = myColorRampItem.color.red();
*theReturnGreenValue = myColorRampItem.color.green();
*theReturnBlueValue = myColorRampItem.color.blue();
*theReturnAlphaValue = myColorRampItem.color.alpha();
//Cache the shaded value
if ( mMaximumColorCacheSize >= mColorCache.size() )
{
Expand Down Expand Up @@ -142,7 +144,7 @@ bool QgsColorRampShader::exactColor( double theValue, int* theReturnRedValue, in
}

bool QgsColorRampShader::interpolatedColor( double theValue, int*
theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue )
theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue , int* theReturnAlphaValue )
{
int myColorRampItemCount = mColorRampItemList.count();
if ( myColorRampItemCount <= 0 )
Expand Down Expand Up @@ -174,9 +176,10 @@ bool QgsColorRampShader::interpolatedColor( double theValue, int*
*theReturnRedValue = ( int )(( double ) myPreviousColorRampItem.color.red() + (( double )( myColorRampItem.color.red() - myPreviousColorRampItem.color.red() ) * scale ) ) ;
*theReturnGreenValue = ( int )(( double ) myPreviousColorRampItem.color.green() + (( double )( myColorRampItem.color.green() - myPreviousColorRampItem.color.green() ) * scale ) );
*theReturnBlueValue = ( int )(( double ) myPreviousColorRampItem.color.blue() + (( double )( myColorRampItem.color.blue() - myPreviousColorRampItem.color.blue() ) * scale ) );
*theReturnAlphaValue = ( int )(( double ) myPreviousColorRampItem.color.alpha() + (( double )( myColorRampItem.color.alpha() - myPreviousColorRampItem.color.alpha() ) * scale ) );
if ( mMaximumColorCacheSize >= mColorCache.size() )
{
QColor myNewColor( *theReturnRedValue, *theReturnGreenValue, *theReturnBlueValue );
QColor myNewColor( *theReturnRedValue, *theReturnGreenValue, *theReturnBlueValue, *theReturnAlphaValue );
mColorCache.insert( theValue, myNewColor );
}
return true;
Expand All @@ -192,9 +195,10 @@ bool QgsColorRampShader::interpolatedColor( double theValue, int*
*theReturnRedValue = myColorRampItem.color.red();
*theReturnGreenValue = myColorRampItem.color.green();
*theReturnBlueValue = myColorRampItem.color.blue();
*theReturnAlphaValue = myColorRampItem.color.alpha();
if ( mMaximumColorCacheSize >= mColorCache.size() )
{
QColor myNewColor( *theReturnRedValue, *theReturnGreenValue, *theReturnBlueValue );
QColor myNewColor( *theReturnRedValue, *theReturnGreenValue, *theReturnBlueValue, *theReturnAlphaValue );
mColorCache.insert( theValue, myNewColor );
}
return true;
Expand Down Expand Up @@ -245,7 +249,7 @@ void QgsColorRampShader::setColorRampType( QString theType )
}
}

bool QgsColorRampShader::shade( double theValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue )
bool QgsColorRampShader::shade( double theValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue , int *theReturnAlphaValue )
{

//Get the shaded value from the cache if it exists already
Expand All @@ -255,6 +259,7 @@ bool QgsColorRampShader::shade( double theValue, int* theReturnRedValue, int* th
*theReturnRedValue = myColor.red();
*theReturnGreenValue = myColor.green();
*theReturnBlueValue = myColor.blue();
*theReturnAlphaValue = myColor.alpha();
return true;
}

Expand All @@ -272,27 +277,29 @@ bool QgsColorRampShader::shade( double theValue, int* theReturnRedValue, int* th

if ( QgsColorRampShader::EXACT == mColorRampType )
{
return exactColor( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue );
return exactColor( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue, theReturnAlphaValue );
}
else if ( QgsColorRampShader::INTERPOLATED == mColorRampType )
{
return interpolatedColor( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue );
return interpolatedColor( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue, theReturnAlphaValue );
}

return discreteColor( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue );
return discreteColor( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue, theReturnAlphaValue );
}

bool QgsColorRampShader::shade( double theRedValue, double theGreenValue,
double theBlueValue, int* theReturnRedValue, int* theReturnGreenValue, int*
theReturnBlueValue )
double theBlueValue, double theAlphaValue, int* theReturnRedValue, int* theReturnGreenValue, int*
theReturnBlueValue , int* theReturnAlphaValue )
{
Q_UNUSED( theRedValue );
Q_UNUSED( theGreenValue );
Q_UNUSED( theBlueValue );
Q_UNUSED( theAlphaValue );

*theReturnRedValue = 0;
*theReturnGreenValue = 0;
*theReturnBlueValue = 0;
*theReturnAlphaValue = 0;

return false;
}
Expand Down
10 changes: 5 additions & 5 deletions src/core/raster/qgscolorrampshader.h
Expand Up @@ -86,10 +86,10 @@ class CORE_EXPORT QgsColorRampShader : public QgsRasterShaderFunction
void setMaximumColorCacheSize( int theSize ) { mMaximumColorCacheSize = theSize; }

/** \brief Generates and new RGB value based on one input value */
bool shade( double, int*, int*, int* );
bool shade( double, int*, int*, int*, int* );

/** \brief Generates and new RGB value based on original RGB value */
bool shade( double, double, double, int*, int*, int* );
bool shade( double, double, double, double, int*, int*, int*, int* );

void legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const;

Expand Down Expand Up @@ -121,17 +121,17 @@ class CORE_EXPORT QgsColorRampShader : public QgsRasterShaderFunction
/** Gets the color for a pixel value from the classification vector
* mValueClassification. Assigns the color of the lower class for every
* pixel between two class breaks.*/
bool discreteColor( double, int*, int*, int* );
bool discreteColor( double, int*, int*, int*, int* );

/** Gets the color for a pixel value from the classification vector
* mValueClassification. Assigns the color of the exact matching value in
* the color ramp item list */
bool exactColor( double, int*, int*, int* );
bool exactColor( double, int*, int*, int*, int* );

/** Gets the color for a pixel value from the classification vector
* mValueClassification. Interpolates the color between two class breaks
* linearly.*/
bool interpolatedColor( double, int*, int*, int* );
bool interpolatedColor( double, int*, int*, int*, int* );

/** Do not render values out of range */
bool mClip;
Expand Down
6 changes: 3 additions & 3 deletions src/core/raster/qgsrasterlayer.cpp
Expand Up @@ -732,9 +732,9 @@ QPixmap QgsRasterLayer::paletteAsPixmap( int theBandNumber )
for ( int myCol = 0; myCol < mySize; myCol++ )
{
myValue = myStep * ( double )( myCol + myRow * mySize );
int c1, c2, c3;
myShader.shade( myValue, &c1, &c2, &c3 );
myLineBuffer[ myCol ] = qRgb( c1, c2, c3 );
int c1, c2, c3, c4;
myShader.shade( myValue, &c1, &c2, &c3, &c4 );
myLineBuffer[ myCol ] = qRgba( c1, c2, c3, c4 );
}
}

Expand Down
11 changes: 7 additions & 4 deletions src/core/raster/qgsrastershader.cpp
Expand Up @@ -45,11 +45,11 @@ QgsRasterShader::~QgsRasterShader()
@param theReturnBlueValue The blue component of the new RGB value
@return True if the return values are valid otherwise false
*/
bool QgsRasterShader::shade( double theValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue )
bool QgsRasterShader::shade( double theValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue , int *theReturnAlpha )
{
if ( 0 != mRasterShaderFunction )
{
return mRasterShaderFunction->shade( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue );
return mRasterShaderFunction->shade( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue, theReturnAlpha );
}

return false;
Expand All @@ -66,11 +66,11 @@ bool QgsRasterShader::shade( double theValue, int* theReturnRedValue, int* theRe
@param theReturnBlueValue The blue component of the new RGB value
@return True if the return values are valid otherwise false
*/
bool QgsRasterShader::shade( double theRedValue, double theGreenValue, double theBlueValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue )
bool QgsRasterShader::shade( double theRedValue, double theGreenValue, double theBlueValue, double theAlphaValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue, int* theReturnAlphaValue )
{
if ( 0 != mRasterShaderFunction )
{
return mRasterShaderFunction->shade( theRedValue, theGreenValue, theBlueValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue );
return mRasterShaderFunction->shade( theRedValue, theGreenValue, theBlueValue, theAlphaValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue, theReturnAlphaValue );
}

return false;
Expand Down Expand Up @@ -150,6 +150,7 @@ void QgsRasterShader::writeXML( QDomDocument& doc, QDomElement& parent ) const
itemElem.setAttribute( "label", itemIt->label );
itemElem.setAttribute( "value", QString::number( itemIt->value ) );
itemElem.setAttribute( "color", itemIt->color.name() );
itemElem.setAttribute( "alpha", itemIt->color.alpha() );
colorRampShaderElem.appendChild( itemElem );
}
rasterShaderElem.appendChild( colorRampShaderElem );
Expand Down Expand Up @@ -180,6 +181,8 @@ void QgsRasterShader::readXML( const QDomElement& elem )
itemValue = itemElem.attribute( "value" ).toDouble();
itemLabel = itemElem.attribute( "label" );
itemColor.setNamedColor( itemElem.attribute( "color" ) );
itemColor.setAlpha( itemElem.attribute( "alpha", "255" ).toInt() );

itemList.push_back( QgsColorRampShader::ColorRampItem( itemValue, itemColor, itemLabel ) );
}
colorRampShader->setColorRampItemList( itemList );
Expand Down
8 changes: 4 additions & 4 deletions src/core/raster/qgsrastershader.h
Expand Up @@ -54,11 +54,11 @@ class CORE_EXPORT QgsRasterShader
* Non-Static methods
*
*/
/** \brief generates and new RGB value based on one input value */
bool shade( double, int*, int*, int* );
/** \brief generates and new RGBA value based on one input value */
bool shade( double, int*, int*, int* , int* );

/** \brief generates and new RGB value based on original RGB value */
bool shade( double, double, double, int*, int*, int* );
/** \brief generates and new RGBA value based on original RGBA value */
bool shade( double, double, double, double, int*, int*, int* , int* );

/** \brief A public method that allows the user to set their own shader function
\note Raster shader takes ownership of the shader function instance */
Expand Down
7 changes: 5 additions & 2 deletions src/core/raster/qgsrastershaderfunction.cpp
Expand Up @@ -63,13 +63,14 @@ void QgsRasterShaderFunction::setMinimumValue( double theValue )
@param theReturnBlueValue The blue component of the new RGB value
@return True if the return values are valid otherwise false
*/
bool QgsRasterShaderFunction::shade( double theValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue )
bool QgsRasterShaderFunction::shade( double theValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue, int* theReturnAlphaValue )
{
Q_UNUSED( theValue );

*theReturnRedValue = 0;
*theReturnGreenValue = 0;
*theReturnBlueValue = 0;
*theReturnAlphaValue = 0;

return false;
}
Expand All @@ -86,15 +87,17 @@ bool QgsRasterShaderFunction::shade( double theValue, int* theReturnRedValue, in
@param theReturnBlueValue The blue component of the new RGB value
@return True if the return values are valid otherwise false
*/
bool QgsRasterShaderFunction::shade( double theRedValue, double theGreenValue, double theBlueValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue )
bool QgsRasterShaderFunction::shade( double theRedValue, double theGreenValue, double theBlueValue, double theAlphaValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue , int *theReturnAlphaValue )
{
Q_UNUSED( theRedValue );
Q_UNUSED( theGreenValue );
Q_UNUSED( theBlueValue );
Q_UNUSED( theAlphaValue );

*theReturnRedValue = 0;
*theReturnGreenValue = 0;
*theReturnBlueValue = 0;
*theReturnAlphaValue = 0;

return false;
}
8 changes: 4 additions & 4 deletions src/core/raster/qgsrastershaderfunction.h
Expand Up @@ -40,11 +40,11 @@ class CORE_EXPORT QgsRasterShaderFunction
/** \brief Return the minimum value */
virtual void setMinimumValue( double );

/** \brief generates and new RGB value based on one input value */
virtual bool shade( double, int*, int*, int* );
/** \brief generates and new RGBA value based on one input value */
virtual bool shade( double, int*, int*, int*, int* );

/** \brief generates and new RGB value based on original RGB value */
virtual bool shade( double, double, double, int*, int*, int* );
/** \brief generates and new RGBA value based on original RGBA value */
virtual bool shade( double, double, double, double, int*, int*, int*, int* );

double minimumMaximumRange() const { return mMinimumMaximumRange; }

Expand Down
16 changes: 12 additions & 4 deletions src/core/raster/qgssinglebandpseudocolorrenderer.cpp
Expand Up @@ -156,16 +156,24 @@ QgsRasterBlock* QgsSingleBandPseudoColorRenderer::block( int bandNo, QgsRectangl
continue;
}
double val = inputBlock->value( i );
int red, green, blue;
if ( !mShader->shade( val, &red, &green, &blue ) )
int red, green, blue, alpha;
if ( !mShader->shade( val, &red, &green, &blue, &alpha ) )
{
outputBlock->setColor( i, myDefaultColor );
continue;
}

if ( alpha < 255 )
{
// Working with premultiplied colors, so multiply values by alpha
red *= ( alpha / 255.0 );
blue *= ( alpha / 255.0 );
green *= ( alpha / 255.0 );
}

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

outputBlock->setColor( i, qRgba( currentOpacity * red, currentOpacity * green, currentOpacity * blue, currentOpacity * 255 ) );
outputBlock->setColor( i, qRgba( currentOpacity * red, currentOpacity * green, currentOpacity * blue, currentOpacity * alpha ) );
}
}

Expand Down

0 comments on commit ff41a1d

Please sign in to comment.