23 QString QgsRasterLayerUniqueValuesReportAlgorithm::name()
 const 
   25   return QStringLiteral( 
"rasterlayeruniquevaluesreport" );
 
   28 QString QgsRasterLayerUniqueValuesReportAlgorithm::displayName()
 const 
   30   return QObject::tr( 
"Raster layer unique values report" );
 
   33 QStringList QgsRasterLayerUniqueValuesReportAlgorithm::tags()
 const 
   35   return QObject::tr( 
"count,area,statistics" ).split( 
',' );
 
   38 QString QgsRasterLayerUniqueValuesReportAlgorithm::group()
 const 
   40   return QObject::tr( 
"Raster analysis" );
 
   43 QString QgsRasterLayerUniqueValuesReportAlgorithm::groupId()
 const 
   45   return QStringLiteral( 
"rasteranalysis" );
 
   48 void QgsRasterLayerUniqueValuesReportAlgorithm::initAlgorithm( 
const QVariantMap & )
 
   51                 QObject::tr( 
"Input layer" ) ) );
 
   53                 QObject::tr( 
"Band number" ), 1, QStringLiteral( 
"INPUT" ) ) );
 
   55                 QObject::tr( 
"Unique values report" ), QObject::tr( 
"HTML files (*.html)" ), QVariant(), 
true ) );
 
   64   addOutput( 
new QgsProcessingOutputNumber( QStringLiteral( 
"NODATA_PIXEL_COUNT" ), QObject::tr( 
"NODATA pixel count" ) ) );
 
   67 QString QgsRasterLayerUniqueValuesReportAlgorithm::shortHelpString()
 const 
   69   return QObject::tr( 
"This algorithm returns the count and area of each unique value in a given raster layer." );
 
   72 QgsRasterLayerUniqueValuesReportAlgorithm *QgsRasterLayerUniqueValuesReportAlgorithm::createInstance()
 const 
   74   return new QgsRasterLayerUniqueValuesReportAlgorithm();
 
   79   QgsRasterLayer *layer = parameterAsRasterLayer( parameters, QStringLiteral( 
"INPUT" ), context );
 
   80   int band = parameterAsInt( parameters, QStringLiteral( 
"BAND" ), context );
 
   85   mBand = parameterAsInt( parameters, QStringLiteral( 
"BAND" ), context );
 
   86   if ( mBand < 1 || mBand > layer->
bandCount() )
 
   87     throw QgsProcessingException( QObject::tr( 
"Invalid band number for BAND (%1): Valid values for input raster are 1 to %2" ).arg( mBand )
 
   92   mLayerWidth = layer->
width();
 
   93   mLayerHeight = layer->
height();
 
  105   QString outputFile = parameterAsFileOutput( parameters, QStringLiteral( 
"OUTPUT_HTML_FILE" ), context );
 
  110   std::unique_ptr< QgsFeatureSink > sink;
 
  111   if ( parameters.contains( QStringLiteral( 
"OUTPUT_TABLE" ) ) && parameters.value( QStringLiteral( 
"OUTPUT_TABLE" ) ).isValid() )
 
  114     outFields.
append( 
QgsField( QStringLiteral( 
"value" ), QVariant::Double, QString(), 20, 8 ) );
 
  115     outFields.
append( 
QgsField( QStringLiteral( 
"count" ), QVariant::Int, QString(), 20 ) );
 
  116     outFields.
append( 
QgsField( areaUnit.replace( QStringLiteral( 
"²" ), QStringLiteral( 
"2" ) ), QVariant::Double, QString(), 20, 8 ) );
 
  122   QHash< double, qgssize > uniqueValues;
 
  128   int nbBlocksWidth = std::ceil( 1.0 * mLayerWidth / maxWidth );
 
  129   int nbBlocksHeight = std::ceil( 1.0 * mLayerHeight / maxHeight );
 
  130   int nbBlocks = nbBlocksWidth * nbBlocksHeight;
 
  133   iter.startRasterRead( mBand, mLayerWidth, mLayerHeight, mExtent );
 
  139   bool isNoData = 
false;
 
  140   std::unique_ptr< QgsRasterBlock > rasterBlock;
 
  141   while ( iter.readNextRasterPart( mBand, iterCols, iterRows, rasterBlock, iterLeft, iterTop ) )
 
  143     feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
 
  144     for ( 
int row = 0; row < iterRows; row++ )
 
  148       for ( 
int column = 0; column < iterCols; column++ )
 
  150         double value = rasterBlock->valueAndNoData( row, column, isNoData );
 
  151         if ( mHasNoDataValue && isNoData )
 
  157           uniqueValues[ value ]++;
 
  163   QMap< double, qgssize > sortedUniqueValues;
 
  164   for ( 
auto it = uniqueValues.constBegin(); it != uniqueValues.constEnd(); ++it )
 
  166     sortedUniqueValues.insert( it.key(), it.value() );
 
  170   outputs.insert( QStringLiteral( 
"EXTENT" ), mExtent.toString() );
 
  171   outputs.insert( QStringLiteral( 
"CRS_AUTHID" ), mCrs.authid() );
 
  172   outputs.insert( QStringLiteral( 
"WIDTH_IN_PIXELS" ), mLayerWidth );
 
  173   outputs.insert( QStringLiteral( 
"HEIGHT_IN_PIXELS" ), mLayerHeight );
 
  174   outputs.insert( QStringLiteral( 
"TOTAL_PIXEL_COUNT" ), layerSize );
 
  175   outputs.insert( QStringLiteral( 
"NODATA_PIXEL_COUNT" ), noDataCount );
 
  177   double pixelArea = mRasterUnitsPerPixelX * mRasterUnitsPerPixelY;
 
  179   if ( !outputFile.isEmpty() )
 
  181     QFile file( outputFile );
 
  182     if ( file.open( QIODevice::WriteOnly | QIODevice::Text ) )
 
  186       QTextStream out( &file );
 
  187       out << QStringLiteral( 
"<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"/></head><body>\n" );
 
  188       out << QStringLiteral( 
"<p>%1: %2 (%3 %4)</p>\n" ).arg( QObject::tr( 
"Analyzed file" ), mSource, QObject::tr( 
"band" ) ).arg( mBand );
 
  189       out << QObject::tr( 
"<p>%1: %2</p>\n" ).arg( QObject::tr( 
"Extent" ), mExtent.toString() );
 
  190       out << QObject::tr( 
"<p>%1: %2</p>\n" ).arg( QObject::tr( 
"Projection" ), mCrs.userFriendlyIdentifier() );
 
  191       out << QObject::tr( 
"<p>%1: %2 (%3 %4)</p>\n" ).arg( QObject::tr( 
"Width in pixels" ) ).arg( mLayerWidth ).arg( QObject::tr( 
"units per pixel" ) ).arg( mRasterUnitsPerPixelX );
 
  192       out << QObject::tr( 
"<p>%1: %2 (%3 %4)</p>\n" ).arg( QObject::tr( 
"Height in pixels" ) ).arg( mLayerHeight ).arg( QObject::tr( 
"units per pixel" ) ).arg( mRasterUnitsPerPixelY );
 
  193       out << QObject::tr( 
"<p>%1: %2</p>\n" ).arg( QObject::tr( 
"Total pixel count" ) ).arg( layerSize );
 
  194       if ( mHasNoDataValue )
 
  195         out << QObject::tr( 
"<p>%1: %2</p>\n" ).arg( QObject::tr( 
"NODATA pixel count" ) ).arg( noDataCount );
 
  196       out << QStringLiteral( 
"<table><tr><td>%1</td><td>%2</td><td>%3 (%4)</td></tr>\n" ).arg( QObject::tr( 
"Value" ), QObject::tr( 
"Pixel count" ), QObject::tr( 
"Area" ), encodedAreaUnit );
 
  198       for ( 
auto it = sortedUniqueValues.constBegin(); it != sortedUniqueValues.constEnd(); ++it )
 
  200         double area = it.value() * pixelArea;
 
  201         out << QStringLiteral( 
"<tr><td>%1</td><td>%2</td><td>%3</td></tr>\n" ).arg( it.key() ).arg( it.value() ).arg( QString::number( area, 
'g', 16 ) );
 
  203       out << QStringLiteral( 
"</table>\n</body></html>" );
 
  204       outputs.insert( QStringLiteral( 
"OUTPUT_HTML_FILE" ), outputFile );
 
  210     for ( 
auto it = sortedUniqueValues.constBegin(); it != sortedUniqueValues.constEnd(); ++it )
 
  213       double area = it.value() * pixelArea;
 
  217     outputs.insert( QStringLiteral( 
"OUTPUT_TABLE" ), tableDest );