I assume, you run your map render context in a standalone application. I'm not sure if you want to produce high resolution images or set only the DPI number.
If you want to produce high resolution images, you could set mapCanvas()mapSettings().setDevicePixelRatio(scaleFactor)
before you call mapCanvas().saveAsImage('FILENAME.PNG')
. The function triggers QgsMapSettings::updateDerived()
and calculates the mapUnitsPerPixel
and the new DPI number.
# line 170
// calculate the translation and scaling parameters
const double mapUnitsPerPixelY = mExtent.height() / myHeight;
const double mapUnitsPerPixelX = mExtent.width() / myWidth;
mMapUnitsPerPixel = mapUnitsPerPixelY > mapUnitsPerPixelX ? mapUnitsPerPixelY : mapUnitsPerPixelX;
...
# Line 192
...
// update the scale
mScaleCalculator.setDpi( mDpi * mDevicePixelRatio );
mScale = mScaleCalculator.calculate( mVisibleExtent, mSize.width() );
I have not tested this befor because, I personally try to avoid the rendering into an image context and use a the pdf printer context instead. In the printer context you have all properties to render your map into a well defined page. You can use imagemagick
or ghostscript
to create DPI correct and anti-aliased images later.
Example code snippet from one of my projects
#!/usr/bin/env python3
import sys
from qgis.core import *
from qgis.gui import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtXml import *
# ---------------------------------------------------
# Constants
# ---------------------------------------------------
SHP_DATA = 'ogr'
QGIS_PATH = '/usr'
PAGE_WIDTH = 300 # mm
PAGE_HEIGHT = 300 # mm
MAP_WIDTH = 130
MAP_HEIGHT = 130
MAP_LEFT = 25
MAP_TOP = 10
MAP_RIGHT = MAP_LEFT + MAP_WIDTH
MAP_BOTTOM = MAP_TOP + MAP_HEIGHT
GAP = 40
LEG_TOP = MAP_TOP
LEG_LEFT = MAP_RIGHT + GAP
# -----------------------------------------------------
# Keys for the map frame
# -----------------------------------------------------
# Label inside or outside of the map
GRID_ANNON_INMAP = 0
GRID_ANNON_OUTMAP = 1
GRID_ANNON_NONE = 2
# Keys for the grid annotation side
GRID_SIDE_RIGHT = 0
GRID_SIDE_LEFT = 1
GRID_SIDE_BOTTOM = 2
GRID_SIDE_TOP = 3
# Keys for the label direction
GRID_ANNON_DIR_0 = 0
GRID_ANNON_DIR_90 = 1
GRID_ANNON_DIR_180 = 2
GRID_ANNON_DIR_270 = 3
# Keys for the axis format
GRID_ANNON_FMT_DEC = 0 # Dezimalzahlen + N, E
GRID_ANNON_FMT_DM = 1 # D°M'N und D°M'E
GRID_ANNON_FMT_DMS = 2 # D°M'S"N und D°M'S"E
GRID_ANNON_FMT_DEC_NONSWE = 3 # Ohne Dezimalzahlen
GRID_ANNON_FMT_DM_NONSWE = 4 # D°M'
# Gridd type
GRID_FRAME_PLAIN = 0 # einfache Linie
GRID_FRAME_ZEBRA = 1 # Kästchen
# -----------------------------------------------------
# Settings for the map frame
# -----------------------------------------------------
# Schrittweite der Label 10km
GRID_FRAME_STEP_LABX = 1/3.0
GRID_FRAME_STEP_LABY = 1/6.0
# Fonts font for the map labels
GRID_FRAME_FONT = QFont('Arial',11,0)
# Precisiion of the labels
GRID_FRAME_PRECISION = 0
# Size of the map crosses 0 if you don't want
GRID_FRAME_CROSS_SIZE = 0
# Breite des Rahmens
GRID_FRAME_WIDTH = 1
# Colors for the frame
GRID_COLOR_LIGHT = QColor('#ffffff')
GRID_COLOR_DARK = QColor('#040404')
# ---------------------------------------------------
# Create a map
# ---------------------------------------------------
# @param page - Composer page
# @param upper - Upper border of the sheet in mm
# @param left - Left border of the sheet in mm
# @param lower - Lower border of the sheet in mm
# @param right - Right border of the sheet in mm
# @param extent - Extent of the map info world coordinates only
# @return Map with border config (..see also GRID_FRAME_*)
# ---------------------------------------------------
def createMap(page, upper, left, lower, right, extent):
# Karte bauen
print "Create ma sheet: (%d, %d) (%d, %d) [mm]" % (upper, left, lower, right)
print " Size UTM: (%2.0f,%2.0f) (%2.0f, %2.0f) [m]" \
% (extent.xMinimum(), extent.yMinimum(), \
extent.xMaximum(), extent.yMaximum())
cmap = QgsComposerMap(page, upper, left, lower, right)
# Kartenabdeckung eintragen
cmap.setNewExtent(extent)
# Create frame and cosses ----------------------
cmap.setGridStyle(GRID_FRAME_ZEBRA)
# Label font
cmap.setGridAnnotationFont(GRID_FRAME_FONT)
# Size of the crosses
cmap.setCrossLength(GRID_FRAME_CROSS_SIZE)
# Intervalabstand setzten
cmap.grid().setCrs(tk.epsgCrs(4326))
cmap.setGridIntervalX(GRID_FRAME_STEP_LABX)
cmap.setGridIntervalY(GRID_FRAME_STEP_LABY)
# Label format
cmap.setGridAnnotationFormat(GRID_ANNON_FMT_DM_NONSWE)
# Precision of the label format
cmap.setGridAnnotationPrecision(GRID_FRAME_PRECISION)
# Ausrichtung des Labels fuer die ensprechende Achse
cmap.setGridAnnotationDirection(GRID_ANNON_DIR_90,
GRID_SIDE_LEFT)
cmap.setGridAnnotationDirection(GRID_ANNON_DIR_90,
GRID_SIDE_RIGHT)
# Label per axis Labelposition
cmap.setGridAnnotationPosition(GRID_ANNON_OUTMAP,
GRID_SIDE_TOP)
cmap.setGridAnnotationPosition(GRID_ANNON_OUTMAP,
GRID_SIDE_RIGHT)
cmap.setGridAnnotationPosition(GRID_ANNON_OUTMAP,
GRID_SIDE_LEFT)
cmap.setGridAnnotationPosition(GRID_ANNON_OUTMAP,
GRID_SIDE_BOTTOM)
# Activate annotation
cmap.setShowGridAnnotation(1)
# Frame style -----------------------------
cmap.setGridFrameStyle(GRID_FRAME_ZEBRA)
# Frame width
cmap.setGridFrameWidth(GRID_FRAME_WIDTH)
# Frame color (hell & dunkel)
cmap.setGridFrameFillColor1(GRID_COLOR_LIGHT)
cmap.setGridFrameFillColor2(GRID_COLOR_DARK)
# Enable frame
cmap.setFrameEnabled(True)
return cmap
# ------------------------------------------------------
# Start application ...
# ------------------------------------------------------
application = QgsApplication([], True)
QgsApplication.setPrefixPath(QGIS_PATH, True)
QgsApplication.initQgis()
# ------------------------------------------------------
# Service function print a page into a pdf
# ------------------------------------------------------
def writePdfFullPage(page, width, height, fileName='out.pdf'):
print "Schreibe PDF: "+fileName
printer = QPrinter()
printer.setOutputFormat(QPrinter.PdfFormat)
printer.setOutputFileName(fileName)
printer.setPaperSize(QSizeF(width, height), QPrinter.Millimeter)
printer.setFullPage(True)
printer.setColorMode(QPrinter.Color)
printer.setResolution(page.printResolution())
pdfPainter = QPainter(printer)
paperRectMM = printer.pageRect(QPrinter.Millimeter)
paperRectPixel = printer.pageRect(QPrinter.DevicePixel)
page.render(pdfPainter, paperRectPixel, paperRectMM)
pdfPainter.end()
# ------------------------------------------------------
# Calculate the map extent
# ------------------------------------------------------
def calcMapExt(lyr, offs=0.01):
result = lyr.extent()
print "Map extent:", result.xMinimum(), result.yMinimum(), result.xMaximum(), result.yMaximum()
result.setXMinimum(result.xMinimum()-offs)
result.setYMinimum(result.yMinimum()-offs)
result.setXMaximum(result.xMaximum()+offs)
result.setYMaximum(result.yMaximum()+offs)
print "Map extent:", result.xMinimum(), result.yMinimum(), result.xMaximum(), result.yMaximum()
return result;
# ---------------------------------------------------
# Open a vector layer
# ---------------------------------------------------
def openVectorLayer(uri, name):
print "Open layer: %s " % (name)
layer = QgsVectorLayer(uri.uri(),name,SHP_DATA)
if not layer.isValid():
msg = "Cannot open layer '"+name+"'\n"
msg += "File: "+uri+"\n"
msg += "Filter: "+where+"\n"
raise ValueError(msg)
print " %d Object(s)" % (layer.featureCount())
return layer
# ----------------------------------------------
# Create the legend
# ----------------------------------------------
def createLegend (page, layers, x, y, title, \
titleFont = QFont('Arial',12,2), \
groupFont = QFont('Arial',11,1),
itemFont = QFont('Arial',10,1) ):
print "Create legend: %s %d %d " % (title, x, y)
cleg = QgsComposerLegend(page)
cleg.setTitle(title)
cleg.rstyle(QgsComposerLegendStyle.Symbol).setMargin(QgsComposerLegendStyle.Top, 1)
cleg.setStyleFont(QgsComposerLegendStyle.Title, titleFont)
cleg.setStyleFont(QgsComposerLegendStyle.Subgroup, groupFont)
cleg.setStyleFont(QgsComposerLegendStyle.SymbolLabel, itemFont)
cleg.setX(x)
cleg.setY(y)
cleg.model().setLayerSet(layers)
return cleg
# ---------------------------------------------------
# Read some layers and add a renderer
# ---------------------------------------------------
# Region of interest
lyrRoi = openVectorLayer('roi.shp','roi')
symRoi = QgsSimpleLineSymbolLayerV2()
symRoi.setColor(QColor('#dd4433'))
symRoi.setWidth(1)
lyrRoi.rendererV2().symbols()[0].changeSymbolLayer(0, symRoi)
# Special protection area
lyrSPA = openVectorLayer('SPA.shp','SPA')
symSPAa = QgsSimpleLineSymbolLayerV2()
colSPA = QColor('#aaaaaa');
symSPAa.setColor(colSPA)
symSPAa.setWidth(0.5)
symSPAb = QgsLinePatternFillSymbolLayer()
symSPAb.setColor(colSPA)
symSPAb.setLineWidth(0.5)
symSPAb.setLineAngle(45.0)
symSPAb.setDistance(1.5);
lyrSPA.rendererV2().symbols()[0].changeSymbolLayer(0, symSPAa)
lyrSPA.rendererV2().symbols()[0].appendSymbolLayer(symSPAb)
# -------------------------------------------
# Open the render engine
# -------------------------------------------
renderer = QgsMapRenderer()
mapCrs = tk.epsgCrs(3395)
renderer.setDestinationCrs(mapCrs)
renderer.setProjectionsEnabled(True)
mapset = []
mapset.append(lyrRoi.id())
mapset.append(lyrContent.id())
...
renderer.setLayerSet(mapset)
mapExtent = calcMapExt(lyrRoi);
mapTrfm = QgsCoordinateTransform(lyrRoi.crs(), mapCrs)
mapExtent = mapTrfm.transform(mapExtent)
renderer.setExtent(mapExtent)
# --------------------------------------------------
# Declare a page and store the PDF
# --------------------------------------------------
page = QgsComposition(renderer)
page.setPlotStyle(QgsComposition.Print)
# Create the map...
cmap= createMap(page, MAP_LEFT, MAP_TOP, \
MAP_RIGHT, MAP_BOTTOM, mapExtent)
...
# Legende
cleg = createLegend( page, mapset, \
LEG_LEFT, LEG_TOP, \
'')
writePdfFullPage(page,PAGE_WIDTH, PAGE_HEIGHT, \
fileName='example.pdf')
print "OK."
QgsApplication.exitQgis()
# EOF