Зберегти вигляд композитора друку / карти QGIS як PNG / PDF за допомогою Python (не змінюючи нічого у видимій макеті)?


11

У мене відкрито подання композитора / друку QGIS з усіма елементами, відрегульованими за бажанням. Тепер мені потрібно роздрукувати / зберегти / експортувати це як PNG або PDF-файл із консолі Python / Python script.

Я не хочу нічого змінювати в поточному макеті. Більшість прикладів, які я знайшов (наприклад: це ), зміни положення або розміру карти у вихідному PDF порівнянні з тим, що я бачу в моєму поданні композитора. Я хочу отримати точно такий же результат, як і при натисканні на Друк -> Експортувати як зображення .

Як я можу це зробити? Атлас не є рішенням для мене.

Відповіді:


7

Я рекомендую використовувати наступний сценарій Тіма Саттона в якості основи, він добре працював для мене: - http://kartoza.com/how-to-create-a-qgis-pdf-report-with-a-few-lines- оф-пітона /

Просто перенесіть порожній дикт на функцію композиції. завантажуйте з планшета () замість використовуваної ним "картки заміни", оскільки вас ця функція не цікавить.

Крім того, оскільки ви запитували про "експортувати як зображення", а не про "експортувати як PDF", вам доведеться зробити трохи більше роботи, ніж використовувати функцію члена ExportAsPDF ().

Нижче наведена модифікована версія коду Тіма, яка повинна виконати трюк, працюючи із зовнішнього сценарію Python. Встановіть мінливі файли DPI та проекту + композитора як потрібно.

(Якщо ви використовуєте консоль Python у рамках QGIS, а не робите це як зовнішній скрипт, ви можете отримати поточне полотно карти за допомогою qgis.iface і не потрібно використовувати весь код завантаження проекту тощо).

import sys
from qgis.core import (
    QgsProject, QgsComposition, QgsApplication, QgsProviderRegistry)
from qgis.gui import QgsMapCanvas, QgsLayerTreeMapCanvasBridge
from PyQt4.QtCore import QFileInfo
from PyQt4.QtXml import QDomDocument

gui_flag = True
app = QgsApplication(sys.argv, gui_flag)

# Make sure QGIS_PREFIX_PATH is set in your env if needed!
app.initQgis()

# Probably you want to tweak this
project_path = 'project.qgs'

# and this
template_path = 'template.qpt'

# Set output DPI
dpi = 300

canvas = QgsMapCanvas()
# Load our project
QgsProject.instance().read(QFileInfo(project_path))
bridge = QgsLayerTreeMapCanvasBridge(
    QgsProject.instance().layerTreeRoot(), canvas)
bridge.setCanvasLayers()

template_file = file(template_path)
template_content = template_file.read()
template_file.close()
document = QDomDocument()
document.setContent(template_content)
ms = canvas.mapSettings())
composition = QgsComposition(ms)
composition.loadFromTemplate(document, {})
# You must set the id in the template
map_item = composition.getComposerItemById('map')
map_item.setMapCanvas(canvas)
map_item.zoomToExtent(canvas.extent())
# You must set the id in the template
legend_item = composition.getComposerItemById('legend')
legend_item.updateLegend()
composition.refreshItems()

dpmm = dpi / 25.4
width = int(dpmm * composition.paperWidth())
height = int(dpmm * composition.paperHeight())

# create output image and initialize it
image = QImage(QSize(width, height), QImage.Format_ARGB32)
image.setDotsPerMeterX(dpmm * 1000)
image.setDotsPerMeterY(dpmm * 1000)
image.fill(0)

# render the composition
imagePainter = QPainter(image)
composition.renderPage(imagePainter, 0)
imagePainter.end()

image.save("out.png", "png")

QgsProject.instance().clear()
QgsApplication.exitQgis()

Мені цікаво використовувати ваш код. Однак я отримую порожню карту ... я розмістив питання про це тут, якщо у вас виникли якісь ідеї: gis.stackexchange.com/questions/216376/…
user25976

Мені також цікаво використовувати це. Я думаю, що я досить близький, але я отримую об’єкт 'AttributeError:' QgsComposerItem 'не має атрибута' setMapCanvas '' Я втрачаю звідки куди поїхати звідти.
jamierob

Як я можу знайти код за посиланням у цій відповіді? Я спробував у двох різних браузерах і, здається, не знаходжу "прикладу", на який посилається повідомлення,python generate_pdf.py
raphael

3

Ви можете запрограмувати його самостійно або використати метод із Maps Printerплагіна. Я опишу другий варіант, тому що він простіший.

Потрібно Maps Printerвстановити плагін, відкрити проект QGIS разом із налаштованим композитором, відкрити консоль QGIS Python та запустити цей фрагмент коду (вам потрібно буде налаштувати його за допомогою власних налаштувань у Your settingsрозділі).

# Your settings
composerTitle = 'my composer' # Name of the composer you want to export
folder = '/path/to/export_folder/'
extension = '.png' # Any extension supported by the plugin

mp = qgis.utils.plugins['MapsPrinter']

for composer in iface.activeComposers():
    title = composer.composerWindow().windowTitle()
    if title == composerTitle:
        mp.exportCompo( composer, folder, title, extension )
        break

Запустивши його, ви отримаєте новий файл у /path/to/export_folder/my composer.png. Ви також можете використовувати '.pdf'як розширення для експорту композитора як PDF.


3

Можливо, також погляньте на мою іншу відповідь, оскільки нові новітні інструменти з'явилися з цього часу.


Я прийшов до коду, який, на жаль, не є повністю функціональним. Це ґрунтується на вищезазначеному рішенні та на цих інших питаннях:

