5

Overall Question: How can I get the rendered tif image to keep the modifications seen in the image produced by map canvas?


I am writing a standalone Python script. I have simplified my code below for debugging purposes. Its purpose is to load a shapefile vector layer, in my case SOUNDG.shp, of the geometry type 'point', and then serve a tif image of the vector layer SOUNDG.

I have experimented with QgsMapCanvas thoroughly and can confirm that this specific vector layer is correctly displayed in the canvas; thus, paths to my file and the creation of a vector layer object are correct. Now, I am abandoning canvas entirely and am transitioning to solely relying on serving up a tif image through my script. I am keeping my modifications of the vector layer in my script as well (the depth values).

Canvas Image of SOUNDG point data

As you can see I have modified the vector layer corresponding to depth values. canvas image

Tif image

In contrast to canvas, when rendering to tif in my script, as seen below, my SOUNDG.tif image is a blank white image. There is nothing displayed. In addition, I receive no error messages. blank image

I have tried rendering multiple layers of other geometries (lines and polygons) to tif and they are rendered with no issues at all. All layers are visible. My only issue lies with vector layers that have point geometries - they aren't visible when rendered to tif.

How can I fix this? (Using only script)

Here is my code based off of PyQgis' Cookbook:

# supply path to qgis install location
QgsApplication.setPrefixPath('/usr', True)
# create a reference to the QgsApplication, setting the
# second argument to False disables the GUI
app = QgsApplication([], True)
# load providers
app.initQgis()

# 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)
renderer = QgsMapRenderer()

# keep track of all layer IDs
mapLayers = []

# create vector layer object
layer = QgsVectorLayer('/ENC_ROOT/US6SP10M/shapefiles/SOUNDG.shp',\
                       'SOUNDG', 'ogr')
QgsMapLayerRegistry.instance().addMapLayer(layer)
mapLayers.append(layer.id())
renderer.setLayerSet(mapLayers)

# set extent
rect = QgsRectangle(renderer.fullExtent())
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("/ENC_ROOT/US6SP10M/shapefiles/SOUNDG.tif", "tif")

app.exitQgis()

I noticed this occurs when also rendering to 'png', or rather, any method of rasterization.

UPDATE: I've begun to experiment with the gdal_rasterize route:

def rasterize(layer, source_dir, output_dir):
# this renders the point to tif correctly but no modifications are considered
call(['gdal_rasterize', '-a', 'DEPTH', '-ts', '800', '600', '-l', layer, source_dir, output_dir])

This method now gives me a .tif image that displays points in a black and white format. When I create modifications to the point layer, such as replacing the dots with ints representing water depths, is there a way such that those modifications would still hold in the rasterized .tif version?

Tif image using gdal_rasterizegdal_rasterize


I've spent numerous edits trying to make this a smooth read and very understandable. If you aren't up voting it then that is telling me that something isn't clear for you. Please make that clear so that I can edit the post as needed; this will hopefully bring me to someone who does have an answer.


5
  • Why don't you simply use gdal_rasterize? Re-inventing the wheel is no good idea if you have little time.
    – AndreJ
    Commented Jul 19, 2016 at 18:41
  • I need to modify these vector layers such as changing marker symbology and appearance. Would a simple gdal_rasterize keep these changes? I've already modified numerous vector layers, all that is needed is to rasterize it. And also, that's kind of the question I'm having here, is what I'm asking for 'reinventing the wheel'? There is a simple method to create a tif which works for the rest of the layers, hence, I'm curious if this 'point' issue is a known issue or not. No one seems to have an issue with it, thus, there must be something going on that I'm unaware of. Commented Jul 19, 2016 at 18:47
  • This question might be related: gis.stackexchange.com/questions/198287/…
    – AndreJ
    Commented Jul 19, 2016 at 18:58
  • Although it gives some alternatives. It seems as though if I go the routes stated in the link you provided, I may not be able to keep my modifications of the layer Commented Jul 20, 2016 at 18:31
  • 1
    Rasterize does not seem to fit, since you want to apply styling to your data. Have you thought about using the print composer? It can output georeferenced tif as well.
    – AndreJ
    Commented Jul 21, 2016 at 18:48

2 Answers 2

5

I think that your issue is only a "Zoom In" problem. I'm going to render to tif these random points with Raster-> Conversion -> Rasterize (Vector to Raster) Tool (cell resolution 30 x 30) of QGIS; equivalent to your standalone Python script.

enter image description here

Loaded raster layer looks as if no point had been rasterized.

enter image description here

However, with point layer as first layer, 'Zoom In' (very low scale) in whatever point and its corresponding rasterized cell appears.

enter image description here

4
  • I'm sorry I don't think I quite understand. I've tried zooming into my tif image and I still don't see any points. Commented Jul 18, 2016 at 13:13
  • I also ran my code then loaded the .tif image as a raster layer in QGIS and still had no success in seeing points. (I tried zooming in as well) Commented Jul 18, 2016 at 14:55
  • I've run into that problem too. It seems like it is a bug creating a new image. If you use an already created image it will work fine. Commented Jul 18, 2016 at 18:28
  • The bug you are talking about is only an issue when running these process specifically through QGIS. I am only using Python scripting to generate this so that is not the issue. Commented Jul 19, 2016 at 16:14
3

In case there are those who may run into the same issue, here is my solution (that works beautifully!)

from qgis.core import *
from qgis.gui import *
from PyQt4.QtCore import *

source_dir = '/home/cassandra/desktop/file_formats/ENC_ROOT/US6SP10M/shapefiles/SOUNDG.shp'
name = 'SOUNDG'
output_dir = '/home/cassandra/desktop/file_formats/ENC_ROOT/US6SP10M/shapefiles/SOUNDG.tif'

# initiate canvas for debugging purposes
# supply path to qgis install location
QgsApplication.setPrefixPath('/usr', True)
# create a reference to the QgsApplication, setting the
# second argument to False disables the GUI
app = QgsApplication([], True)
# load providers
app.initQgis()
# create Qt mapCanvas widget
canvas = QgsMapCanvas()
canvas.setCanvasColor(Qt.white)
# enable this for smooth rendering
canvas.enableAntiAliasing(True)

# load vector layer into canvas
layer = QgsVectorLayer(source_dir, name, 'ogr')
# register the vector layer to the layer registry
QgsMapLayerRegistry.instance().addMapLayer(layer)

# set extent of canvas as well as what layers you would like to display
canvas.setExtent(layer.extent())
canvas.setLayerSet([QgsMapCanvasLayer(layer)])
canvas.refresh()

# rendering my map canvas to tif image
settings = canvas.mapSettings()
settings.setLayers([layer.id()])
job = QgsMapRendererParallelJob(settings)
job.start()
job.waitForFinished()
image = job.renderedImage()
image.save(output_dir)

app.exitQgis()
3
  • So you had to use QgsMapCanvas after all? Did you submit a bug ticket? Commented Jul 23, 2016 at 7:52
  • I'm still a bit unsure as to what is going on under the hood of these working statements, but yes, I think I am relying on QgsMapCanvas. and No I did not, but I will go ahead and do that. Commented Jul 24, 2016 at 16:17
  • I recommend the suggested method as opposite to saveToImage() because using it with a custom QgsMapCanvas() give back unreadable images Commented Mar 13, 2017 at 12:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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