26QString QgsRasterLayerUniqueValuesReportAlgorithm::name()
 const 
   28  return QStringLiteral( 
"rasterlayeruniquevaluesreport" );
 
   31QString QgsRasterLayerUniqueValuesReportAlgorithm::displayName()
 const 
   33  return QObject::tr( 
"Raster layer unique values report" );
 
   36QStringList QgsRasterLayerUniqueValuesReportAlgorithm::tags()
 const 
   38  return QObject::tr( 
"count,area,statistics" ).split( 
',' );
 
   41QString QgsRasterLayerUniqueValuesReportAlgorithm::group()
 const 
   43  return QObject::tr( 
"Raster analysis" );
 
   46QString QgsRasterLayerUniqueValuesReportAlgorithm::groupId()
 const 
   48  return QStringLiteral( 
"rasteranalysis" );
 
   51void QgsRasterLayerUniqueValuesReportAlgorithm::initAlgorithm( 
const QVariantMap & )
 
   54  addParameter( 
new QgsProcessingParameterBand( QStringLiteral( 
"BAND" ), QObject::tr( 
"Band number" ), 1, QStringLiteral( 
"INPUT" ) ) );
 
   55  addParameter( 
new QgsProcessingParameterFileDestination( QStringLiteral( 
"OUTPUT_HTML_FILE" ), QObject::tr( 
"Unique values report" ), QObject::tr( 
"HTML files (*.html)" ), QVariant(), 
true ) );
 
   63  addOutput( 
new QgsProcessingOutputNumber( QStringLiteral( 
"NODATA_PIXEL_COUNT" ), QObject::tr( 
"NoData pixel count" ) ) );
 
   66QString QgsRasterLayerUniqueValuesReportAlgorithm::shortHelpString()
 const 
   68  return QObject::tr( 
"This algorithm returns the count and area of each unique value in a given raster layer. " 
   69                      "The area calculation is done in the area unit of the layer's CRS." );
 
   72QString QgsRasterLayerUniqueValuesReportAlgorithm::shortDescription()
 const 
   74  return QObject::tr( 
"Returns the count and area of each unique value in a given raster layer." );
 
   77QgsRasterLayerUniqueValuesReportAlgorithm *QgsRasterLayerUniqueValuesReportAlgorithm::createInstance()
 const 
   79  return new QgsRasterLayerUniqueValuesReportAlgorithm();
 
   84  QgsRasterLayer *layer = parameterAsRasterLayer( parameters, QStringLiteral( 
"INPUT" ), context );
 
   85  const int band = parameterAsInt( parameters, QStringLiteral( 
"BAND" ), context );
 
   90  mBand = parameterAsInt( parameters, QStringLiteral( 
"BAND" ), context );
 
   91  if ( mBand < 1 || mBand > layer->
bandCount() )
 
   92    throw QgsProcessingException( QObject::tr( 
"Invalid band number for BAND (%1): Valid values for input raster are 1 to %2" ).arg( mBand ).arg( layer->
bandCount() ) );
 
   96  mLayerWidth = layer->
width();
 
   97  mLayerHeight = layer->
height();
 
  102  mSource = layer->
source();
 
  109  const QString outputFile = parameterAsFileOutput( parameters, QStringLiteral( 
"OUTPUT_HTML_FILE" ), context );
 
  114  std::unique_ptr<QgsFeatureSink> sink;
 
  115  if ( parameters.contains( QStringLiteral( 
"OUTPUT_TABLE" ) ) && parameters.value( QStringLiteral( 
"OUTPUT_TABLE" ) ).isValid() )
 
  118    outFields.
append( 
QgsField( QStringLiteral( 
"value" ), QMetaType::Type::Double, QString(), 20, 8 ) );
 
  119    outFields.
append( 
QgsField( QStringLiteral( 
"count" ), QMetaType::Type::LongLong, QString(), 20 ) );
 
  120    outFields.
append( 
QgsField( areaUnit.replace( QStringLiteral( 
"²" ), QStringLiteral( 
"2" ) ), QMetaType::Type::Double, QString(), 20, 8 ) );
 
  126  QHash<double, qgssize> uniqueValues;
 
  129  const qgssize layerSize = 
static_cast<qgssize>( mLayerWidth ) * 
static_cast<qgssize>( mLayerHeight );
 
  132  const int nbBlocksWidth = std::ceil( 1.0 * mLayerWidth / maxWidth );
 
  133  const int nbBlocksHeight = std::ceil( 1.0 * mLayerHeight / maxHeight );
 
  134  const int nbBlocks = nbBlocksWidth * nbBlocksHeight;
 
  137  iter.startRasterRead( mBand, mLayerWidth, mLayerHeight, mExtent );
 
  143  bool isNoData = 
