Fixed #26417 -- Allowed setting GDALBand data with partial values.
This commit is contained in:
parent
03b6947728
commit
870dd1d38b
|
@ -170,7 +170,7 @@ class GDALBand(GDALBase):
|
|||
dtype = GDAL_PIXEL_TYPES[dtype]
|
||||
return dtype
|
||||
|
||||
def data(self, data=None, offset=None, size=None, as_memoryview=False):
|
||||
def data(self, data=None, offset=None, size=None, shape=None, as_memoryview=False):
|
||||
"""
|
||||
Reads or writes pixel values for this band. Blocks of data can
|
||||
be accessed by specifying the width, height and offset of the
|
||||
|
@ -185,6 +185,9 @@ class GDALBand(GDALBase):
|
|||
if not size:
|
||||
size = (self.width - offset[0], self.height - offset[1])
|
||||
|
||||
if not shape:
|
||||
shape = size
|
||||
|
||||
if any(x <= 0 for x in size):
|
||||
raise ValueError('Offset too big for this raster.')
|
||||
|
||||
|
@ -192,7 +195,7 @@ class GDALBand(GDALBase):
|
|||
raise ValueError('Size is larger than raster.')
|
||||
|
||||
# Create ctypes type array generator
|
||||
ctypes_array = GDAL_TO_CTYPES[self.datatype()] * (size[0] * size[1])
|
||||
ctypes_array = GDAL_TO_CTYPES[self.datatype()] * (shape[0] * shape[1])
|
||||
|
||||
if data is None:
|
||||
# Set read mode
|
||||
|
@ -211,8 +214,8 @@ class GDALBand(GDALBase):
|
|||
|
||||
# Access band
|
||||
capi.band_io(self._ptr, access_flag, offset[0], offset[1],
|
||||
size[0], size[1], byref(data_array), size[0],
|
||||
size[1], self.datatype(), 0, 0)
|
||||
size[0], size[1], byref(data_array), shape[0],
|
||||
shape[1], self.datatype(), 0, 0)
|
||||
|
||||
# Return data as numpy array if possible, otherwise as list
|
||||
if data is None:
|
||||
|
|
|
@ -1477,7 +1477,7 @@ blue.
|
|||
``GDT_UInt32``, ``GDT_Int32``, ``GDT_Float32``, ``GDT_Float64``,
|
||||
``GDT_CInt16``, ``GDT_CInt32``, ``GDT_CFloat32``, and ``GDT_CFloat64``.
|
||||
|
||||
.. method:: data(data=None, offset=None, size=None)
|
||||
.. method:: data(data=None, offset=None, size=None, shape=None)
|
||||
|
||||
.. versionadded:: 1.9
|
||||
|
||||
|
@ -1490,9 +1490,17 @@ blue.
|
|||
|
||||
Data is written to the ``GDALBand`` if the ``data`` parameter is provided.
|
||||
The input can be of one of the following types - packed string, buffer, list,
|
||||
array, and NumPy array. The number of items in the input must correspond to the
|
||||
total number of pixels in the band, or to the number of pixels for a specific
|
||||
block of pixel values if the ``offset`` and ``size`` parameters are provided.
|
||||
array, and NumPy array. The number of items in the input should normally
|
||||
correspond to the total number of pixels in the band, or to the number
|
||||
of pixels for a specific block of pixel values if the ``offset`` and
|
||||
``size`` parameters are provided.
|
||||
|
||||
If the number of items in the input is different from the target pixel
|
||||
block, the ``shape`` parameter must be specified. The shape is a tuple
|
||||
that specifies the width and height of the input data in pixels. The
|
||||
data is then replicated to update the pixel values of the selected
|
||||
block. This is useful to fill an entire band with a single value, for
|
||||
instance.
|
||||
|
||||
For example:
|
||||
|
||||
|
@ -1519,6 +1527,22 @@ blue.
|
|||
[ 4, -99, -88, 7],
|
||||
[ 8, -77, -66, 11],
|
||||
[ 12, 13, 14, 15]], dtype=int8)
|
||||
>>> bnd.data([1], shape=(1, 1))
|
||||
>>> bnd.data()
|
||||
array([[1, 1, 1, 1],
|
||||
[1, 1, 1, 1],
|
||||
[1, 1, 1, 1],
|
||||
[1, 1, 1, 1]], dtype=uint8)
|
||||
>>> bnd.data(range(4), shape=(1, 4))
|
||||
array([[0, 0, 0, 0],
|
||||
[1, 1, 1, 1],
|
||||
[2, 2, 2, 2],
|
||||
[3, 3, 3, 3]], dtype=uint8)
|
||||
|
||||
.. versionchanged:: 1.10
|
||||
|
||||
The ``shape`` parameter and the ability to replicate data input when
|
||||
setting ``GDALBand`` data was added.
|
||||
|
||||
Settings
|
||||
========
|
||||
|
|
|
@ -143,6 +143,10 @@ Minor features
|
|||
primary key of objects in the ``properties`` dictionary if specific fields
|
||||
aren't specified.
|
||||
|
||||
* The ability to replicate input data on the :meth:`GDALBand.data()
|
||||
<django.contrib.gis.gdal.GDALBand.data>` method was added. Band data can
|
||||
now be updated with repeated values efficiently.
|
||||
|
||||
:mod:`django.contrib.messages`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -483,3 +483,24 @@ class GDALBandTests(SimpleTestCase):
|
|||
else:
|
||||
rsmem.bands[0].nodata_value = None
|
||||
self.assertIsNone(rsmem.bands[0].nodata_value)
|
||||
|
||||
def test_band_data_replication(self):
|
||||
band = GDALRaster({
|
||||
'srid': 4326,
|
||||
'width': 3,
|
||||
'height': 3,
|
||||
'bands': [{'data': range(10, 19), 'nodata_value': 0}],
|
||||
}).bands[0]
|
||||
|
||||
# Variations for input (data, shape, expected result).
|
||||
combos = (
|
||||
([1], (1, 1), [1] * 9),
|
||||
(range(3), (1, 3), [0, 0, 0, 1, 1, 1, 2, 2, 2]),
|
||||
(range(3), (3, 1), [0, 1, 2, 0, 1, 2, 0, 1, 2]),
|
||||
)
|
||||
for combo in combos:
|
||||
band.data(combo[0], shape=combo[1])
|
||||
if numpy:
|
||||
numpy.testing.assert_equal(band.data(), numpy.array(combo[2]).reshape(3, 3))
|
||||
else:
|
||||
self.assertEqual(band.data(), list(combo[2]))
|
||||
|
|
Loading…
Reference in New Issue