34 #include <QtConcurrent> 
   38 QString QgsRasterizeAlgorithm::name()
 const 
   40   return QStringLiteral( 
"rasterize" );
 
   43 QString QgsRasterizeAlgorithm::displayName()
 const 
   45   return QObject::tr( 
"Convert map to raster" );
 
   48 QStringList QgsRasterizeAlgorithm::tags()
 const 
   50   return QObject::tr( 
"layer,raster,convert,file,map themes,tiles,render" ).split( 
',' );
 
   53 QgsProcessingAlgorithm::Flags QgsRasterizeAlgorithm::flags()
 const 
   58 QString QgsRasterizeAlgorithm::group()
 const 
   60   return QObject::tr( 
"Raster tools" );
 
   63 QString QgsRasterizeAlgorithm::groupId()
 const 
   65   return QStringLiteral( 
"rastertools" );
 
   68 void QgsRasterizeAlgorithm::initAlgorithm( 
const QVariantMap & )
 
   71                   QStringLiteral( 
"EXTENT" ),
 
   72                   QObject::tr( 
"Minimum extent to render" ) ) );
 
   74                   QStringLiteral( 
"EXTENT_BUFFER" ),
 
   75                   QObject::tr( 
"Buffer around tiles in map units" ),
 
   76                   QgsProcessingParameterNumber::Type::Double,
 
   81                   QStringLiteral( 
"TILE_SIZE" ),
 
   82                   QObject::tr( 
"Tile size" ),
 
   83                   QgsProcessingParameterNumber::Type::Integer,
 
   88                   QStringLiteral( 
"MAP_UNITS_PER_PIXEL" ),
 
   89                   QObject::tr( 
"Map units per pixel" ),
 
   90                   QgsProcessingParameterNumber::Type::Double,
 
   95                   QStringLiteral( 
"MAKE_BACKGROUND_TRANSPARENT" ),
 
   96                   QObject::tr( 
"Make background transparent" ),
 
  100                   QStringLiteral( 
"MAP_THEME" ),
 
  101                   QObject::tr( 
"Map theme to render" ),
 
  102                   QVariant(), 
true ) );
 
  106                   QStringLiteral( 
"LAYERS" ),
 
  107                   QObject::tr( 
"Layers to render" ),
 
  113                   QStringLiteral( 
"OUTPUT" ),
 
  114                   QObject::tr( 
"Output layer" ) ) );
 
  118 QString QgsRasterizeAlgorithm::shortDescription()
 const 
  120   return QObject::tr( 
"Renders the map canvas to a raster file." );
 
  123 QString QgsRasterizeAlgorithm::shortHelpString()
 const 
  125   return QObject::tr( 
"This algorithm rasterizes map canvas content.\n\n" 
  126                       "A map theme can be selected to render a predetermined set of layers with a defined style for each layer. " 
  127                       "Alternatively, a set of layers can be selected if no map theme is set. " 
  128                       "If neither map theme nor layer is set, all the visible layers in the set extent will be rendered.\n\n" 
  129                       "The minimum extent entered will internally be extended to a multiple of the tile size." );
 
  132 QgsRasterizeAlgorithm *QgsRasterizeAlgorithm::createInstance()
 const 
  134   return new QgsRasterizeAlgorithm();
 
  141   const QgsRectangle extent { parameterAsExtent( parameters, QStringLiteral( 
"EXTENT" ), context, context.
project()->
crs() ) };
 
  142   const int tileSize { parameterAsInt( parameters, QStringLiteral( 
"TILE_SIZE" ), context ) };
 
  143   const bool transparent { parameterAsBool( parameters, QStringLiteral( 
"MAKE_BACKGROUND_TRANSPARENT" ), context ) };
 
  144   const double mapUnitsPerPixel { parameterAsDouble( parameters, QStringLiteral( 
"MAP_UNITS_PER_PIXEL" ), context ) };
 
  145   const double extentBuffer { parameterAsDouble( parameters, QStringLiteral( 
"EXTENT_BUFFER" ), context ) };
 
  146   const QString outputLayerFileName { parameterAsOutputLayer( parameters, QStringLiteral( 
"OUTPUT" ), context )};
 
  148   int xTileCount { 
static_cast<int>( ceil( extent.width() / mapUnitsPerPixel / tileSize ) )};
 
  149   int yTileCount { 
static_cast<int>( ceil( extent.height() / mapUnitsPerPixel / tileSize ) )};
 
  150   int width { xTileCount * tileSize };
 
  151   int height { yTileCount * tileSize };
 
  152   int nBands { transparent ? 4 : 3 };
 
  155   if ( driverName.isEmpty() )
 
  160   GDALDriverH hOutputFileDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
 
  161   if ( !hOutputFileDriver )
 
  166   gdal::dataset_unique_ptr hOutputDataset( GDALCreate( hOutputFileDriver, outputLayerFileName.toLocal8Bit().constData(), width, height, nBands, GDALDataType::GDT_Byte, 
nullptr ) );
 
  167   if ( !hOutputDataset )
 
  173   double geoTransform[6];
 
  174   geoTransform[0] = extent.xMinimum();
 
  175   geoTransform[1] = mapUnitsPerPixel;
 
  177   geoTransform[3] = extent.yMaximum();
 
  179   geoTransform[5] = - mapUnitsPerPixel;
 
  180   GDALSetGeoTransform( hOutputDataset.get(), geoTransform );
 
  182   int red = context.
