1

Next code, read and print original and modified raster pixels values by using a QgsRasterBlock object ('block' method of QgsRasterDataProvider). The objective is to obtain a new raster with the new block values. However, these new values are not overwritten in the provider; as it can be observed at next image (with the help of Value Tool plugin).

enter image description here

Complete code is:

layer = iface.activeLayer()

provider = layer.dataProvider()

extent = provider.extent()

rows = layer.height()
cols = layer.width()

xsize = layer.rasterUnitsPerPixelX()
ysize = layer.rasterUnitsPerPixelY()

print rows, cols

block = provider.block(1, extent, cols, rows)

print "original block"

for i in range(rows):
    for j in range(cols):
        print block.value(i,j)

for i in range(rows):
    for j in range(cols):
        if block.value(i,j) == 4:
            block.setValue(i, j, 25)

print "modified block"

for i in range(rows):
    for j in range(cols):
        print block.value(i,j)

pipe = QgsRasterPipe()

pipe.set(provider.clone())

rasterWriter = QgsRasterFileWriter("/home/zeito/pyqgis_data/test_write.tif")

xSize = provider.xSize()
ySize = provider.ySize()

CRS = layer.crs()

error = rasterWriter.writeRaster(pipe, xSize, ySize, provider.extent(), CRS)

if error == QgsRasterFileWriter.NoError:
    print "Raster was saved successfully!"

else:
    print "Raster was not saved!"

After running the code at the Python Console of QGIS, it can be corroborated that block object was modified as expected.

3 3
original block
10.0
2.0
2.0
10.0
3.0
2.0
8.0
4.0
4.0
modified block
10.0
2.0
2.0
10.0
3.0
2.0
8.0
25.0
25.0
Raster was saved successfully!

When I try to create a new instance of QgsRasterDataProvider, I got that "cannot be instantiated".

TypeError: qgis._core.QgsRasterDataProvider represents a C++ abstract class
and cannot be instantiated

How can I overwrite correctly the new block values in the original (or a new) provider?

1

I found out a solution to the problem of overwrite block values in the original provider. It is necessary to use two additional QgsRasterDataProvider methods: 'setEditable' and 'writeBlock'. However, following code (with only two additional lines including above methods) modify original raster as expected resulting raster and written raster has the values of original raster.

layer = iface.activeLayer()

provider = layer.dataProvider()

extent = provider.extent()

rows = layer.height()
cols = layer.width()

xsize = layer.rasterUnitsPerPixelX()
ysize = layer.rasterUnitsPerPixelY()

print (rows, cols)

block = provider.block(1, extent, cols, rows)
provider.setEditable(True)

print ("original block")

for i in range(rows):
    for j in range(cols):
        print (block.value(i,j))

for i in range(rows):
    for j in range(cols):
        if block.value(i,j) == 4:
            block.setValue(i, j, 25)

print ("modified block")

for i in range(rows):
    for j in range(cols):
        print (block.value(i,j))

provider.writeBlock(block, 1)

pipe = QgsRasterPipe()
pipe.set(provider.clone())

rasterWriter = QgsRasterFileWriter("/home/zeito/pyqgis_data/test_write.tif")

xSize = provider.xSize()
ySize = provider.ySize()

CRS = layer.crs()

error = rasterWriter.writeRaster(pipe, xSize, ySize, provider.extent(), CRS)

if error == QgsRasterFileWriter.NoError:
    print ("Raster was saved successfully!")

else:
    print ("Raster was not saved!")

In following image, with the help of Value Tool Plugin, it can be observed that they were swapped:

enter image description here

On the other hand, if this line:

pipe.set(provider.clone())

is changed to:

pipe.set(provider)

resulting raster is gotten as expected but issue in original raster persist: their values are the same of resulting raster.

| improve this answer | |

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.