Commit 870dd1d3 authored by Daniel Wiesmann's avatar Daniel Wiesmann Committed by Tim Graham
Browse files

Fixed #26417 -- Allowed setting GDALBand data with partial values.

parent 03b69477
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -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:
+28 −4
Original line number Diff line number Diff line
@@ -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
========
+4 −0
Original line number Diff line number Diff line
@@ -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`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

+21 −0
Original line number Diff line number Diff line
@@ -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]))