QGIS API Documentation  master-28efcda
src/core/raster/qgssinglebandpseudocolorrenderer.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines