27 #include <QDomDocument> 
   28 #include <QDomElement> 
   34 const int QgsPalettedRasterRenderer::MAX_FLOAT_CLASSES = 65536;
 
   39   , mClassData( classes )
 
   47   if ( mSourceColorRamp )
 
   61   int bandNumber = elem.attribute( QStringLiteral( 
"band" ), QStringLiteral( 
"-1" ) ).toInt();
 
   64   QDomElement paletteElem = elem.firstChildElement( QStringLiteral( 
"colorPalette" ) );
 
   65   if ( !paletteElem.isNull() )
 
   67     QDomNodeList paletteEntries = paletteElem.elementsByTagName( QStringLiteral( 
"paletteEntry" ) );
 
   69     QDomElement entryElem;
 
   72     for ( 
int i = 0; i < paletteEntries.size(); ++i )
 
   76       entryElem = paletteEntries.at( i ).toElement();
 
   77       value = entryElem.attribute( QStringLiteral( 
"value" ), QStringLiteral( 
"0" ) ).toDouble();
 
   78       color = QColor( entryElem.attribute( QStringLiteral( 
"color" ), QStringLiteral( 
"#000000" ) ) );
 
   79       color.setAlpha( entryElem.attribute( QStringLiteral( 
"alpha" ), QStringLiteral( 
"255" ) ).toInt() );
 
   80       label = entryElem.attribute( QStringLiteral( 
"label" ) );
 
   81       QgsDebugMsgLevel( QStringLiteral( 
"Value: %1, label: %2, color: %3" ).arg( value ).arg( 
label, entryElem.attribute( QStringLiteral( 
"color" ) ) ), 4 );
 
   90   QDomElement sourceColorRampElem = elem.firstChildElement( QStringLiteral( 
"colorramp" ) );
 
   91   if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( QStringLiteral( 
"name" ) ) == QLatin1String( 
"[source]" ) )
 
  106   const auto constMClassData = mClassData;
 
  107   for ( 
const Class &
c : constMClassData )
 
  109     if ( 
c.value == idx )
 
  118   ClassData::iterator cIt = mClassData.begin();
 
  119   for ( ; cIt != mClassData.end(); ++cIt )
 
  121     if ( cIt->value == idx )
 
  131   std::unique_ptr< QgsRasterBlock > outputBlock( 
new QgsRasterBlock() );
 
  132   if ( !
mInput || mClassData.isEmpty() )
 
  134     return outputBlock.release();
 
  137   std::shared_ptr< QgsRasterBlock > inputBlock( 
mInput->
block( mBand, 
extent, width, height, feedback ) );
 
  139   if ( !inputBlock || inputBlock->isEmpty() )
 
  141     QgsDebugMsg( QStringLiteral( 
"No raster data!" ) );
 
  142     return outputBlock.release();
 
  150   std::shared_ptr< QgsRasterBlock > alphaBlock;
 
  155     if ( !alphaBlock || alphaBlock->isEmpty() )
 
  157       return outputBlock.release();
 
  162     alphaBlock = inputBlock;
 
  167     return outputBlock.release();
 
  174   Q_ASSERT( outputBlock ); 
 
  175   unsigned int *outputData = ( 
unsigned int * )( outputBlock->bits() );
 
  178   bool isNoData = 
false;
 
  179   for ( 
qgssize i = 0; i < rasterSize; ++i )
 
  181     const double value = inputBlock->valueAndNoData( i, isNoData );
 
  184       outputData[i] = myDefaultColor;
 
  187     if ( !mColors.contains( value ) )
 
  189       outputData[i] = myDefaultColor;
 
  193     if ( !hasTransparency )
 
  195       outputData[i] = mColors.value( value );
 
  206         currentOpacity *= alphaBlock->value( i ) / 255.0;
 
  209       QRgb 
