QGIS API Documentation  master-59fd5e0
src/core/raster/qgspalettedrasterrenderer.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                          qgspalettedrasterrenderer.cpp
00003                          -----------------------------
00004     begin                : December 2011
00005     copyright            : (C) 2011 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 "qgspalettedrasterrenderer.h"
00019 #include "qgsrastertransparency.h"
00020 #include "qgsrasterviewport.h"
00021 #include <QColor>
00022 #include <QDomDocument>
00023 #include <QDomElement>
00024 #include <QImage>
00025 
00026 QgsPalettedRasterRenderer::QgsPalettedRasterRenderer( QgsRasterInterface* input, int bandNumber,
00027     QColor* colorArray, int nColors ):
00028     QgsRasterRenderer( input, "paletted" ), mBand( bandNumber ), mNColors( nColors )
00029 {
00030   mColors = new QRgb[nColors];
00031   for ( int i = 0; i < nColors; ++i )
00032   {
00033     mColors[i] = colorArray[i].rgba();
00034   }
00035   delete[] colorArray;
00036 }
00037 
00038 QgsPalettedRasterRenderer::QgsPalettedRasterRenderer( QgsRasterInterface* input, int bandNumber, QRgb* colorArray, int nColors ):
00039     QgsRasterRenderer( input, "paletted" ), mBand( bandNumber ), mColors( colorArray ), mNColors( nColors )
00040 {
00041 }
00042 
00043 QgsPalettedRasterRenderer::~QgsPalettedRasterRenderer()
00044 {
00045   delete[] mColors;
00046 }
00047 
00048 QgsRasterInterface * QgsPalettedRasterRenderer::clone() const
00049 {
00050   QgsPalettedRasterRenderer * renderer = new QgsPalettedRasterRenderer( 0, mBand, rgbArray(), mNColors );
00051   renderer->setOpacity( mOpacity );
00052   renderer->setAlphaBand( mAlphaBand );
00053   renderer->setRasterTransparency( mRasterTransparency );
00054   return renderer;
00055 }
00056 
00057 QgsRasterRenderer* QgsPalettedRasterRenderer::create( const QDomElement& elem, QgsRasterInterface* input )
00058 {
00059   if ( elem.isNull() )
00060   {
00061     return 0;
00062   }
00063 
00064   int bandNumber = elem.attribute( "band", "-1" ).toInt();
00065   int nColors = 0;
00066   QRgb* colors = 0;
00067 
00068   QDomElement paletteElem = elem.firstChildElement( "colorPalette" );
00069   if ( !paletteElem.isNull() )
00070   {
00071     QDomNodeList paletteEntries = paletteElem.elementsByTagName( "paletteEntry" );
00072 
00073     QDomElement entryElem;
00074     int value;
00075     nColors = 0;
00076 
00077     // We cannot believe that data are correct, check first max value
00078     for ( int i = 0; i < paletteEntries.size(); ++i )
00079     {
00080       entryElem = paletteEntries.at( i ).toElement();
00081       // Could be written as doubles (with .0000) in old project files
00082       value = ( int )entryElem.attribute( "value", "0" ).toDouble();
00083       if ( value >= nColors && value <= 10000 ) nColors = value + 1;
00084     }
00085     QgsDebugMsg( QString( "nColors = %1" ).arg( nColors ) );
00086 
00087     colors = new QRgb[ nColors ];
00088 
00089     for ( int i = 0; i < nColors; ++i )
00090     {
00091       entryElem = paletteEntries.at( i ).toElement();
00092       value = ( int )entryElem.attribute( "value", "0" ).toDouble();
00093       QgsDebugMsg( entryElem.attribute( "color", "#000000" ) );
00094       if ( value >= 0 && value < nColors )
00095       {
00096         colors[value] = QColor( entryElem.attribute( "color", "#000000" ) ).rgba();
00097       }
00098       else
00099       {
00100         QgsDebugMsg( QString( "value %1 out of range" ).arg( value ) );
00101       }
00102     }
00103   }
00104   QgsRasterRenderer* r = new QgsPalettedRasterRenderer( input, bandNumber, colors, nColors );
00105   r->readXML( elem );
00106   return r;
00107 }
00108 
00109 QColor* QgsPalettedRasterRenderer::colors() const
00110 {
00111   if ( mNColors < 1 )
00112   {
00113     return 0;
00114   }
00115   QColor* colorArray = new QColor[ mNColors ];
00116   for ( int i = 0; i < mNColors; ++i )
00117   {
00118     colorArray[i] = QColor( mColors[i] );
00119   }
00120   return colorArray;
00121 }
00122 
00123 QRgb* QgsPalettedRasterRenderer::rgbArray() const
00124 {
00125   if ( mNColors < 1 )
00126   {
00127     return 0;
00128   }
00129   QRgb* rgbValues = new QRgb[mNColors];
00130   for ( int i = 0; i < mNColors; ++i )
00131   {
00132     rgbValues[i] = mColors[i];
00133   }
00134   return rgbValues;
00135 }
00136 
00137 QgsRasterBlock * QgsPalettedRasterRenderer::block( int bandNo, QgsRectangle  const & extent, int width, int height )
00138 {
00139   QgsRasterBlock *outputBlock = new QgsRasterBlock();
00140   if ( !mInput )
00141   {
00142     return outputBlock;
00143   }
00144 
00145   QgsRasterBlock *inputBlock = mInput->block( bandNo, extent, width, height );
00146 
00147   if ( !inputBlock || inputBlock->isEmpty() )
00148   {
00149     QgsDebugMsg( "No raster data!" );
00150     delete inputBlock;
00151     return outputBlock;
00152   }
00153 
00154   double currentOpacity = mOpacity;
00155 
00156   //rendering is faster without considering user-defined transparency
00157   bool hasTransparency = usesTransparency();
00158   QgsRasterBlock *alphaBlock = 0;
00159 
00160   if ( mAlphaBand > 0 && mAlphaBand != mBand )
00161   {
00162     alphaBlock = mInput->block( mAlphaBand, extent, width, height );
00163     if ( !alphaBlock || alphaBlock->isEmpty() )
00164     {
00165       delete inputBlock;
00166       delete alphaBlock;
00167       return outputBlock;
00168     }
00169   }
00170   else if ( mAlphaBand == mBand )
00171   {
00172     alphaBlock = inputBlock;
00173   }
00174 
00175   if ( !outputBlock->reset( QGis::ARGB32_Premultiplied, width, height ) )
00176   {
00177     delete inputBlock;
00178     delete alphaBlock;
00179     return outputBlock;
00180   }
00181 
00182   QRgb myDefaultColor = NODATA_COLOR;
00183 
00184   //use direct data access instead of QgsRasterBlock::setValue
00185   //because of performance
00186   unsigned int* outputData = ( unsigned int* )( outputBlock->bits() );
00187 
00188   size_t rasterSize = ( size_t )width * height;
00189   for ( size_t i = 0; i < rasterSize; ++i )
00190   {
00191     if ( inputBlock->isNoData( i ) )
00192     {
00193       outputData[i] = myDefaultColor;
00194       continue;
00195     }
00196     int val = ( int ) inputBlock->value( i );
00197     if ( !hasTransparency )
00198     {
00199       outputData[i] = mColors[val];
00200     }
00201     else
00202     {
00203       currentOpacity = mOpacity;
00204       if ( mRasterTransparency )
00205       {
00206         currentOpacity = mRasterTransparency->alphaValue( val, mOpacity * 255 ) / 255.0;
00207       }
00208       if ( mAlphaBand > 0 )
00209       {
00210         currentOpacity *=  alphaBlock->value( i ) / 255.0;
00211       }
00212       QColor currentColor = QColor( mColors[val] );
00213       outputData[i] = qRgba( currentOpacity * currentColor.red(), currentOpacity * currentColor.green(), currentOpacity * currentColor.blue(), currentOpacity * 255 );
00214     }
00215   }
00216 
00217   delete inputBlock;
00218   if ( mAlphaBand > 0 && mBand != mAlphaBand )
00219   {
00220     delete alphaBlock;
00221   }
00222 
00223   return outputBlock;
00224 }
00225 
00226 void QgsPalettedRasterRenderer::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
00227 {
00228   if ( parentElem.isNull() )
00229   {
00230     return;
00231   }
00232 
00233   QDomElement rasterRendererElem = doc.createElement( "rasterrenderer" );
00234   _writeXML( doc, rasterRendererElem );
00235 
00236   rasterRendererElem.setAttribute( "band", mBand );
00237   QDomElement colorPaletteElem = doc.createElement( "colorPalette" );
00238   for ( int i = 0; i < mNColors; ++i )
00239   {
00240     QDomElement colorElem = doc.createElement( "paletteEntry" );
00241     colorElem.setAttribute( "value", i );
00242     colorElem.setAttribute( "color", QColor( mColors[i] ).name() );
00243     colorPaletteElem.appendChild( colorElem );
00244   }
00245   rasterRendererElem.appendChild( colorPaletteElem );
00246 
00247   parentElem.appendChild( rasterRendererElem );
00248 }
00249 
00250 void QgsPalettedRasterRenderer::legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const
00251 {
00252   for ( int i = 0; i < mNColors; ++i )
00253   {
00254     symbolItems.push_back( qMakePair( QString::number( i ), QColor( mColors[i] ) ) );
00255   }
00256 }
00257 
00258 QList<int> QgsPalettedRasterRenderer::usesBands() const
00259 {
00260   QList<int> bandList;
00261   if ( mBand != -1 )
00262   {
00263     bandList << mBand;
00264   }
00265   return bandList;
00266 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines