Ejemplo n.º 1
0
 def create_job(settings):
     return QgsMapRendererCustomPainterJob(settings, p)
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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()
Ejemplo n.º 4
0
    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)