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]
|
dtype = GDAL_PIXEL_TYPES[dtype]
|
||||||
return 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
|
Reads or writes pixel values for this band. Blocks of data can
|
||||||
be accessed by specifying the width, height and offset of the
|
be accessed by specifying the width, height and offset of the
|
||||||
|
@ -185,6 +185,9 @@ class GDALBand(GDALBase):
|
||||||
if not size:
|
if not size:
|
||||||
size = (self.width - offset[0], self.height - offset[1])
|
size = (self.width - offset[0], self.height - offset[1])
|
||||||
|
|
||||||
|
if not shape:
|
||||||
|
shape = size
|
||||||
|
|
||||||
if any(x <= 0 for x in size):
|
if any(x <= 0 for x in size):
|
||||||
raise ValueError('Offset too big for this raster.')
|
raise ValueError('Offset too big for this raster.')
|
||||||
|
|
||||||
|
@ -192,7 +195,7 @@ class GDALBand(GDALBase):
|
||||||
raise ValueError('Size is larger than raster.')
|
raise ValueError('Size is larger than raster.')
|
||||||
|
|
||||||
# Create ctypes type array generator
|
# 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:
|
if data is None:
|
||||||
# Set read mode
|
# Set read mode
|
||||||
|
@ -211,8 +214,8 @@ class GDALBand(GDALBase):
|
||||||
|
|
||||||
# Access band
|
# Access band
|
||||||
capi.band_io(self._ptr, access_flag, offset[0], offset[1],
|
capi.band_io(self._ptr, access_flag, offset[0], offset[1],
|
||||||
size[0], size[1], byref(data_array), size[0],
|
size[0], size[1], byref(data_array), shape[0],
|
||||||
size[1], self.datatype(), 0, 0)
|
shape[1], self.datatype(), 0, 0)
|
||||||
|
|
||||||
# Return data as numpy array if possible, otherwise as list
|
# Return data as numpy array if possible, otherwise as list
|
||||||
if data is None:
|
if data is None:
|
||||||
|
|
|
@ -1477,7 +1477,7 @@ blue.
|
||||||
``GDT_UInt32``, ``GDT_Int32``, ``GDT_Float32``, ``GDT_Float64``,
|
``GDT_UInt32``, ``GDT_Int32``, ``GDT_Float32``, ``GDT_Float64``,
|
||||||
``GDT_CInt16``, ``GDT_CInt32``, ``GDT_CFloat32``, and ``GDT_CFloat64``.
|
``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
|
.. versionadded:: 1.9
|
||||||
|
|
||||||
|
@ -1490,9 +1490,17 @@ blue.
|
||||||
|
|
||||||
Data is written to the ``GDALBand`` if the ``data`` parameter is provided.
|
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,
|
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
|
array, and NumPy array. The number of items in the input should normally
|
||||||
total number of pixels in the band, or to the number of pixels for a specific
|
correspond to the total number of pixels in the band, or to the number
|
||||||
block of pixel values if the ``offset`` and ``size`` parameters are provided.
|
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:
|
For example:
|
||||||
|
|
||||||
|
@ -1519,6 +1527,22 @@ blue.
|
||||||
[ 4, -99, -88, 7],
|
[ 4, -99, -88, 7],
|
||||||
[ 8, -77, -66, 11],
|
[ 8, -77, -66, 11],
|
||||||
[ 12, 13, 14, 15]], dtype=int8)
|
[ 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
|
Settings
|
||||||
========
|
========
|
||||||
|
|
|
@ -143,6 +143,10 @@ Minor features
|
||||||
primary key of objects in the ``properties`` dictionary if specific fields
|
primary key of objects in the ``properties`` dictionary if specific fields
|
||||||
aren't specified.
|
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`
|
:mod:`django.contrib.messages`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -483,3 +483,24 @@ class GDALBandTests(SimpleTestCase):
|
||||||
else:
|
else:
|
||||||
rsmem.bands[0].nodata_value = None
|
rsmem.bands[0].nodata_value = None
|
||||||
self.assertIsNone(rsmem.bands[0].nodata_value)
|
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