def create_job(settings): return QgsMapRendererCustomPainterJob(settings, p)
def processAlgorithm(self, parameters, context, feedback): feedback.setProgress(1) extent = self.parameterAsExtent(parameters, self.EXTENT, context) min_zoom = self.parameterAsInt(parameters, self.ZOOM_MIN, context) max_zoom = self.parameterAsInt(parameters, self.ZOOM_MAX, context) dpi = self.parameterAsInt(parameters, self.DPI, context) tile_format = self.formats[self.parameterAsEnum( parameters, self.TILE_FORMAT, context)] output_format = self.outputs[self.parameterAsEnum( parameters, self.OUTPUT_FORMAT, context)] if output_format == 'Directory': output_dir = self.parameterAsString(parameters, self.OUTPUT_DIRECTORY, context) if not output_dir: raise QgsProcessingException( self.tr('You need to specify output directory.')) else: # MBTiles output_file = self.parameterAsString(parameters, self.OUTPUT_FILE, context) if not output_file: raise QgsProcessingException( self.tr('You need to specify output filename.')) tile_width = 256 tile_height = 256 wgs_crs = QgsCoordinateReferenceSystem('EPSG:4326') dest_crs = QgsCoordinateReferenceSystem('EPSG:3857') project = context.project() src_to_wgs = QgsCoordinateTransform(project.crs(), wgs_crs, context.transformContext()) wgs_to_dest = QgsCoordinateTransform(wgs_crs, dest_crs, context.transformContext()) settings = QgsMapSettings() settings.setOutputImageFormat(QImage.Format_ARGB32_Premultiplied) settings.setDestinationCrs(dest_crs) settings.setLayers(self.layers) settings.setOutputDpi(dpi) wgs_extent = src_to_wgs.transformBoundingBox(extent) wgs_extent = [ wgs_extent.xMinimum(), wgs_extent.yMinimum(), wgs_extent.xMaximum(), wgs_extent.yMaximum() ] metatiles_by_zoom = {} metatiles_count = 0 for zoom in range(min_zoom, max_zoom + 1): metatiles = get_metatiles(wgs_extent, zoom, 4) metatiles_by_zoom[zoom] = metatiles metatiles_count += len(metatiles) lab_buffer_px = 100 progress = 0 tile_params = { 'format': tile_format, 'quality': 75, 'width': tile_width, 'height': tile_height } if output_format == 'Directory': writer = DirectoryWriter(output_dir, tile_params) else: writer = MBTilesWriter(output_file, tile_params, wgs_extent, min_zoom, max_zoom) for zoom in range(min_zoom, max_zoom + 1): feedback.pushConsoleInfo('Generating tiles for zoom level: %s' % zoom) for i, metatile in enumerate(metatiles_by_zoom[zoom]): size = QSize(tile_width * metatile.rows(), tile_height * metatile.columns()) extent = QgsRectangle(*metatile.extent()) settings.setExtent(wgs_to_dest.transformBoundingBox(extent)) settings.setOutputSize(size) label_area = QgsRectangle(settings.extent()) lab_buffer = label_area.width() * (lab_buffer_px / size.width()) label_area.set(label_area.xMinimum() + lab_buffer, label_area.yMinimum() + lab_buffer, label_area.xMaximum() - lab_buffer, label_area.yMaximum() - lab_buffer) settings.setLabelBoundaryGeometry( QgsGeometry.fromRect(label_area)) image = QImage(size, QImage.Format_ARGB32_Premultiplied) image.fill(Qt.transparent) dpm = settings.outputDpi() / 25.4 * 1000 image.setDotsPerMeterX(dpm) image.setDotsPerMeterY(dpm) painter = QPainter(image) job = QgsMapRendererCustomPainterJob(settings, painter) job.renderSynchronously() painter.end() # For analysing metatiles (labels, etc.) # metatile_dir = os.path.join(output_dir, str(zoom)) # os.makedirs(metatile_dir, exist_ok=True) # image.save(os.path.join(metatile_dir, 'metatile_%s.png' % i)) for r, c, tile in metatile.tiles: tile_img = image.copy(tile_width * r, tile_height * c, tile_width, tile_height) writer.writeTile(tile, tile_img) progress += 1 feedback.setProgress(100 * (progress / metatiles_count)) writer.close() results = {} if output_format == 'Directory': results['OUTPUT_DIRECTORY'] = output_dir else: # MBTiles results['OUTPUT_FILE'] = output_file return results
def generate(self, writer, parameters, context, feedback): feedback.setProgress(1) extent = self.parameterAsExtent(parameters, self.EXTENT, context) self.min_zoom = self.parameterAsInt(parameters, self.ZOOM_MIN, context) self.max_zoom = self.parameterAsInt(parameters, self.ZOOM_MAX, context) dpi = self.parameterAsInt(parameters, self.DPI, context) self.tile_format = self.formats[self.parameterAsEnum(parameters, self.TILE_FORMAT, context)] transparent = self.parameterAsBool(parameters, self.TRANSPARENT, context) quality = self.parameterAsInt(parameters, self.QUALITY, context) try: tile_width = self.parameterAsInt(parameters, self.TILE_WIDTH, context) tile_height = self.parameterAsInt(parameters, self.TILE_HEIGHT, context) except AttributeError: # for mbtiles we don't have such settings tile_width = 256 tile_height = 256 wgs_crs = QgsCoordinateReferenceSystem('EPSG:4326') dest_crs = QgsCoordinateReferenceSystem('EPSG:3857') project = context.project() src_to_wgs = QgsCoordinateTransform(project.crs(), wgs_crs, context.transformContext()) wgs_to_dest = QgsCoordinateTransform(wgs_crs, dest_crs, context.transformContext()) settings = QgsMapSettings() settings.setOutputImageFormat(QImage.Format_ARGB32_Premultiplied) settings.setDestinationCrs(dest_crs) settings.setLayers(self.layers) settings.setOutputDpi(dpi) canvas_red = QgsProject.instance().readNumEntry('Gui', '/CanvasColorRedPart', 255)[0] canvas_green = QgsProject.instance().readNumEntry('Gui', '/CanvasColorGreenPart', 255)[0] canvas_blue = QgsProject.instance().readNumEntry('Gui', '/CanvasColorBluePart', 255)[0] color = QColor(canvas_red, canvas_green, canvas_blue, 255) if self.tile_format == 'PNG' and transparent: color.setAlpha(0) settings.setBackgroundColor(color) # disable partial labels (they would be cut at the edge of tiles) labeling_engine_settings = settings.labelingEngineSettings() labeling_engine_settings.setFlag(QgsLabelingEngineSettings.UsePartialCandidates, False) settings.setLabelingEngineSettings(labeling_engine_settings) self.wgs_extent = src_to_wgs.transformBoundingBox(extent) self.wgs_extent = [self.wgs_extent.xMinimum(), self.wgs_extent.yMinimum(), self.wgs_extent.xMaximum(), self.wgs_extent.yMaximum()] metatiles_by_zoom = {} metatiles_count = 0 for zoom in range(self.min_zoom, self.max_zoom + 1): metatiles = get_metatiles(self.wgs_extent, zoom, 4) metatiles_by_zoom[zoom] = metatiles metatiles_count += len(metatiles) lab_buffer_px = 100 progress = 0 tile_params = { 'format': self.tile_format, 'quality': quality, 'width': tile_width, 'height': tile_height, 'min_zoom': self.min_zoom, 'max_zoom': self.max_zoom, 'extent': self.wgs_extent, } writer.set_parameters(tile_params) for zoom in range(self.min_zoom, self.max_zoom + 1): feedback.pushConsoleInfo('Generating tiles for zoom level: %s' % zoom) for i, metatile in enumerate(metatiles_by_zoom[zoom]): if feedback.isCanceled(): break size = QSize(tile_width * metatile.rows(), tile_height * metatile.columns()) extent = QgsRectangle(*metatile.extent()) settings.setExtent(wgs_to_dest.transformBoundingBox(extent)) settings.setOutputSize(size) image = QImage(size, QImage.Format_ARGB32_Premultiplied) image.fill(Qt.transparent) dpm = settings.outputDpi() / 25.4 * 1000 image.setDotsPerMeterX(dpm) image.setDotsPerMeterY(dpm) painter = QPainter(image) job = QgsMapRendererCustomPainterJob(settings, painter) job.renderSynchronously() painter.end() # For analysing metatiles (labels, etc.) # metatile_dir = os.path.join(output_dir, str(zoom)) # os.makedirs(metatile_dir, exist_ok=True) # image.save(os.path.join(metatile_dir, 'metatile_%s.png' % i)) for r, c, tile in metatile.tiles: tile_img = image.copy(tile_width * r, tile_height * c, tile_width, tile_height) writer.write_tile(tile, tile_img) progress += 1 feedback.setProgress(100 * (progress / metatiles_count)) writer.close()
def renderedImage(self, width, height, extent, transp_background=False, layerids=None): if QGis.QGIS_VERSION_INT < 20700: return self._renderedImage2(width, height, extent, transp_background, layerids) # render layers with QgsMapRendererCustomPainterJob from qgis.core import QgsMapRendererCustomPainterJob antialias = True settings = self.exportSettings.mapSettings # store old map settings old_outputSize = settings.outputSize() old_extent = settings.extent() old_rotation = settings.rotation() old_layerids = settings.layers() old_backgroundColor = settings.backgroundColor() # map settings settings.setOutputSize(QSize(width, height)) settings.setExtent(extent.unrotatedRect()) settings.setRotation(extent.rotation()) if layerids is not None: settings.setLayers(layerids) if transp_background: settings.setBackgroundColor(QColor(Qt.transparent)) #else: #TODO: remove #settings.setBackgroundColor(self.exportSettings.canvas.canvasColor()) has_pluginlayer = False for layerId in settings.layers(): layer = QgsMapLayerRegistry.instance().mapLayer(layerId) if layer and layer.type() == QgsMapLayer.PluginLayer: has_pluginlayer = True break # create an image image = QImage(width, height, QImage.Format_ARGB32_Premultiplied) painter = QPainter() painter.begin(image) if antialias: painter.setRenderHint(QPainter.Antialiasing) # rendering job = QgsMapRendererCustomPainterJob(settings, painter) if has_pluginlayer: job.renderSynchronously( ) # use this method so that TileLayerPlugin layer is rendered correctly else: job.start() job.waitForFinished() painter.end() # restore map settings settings.setOutputSize(old_outputSize) settings.setExtent(old_extent) settings.setRotation(old_rotation) settings.setLayers(old_layerids) settings.setBackgroundColor(old_backgroundColor) return tools.base64image(image)