2

Let's say I want to write a single pixel or a 1D array of pixels (e.g.all at the same latitude) of pixels to a single-band of a Float32 GeoTIFF using the Python GDAL bindings. How can I do so? Or is it not possible?

I currently have the following method for truly 2D ndarrays. But occasionally I get requests for a pixel or line of pixels, which cause this method to fail.

raster_band.WriteArray(my_pixel_array)

FURTHER CLARIFICATION:

I'm trying to write a new image where the entire extent of the new image is either just one pixel or just a line of pixels. Thus, I've tried just setting xoff and yoff to 0, and this fails the same way as without xoff and yoff. The error I'm getting is expected array of dim 2, e.g. when the shape of my ndarray is (4,) (and when the GDAL raster is initialized with RasterXSize to 4 and RasterYSize to 1 via a pertinent out_raster.SetGeoTransform (EPSG:4326 location and size) method).

  • See @zwnk's answer to my question try this: np.reshape(my_pixel_array, (len(my_pixel_array), 1)) – zwnk below. – ksed Jul 2 at 13:45
3

The WriteArray() method has two useful optional arguments to accomplish this:

  • xoff: specifies the offset on the x axis.
  • yoff: specifies the offset on the y axis.

This means that it will write a 2D array (this is very important) to the band, starting from the specified offsets (which are 0 by default). This is very useful because you don't have to read the whole array into memory, change one pixel or one row, and then write it again. This lets you specify where you want to write the data in the array. Imagine you wanted to replace all the pixels in the last row of the raster with values of 100, and you also wanted to replace the most upper right pixel with a value of 99.

import gdal
import numpy as np

# open the raster in writing mode
ds = gdal.Open('path/to/raster.tif', 1)

# get first band and raster dimensions
band = ds.GetRasterBand(1)
cols = ds.RasterXSize
rows = ds.RasterYSize

# create the arrays you are going to write
row_data = np.full(shape=(1, cols), fill_value=100)  # note that eventhough it contains just one row of data it is a 2D array
pixel_data = np.array([[99]])  # again, a 2D array. This time it contains just one value

# write the arrays specifying the proper offsets
band.WriteArray(row_data, xoff=0, yoff=(rows-1))
band.WriteArray(pixel_data, xoff=(cols-1), yoff=0)

# save and close the file
del band, ds

Note that the WriteArray() method only accepts a 2D array, whether it has just one value, one row, or many rows. Furthermore, if you try to write an array with higher dimensions (e.g. you set the offset to be the last row but pass an array with two rows or more columns that ds.RasterXSize), it will throw an Exception because the array does not fit.

  • Thanks for this explanation, but in my case, I'm not opening an existing GeoTIFF in order to replace pixels. I'm trying to write a new image where the entire extent of the new image is either just one pixel or just a line of pixels. Thus, I've trying just setting xoff and yoff to 0, and this fails the same way as without xoff and yoff. Thus, is there more too it, somehow, when the only extent is a pixel or line of pixels? I'll edit the question to make this more obvious. – ksed Jul 2 at 12:41
  • 1
    and what exacty is failing? can you provide the error msg? is the array you are trying to write a numpy array? – zwnk Jul 2 at 12:50
  • Thanks @zwnk. I've added an example error message. – ksed Jul 2 at 12:58
  • 1
    try this: np.reshape(my_pixel_array, (len(my_pixel_array), 1)) – zwnk Jul 2 at 13:07
  • 2
    @ksed You need to reshape it for the same reason I mentioned above. It has to be a 2D array, even if it has only one value or one row of values. – Marcelo Villa Jul 2 at 13:55

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.