5

I would like to use standalone appliction to apply .qml style to a layer and use QgsMapRenderer() to save it as image on a hard disk. The are a lot of questions like mine at this site and it seems that most of the issues emerge from settings for QgsApplication(). Unfortunately it seems that I wasn't able to setup QgsApplication() in a right way. My code is pretty standart rendering code from PyQGIS Cookbook that was used as a template in other questions like mine. It produces transparent .png inage with no layer rendered. Though this code works (without initialisation of QgsApplication()) if I ran it line by line in QGIS console (QGIS 2.4).

So I have following QgsApplication() settings (on Alt Linux).

Application state:
QGIS_PREFIX_PATH env var:       
Prefix:     /usr
Plugin Path:        /usr/lib64/qgis
Package Data Path:  /usr/share/qgis
Active Theme Name:  
Active Theme Path:  :/images/themes//
Default Theme Path: :/images/themes/default/
SVG Search Paths:   /usr/share/qgis/svg/
User DB Path:   /usr/share/qgis/resources/qgis.db 

The code itself:

from qgis.core import * 
from qgis.utils import *
from qgis.gui import *
from PyQt4.QtCore import QSize
from PyQt4.QtGui import QPainter, QImage, QColor

QgsApplication.setPrefixPath('/usr', True)
QgsApplication.initQgis()
print QgsApplication.showSettings()


lyr = QgsVectorLayer('test.shp', 'points', 'ogr')
lyr_id = lyr.id()
QgsMapLayerRegistry.instance().addMapLayer(lyr)
lyr.loadNamedStyle( 'test.qml')


# create image
img = QImage(QSize(800, 600), QImage.Format_ARGB32_Premultiplied)

# set image's background color
# color = QColor(255, 255, 255)
# img.fill(color.rgb())

# create painter
p = QPainter()
p.begin(img)
p.setRenderHint(QPainter.Antialiasing)

layers = QgsMapLayerRegistry.instance().mapLayers()
lst = layers.keys()
print 'lst', lst
renderer = QgsMapRenderer()
renderer.setLayerSet(lst)

extent = renderer.fullExtent()
rect = QgsRectangle(extent)
# print rect.toString()
rect.scale(1.1)
renderer.setExtent(rect)

# set output size
renderer.setOutputSize(img.size(), img.logicalDpiX())

# do the rendering
renderer.render(p)
p.end()

# save image
img.save('test.png', 'png')

QgsApplication.exitQgis()
  • Are you locked to 2.4? This is a lot easier 2.8+ as the new rendering code is easier to use. – Nathan W Apr 26 '16 at 22:57
  • @NathanW, yeah, I'm kinda locked to 2.4, though I have plans to migrate to newer version. Do you have an example of rendering code for versions 2.8+? – SS_Rebelious Apr 27 '16 at 10:20
  • Yep I will post one. – Nathan W Apr 27 '16 at 10:24
3
+100

I got it to work on my GNU/Linux machine by replacing this code block from your script:

QgsApplication.setPrefixPath('/usr', True)
QgsApplication.initQgis()

by this one:

qgisApp = QgsApplication([], True)
QgsApplication.setPrefixPath('/usr', True)
QgsApplication.initQgis()

The first line of this code block initializes the QgsApplication class, making it clear (second parameter set to True) that we want a GUI-enabled application, not only a console one. After all, the script relies on some Qt4 GUI classes.

I tested it using QGIS 2.14.1. Hope this solves your question.

By the way, there's no need to import anything from qgis.utils nor qgis.gui.

  • Nope, this doesn't work for me T_T. Also why do you create qgisApp and then use QgsApplication anyway? – SS_Rebelious Apr 27 '16 at 10:43
  • You could also use qgisApp to call setPrefix and initQgis, that's how I posted it originally, but then had a look at the PyQGIS cookbook and changed it. Do you still get no layers in the image? I was getting a segmentation fault with your script, until I modified it. Don't have QGIS 2.4 to test it, I would really upgrade. – Germán Carrillo Apr 27 '16 at 11:57
  • 1
    Just wondering whether there is a problem with the layer extent (namely, with the layer projection). Have you tried to set it manually in your script? Could you upload your vector layer somewhere, so that I can give it a try with your data? – Germán Carrillo Apr 28 '16 at 13:24
3

I have done a similar stuff, mine does work. Check it out. It is for 2.14 qgis. If you are locked you should probably check http://docs.qgis.org/2.2/en/docs/pyqgis_developer_cookbook/raster.html (see the version number on the link)

from PyQt4.QtCore import QSize
from PyQt4.QtGui import QPainter, QImage, QColor
from PyQt4.QtCore import QFileInfo

from qgis.core import *
import qgis.utils



app = QgsApplication([],True)

# supply path to where is your qgis installed
QgsApplication.setPrefixPath("/usr/", True)

# load providers
QgsApplication.initQgis()

fileName = '/home/pegg/Downloads/ECMWF_ATP_160_10UV_015.tiff'
dst_filename = '/home/pegg/Downloads/test.png'


fileInfo = QFileInfo(fileName)
baseName = fileInfo.baseName()
rlayer = QgsRasterLayer(fileName, baseName)
if not rlayer.isValid():
  print "Layer failed to load!"




#rlayer.setDrawingStyle('MultiBandColor') #make sure
QgsMapLayerRegistry.instance().addMapLayer(rlayer)

# create image
w=rlayer.width()
h=rlayer.height()
img = QImage(QSize(w, h), QImage.Format_ARGB32_Premultiplied)

# set image's background color
color = QColor(255, 255, 255)
img.fill(color.rgb())

# create painter
p = QPainter()
p.begin(img)
p.setRenderHint(QPainter.Antialiasing)

render = QgsMapRenderer()

# set layer set
lst = [rlayer.id()]  # add ID of every layer
render.setLayerSet(lst)

# set extent
rect = QgsRectangle(render.fullExtent())
rect.scale(1.0)

render.setExtent(rect)

# set output size
render.setOutputSize(img.size(), img.logicalDpiX())

# do the rendering
render.render(p)

p.end()

# save image
img.save(dst_filename,"png")




QgsApplication.exitQgis()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.