false;
 
  144  std::unique_ptr<QgsRasterBlock> rasterBlock;
 
  145  while ( iter.readNextRasterPart( mBand, iterCols, iterRows, rasterBlock, iterLeft, iterTop ) )
 
  147    feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
 
  148    for ( 
int row = 0; row < iterRows; row++ )
 
  152      for ( 
int column = 0; column < iterCols; column++ )
 
  154        const double value = rasterBlock->valueAndNoData( row, column, isNoData );
 
  155        if ( mHasNoDataValue && isNoData )
 
  161          uniqueValues[value]++;
 
  169  QMap<double, qgssize> sortedUniqueValues;
 
  170  for ( 
auto it = uniqueValues.constBegin(); it != uniqueValues.constEnd(); ++it )
 
  172    sortedUniqueValues.insert( it.key(), it.value() );
 
  176  outputs.insert( QStringLiteral( 
"EXTENT" ), mExtent.toString() );
 
  177  outputs.insert( QStringLiteral( 
"CRS_AUTHID" ), mCrs.authid() );
 
  178  outputs.insert( QStringLiteral( 
"WIDTH_IN_PIXELS" ), mLayerWidth );
 
  179  outputs.insert( QStringLiteral( 
"HEIGHT_IN_PIXELS" ), mLayerHeight );
 
  180  outputs.insert( QStringLiteral( 
"TOTAL_PIXEL_COUNT" ), layerSize );
 
  181  outputs.insert( QStringLiteral( 
"NODATA_PIXEL_COUNT" ), noDataCount );
 
  183  const double pixelArea = mRasterUnitsPerPixelX * mRasterUnitsPerPixelY;
 
  185  if ( !outputFile.isEmpty() )
 
  187    QFile file( outputFile );
 
  188    if ( file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
 
  192      QTextStream out( &file );
 
  193#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) 
  194      out.setCodec( 
"UTF-8" );
 
  196      out << QStringLiteral( 
"<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"/></head><body>\n" );
 
  197      out << QStringLiteral( 
"<p>%1: %2 (%3 %4)</p>\n" ).arg( QObject::tr( 
"Analyzed file" ), mSource, QObject::tr( 
"band" ) ).arg( mBand );
 
  198      out << QObject::tr( 
"<p>%1: %2</p>\n" ).arg( QObject::tr( 
"Extent" ), mExtent.toString() );
 
  199      out << QObject::tr( 
"<p>%1: %2</p>\n" ).arg( QObject::tr( 
"Projection" ), mCrs.userFriendlyIdentifier() );
 
  200      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 );
 
  201      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 );
 
  202      out << QObject::tr( 
"<p>%1: %2</p>\n" ).arg( QObject::tr( 
"Total pixel count" ) ).arg( layerSize );
 
  203      if ( mHasNoDataValue )
 
  204        out << QObject::tr( 
"<p>%1: %2</p>\n" ).arg( QObject::tr( 
"NoData pixel count" ) ).arg( noDataCount );
 
  205      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 );
 
  207      for ( 
auto it = sortedUniqueValues.constBegin(); it != sortedUniqueValues.constEnd(); ++it )
 
  209        const double area = it.value() * pixelArea;
 
  210        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 ) );
 
  212      out << QStringLiteral( 
"</table>\n</body></html>" );
 
  213      outputs.insert( QStringLiteral( 
"OUTPUT_HTML_FILE" ), outputFile );
 
  219    for ( 
auto it = sortedUniqueValues.constBegin(); it != sortedUniqueValues.constEnd(); ++it )
 
  222      const double area = it.value() * pixelArea;
 
  225        throw QgsProcessingException( writeFeatureError( sink.get(), parameters, QStringLiteral( 
"OUTPUT_TABLE" ) ) );
 
  228    outputs.insert( QStringLiteral( 
"OUTPUT_TABLE" ), tableDest );
 
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
 
Represents a coordinate reference system (CRS).
 
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
 
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
 
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
 
bool isCanceled() const
Tells whether the operation has been canceled already.
 
void setProgress(double progress)
Sets the current progress for the feedback object.
 
Encapsulate a field in an attribute table or data source.
 
Container of fields for a vector layer.
 
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
 
virtual QgsRectangle extent() const
Returns the extent of the layer.
 
QString source() const
Returns the source for the layer.
 
QgsCoordinateReferenceSystem crs
 
Contains information about the context in which a processing algorithm is executed.
 
Custom exception class for processing related exceptions.
 
Base class for providing feedback from a processing algorithm.
 
A numeric output for processing algorithms.
 
A string output for processing algorithms.
 
A raster band parameter for Processing algorithms.
 
A feature sink output for processing algorithms.
 
A generic file based destination parameter, for specifying the destination path for a file (non-map l...
 
A raster layer parameter for processing algorithms.
 
QgsRasterDataProvider * clone() const override=0
Clone itself, create deep copy.
 
virtual bool sourceHasNoDataValue(int bandNo) const
Returns true if source band has no data value.
 
Iterator for sequentially processing raster cells.
 
static const int DEFAULT_MAXIMUM_TILE_WIDTH
Default maximum tile width.
 
static const int DEFAULT_MAXIMUM_TILE_HEIGHT
Default maximum tile height.
 
Represents a raster layer.
 
int height() const
Returns the height of the (unclipped) raster.
 
int bandCount() const
Returns the number of bands in this layer.
 
double rasterUnitsPerPixelX() const
Returns the number of raster units per each raster pixel in X axis.
 
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
 
double rasterUnitsPerPixelY() const
Returns the number of raster units per each raster pixel in Y axis.
 
int width() const
Returns the width of the (unclipped) raster.
 
static QString ampersandEncode(const QString &string)
Makes a raw string safe for inclusion as a HTML/XML string literal.
 
static Q_INVOKABLE QString toAbbreviatedString(Qgis::DistanceUnit unit)
Returns a translated abbreviation representing a distance unit.
 
static Q_INVOKABLE Qgis::AreaUnit distanceToAreaUnit(Qgis::DistanceUnit distanceUnit)
Converts a distance unit to its corresponding area unit, e.g., meters to square meters.
 
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...