1 /***************************************************************************
2 qgssinglebandcolordatarenderer.cpp
3 ----------------------------------
4 begin : January 2012
5 copyright : (C) 2012 by Marco Hugentobler
6 email : marco at sourcepole dot ch
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "qgssinglebandcolordatarenderer.h"
19 #include "qgsrastertransparency.h"
20 #include "qgsrasterviewport.h"
21 #include <QDomDocument>
22 #include <QDomElement>
23 #include <QImage>
24 #include <memory>
25
QgsSingleBandColorDataRenderer(QgsRasterInterface * input,int band)26 QgsSingleBandColorDataRenderer::QgsSingleBandColorDataRenderer( QgsRasterInterface *input, int band ):
27 QgsRasterRenderer( input, QStringLiteral( "singlebandcolordata" ) ), mBand( band )
28 {
29
30 }
31
clone() const32 QgsSingleBandColorDataRenderer *QgsSingleBandColorDataRenderer::clone() const
33 {
34 QgsSingleBandColorDataRenderer *renderer = new QgsSingleBandColorDataRenderer( nullptr, mBand );
35 renderer->copyCommonProperties( this );
36 return renderer;
37 }
38
create(const QDomElement & elem,QgsRasterInterface * input)39 QgsRasterRenderer *QgsSingleBandColorDataRenderer::create( const QDomElement &elem, QgsRasterInterface *input )
40 {
41 if ( elem.isNull() )
42 {
43 return nullptr;
44 }
45
46 int band = elem.attribute( QStringLiteral( "band" ), QStringLiteral( "-1" ) ).toInt();
47 QgsRasterRenderer *r = new QgsSingleBandColorDataRenderer( input, band );
48 r->readXml( elem );
49 return r;
50 }
51
block(int bandNo,QgsRectangle const & extent,int width,int height,QgsRasterBlockFeedback * feedback)52 QgsRasterBlock *QgsSingleBandColorDataRenderer::block( int bandNo, QgsRectangle const &extent, int width, int height, QgsRasterBlockFeedback *feedback )
53 {
54 Q_UNUSED( bandNo )
55
56 std::unique_ptr< QgsRasterBlock > outputBlock( new QgsRasterBlock() );
57 if ( !mInput )
58 {
59 return outputBlock.release();
60 }
61
62 std::unique_ptr< QgsRasterBlock > inputBlock( mInput->block( mBand, extent, width, height, feedback ) );
63 if ( !inputBlock || inputBlock->isEmpty() )
64 {
65 QgsDebugMsg( QStringLiteral( "No raster data!" ) );
66 return outputBlock.release();
67 }
68
69 bool hasTransparency = usesTransparency();
70 if ( !hasTransparency )
71 {
72 // Nothing to do, just retype if necessary
73 inputBlock->convert( Qgis::ARGB32_Premultiplied );
74 return inputBlock.release();
75 }
76
77 if ( !outputBlock->reset( Qgis::ARGB32_Premultiplied, width, height ) )
78 {
79 return outputBlock.release();
80 }
81
82 // make sure input is also premultiplied!
83 inputBlock->convert( Qgis::ARGB32_Premultiplied );
84
85 QRgb *inputBits = ( QRgb * )inputBlock->bits();
86 QRgb *outputBits = ( QRgb * )outputBlock->bits();
87 for ( qgssize i = 0; i < ( qgssize )width * height; i++ )
88 {
89 QRgb c = inputBits[i];
90 outputBits[i] = qRgba( mOpacity * qRed( c ), mOpacity * qGreen( c ), mOpacity * qBlue( c ), mOpacity * qAlpha( c ) );
91 }
92
93 return outputBlock.release();
94 }
95
writeXml(QDomDocument & doc,QDomElement & parentElem) const96 void QgsSingleBandColorDataRenderer::writeXml( QDomDocument &doc, QDomElement &parentElem ) const
97 {
98 if ( parentElem.isNull() )
99 return;
100
101 QDomElement rasterRendererElem = doc.createElement( QStringLiteral( "rasterrenderer" ) );
102 _writeXml( doc, rasterRendererElem );
103 rasterRendererElem.setAttribute( QStringLiteral( "band" ), mBand );
104 parentElem.appendChild( rasterRendererElem );
105 }
106
usesBands() const107 QList<int> QgsSingleBandColorDataRenderer::usesBands() const
108 {
109 QList<int> bandList;
110 if ( mBand != -1 )
111 {
112 bandList << mBand;
113 }
114 return bandList;
115 }
116
setInput(QgsRasterInterface * input)117 bool QgsSingleBandColorDataRenderer::setInput( QgsRasterInterface *input )
118 {
119 // Renderer can only work with numerical values in at least 1 band
120 if ( !input ) return false;
121
122 if ( !mOn )
123 {
124 // In off mode we can connect to anything
125 mInput = input;
126 return true;
127 }
128
129 if ( input->dataType( 1 ) == Qgis::ARGB32 ||
130 input->dataType( 1 ) == Qgis::ARGB32_Premultiplied )
131 {
132 mInput = input;
133 return true;
134 }
135 return false;
136 }
137