|
QGIS API Documentation
master-59fd5e0
|
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 }