Exemple #1
0
    def renderer(self):
        if 'QGIS_AUTH_DB_DIR_PATH' not in os.environ:
            os.environ['QGIS_AUTH_DB_DIR_PATH'] = '/tmp'

        qgis = None
        while True:
            options, result = self.queue.get()

            # Don't start QGIS until first request
            if qgis is None:
                qgis = QgsApplication([], False)
                qgis.setPrefixPath(self.settings.get('path'), True)
                qgis.setDefaultSvgPaths(qgis.svgPaths() +
                                        self.settings.get('svgpaths'))
                qgis.setMaxThreads(1)
                qgis.initQgis()

            try:
                if isinstance(options, LegendOptions):
                    style, = options

                    layer = self._qgs_memory_layer(style)
                    layer.setName(style.parent.display_name)

                    QgsMapLayerRegistry.instance().addMapLayer(layer)

                    root = QgsLayerTreeGroup()
                    root.addLayer(layer)

                    # 'Cannot create a QPixmap when no GUI is being used'
                    #  warning occurs here
                    model = QgsLayerTreeModel(root)

                    settings = QgsLegendSettings()
                    settings.setTitle('')
                    settings.setBoxSpace(1)
                    settings.setSymbolSize(QSizeF(5, 3))
                    settings.setDpi(96)

                    renderer = QgsLegendRenderer(model, settings)

                    # Dots per mm
                    dpmm = settings.dpi() / 25.4

                    min_size = renderer.minimumSize()
                    size = QSize(dpmm * min_size.width(),
                                 dpmm * min_size.height())
                    img = QImage(size, QImage.Format_ARGB32)
                    img.fill(QColor(0, 0, 0, 0))

                    painter = QPainter()
                    painter.begin(img)
                    painter.scale(dpmm, dpmm)
                    renderer.drawLegend(painter)
                    painter.end()

                    QgsMapLayerRegistry.instance().removeAllMapLayers()

                    ba = QByteArray()
                    bf = QBuffer(ba)
                    bf.open(QIODevice.WriteOnly)
                    img.save(bf, 'PNG')
                    bf.close()

                    buf = StringIO()
                    buf.write(bf.data())
                    buf.seek(0)
                    result.put(buf)

                else:
                    path = features = None
                    if isinstance(options, VectorRenderOptions):
                        style, features, render_size, \
                            extended, target_box = options
                        layer = self._qgs_memory_layer(style,
                                                       features=features)
                    elif isinstance(options, RasterRenderOptions):
                        style, path, render_size, \
                            extended, target_box = options
                        layer = QgsRasterLayer(path)
                        layer.loadNamedStyle(
                            self.env.file_storage.filename(style.qml_fileobj))

                    settings = QgsMapSettings()
                    settings.setLayers([layer.id()])
                    settings.setFlag(QgsMapSettings.DrawLabeling)
                    settings.setFlag(QgsMapSettings.Antialiasing)

                    settings.setCrsTransformEnabled(True)
                    settings.setDestinationCrs(layer.crs())
                    settings.setMapUnits(layer.crs().mapUnits())
                    settings.setOutputSize(QSize(*render_size))
                    settings.setExtent(QgsRectangle(*extended))

                    settings.setOutputImageFormat(QImage.Format_ARGB32)
                    bgcolor = QColor.fromRgba(qRgba(255, 255, 255, 0))
                    settings.setBackgroundColor(bgcolor)
                    settings.setOutputDpi(96)

                    QgsMapLayerRegistry.instance().addMapLayer(layer)
                    settings.setLayers([layer.id()])

                    # Create QImage by hand to be able to use
                    # QgsMapRendererCustomPainterJob. Others will not
                    # allow to workaround a bug with overlay rendering.
                    img = QImage(settings.outputSize(), QImage.Format_ARGB32)

                    # These cludges are needed for rendering
                    # on transparent background, otherwise it's a mess.
                    img.fill(QColor.fromRgba(qRgba(255, 255, 255, 255)))
                    img.fill(QColor.fromRgba(qRgba(255, 255, 255, 0)))

                    # DPI should be equal to settings, otherwise an error.
                    # In QImage the resolution is set in dots per meter
                    # for each axis.
                    dpm = settings.outputDpi() / 25.4 * 1000
                    img.setDotsPerMeterX(dpm)
                    img.setDotsPerMeterY(dpm)

                    painter = QPainter(img)
                    job = QgsMapRendererCustomPainterJob(settings, painter)
                    job.renderSynchronously()
                    painter.end()

                    QgsMapLayerRegistry.instance().removeAllMapLayers()

                    img = self._qimage_to_pil(img)

                    # Clip needed part
                    result.put(img.crop(target_box))

                    # Cleanup
                    if path is not None:
                        gdal.Unlink(path)

            except Exception as exc:
                self.logger.error(exc.message)
                result.put(exc)

        qgis.exitQgis()
