Сохранить Print / Map QGIS composer view как PNG / PDF с использованием Python (без изменений в видимом макете)?
11
У меня открывается окно просмотра / печати QGIS со всеми элементами, отрегулированными так, как я хочу. Теперь мне нужно распечатать / сохранить / экспортировать это как файл PNG или PDF из консоли Python / скрипта Python.
Я не хочу ничего менять в текущем макете. Большинство примеров, которые я нашел (например, это ), изменяют положение или размер карты в выходном PDF по сравнению с тем, что я вижу в моем текущем представлении композитора. Я хочу получить точно такой же результат, как и при нажатии «Печать» -> « Экспортировать как изображение» .
Как я могу это сделать? Атлас не является решением для меня.
Просто передайте пустой dict в функцию component.loadFromTemplate () вместо «карты замещения», которую он использует, поскольку вас не интересует эта функциональность.
Кроме того, поскольку вы спрашивали о «экспортировать как изображение», а не «экспортировать как PDF», вам придется выполнить немного больше работы, чем использовать функцию-член exportAsPDF ().
Ниже приведена модифицированная версия кода Тима, которая должна сделать свое дело, работая из внешнего скрипта Python. Установите DPI и переменные файла project + composer, как требуется.
(Если вы используете консоль Python в QGIS вместо того, чтобы делать это как внешний скрипт, вы можете получить текущий холст карты, используя qgis.iface, и вам не нужно использовать весь код загрузки проекта и т. Д.).
import sysfrom qgis.core import(QgsProject,QgsComposition,QgsApplication,QgsProviderRegistry)from qgis.gui importQgsMapCanvas,QgsLayerTreeMapCanvasBridgefromPyQt4.QtCoreimportQFileInfofromPyQt4.QtXmlimportQDomDocument
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 projectQgsProject.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.
Мой код может извлечь .qpt из файла .qgs и успешно загрузить композитор из шаблона. Он также печатает композитор в файл .png и правильно отображает метки и формы, хранящиеся в композиторе.
Однако не удается загрузить все элементы, связанные с фактической картой и слоями (метка, содержащая выражение из слоя, также не рисуется). Я думаю, что я немного упустил, как проект должен быть загружен и связан с композитором.
Некоторые люди в комментарии к оригинальной статье Тима Саттона упоминали, что они застряли на одной и той же стадии под Windows (это мой случай). Это действительно расстраивает, потому что я чувствую, что ответ действительно очень близок. Уважаемый интернет, помогите пожалуйста!
Также это мои первые попытки на Python, поэтому я надеюсь, что вы будете добрыми;)
#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 : /gis//a/130102/17548import sysfromPyQt4.QtCoreimport*fromPyQt4.QtXmlimport*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 ()
Я только что установил виртуальную машину с Unbuntu 14.04, и этот код работает очень быстро. Так что проблема связана с версией PyQgis для Windows (протестирована на Window10 с установкой Osgeo4w64), я посмотрю, открыт ли тикет в трекере ошибок.
MarHoff
1
Еще один более актуальный вариант - взглянуть на набор инструментов, разработанный сообществом QGIS. Поскольку Map-sprinter активно поддерживается, следует ожидать, что скрипты будут обновлены в следующих версиях QGIS.
Оба инструмента предоставляют графический интерфейс, но базовые сценарии написаны на Python
python generate_pdf.py
Вы можете запрограммировать его самостоятельно или повторно использовать метод из
Maps Printer
плагина. Я опишу второй вариант, потому что он проще.Вам нужно установить
Maps Printer
плагин, открыть проект QGIS с настроенным композитором, открыть консоль QGIS Python и запустить этот фрагмент кода (вам необходимо настроить его в соответствии с собственными настройками вYour settings
разделе).После запуска вы получите новый файл в
/path/to/export_folder/my composer.png
. Вы также можете использовать в'.pdf'
качестве расширения для экспорта композитора в формате PDF.источник
Возможно также посмотрите на мой другой ответ, поскольку новые более современные инструменты появились после этого.
Я пришел к приведенному ниже коду, который, к сожалению, не полностью функционален. Это основано на решении выше и на этих других вопросах:
Как программно экспортировать композицию как изображение?
Как я могу прочитать настройки для QgsPaperItem из XML?
Сохранить Map Canvas в формате PNG с прозрачным фоном программно с помощью QGIS?
Мой код может извлечь .qpt из файла .qgs и успешно загрузить композитор из шаблона. Он также печатает композитор в файл .png и правильно отображает метки и формы, хранящиеся в композиторе.
Однако не удается загрузить все элементы, связанные с фактической картой и слоями (метка, содержащая выражение из слоя, также не рисуется). Я думаю, что я немного упустил, как проект должен быть загружен и связан с композитором.
Некоторые люди в комментарии к оригинальной статье Тима Саттона упоминали, что они застряли на одной и той же стадии под Windows (это мой случай). Это действительно расстраивает, потому что я чувствую, что ответ действительно очень близок. Уважаемый интернет, помогите пожалуйста!
Также это мои первые попытки на Python, поэтому я надеюсь, что вы будете добрыми;)
Я удалил эти строки из предыдущего кода, так как они, казалось, ничего не делали. Они не породили ошибок, но не сделали ничего лучше.
и те тоже удалены, потому что они казались ненужными при использовании printPageAsRaster ()
источник
Еще один более актуальный вариант - взглянуть на набор инструментов, разработанный сообществом QGIS. Поскольку Map-sprinter активно поддерживается, следует ожидать, что скрипты будут обновлены в следующих версиях QGIS.
Оба инструмента предоставляют графический интерфейс, но базовые сценарии написаны на Python
Экспорт композиторов в файлы - https://github.com/DelazJ/MapsPrinter
Экспорт композиторов из нескольких проектов - https://github.com/gacarrillor/QGIS-Resources
источник