c = mColors.value( value );
 
  210       outputData[i] = qRgba( currentOpacity * qRed( 
c ), currentOpacity * qGreen( 
c ), currentOpacity * qBlue( 
c ), currentOpacity * qAlpha( 
c ) );
 
  214   return outputBlock.release();
 
  219   if ( parentElem.isNull() )
 
  224   QDomElement rasterRendererElem = doc.createElement( QStringLiteral( 
"rasterrenderer" ) );
 
  227   rasterRendererElem.setAttribute( QStringLiteral( 
"band" ), mBand );
 
  228   QDomElement colorPaletteElem = doc.createElement( QStringLiteral( 
"colorPalette" ) );
 
  229   ClassData::const_iterator it = mClassData.constBegin();
 
  230   for ( ; it != mClassData.constEnd(); ++it )
 
  232     QColor color = it->color;
 
  233     QDomElement colorElem = doc.createElement( QStringLiteral( 
"paletteEntry" ) );
 
  234     colorElem.setAttribute( QStringLiteral( 
"value" ), it->value );
 
  235     colorElem.setAttribute( QStringLiteral( 
"color" ), color.name() );
 
  236     colorElem.setAttribute( QStringLiteral( 
"alpha" ), color.alpha() );
 
  237     if ( !it->label.isEmpty() )
 
  239       colorElem.setAttribute( QStringLiteral( 
"label" ), it->label );
 
  241     colorPaletteElem.appendChild( colorElem );
 
  243   rasterRendererElem.appendChild( colorPaletteElem );
 
  246   if ( mSourceColorRamp )
 
  249     rasterRendererElem.appendChild( colorRampElem );
 
  252   parentElem.appendChild( rasterRendererElem );
 
  261   QDomNodeList elements = element.elementsByTagName( QStringLiteral( 
"sld:RasterSymbolizer" ) );
 
  262   if ( elements.size() == 0 )
 
  266   QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
 
  269   QDomElement channelSelectionElem = doc.createElement( QStringLiteral( 
"sld:ChannelSelection" ) );
 
  270   rasterSymbolizerElem.appendChild( channelSelectionElem );
 
  273   QDomElement channelElem = doc.createElement( QStringLiteral( 
"sld:GrayChannel" ) );
 
  274   channelSelectionElem.appendChild( channelElem );
 
  277   QDomElement sourceChannelNameElem = doc.createElement( QStringLiteral( 
"sld:SourceChannelName" ) );
 
  278   sourceChannelNameElem.appendChild( doc.createTextNode( QString::number( 
band() ) ) );
 
  279   channelElem.appendChild( sourceChannelNameElem );
 
  282   QDomElement colorMapElem = doc.createElement( QStringLiteral( 
"sld:ColorMap" ) );
 
  283   colorMapElem.setAttribute( QStringLiteral( 
"type" ), QStringLiteral( 
"values" ) );
 
  284   if ( this->
classes().size() >= 255 )
 
  285     colorMapElem.setAttribute( QStringLiteral( 
"extended" ), QStringLiteral( 
"true" ) );
 
  286   rasterSymbolizerElem.appendChild( colorMapElem );
 
  290   QList<QgsPalettedRasterRenderer::Class> 
classes = this->
classes();
 
  291   QList<QgsPalettedRasterRenderer::Class>::const_iterator classDataIt = 
classes.constBegin();
 
  292   for ( ; classDataIt != 
classes.constEnd();  ++classDataIt )
 
  294     QDomElement colorMapEntryElem = doc.createElement( QStringLiteral( 
"sld:ColorMapEntry" ) );
 
  295     colorMapElem.appendChild( colorMapEntryElem );
 
  298     colorMapEntryElem.setAttribute( QStringLiteral( 
"color" ), classDataIt->color.name() );
 
  299     colorMapEntryElem.setAttribute( QStringLiteral( 
"quantity" ), QString::number( classDataIt->value ) );
 
  300     colorMapEntryElem.setAttribute( QStringLiteral( 
"label" ), classDataIt->label );
 
  301     if ( classDataIt->color.alphaF() != 1.0 )
 
  303       colorMapEntryElem.setAttribute( QStringLiteral( 
"opacity" ), QString::number( classDataIt->color.alphaF() ) );
 
  310   if ( mSourceColorRamp )
 
  322   ClassData::const_iterator it = mClassData.constBegin();
 
  323   for ( ; it != mClassData.constEnd(); ++it )
 
  325     QString lab = it->label.isEmpty() ? QString::number( it->value ) : it->label;
 
  326     symbolItems << qMakePair( lab, it->color );
 
  342   mSourceColorRamp.reset( ramp );
 
  347   return mSourceColorRamp.get();
 
  352   QList<QgsColorRampShader::ColorRampItem>::const_iterator colorIt = table.constBegin();
 
  354   for ( ; colorIt != table.constEnd(); ++colorIt )
 
  356     int idx = ( int )( colorIt->value );
 
  366   QRegularExpression linePartRx( QStringLiteral( 
"[\\s,:]+" ) );
 
  368   QStringList parts = 
