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() );