I am attempting to export an image based on a portion of the map.
I have written code that successfully identifies the area of the map I would like to output, but I am having trouble exporting anything other then a white screen.
I think it has something to do with the following two lines I'm not sure I am actually moving the canvas to the correct portion of the map and I am not sure I am pointing the mapexport to the same layout I am filling up.
map.zoomToExtent(iface.mapCanvas().extent())
mapexport = QgsLayoutExporter(layout)
import os
from qgis.core import (
QgsGeometry,
QgsMapSettings,
QgsPrintLayout,
QgsMapSettings,
QgsMapRendererParallelJob,
QgsLayoutItemLabel,
QgsLayoutItemLegend,
QgsLayoutItemMap,
QgsLayoutItemPolygon,
QgsLayoutItemScaleBar,
QgsLayoutExporter,
QgsLayoutItem,
QgsLayoutPoint,
QgsLayoutSize,
QgsUnitTypes,
QgsProject,
QgsFillSymbol,
QgsAbstractValidityCheck,
check,
)
from qgis.PyQt.QtGui import (
QPolygonF,
QColor,
)
from qgis.PyQt.QtCore import (
QPointF,
QRectF,
QSize,
)
metersPerPixel = 16
image_location = os.path.join(QgsProject.instance().homePath(), "render.png")
sizelayer = iface.activeLayer()
settings = QgsMapSettings()
settings.setLayers([sizelayer])
settings.setBackgroundColor(QColor(255, 255, 255))
totalmapRect = sizelayer.extent()
xStart = totalmapRect.xMinimum()
xEnd = totalmapRect.xMaximum()
print(xStart)
print(xEnd)
yStart = totalmapRect.yMinimum()
yEnd = totalmapRect.yMaximum()
corner1 = QgsPointXY(xStart,yStart)
corner2 = QgsPointXY(xStart,yEnd)
corner3 = QgsPointXY(xEnd,yEnd)
corner4 = QgsPointXY(xEnd,yStart)
#Create a measure object
distance = QgsDistanceArea()
#distance.setEllipsoid(True)
#Set the ellipsoid over which QGIS will perform calculations, e.g., WGS84:
distance.setEllipsoid('WGS84')
#Now you can measure the distance once again (which will give you ~322.48m.):
#Measure the distance
height = distance.measureLine(corner1, corner2)
width = distance.measureLine(corner2, corner3)
print(width)
print(height)
#printed raster will have (width * metersPerPixel) meters in X and
#(height * metersPerPixel) meters in Y
xpixels = width / metersPerPixel
ypixels = height / metersPerPixel
print(xpixels)
print(ypixels)
settings.setOutputSize(QSize(xpixels, ypixels))
settings.setExtent(sizelayer.extent())
#Insert Layout Information
project = QgsProject.instance()
layout = QgsPrintLayout(project)
layout.initializeDefaults()
map = QgsLayoutItemMap(layout)
Set map item position and size (by default, it is a 0 width/0 height item placed at 0,0)
map.attemptMove(QgsLayoutPoint(0,0, QgsUnitTypes.LayoutMillimeters))
map.attemptResize(QgsLayoutSize(width,height, QgsUnitTypes.LayoutMeters))
Provide an extent to render
map.zoomToExtent(iface.mapCanvas().extent())
base_path = os.path.join(QgsProject.instance().homePath())
pdf_path = os.path.join('C:/VBS Logs/', "output.pdf")
mapexport = QgsLayoutExporter(layout)
mapexport.exportToPdf(pdf_path, QgsLayoutExporter.PdfExportSettings())
mapexport.exportToImage('C:/VBS Logs/test_render2.png', QgsLayoutExporter.ImageExportSettings())
render = QgsMapRendererParallelJob(settings)
def finished():
img = render.renderedImage()
# save the image; e.g. img.save("/Users/myuser/render.png","png")
#img.save(image_location, "png")
img.save('C:/VBS Logs/test_render1.png', "png")
render.finished.connect(finished)
Start the rendering
render.start()
The following loop is not normally required, we
are using it here because this is a standalone example.
from qgis.PyQt.QtCore import QEventLoop
loop = QEventLoop()
render.finished.connect(loop.quit)
loop.exec_()
I tried to search the documentation and the forums, but don't see anything that corresponds.
I found the following, but that seems to apply to layouts in the print composer not just straight map exports. https://api.qgis.org/api/classQgsLayoutExporter.html#details
The exact functionality I am looking for lies entirely within the manual operation Project menu -> Save Image As, I just can't seem to find documentation that matches that functionality. Thanks, Jim
– JGiacchi Jul 02 '23 at 04:00