string.split( 
'\n', QString::SkipEmptyParts );
 
  369   const auto constParts = parts;
 
  370   for ( 
const QString &part : constParts )
 
  372     QStringList lineParts = part.split( linePartRx, QString::SkipEmptyParts );
 
  374     switch ( lineParts.count() )
 
  378         int value = lineParts.at( 0 ).toInt( &ok );
 
  388         int value = lineParts.at( 0 ).toInt( &ok );
 
  392         QColor 
c( lineParts.at( 1 ) );
 
  400         if ( lineParts.count() < 4 )
 
  403         int value = lineParts.at( 0 ).toInt( &ok );
 
  408         double r = lineParts.at( 1 ).toDouble( &rOk );
 
  410         double g = lineParts.at( 2 ).toDouble( &gOk );
 
  412         double b = lineParts.at( 3 ).toDouble( &bOk );
 
  415         if ( rOk && gOk && bOk )
 
  417           c = QColor( r, g, b );
 
  420         if ( lineParts.count() >= 5 )
 
  422           double alpha = lineParts.at( 4 ).toDouble( &ok );
 
  428         if ( lineParts.count() > 5 )
 
  430           label = lineParts.mid( 5 ).join( 
' ' );
 
  444   QFile inputFile( path );
 
  446   if ( inputFile.open( QIODevice::ReadOnly ) )
 
  448     QTextStream in( &inputFile );
 
  449     input = in.readAll();
 
  460   std::sort( cd.begin(), cd.end(), []( 
const Class & a, 
const Class & b ) -> 
bool 
  462     return a.value < b.value;
 
  465   const auto constCd = cd;
 
  466   for ( 
const Class &
c : constCd )
 
  468     out << QStringLiteral( 
"%1 %2 %3 %4 %5 %6" ).arg( 
c.value ).arg( 
c.color.red() )
 
  469         .arg( 
c.color.green() ).arg( 
c.color.blue() ).arg( 
c.color.alpha() ).arg( 
c.label );
 
  471   return out.join( 
'\n' );
 
  480   qlonglong numClasses = 0;
 
  486   if ( raster->
dataType( bandNumber ) == Qgis::DataType::Float32 || raster->
dataType( bandNumber ) == Qgis::DataType::Float64 )
 
  494     std::set<double> values;
 
  502     int nbBlocksWidth = 
static_cast< int >( std::ceil( 1.0 * raster->
ySize() / maxWidth ) );
 
  503     int nbBlocksHeight = 
static_cast< int >( std::ceil( 1.0 * raster->
ySize() / maxHeight ) );
 
  504     int nbBlocks = nbBlocksWidth * nbBlocksHeight;
 
  510     std::unique_ptr< QgsRasterBlock > rasterBlock;
 
  512     bool isNoData = 
false;
 
  513     while ( iter.
readNextRasterPart( bandNumber, iterCols, iterRows, rasterBlock, iterLeft, iterTop, &blockExtent ) )
 
  516         feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
 
  521       for ( 
int row = 0; row < iterRows; row++ )
 
  526         for ( 
int column = 0; column < iterCols; column++ )
 
  531           const double currentValue = rasterBlock->valueAndNoData( row, column, isNoData );
 
  532           if ( numClasses >= MAX_FLOAT_CLASSES )
 
  534             QgsMessageLog::logMessage( QStringLiteral( 
"Number of classes exceeded maximum (%1)." ).arg( MAX_FLOAT_CLASSES ), QStringLiteral( 
"Raster" ) );
 
  537           if ( !isNoData && values.find( currentValue ) == values.end() )
 
  539             values.insert( currentValue );
 
  540             data.push_back( 
Class( currentValue, QColor(), QLocale().toString( currentValue ) ) );
 
  557     int bins = std::ceil( max - min ) + 1;
 
  572         data << 
Class( currentValue, QColor(), QLocale().toString( currentValue ) );
 
  575       currentValue += interval;
 
  588       randomRamp->setTotalColorCount( data.count() );
 
  591     if ( numClasses > 1 )
 
  594     QgsPalettedRasterRenderer::ClassData::iterator cIt = data.begin();
 
  595     for ( ; cIt != data.end(); ++cIt )
 
  600         feedback->
setProgress( std::max<int>( 1, 100 * ( i + 1 ) / numClasses ) );
 
  602       cIt->color = ramp->
color( i / 
static_cast<double>( numClasses ) );
 
  609 void QgsPalettedRasterRenderer::updateArrays()
 
  613   ClassData::const_iterator it = mClassData.constBegin();
 
  614   for ( ; it != mClassData.constEnd(); ++it )
 
  616     mColors[it->value] = qPremultiply( it->color.rgba() );