Exemple #2
0
    def renderer(self):
        qgis = QgsApplication([], False)
        qgis.setPrefixPath(self.settings.get('path'), True)
        qgis.setMaxThreads(1)
        qgis.initQgis()

        while True:
            try:
                fndata, srs, render_size, extended, \
                    target_box, result = self.queue.get()

                layer = QgsVectorLayer(fndata, 'layer', 'ogr')

                crs = QgsCoordinateReferenceSystem(srs.id)
                layer.setCrs(crs)

                settings = QgsMapSettings()
                settings.setLayers([layer.id()])
                settings.setFlag(QgsMapSettings.DrawLabeling)
                settings.setFlag(QgsMapSettings.Antialiasing)

                settings.setCrsTransformEnabled(True)
                settings.setDestinationCrs(crs)
                settings.setMapUnits(crs.mapUnits())
                settings.setOutputSize(QSize(*render_size))
                settings.setExtent(QgsRectangle(*extended))

                settings.setOutputImageFormat(QImage.Format_ARGB32)
                bgcolor = QColor.fromRgba(qRgba(255, 255, 255, 0))
                settings.setBackgroundColor(bgcolor)
                settings.setOutputDpi(96)

                QgsMapLayerRegistry.instance().addMapLayer(layer)
                settings.setLayers([layer.id()])

                # Создаем QImage руками чтобы можно было использовать
                # QgsMapRendererCustomPainterJob. Остальные не позволяют
                # обойти баг с рисованием поверх старого.
                img = QImage(settings.outputSize(), QImage.Format_ARGB32)

                # Эти костыли нужны для того, чтобы корректно рисовались
                # слои на прозрачном фоне, без этого получается каша.
                img.fill(QColor.fromRgba(qRgba(255, 255, 255, 255)))
                img.fill(QColor.fromRgba(qRgba(255, 255, 255, 0)))

                # DPI должно быть таким же как в settings, иначе ошибка. В QImage
                # разрешение указывается в точках на метр по каждой оси.
                dpm = settings.outputDpi() / 25.4 * 1000
                img.setDotsPerMeterX(dpm)
                img.setDotsPerMeterY(dpm)

                painter = QPainter(img)
                job = QgsMapRendererCustomPainterJob(settings, painter)
                job.renderSynchronously()
                painter.end()

                QgsMapLayerRegistry.instance().removeAllMapLayers()

                # Преобразование QImage в PIL
                ba = QByteArray()
                bf = QBuffer(ba)
                bf.open(QIODevice.WriteOnly)
                img.save(bf, 'PNG')
                bf.close()

                buf = StringIO()
                buf.write(bf.data())
                buf.seek(0)

                img = PIL.Image.open(buf)

                # Вырезаем нужный нам кусок изображения
                result.put(img.crop(target_box))

            except Exception as e:
                self.logger.error(e.message)

        qgis.exitQgis()