Як програмно експортувати композицію як зображення?
Як я можу прочитати налаштування для QgsPaperItem з XML?
Збереження карти Canvas як PNG з прозорим фоном програмно за допомогою QGIS?

Мій код може витягнути .qpt з .qgs-файлу та успішно завантажити композитор із шаблону. Він також друкує композитора до .png-файлу та відображає правильно мітки та форми, що зберігаються у композиторі.

Однак він не може завантажити всі елементи, пов'язані з фактичною картою та шарами (мітка, що містить вираз із шару, також не намальована). Я думаю, що я трохи пропустив, як проект повинен бути завантажений і пов'язаний з композитором.

Деякі люди в коментарі до початкової статті від Тіма Саттона згадували, що вони застрягли на тому ж етапі під Windows (це мій випадок). Це насправді засмучує, бо я відчуваю, що відповідь насправді поруч. Шановний Інтернет, будь ласка, допоможіть!

Також це мої перші спроби пітона, тому я сподіваюся, що ви будете добрі;)

#This python code aim to programmatically export the first composer stored in a qgs file using PyQgis API v 2.10
#Version 0.4 (non functional) WTFPL MarHoff 2015 - This code is mostly a "frankenstein" stub made with a lot of other snippets. Feel welcome to improve!
#Credits to gis.stackexchange community : drnextgis,ndawson,patdevelop,dakcarto,ahoi, underdark & Tim Sutton from kartoza
#More informations and feedback can be found at /gis/144792/

#This script assume your environement is setup for PyGis as a stand-alone script. Some nice hints for windows users : https://gis.stackexchange.com/a/130102/17548

import sys
from PyQt4.QtCore import *
from PyQt4.QtXml import *
from qgis.core import *
from qgis.gui import *

gui_flag = True
app = QgsApplication(sys.argv, gui_flag)

# Make sure QGIS_PREFIX_PATH is set in your env if needed!
app.initQgis()

# Name of the .qgs file without extension
project_name = 'myproject'

#Important : The code is assuming that the .py file is in the same folder as the project
folderPath = QString(sys.path[0])+'/'
projectPath = QString(folderPath+project_name+'.qgs')
templatePath = QString(folderPath+project_name+'_firstcomposer.qpt')
imagePath = QString(folderPath+project_name+'.png')

#Getting project as Qfile and the first composer of the project as a QDomElement from the .qgs
projectAsFile = QFile(projectPath)
projectAsDocument = QDomDocument()
projectAsDocument.setContent(projectAsFile)
composerAsElement = projectAsDocument.elementsByTagName("Composer").at(0).toElement()

#This block store the composer into a template file
templateFile = QFile(templatePath)
templateFile.open(QIODevice.WriteOnly)
out = QTextStream(templateFile)
#I need next line cause UTF-8 is somewhat tricky in my setup, comment out if needed
out.setCodec("UTF-8")
param = QString
composerAsElement.save(out,2)
templateFile.close()

#And this block load back the composer into a QDomDocument
#Nb: This is ugly as hell, i guess there is a way to convert a QDomElement to a QDomDocument but every attemps failed on my side...
composerAsDocument = QDomDocument()
composerAsDocument.setContent(templateFile)

#Now that we got all we can open our project
canvas = QgsMapCanvas()
QgsProject.instance().read(QFileInfo(projectAsFile))
bridge = QgsLayerTreeMapCanvasBridge(
    QgsProject.instance().layerTreeRoot(), canvas)
bridge.setCanvasLayers()


#Lets try load that composer template we just extracted
composition = QgsComposition(canvas.mapSettings())
composition.loadFromTemplate(composerAsDocument, {})


#And lets print in our .png
image = composition.printPageAsRaster(0)
image.save(imagePath,'png')

#Some cleanup maybe?
QgsProject.instance().clear()
QgsApplication.exitQgis()



Я відкинув рядки тез із попереднього коду, оскільки, здавалося, вони взагалі нічого не роблять. Вони не породили помилок, але нічого кращого не зробили.

# You must set the id in the template
map_item = composition.getComposerItemById('map')
map_item.setMapCanvas(canvas)
map_item.zoomToExtent(canvas.extent())
# You must set the id in the template
legend_item = composition.getComposerItemById('legend')
legend_item.updateLegend()
composition.refreshItems()

і тіги видаляються, тому що вони видаються непотрібними при використанні printPageAsRaster ()

dpmm = dpi / 25.4
width = int(dpmm * composition.paperWidth())
height = int(dpmm * composition.paperHeight())    

# create output image and initialize it
image = QImage(QSize(width, height), QImage.Format_ARGB32)
image.setDotsPerMeterX(dpmm * 1000)
image.setDotsPerMeterY(dpmm * 1000)
image.fill(0)    

# render the composition
imagePainter = QPainter(image)
composition.renderPage(imagePainter, 0)
imagePainter.end()

Я просто налаштував VM з Unbuntu 14.04, і цей код працює як вітер. Тож питання пов’язане з версією Windows PyQgis (тестується на Window10 з встановленням Osgeo4w64), я подивлюсь, чи в трекер помилок вже відкритий квиток.
MarHoff

1

Іншим більш сучасним варіантом було б ознайомлення з набором 2-х інструментів, розроблених спільнотою QGIS. Оскільки Map-sprinter активно підтримується, слід очікувати, що сценарії будуть оновлені новими версіями QGIS.

Обидва інструменти забезпечують графічний інтерфейс, але основні сценарії записані в Python

Експортуйте композиторів у файли - https://github.com/DelazJ/MapsPrinter
Експортуйте композиторів з декількох проектів - https://github.com/gacarrillor/QGIS-Resources

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.