From f02e4ad98fe40c482f6c8af5368ae7ffc8e5bfb8 Mon Sep 17 00:00:00 2001 From: nirvn Date: Sat, 10 Dec 2016 10:30:48 +0700 Subject: [PATCH] [FEATURE][raster] transparency support for paletted renderer --- doc/api_break.dox | 5 ++++ .../core/raster/qgspalettedrasterrenderer.sip | 5 ---- src/core/raster/qgspalettedrasterrenderer.cpp | 22 +++++++++----- src/core/raster/qgspalettedrasterrenderer.h | 13 +++++---- src/gui/raster/qgspalettedrendererwidget.cpp | 29 ++++++++++++++++++- src/gui/raster/qgspalettedrendererwidget.h | 1 + ...qgssinglebandpseudocolorrendererwidget.cpp | 2 +- 7 files changed, 57 insertions(+), 20 deletions(-) diff --git a/doc/api_break.dox b/doc/api_break.dox index d02a6b2bf51..e8731272ef5 100644 --- a/doc/api_break.dox +++ b/doc/api_break.dox @@ -1246,6 +1246,11 @@ has improved sort capabilities including the ability to set custom sort values f and for forcing certain items to always sort on top. +QgsPalettedRasterRenderer {#qgis_api_break_3_0_QgsPalettedRasterRenderer} +------------------------- + +- The rgbArray() method was made private + QgsPalLabeling {#qgis_api_break_3_0_QgsPalLabeling} -------------- diff --git a/python/core/raster/qgspalettedrasterrenderer.sip b/python/core/raster/qgspalettedrasterrenderer.sip index 4b19d334c01..e8e5eb416cc 100644 --- a/python/core/raster/qgspalettedrasterrenderer.sip +++ b/python/core/raster/qgspalettedrasterrenderer.sip @@ -17,11 +17,6 @@ class QgsPalettedRasterRenderer : QgsRasterRenderer /** Returns copy of color array (caller takes ownership)*/ QColor* colors() const /Factory/; - /** Returns copy of rgb array (caller takes ownership) - @note not available in python bindings - */ - // QRgb* rgbArray() const; - /** Return optional category label * @note added in 2.1 */ QString label( int idx ) const; diff --git a/src/core/raster/qgspalettedrasterrenderer.cpp b/src/core/raster/qgspalettedrasterrenderer.cpp index 24a0f4fe532..2aa9f438132 100644 --- a/src/core/raster/qgspalettedrasterrenderer.cpp +++ b/src/core/raster/qgspalettedrasterrenderer.cpp @@ -18,6 +18,7 @@ #include "qgspalettedrasterrenderer.h" #include "qgsrastertransparency.h" #include "qgsrasterviewport.h" + #include #include #include @@ -31,7 +32,7 @@ QgsPalettedRasterRenderer::QgsPalettedRasterRenderer( QgsRasterInterface* input, mColors = new QRgb[nColors]; for ( int i = 0; i < nColors; ++i ) { - mColors[i] = colorArray[i].rgba(); + mColors[i] = qPremultiply( colorArray[i].rgba() ); } delete[] colorArray; } @@ -95,7 +96,9 @@ QgsRasterRenderer* QgsPalettedRasterRenderer::create( const QDomElement& elem, Q QgsDebugMsgLevel( entryElem.attribute( "color", "#000000" ), 4 ); if ( value >= 0 && value < nColors ) { - colors[value] = QColor( entryElem.attribute( QStringLiteral( "color" ), QStringLiteral( "#000000" ) ) ).rgba(); + QColor color = QColor( entryElem.attribute( QStringLiteral( "color" ), QStringLiteral( "#000000" ) ) ); + color.setAlpha( entryElem.attribute( QStringLiteral( "alpha" ), QStringLiteral( "255" ) ).toInt() ); + colors[value] = qPremultiply( color.rgba() ); QString label = entryElem.attribute( QStringLiteral( "label" ) ); if ( !label.isEmpty() ) { @@ -123,7 +126,7 @@ QColor* QgsPalettedRasterRenderer::colors() const QColor* colorArray = new QColor[ mNColors ]; for ( int i = 0; i < mNColors; ++i ) { - colorArray[i] = QColor( mColors[i] ); + colorArray[i] = QColor::fromRgba( qUnpremultiply( mColors[i] ) ); } return colorArray; } @@ -172,6 +175,7 @@ QgsRasterBlock * QgsPalettedRasterRenderer::block( int bandNo, QgsRectangle con //rendering is faster without considering user-defined transparency bool hasTransparency = usesTransparency(); + QgsRasterBlock *alphaBlock = nullptr; if ( mAlphaBand > 0 && mAlphaBand != mBand ) @@ -211,6 +215,7 @@ QgsRasterBlock * QgsPalettedRasterRenderer::block( int bandNo, QgsRectangle con continue; } int val = ( int ) inputBlock->value( i ); + if ( !hasTransparency ) { outputData[i] = mColors[val]; @@ -226,8 +231,9 @@ QgsRasterBlock * QgsPalettedRasterRenderer::block( int bandNo, QgsRectangle con { currentOpacity *= alphaBlock->value( i ) / 255.0; } - QColor currentColor = QColor( mColors[val] ); - outputData[i] = qRgba( currentOpacity * currentColor.red(), currentOpacity * currentColor.green(), currentOpacity * currentColor.blue(), currentOpacity * 255 ); + + QRgb c = mColors[val]; + outputData[i] = qRgba( currentOpacity * qRed( c ), currentOpacity * qGreen( c ), currentOpacity * qBlue( c ), currentOpacity * qAlpha( c ) ); } } @@ -254,9 +260,11 @@ void QgsPalettedRasterRenderer::writeXml( QDomDocument& doc, QDomElement& parent QDomElement colorPaletteElem = doc.createElement( QStringLiteral( "colorPalette" ) ); for ( int i = 0; i < mNColors; ++i ) { + QColor color = QColor::fromRgba( qUnpremultiply( mColors[i] ) ); QDomElement colorElem = doc.createElement( QStringLiteral( "paletteEntry" ) ); colorElem.setAttribute( QStringLiteral( "value" ), i ); - colorElem.setAttribute( QStringLiteral( "color" ), QColor( mColors[i] ).name() ); + colorElem.setAttribute( QStringLiteral( "color" ), color.name() ); + colorElem.setAttribute( QStringLiteral( "alpha" ), color.alpha() ); if ( !label( i ).isEmpty() ) { colorElem.setAttribute( QStringLiteral( "label" ), label( i ) ); @@ -273,7 +281,7 @@ void QgsPalettedRasterRenderer::legendSymbologyItems( QList< QPair< QString, QCo for ( int i = 0; i < mNColors; ++i ) { QString lab = label( i ).isEmpty() ? QString::number( i ) : label( i ); - symbolItems.push_back( qMakePair( lab, QColor( mColors[i] ) ) ); + symbolItems.push_back( qMakePair( lab, QColor::fromRgba( qUnpremultiply( mColors[i] ) ) ) ); } } diff --git a/src/core/raster/qgspalettedrasterrenderer.h b/src/core/raster/qgspalettedrasterrenderer.h index 272dc54aa28..e28f8b3858f 100644 --- a/src/core/raster/qgspalettedrasterrenderer.h +++ b/src/core/raster/qgspalettedrasterrenderer.h @@ -31,6 +31,7 @@ class QDomElement; class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer { public: + //! Renderer owns color array QgsPalettedRasterRenderer( QgsRasterInterface* input, int bandNumber, QColor* colorArray, int nColors, const QVector& labels = QVector() ); QgsPalettedRasterRenderer( QgsRasterInterface* input, int bandNumber, QRgb* colorArray, int nColors, const QVector& labels = QVector() ); @@ -45,11 +46,6 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer //! Returns copy of color array (caller takes ownership) QColor* colors() const; - /** Returns copy of rgb array (caller takes ownership) - @note not available in python bindings - */ - QRgb* rgbArray() const; - /** Return optional category label * @note added in 2.1 */ QString label( int idx ) const { return mLabels.value( idx ); } @@ -65,8 +61,13 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer QList usesBands() const override; private: + + /** Returns copy of premultiplied rgb array (caller takes ownership) + */ + QRgb* rgbArray() const; + int mBand; - //! Color array + //! Premultiplied color array QRgb* mColors; //! Number of colors int mNColors; diff --git a/src/gui/raster/qgspalettedrendererwidget.cpp b/src/gui/raster/qgspalettedrendererwidget.cpp index f9db622e42f..9c3b3e50e30 100644 --- a/src/gui/raster/qgspalettedrendererwidget.cpp +++ b/src/gui/raster/qgspalettedrendererwidget.cpp @@ -31,6 +31,7 @@ QgsPalettedRendererWidget::QgsPalettedRendererWidget( QgsRasterLayer* layer, con contextMenu = new QMenu( tr( "Options" ), this ); contextMenu->addAction( tr( "Change color" ), this, SLOT( changeColor() ) ); + contextMenu->addAction( tr( "Change transparency" ), this, SLOT( changeTransparency() ) ); mTreeWidget->setColumnWidth( ColorColumn, 50 ); mTreeWidget->setContextMenuPolicy( Qt::CustomContextMenu ); @@ -87,7 +88,7 @@ void QgsPalettedRendererWidget::on_mTreeWidget_itemDoubleClicked( QTreeWidgetIte if ( column == ColorColumn && item ) //change item color { item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable ); - QColor c = QgsColorDialog::getColor( item->background( column ).color(), nullptr ); + QColor c = QgsColorDialog::getColor( item->background( column ).color(), this, QStringLiteral( "Change color" ), true ); if ( c.isValid() ) { item->setBackground( column, QBrush( c ) ); @@ -167,3 +168,29 @@ void QgsPalettedRendererWidget::changeColor() emit widgetChanged(); } } + +void QgsPalettedRendererWidget::changeTransparency() +{ + QList itemList; + itemList = mTreeWidget->selectedItems(); + if ( itemList.isEmpty() ) + { + return; + } + QTreeWidgetItem* firstItem = itemList.first(); + + bool ok; + double oldTransparency = ( firstItem->background( ColorColumn ).color().alpha() / 255.0 ) * 100.0; + double transparency = QInputDialog::getDouble( this, tr( "Transparency" ), tr( "Change color transparency [%]" ), oldTransparency, 0.0, 100.0, 0, &ok ); + if ( ok ) + { + int newTransparency = transparency / 100 * 255; + Q_FOREACH ( QTreeWidgetItem *item, itemList ) + { + QColor newColor = item->background( ColorColumn ).color(); + newColor.setAlpha( newTransparency ); + item->setBackground( ColorColumn, QBrush( newColor ) ); + } + emit widgetChanged(); + } +} diff --git a/src/gui/raster/qgspalettedrendererwidget.h b/src/gui/raster/qgspalettedrendererwidget.h index 59c4db8846d..ac3ce13a332 100644 --- a/src/gui/raster/qgspalettedrendererwidget.h +++ b/src/gui/raster/qgspalettedrendererwidget.h @@ -56,6 +56,7 @@ class GUI_EXPORT QgsPalettedRendererWidget: public QgsRasterRendererWidget, priv void on_mTreeWidget_itemDoubleClicked( QTreeWidgetItem * item, int column ); void on_mTreeWidget_itemChanged( QTreeWidgetItem * item, int column ); void changeColor(); + void changeTransparency(); }; #endif // QGSPALETTEDRENDERERWIDGET_H diff --git a/src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp b/src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp index 98303f07ccb..aca67759fec 100644 --- a/src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp +++ b/src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp @@ -982,7 +982,7 @@ void QgsSingleBandPseudoColorRendererWidget::changeTransparency() bool ok; double oldTransparency = firstItem->background( ColorColumn ).color().alpha() / 255 * 100; - double transparency = QInputDialog::getDouble( this, tr( "Transparency" ), tr( "Change symbol transparency [%]" ), oldTransparency, 0.0, 100.0, 0, &ok ); + double transparency = QInputDialog::getDouble( this, tr( "Transparency" ), tr( "Change color transparency [%]" ), oldTransparency, 0.0, 100.0, 0, &ok ); if ( ok ) { int newTransparency = transparency / 100 * 255;