|
QGIS API Documentation
master-28efcda
|
00001 /*************************************************************************** 00002 qgssinglebandpseudocolorrenderer.cpp 00003 ------------------------------------ 00004 begin : January 2012 00005 copyright : (C) 2012 by Marco Hugentobler 00006 email : marco at sourcepole dot ch 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #include "qgssinglebandpseudocolorrenderer.h" 00019 #include "qgsrastershader.h" 00020 #include "qgsrastertransparency.h" 00021 #include "qgsrasterviewport.h" 00022 #include <QDomDocument> 00023 #include <QDomElement> 00024 #include <QImage> 00025 00026 QgsSingleBandPseudoColorRenderer::QgsSingleBandPseudoColorRenderer( QgsRasterInterface* input, int band, QgsRasterShader* shader ): 00027 QgsRasterRenderer( input, "singlebandpseudocolor" ) 00028 , mShader( shader ) 00029 , mBand( band ) 00030 , mClassificationMin( std::numeric_limits<double>::quiet_NaN() ) 00031 , mClassificationMax( std::numeric_limits<double>::quiet_NaN() ) 00032 , mClassificationMinMaxOrigin( QgsRasterRenderer::MinMaxUnknown ) 00033 { 00034 } 00035 00036 QgsSingleBandPseudoColorRenderer::~QgsSingleBandPseudoColorRenderer() 00037 { 00038 delete mShader; 00039 } 00040 00041 QgsRasterInterface * QgsSingleBandPseudoColorRenderer::clone() const 00042 { 00043 QgsRasterShader *shader = 0; 00044 00045 if ( mShader ) 00046 { 00047 shader = new QgsRasterShader( mShader->minimumValue(), mShader->maximumValue() ); 00048 00049 // Shader function 00050 const QgsColorRampShader* origColorRampShader = dynamic_cast<const QgsColorRampShader*>( mShader->rasterShaderFunction() ); 00051 00052 if ( origColorRampShader ) 00053 { 00054 QgsColorRampShader * colorRampShader = new QgsColorRampShader( mShader->minimumValue(), mShader->maximumValue() ); 00055 00056 colorRampShader->setColorRampType( origColorRampShader->colorRampType() ); 00057 00058 colorRampShader->setColorRampItemList( origColorRampShader->colorRampItemList() ); 00059 shader->setRasterShaderFunction( colorRampShader ); 00060 } 00061 } 00062 QgsSingleBandPseudoColorRenderer * renderer = new QgsSingleBandPseudoColorRenderer( 0, mBand, shader ); 00063 00064 renderer->setOpacity( mOpacity ); 00065 renderer->setAlphaBand( mAlphaBand ); 00066 renderer->setRasterTransparency( mRasterTransparency ); 00067 00068 return renderer; 00069 } 00070 00071 void QgsSingleBandPseudoColorRenderer::setShader( QgsRasterShader* shader ) 00072 { 00073 delete mShader; 00074 mShader = shader; 00075 } 00076 00077 QgsRasterRenderer* QgsSingleBandPseudoColorRenderer::create( const QDomElement& elem, QgsRasterInterface* input ) 00078 { 00079 if ( elem.isNull() ) 00080 { 00081 return 0; 00082 } 00083 00084 int band = elem.attribute( "band", "-1" ).toInt(); 00085 QgsRasterShader* shader = 0; 00086 QDomElement rasterShaderElem = elem.firstChildElement( "rastershader" ); 00087 if ( !rasterShaderElem.isNull() ) 00088 { 00089 shader = new QgsRasterShader(); 00090 shader->readXML( rasterShaderElem ); 00091 } 00092 00093 QgsSingleBandPseudoColorRenderer* r = new QgsSingleBandPseudoColorRenderer( input, band, shader ); 00094 r->readXML( elem ); 00095 00096 // TODO: add _readXML in superclass? 00097 r->setClassificationMin( elem.attribute( "classificationMin", "NaN" ).toDouble() ); 00098 r->setClassificationMax( elem.attribute( "classificationMax", "NaN" ).toDouble() ); 00099 r->setClassificationMinMaxOrigin( QgsRasterRenderer::minMaxOriginFromName( elem.attribute( "classificationMinMaxOrigin", "Unknown" ) ) ); 00100 00101 return r; 00102 } 00103 00104 QgsRasterBlock* QgsSingleBandPseudoColorRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height ) 00105 { 00106 Q_UNUSED( bandNo ); 00107 00108 QgsRasterBlock *outputBlock = new QgsRasterBlock(); 00109 if ( !mInput || !mShader ) 00110 { 00111 return outputBlock; 00112 } 00113 00114 00115 QgsRasterBlock *inputBlock = mInput->block( mBand, extent, width, height ); 00116 if ( !inputBlock || inputBlock->isEmpty() ) 00117 { 00118 QgsDebugMsg( "No raster data!" ); 00119 delete inputBlock; 00120 return outputBlock; 00121 } 00122 00123 //rendering is faster without considering user-defined transparency 00124 bool hasTransparency = usesTransparency(); 00125 00126 QgsRasterBlock *alphaBlock = 0; 00127 if ( mAlphaBand > 0 && mAlphaBand != mBand ) 00128 { 00129 alphaBlock = mInput->block( mAlphaBand, extent, width, height ); 00130 if ( !alphaBlock || alphaBlock->isEmpty() ) 00131 { 00132 delete inputBlock; 00133 delete alphaBlock; 00134 return outputBlock; 00135 } 00136 } 00137 else if ( mAlphaBand == mBand ) 00138 { 00139 alphaBlock = inputBlock; 00140 } 00141 00142 if ( !outputBlock->reset( QGis::ARGB32_Premultiplied, width, height ) ) 00143 { 00144 delete inputBlock; 00145 delete alphaBlock; 00146 return outputBlock; 00147 } 00148 00149 QRgb myDefaultColor = NODATA_COLOR; 00150 00151 for ( size_t i = 0; i < ( size_t )width*height; i++ ) 00152 { 00153 if ( inputBlock->isNoData( i ) ) 00154 { 00155 outputBlock->setColor( i, myDefaultColor ); 00156 continue; 00157 } 00158 double val = inputBlock->value( i ); 00159 int red, green, blue, alpha; 00160 if ( !mShader->shade( val, &red, &green, &blue, &alpha ) ) 00161 { 00162 outputBlock->setColor( i, myDefaultColor ); 00163 continue; 00164 } 00165 00166 if ( alpha < 255 ) 00167 { 00168 // Working with premultiplied colors, so multiply values by alpha 00169 red *= ( alpha / 255.0 ); 00170 blue *= ( alpha / 255.0 ); 00171 green *= ( alpha / 255.0 ); 00172 } 00173 00174 if ( !hasTransparency ) 00175 { 00176 outputBlock->setColor( i, qRgba( red, green, blue, alpha ) ); 00177 } 00178 else 00179 { 00180 //opacity 00181 double currentOpacity = mOpacity; 00182 if ( mRasterTransparency ) 00183 { 00184 currentOpacity = mRasterTransparency->alphaValue( val, mOpacity * 255 ) / 255.0; 00185 } 00186 if ( mAlphaBand > 0 ) 00187 { 00188 currentOpacity *= alphaBlock->value( i ) / 255.0; 00189 } 00190 00191 outputBlock->setColor( i, qRgba( currentOpacity * red, currentOpacity * green, currentOpacity * blue, currentOpacity * alpha ) ); 00192 } 00193 } 00194 00195 delete inputBlock; 00196 if ( mAlphaBand > 0 && mBand != mAlphaBand ) 00197 { 00198 delete alphaBlock; 00199 } 00200 00201 return outputBlock; 00202 } 00203 00204 void QgsSingleBandPseudoColorRenderer::writeXML( QDomDocument& doc, QDomElement& parentElem ) const 00205 { 00206 if ( parentElem.isNull() ) 00207 { 00208 return; 00209 } 00210 00211 QDomElement rasterRendererElem = doc.createElement( "rasterrenderer" ); 00212 _writeXML( doc, rasterRendererElem ); 00213 rasterRendererElem.setAttribute( "band", mBand ); 00214 if ( mShader ) 00215 { 00216 mShader->writeXML( doc, rasterRendererElem ); //todo: include color ramp items directly in this renderer 00217 } 00218 rasterRendererElem.setAttribute( "classificationMin", QString::number( mClassificationMin ) ); 00219 rasterRendererElem.setAttribute( "classificationMax", QString::number( mClassificationMax ) ); 00220 rasterRendererElem.setAttribute( "classificationMinMaxOrigin", QgsRasterRenderer::minMaxOriginName( mClassificationMinMaxOrigin ) ); 00221 00222 parentElem.appendChild( rasterRendererElem ); 00223 } 00224 00225 void QgsSingleBandPseudoColorRenderer::legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const 00226 { 00227 if ( mShader ) 00228 { 00229 QgsRasterShaderFunction* shaderFunction = mShader->rasterShaderFunction(); 00230 if ( shaderFunction ) 00231 { 00232 shaderFunction->legendSymbologyItems( symbolItems ); 00233 } 00234 } 00235 } 00236 00237 QList<int> QgsSingleBandPseudoColorRenderer::usesBands() const 00238 { 00239 QList<int> bandList; 00240 if ( mBand != -1 ) 00241 { 00242 bandList << mBand; 00243 } 00244 return bandList; 00245 }