0

I want to export a lot of raster layers as rendered images. After looking around, I got to this code:

myDir = 'e:/Data/'
layers = [layer for layer in QgsProject.instance().mapLayers().values()]
pipe = QgsRasterPipe()
for layer in layers:
   extent = layer.extent()
   width, height = layer.width(), layer.height()
   renderer = layer.renderer()
   provider=layer.dataProvider()
   crs = layer.crs().toWkt() 
   pipe.set(provider.clone())
   pipe.set(renderer.clone())
   file_writer = QgsRasterFileWriter(myDir + layer.name() + ".tif")
   file_writer.writeRaster(pipe,
                           width,
                           height,
                           extent,
                           layer.crs())

But when I run it, I get this error:

Traceback (most recent call last):
  File "C:\PROGRA~1\QGIS3~1.12\apps\Python37\lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "<input>", line 1, in <module>
  File "<string>", line 6, in <module>
AttributeError: 'QgsVectorLayer' object has no attribute 'width'

I'm using QGIS 3.12.2. Any suggestions?

1 Answer 1

1

To help you understand the cause of the error, in the block of code you are iterating through all the layers loaded in the current project. In each iteration, you are calling methods such as width() and height() on the object referenced in the layer identifier. The object stored in this reference changes dynamically on each iteration of the for loop. I am guessing you have at least one vector layer loaded in your project as well as raster layers. Since QgsVectorLayer objects do not have the width() or height() methods, when the for loop hits a vector layer the error you received is raised.

This can be avoided by adding a conditional to the list comprehension so that only QgsRasterLayer objects are collected. You could use something like:

if isinstance(layer, QgsRasterLayer)

However, this would also include WMS layers etc. which may not be what you want. I used:

if layer.dataProvider().name() == 'gdal'

The code below is working for me (tested in 3.14.15). I have made a few other small changes. Since 3.8 you should also pass a QgsCoordinateTransformContext() argument to the writeRaster() method.

See: https://qgis.org/api/classQgsRasterFileWriter.html#a16e7914edef28fd41db83f599224f560

Also, I recommend using os.path.join() for constructing file path strings.

import os

myDir = 'e:/Data'
project = QgsProject().instance()
layers = [layer for layer in QgsProject.instance().mapLayers().values()
            if layer.dataProvider().name() == 'gdal']
pipe = QgsRasterPipe()
for layer in layers:
    pipe.set(layer.dataProvider().clone())
    pipe.set(layer.renderer().clone())
    output_path = os.path.join(myDir, '{}.tif'.format(layer.name()))
    file_writer = QgsRasterFileWriter(output_path)
    file_writer.Mode=1
    file_writer.writeRaster(pipe,
                           layer.width(),
                           layer.height(),
                           layer.extent(),
                           layer.crs(),
                           project.transformContext())

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.