project()->
readNumEntry( QStringLiteral( 
"Gui" ), 
"/CanvasColorRedPart", 255 );
 
  183   int green = context.
project()->
readNumEntry( QStringLiteral( 
"Gui" ), 
"/CanvasColorGreenPart", 255 );
 
  184   int blue = context.
project()->
readNumEntry( QStringLiteral( 
"Gui" ), 
"/CanvasColorBluePart", 255 );
 
  189     bgColor = QColor( red, green, blue, 0 );
 
  193     bgColor = QColor( red, green, blue );
 
  207   QList<QgsMapLayer *> layers;
 
  208   for ( 
const auto &lptr : mMapLayers )
 
  210     layers.push_back( lptr.get() );
 
  216   const double extentRatio { mapUnitsPerPixel * tileSize };
 
  217   const int numTiles { xTileCount * yTileCount };
 
  218   const QString fileExtension { QFileInfo( outputLayerFileName ).suffix() };
 
  223     void operator()( uint8_t *ptr )
 const 
  229   QAtomicInt rendered = 0;
 
  230   QMutex rasterWriteLocker;
 
  232   const auto renderJob = [ & ]( 
const int x, 
const int y, 
QgsMapSettings mapSettings )
 
  234     QImage image { tileSize, tileSize, QImage::Format::Format_ARGB32 };
 
  237     QPainter painter { &image };
 
  242     image.fill( transparent ? bgColor.rgba() : bgColor.rgb() );
 
  244                              extent.xMinimum() + x * extentRatio,
 
  245                              extent.yMaximum() - ( y + 1 ) * extentRatio,
 
  246                              extent.xMinimum() + ( x + 1 ) * extentRatio,
 
  247                              extent.yMaximum() - y * extentRatio
 
  251     job.waitForFinished();
 
  254     if ( !hIntermediateDataset )
 
  259     const int xOffset { x * tileSize };
 
  260     const int yOffset { y * tileSize };
 
  262     std::unique_ptr<uint8_t, CPLDelete> buffer( 
static_cast< uint8_t * 
>( CPLMalloc( 
sizeof( uint8_t ) * 
static_cast<size_t>( tileSize * tileSize * nBands ) ) ) );
 
  263     CPLErr err = GDALDatasetRasterIO( hIntermediateDataset.get(),
 
  264                                       GF_Read, 0, 0, tileSize, tileSize,
 
  266                                       tileSize, tileSize, GDT_Byte, nBands, 
nullptr, 0, 0, 0 );
 
  267     if ( err != CE_None )
 
  273       QMutexLocker locker( &rasterWriteLocker );
 
  274       err = GDALDatasetRasterIO( hOutputDataset.get(),
 
  275                                  GF_Write, xOffset, yOffset, tileSize, tileSize,
 
  277                                  tileSize, tileSize, GDT_Byte, nBands, 
nullptr, 0, 0, 0 );
 
  279       feedback->
setProgress( 
static_cast<double>( rendered ) / numTiles * 100.0 );
 
  281     if ( err != CE_None )
 
  289   std::vector<QFuture<void>> futures;
 
  291   for ( 
int x = 0; x < xTileCount; ++x )
 
  293     for ( 
int y = 0; y < yTileCount; ++y )
 
  299       futures.push_back( QtConcurrent::run( renderJob, x, y, mapSettings ) );
 
  303   for ( 
auto &f : futures )
 
  308   return { { QStringLiteral( 
"OUTPUT" ), outputLayerFileName } };
 
  316   const QString mapTheme { parameterAsString( parameters, QStringLiteral( 
"MAP_THEME" ), context ) };
 
  317   const QList<QgsMapLayer *> mapLayers { parameterAsLayerList( parameters, QStringLiteral( 
"LAYERS" ), context ) };
 
  323       mMapLayers.push_back( std::unique_ptr<QgsMapLayer>( ml->clone( ) ) );
 
  327   else if ( ! mapLayers.isEmpty() )
 
  329     for ( 
const QgsMapLayer *ml : std::as_const( mapLayers ) )
 
  331       mMapLayers.push_back( std::unique_ptr<QgsMapLayer>( ml->clone( ) ) );
 
  335   if ( mMapLayers.size() == 0 )
 
  337     QList<QgsMapLayer *> layers;
 
  342       if ( nodeLayer->isVisible() && root->
layerOrder().contains( layer ) )
 
  346     for ( 
const QgsMapLayer *ml : std::as_const( layers ) )
 
  348       mMapLayers.push_back( std::unique_ptr<QgsMapLayer>( ml->clone( ) ) );
 
  351   return mMapLayers.size() > 0;
 
@ WKT_PREFERRED_GDAL
Preferred format for conversion of CRS to WKT for use with the GDAL library.
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
static gdal::dataset_unique_ptr imageToMemoryDataset(const QImage &image)
Converts an image to a GDAL memory dataset by borrowing image data.
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
Layer tree node points to a map layer.
Namespace with helper functions for layer tree operations.
QList< QgsMapLayer * > layerOrder() const
The order in which layers will be rendered on the canvas.
Base class for all map layer types.
Job implementation that renders everything sequentially using a custom painter.
The QgsMapSettings class contains configuration for rendering of the map.
void setLayers(const QList< QgsMapLayer * > &layers)
Sets the list of layers to render in the map.
@ Antialiasing
Enable anti-aliasing for map rendering.
@ UseAdvancedEffects
Enable layer opacity and blending effects.
@ RenderMapTile
Draw map such that there are no problems between adjacent tiles.
void setOutputDpi(double dpi)
Sets the dpi (dots per inch) used for conversion between real world units (e.g.
void setOutputImageFormat(QImage::Format format)
sets format of internal QImage
void setLayerStyleOverrides(const QMap< QString, QString > &overrides)
Sets the map of map layer style overrides (key: layer ID, value: style name) where a different style ...
void setExtent(const QgsRectangle &rect, bool magnified=true)
Sets the coordinates of the rectangle which should be rendered.
void setExtentBuffer(double buffer)
Sets the buffer in map units to use around the visible extent for rendering symbols whose correspondi...
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the coordinate transform context, which stores various information regarding which datum transfo...
void setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
void setOutputSize(QSize size)
Sets the size of the resulting map image, in pixels.
void setBackgroundColor(const QColor &color)
Sets the background color of the map.
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
Sets the destination crs (coordinate reference system) for the map render.
bool hasMapTheme(const QString &name) const
Returns whether a map theme with a matching name exists.
QList< QgsMapLayer * > mapThemeVisibleLayers(const QString &name) const
Returns the list of layers that are visible for the specified map theme.
QMap< QString, QString > mapThemeStyleOverrides(const QString &name)
Gets layer style overrides (for QgsMapSettings) of the visible layers for given map theme.
virtual Flags flags() const
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
Contains information about the context in which a processing algorithm is executed.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
QgsProject * project() const
Returns the project in which the algorithm is being executed.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
A boolean parameter for processing algorithms.
A rectangular map extent parameter for processing algorithms.
A map theme parameter for processing algorithms, allowing users to select an existing map theme from ...
A parameter for processing algorithms which accepts multiple map layers.
A numeric parameter for processing algorithms.
A raster layer destination parameter, for specifying the destination path for a raster layer created ...
@ TypeMapLayer
Any map layer type (raster or vector or mesh)
int readNumEntry(const QString &scope, const QString &key, int def=0, bool *ok=nullptr) const
Reads an integer from the specified scope and key.
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsMapThemeCollection * mapThemeCollection
QgsLayerTree * layerTreeRoot() const
Returns pointer to the root (invisible) node of the project's layer tree.
QgsCoordinateReferenceSystem crs
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
static QString driverForExtension(const QString &extension)
Returns the GDAL driver name for a specified file extension.
A rectangle specified with double values.
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.