1 votos

Cambiar la resolución al exportar el lienzo del mapa como imagen con python

Quiero crear un png de georeferencia del lienzo del mapa en QGIS usando Python con:

mapCanvas().saveAsImage('filename.png')

Quiero poder cambiar la resolución de la predeterminada de 96 ppp.

¿Hay alguna manera de ajustar esto usando el editor de Python dentro de QGIS?

2voto

huckfinn Puntos 698

Supongo que ejecuta su contexto de renderización de mapas en una aplicación independiente. No estoy seguro de si usted quiere producir imágenes de alta resolución o establecer sólo el número de DPI.

Si quieres producir imágenes de alta resolución, puedes poner mapCanvas()mapSettings().setDevicePixelRatio(scaleFactor) antes de llamar mapCanvas().saveAsImage('FILENAME.PNG') . La función activa QgsMapSettings::updateDerived() y calcula el mapUnitsPerPixel y el nuevo número de DPI.

 # 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() );

No he probado esto antes porque, personalmente, trato de evitar la representación en un contexto de imagen y utilizar un contexto de impresora pdf en su lugar. En el contexto de la impresora tienes todas las propiedades para renderizar tu mapa en una página bien definida. Puedes usar imagemagick o ghostscript para crear imágenes correctas en DPI y con antialiasing posteriormente.

Ejemplo de fragmento de código de uno de mis proyectos

#!/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

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X