Loading django/contrib/gis/gdal/prototypes/raster.py +3 −0 Original line number Diff line number Diff line Loading @@ -69,3 +69,6 @@ get_band_maximum = double_output(std_call('GDALGetRasterMaximum'), [c_void_p, PO reproject_image = void_output(std_call('GDALReprojectImage'), [c_void_p, c_char_p, c_void_p, c_char_p, c_int, c_double, c_double, c_void_p, c_void_p, c_void_p] ) auto_create_warped_vrt = voidptr_output(std_call('GDALAutoCreateWarpedVRT'), [c_void_p, c_char_p, c_char_p, c_int, c_double, c_void_p] ) django/contrib/gis/gdal/raster/const.py +11 −0 Original line number Diff line number Diff line Loading @@ -32,3 +32,14 @@ GDAL_TO_CTYPES = [ None, c_byte, c_uint16, c_int16, c_uint32, c_int32, c_float, c_double, None, None, None, None ] # List of resampling algorithms that can be used to warp a GDALRaster. GDAL_RESAMPLE_ALGORITHMS = { 'NearestNeighbour': 0, 'Bilinear': 1, 'Cubic': 2, 'CubicSpline': 3, 'Lanczos': 4, 'Average': 5, 'Mode': 6, } django/contrib/gis/gdal/raster/source.py +115 −1 Original line number Diff line number Diff line import json import os from ctypes import addressof, byref, c_double from ctypes import addressof, byref, c_double, c_void_p from django.contrib.gis.gdal.base import GDALBase from django.contrib.gis.gdal.driver import Driver from django.contrib.gis.gdal.error import GDALException from django.contrib.gis.gdal.prototypes import raster as capi from django.contrib.gis.gdal.raster.band import GDALBand from django.contrib.gis.gdal.raster.const import GDAL_RESAMPLE_ALGORITHMS from django.contrib.gis.gdal.srs import SpatialReference, SRSException from django.contrib.gis.geometry.regex import json_regex from django.utils import six Loading Loading @@ -123,6 +124,9 @@ class GDALRaster(GDALBase): if 'skew' in ds_input: self.skew.x, self.skew.y = ds_input['skew'] elif isinstance(ds_input, c_void_p): # Instantiate the object using an existing pointer to a gdal raster. self._ptr = ds_input else: raise GDALException('Invalid data source input type: "{}".'.format(type(ds_input))) Loading Loading @@ -278,3 +282,113 @@ class GDALRaster(GDALBase): for idx in range(1, capi.get_ds_raster_count(self._ptr) + 1): bands.append(GDALBand(self, idx)) return bands def warp(self, ds_input, resampling='NearestNeighbour', max_error=0.0): """ Returns a warped GDALRaster with the given input characteristics. The input is expected to be a dictionary containing the parameters of the target raster. Allowed values are width, height, SRID, origin, scale, skew, datatype, driver, and name (filename). By default, the warp functions keeps all parameters equal to the values of the original source raster. For the name of the target raster, the name of the source raster will be used and appended with _copy. + source_driver_name. In addition, the resampling algorithm can be specified with the "resampling" input parameter. The default is NearestNeighbor. For a list of all options consult the GDAL_RESAMPLE_ALGORITHMS constant. """ # Get the parameters defining the geotransform, srid, and size of the raster if 'width' not in ds_input: ds_input['width'] = self.width if 'height' not in ds_input: ds_input['height'] = self.height if 'srid' not in ds_input: ds_input['srid'] = self.srs.srid if 'origin' not in ds_input: ds_input['origin'] = self.origin if 'scale' not in ds_input: ds_input['scale'] = self.scale if 'skew' not in ds_input: ds_input['skew'] = self.skew # Get the driver, name, and datatype of the target raster if 'driver' not in ds_input: ds_input['driver'] = self.driver.name if 'name' not in ds_input: ds_input['name'] = self.name + '_copy.' + self.driver.name if 'datatype' not in ds_input: ds_input['datatype'] = self.bands[0].datatype() # Set the number of bands ds_input['nr_of_bands'] = len(self.bands) # Create target raster target = GDALRaster(ds_input, write=True) # Copy nodata values to warped raster for index, band in enumerate(self.bands): target.bands[index].nodata_value = band.nodata_value # Select resampling algorithm algorithm = GDAL_RESAMPLE_ALGORITHMS[resampling] # Reproject image capi.reproject_image( self._ptr, self.srs.wkt.encode(), target._ptr, target.srs.wkt.encode(), algorithm, 0.0, max_error, c_void_p(), c_void_p(), c_void_p() ) # Make sure all data is written to file target._flush() return target def transform(self, srid, driver=None, name=None, resampling='NearestNeighbour', max_error=0.0): """ Returns a copy of this raster reprojected into the given SRID. """ # Convert the resampling algorithm name into an algorithm id algorithm = GDAL_RESAMPLE_ALGORITHMS[resampling] # Instantiate target spatial reference system target_srs = SpatialReference(srid) # Create warped virtual dataset in the target reference system target = capi.auto_create_warped_vrt( self._ptr, self.srs.wkt.encode(), target_srs.wkt.encode(), algorithm, max_error, c_void_p() ) target = GDALRaster(target) # Construct the target warp dictionary from the virtual raster data = { 'srid': srid, 'width': target.width, 'height': target.height, 'origin': [target.origin.x, target.origin.y], 'scale': [target.scale.x, target.scale.y], 'skew': [target.skew.x, target.skew.y], } # Set the driver and filepath if provided if driver: data['driver'] = driver if name: data['name'] = name # Warp the raster into new srid return self.warp(data, resampling=resampling, max_error=max_error) docs/ref/contrib/gis/gdal.txt +84 −2 Original line number Diff line number Diff line Loading @@ -1119,7 +1119,7 @@ blue. values defining the properties of a new raster (such as size and name). If the input is a file path, the second parameter specifies if the raster should be opened with write access. If the input is raw data, the parameters ``width``, ``heigth``, and ``srid`` are required. The following example shows how rasters ``height``, and ``srid`` are required. The following example shows how rasters can be created from different input sources (using the sample data from the GeoDjango tests, see also the :ref:`gdal_sample_data` section):: Loading Loading @@ -1288,6 +1288,89 @@ blue. >>> rst.bands[1].data() array([[ 2., 3.]], dtype=float32) .. method:: warp(ds_input, resampling='NearestNeighbour', max_error=0.0) .. versionadded:: 1.9 Returns a warped version of this raster. The warping parameters can be specified through the ``ds_input`` argument. The use of ``ds_input`` is analogous to the corresponding argument of the class constructor. It is a dictionary with the characteristics of the target raster. Allowed dictionary key values are width, height, SRID, origin, scale, skew, datatype, driver, and name (filename). By default, the warp functions keeps most parameters equal to the values of the original source raster, so only parameters that should be changed need to be specified. Note that this includes the driver, so for file-based rasters the warp function will create a new raster on disk. The only parameter that is set differently from the source raster is the name. The default value of the the raster name is the name of the source raster appended with ``'_copy' + source_driver_name``. For file-based rasters it is recommended to provide the file path of the target raster. The resampling algorithm used for warping can be specified with the ``resampling`` argument. The default is ``NearestNeighbor``, and the other allowed values are ``Bilinear``, ``Cubic``, ``CubicSpline``, ``Lanczos``, ``Average``, and ``Mode``. The ``max_error`` argument can be used to specify the maximum error measured in input pixels that is allowed in approximating the transformation. The default is 0.0 for exact calculations. For users familiar with ``GDAL``, this function has a similar functionality to the ``gdalwarp`` command-line utility. For example, the warp function can be used for aggregating a raster to the double of its original pixel scale: >>> rst = GDALRaster({ ... "width": 6, "height": 6, "srid": 3086, ... "origin": [500000, 400000], ... "scale": [100, -100], ... "bands": [{"data": range(36), "nodata_value": 99}] ... }) >>> target = rst.warp({"scale": [200, -200], "width": 3, "height": 3}) >>> target.bands[0].data() array([[ 7., 9., 11.], [ 19., 21., 23.], [ 31., 33., 35.]], dtype=float32) .. method:: transform(srid, driver=None, name=None, resampling='NearestNeighbour', max_error=0.0) .. versionadded:: 1.9 Returns a transformed version of this raster with the specified SRID. This function transforms the current raster into a new spatial reference system that can be specified with an ``srid``. It calculates the bounds and scale of the current raster in the new spatial reference system and warps the raster using the :attr:`~GDALRaster.warp` function. By default, the driver of the source raster is used and the name of the raster is the original name appended with ``'_copy' + source_driver_name``. A different driver or name can be specified with the ``driver`` and ``name`` arguments. The default resampling algorithm is ``NearestNeighbour`` but can be changed using the ``resampling`` argument. The default maximum allowed error for resampling is 0.0 and can be changed using the ``max_error`` argument. Consult the :attr:`~GDALRaster.warp` documentation for detail on those arguments. >>> rst = GDALRaster({ ... "width": 6, "height": 6, "srid": 3086, ... "origin": [500000, 400000], ... "scale": [100, -100], ... "bands": [{"data": range(36), "nodata_value": 99}] ... }) >>> target = rst.transform(4326) >>> target.origin [-82.98492744885776, 27.601924753080144] ``GDALBand`` ------------ Loading Loading @@ -1385,7 +1468,6 @@ blue. [ 8, -77, -66, 11], [ 12, 13, 14, 15]], dtype=int8) Settings ======== Loading docs/releases/1.9.txt +9 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,15 @@ Minor features It supports automatic spatial index creation and reprojection when saving a model. It does not yet support spatial querying. * The new :meth:`GDALRaster.warp() <django.contrib.gis.gdal.GDALRaster.warp>` method allows warping a raster by specifying target raster properties such as origin, width, height, or pixel size (amongst others). * The new :meth:`GDALRaster.transform() <django.contrib.gis.gdal.GDALRaster.transform>` method allows transforming a raster into a different spatial reference system by specifying a target ``srid``. :mod:`django.contrib.messages` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Loading Loading
django/contrib/gis/gdal/prototypes/raster.py +3 −0 Original line number Diff line number Diff line Loading @@ -69,3 +69,6 @@ get_band_maximum = double_output(std_call('GDALGetRasterMaximum'), [c_void_p, PO reproject_image = void_output(std_call('GDALReprojectImage'), [c_void_p, c_char_p, c_void_p, c_char_p, c_int, c_double, c_double, c_void_p, c_void_p, c_void_p] ) auto_create_warped_vrt = voidptr_output(std_call('GDALAutoCreateWarpedVRT'), [c_void_p, c_char_p, c_char_p, c_int, c_double, c_void_p] )
django/contrib/gis/gdal/raster/const.py +11 −0 Original line number Diff line number Diff line Loading @@ -32,3 +32,14 @@ GDAL_TO_CTYPES = [ None, c_byte, c_uint16, c_int16, c_uint32, c_int32, c_float, c_double, None, None, None, None ] # List of resampling algorithms that can be used to warp a GDALRaster. GDAL_RESAMPLE_ALGORITHMS = { 'NearestNeighbour': 0, 'Bilinear': 1, 'Cubic': 2, 'CubicSpline': 3, 'Lanczos': 4, 'Average': 5, 'Mode': 6, }
django/contrib/gis/gdal/raster/source.py +115 −1 Original line number Diff line number Diff line import json import os from ctypes import addressof, byref, c_double from ctypes import addressof, byref, c_double, c_void_p from django.contrib.gis.gdal.base import GDALBase from django.contrib.gis.gdal.driver import Driver from django.contrib.gis.gdal.error import GDALException from django.contrib.gis.gdal.prototypes import raster as capi from django.contrib.gis.gdal.raster.band import GDALBand from django.contrib.gis.gdal.raster.const import GDAL_RESAMPLE_ALGORITHMS from django.contrib.gis.gdal.srs import SpatialReference, SRSException from django.contrib.gis.geometry.regex import json_regex from django.utils import six Loading Loading @@ -123,6 +124,9 @@ class GDALRaster(GDALBase): if 'skew' in ds_input: self.skew.x, self.skew.y = ds_input['skew'] elif isinstance(ds_input, c_void_p): # Instantiate the object using an existing pointer to a gdal raster. self._ptr = ds_input else: raise GDALException('Invalid data source input type: "{}".'.format(type(ds_input))) Loading Loading @@ -278,3 +282,113 @@ class GDALRaster(GDALBase): for idx in range(1, capi.get_ds_raster_count(self._ptr) + 1): bands.append(GDALBand(self, idx)) return bands def warp(self, ds_input, resampling='NearestNeighbour', max_error=0.0): """ Returns a warped GDALRaster with the given input characteristics. The input is expected to be a dictionary containing the parameters of the target raster. Allowed values are width, height, SRID, origin, scale, skew, datatype, driver, and name (filename). By default, the warp functions keeps all parameters equal to the values of the original source raster. For the name of the target raster, the name of the source raster will be used and appended with _copy. + source_driver_name. In addition, the resampling algorithm can be specified with the "resampling" input parameter. The default is NearestNeighbor. For a list of all options consult the GDAL_RESAMPLE_ALGORITHMS constant. """ # Get the parameters defining the geotransform, srid, and size of the raster if 'width' not in ds_input: ds_input['width'] = self.width if 'height' not in ds_input: ds_input['height'] = self.height if 'srid' not in ds_input: ds_input['srid'] = self.srs.srid if 'origin' not in ds_input: ds_input['origin'] = self.origin if 'scale' not in ds_input: ds_input['scale'] = self.scale if 'skew' not in ds_input: ds_input['skew'] = self.skew # Get the driver, name, and datatype of the target raster if 'driver' not in ds_input: ds_input['driver'] = self.driver.name if 'name' not in ds_input: ds_input['name'] = self.name + '_copy.' + self.driver.name if 'datatype' not in ds_input: ds_input['datatype'] = self.bands[0].datatype() # Set the number of bands ds_input['nr_of_bands'] = len(self.bands) # Create target raster target = GDALRaster(ds_input, write=True) # Copy nodata values to warped raster for index, band in enumerate(self.bands): target.bands[index].nodata_value = band.nodata_value # Select resampling algorithm algorithm = GDAL_RESAMPLE_ALGORITHMS[resampling] # Reproject image capi.reproject_image( self._ptr, self.srs.wkt.encode(), target._ptr, target.srs.wkt.encode(), algorithm, 0.0, max_error, c_void_p(), c_void_p(), c_void_p() ) # Make sure all data is written to file target._flush() return target def transform(self, srid, driver=None, name=None, resampling='NearestNeighbour', max_error=0.0): """ Returns a copy of this raster reprojected into the given SRID. """ # Convert the resampling algorithm name into an algorithm id algorithm = GDAL_RESAMPLE_ALGORITHMS[resampling] # Instantiate target spatial reference system target_srs = SpatialReference(srid) # Create warped virtual dataset in the target reference system target = capi.auto_create_warped_vrt( self._ptr, self.srs.wkt.encode(), target_srs.wkt.encode(), algorithm, max_error, c_void_p() ) target = GDALRaster(target) # Construct the target warp dictionary from the virtual raster data = { 'srid': srid, 'width': target.width, 'height': target.height, 'origin': [target.origin.x, target.origin.y], 'scale': [target.scale.x, target.scale.y], 'skew': [target.skew.x, target.skew.y], } # Set the driver and filepath if provided if driver: data['driver'] = driver if name: data['name'] = name # Warp the raster into new srid return self.warp(data, resampling=resampling, max_error=max_error)
docs/ref/contrib/gis/gdal.txt +84 −2 Original line number Diff line number Diff line Loading @@ -1119,7 +1119,7 @@ blue. values defining the properties of a new raster (such as size and name). If the input is a file path, the second parameter specifies if the raster should be opened with write access. If the input is raw data, the parameters ``width``, ``heigth``, and ``srid`` are required. The following example shows how rasters ``height``, and ``srid`` are required. The following example shows how rasters can be created from different input sources (using the sample data from the GeoDjango tests, see also the :ref:`gdal_sample_data` section):: Loading Loading @@ -1288,6 +1288,89 @@ blue. >>> rst.bands[1].data() array([[ 2., 3.]], dtype=float32) .. method:: warp(ds_input, resampling='NearestNeighbour', max_error=0.0) .. versionadded:: 1.9 Returns a warped version of this raster. The warping parameters can be specified through the ``ds_input`` argument. The use of ``ds_input`` is analogous to the corresponding argument of the class constructor. It is a dictionary with the characteristics of the target raster. Allowed dictionary key values are width, height, SRID, origin, scale, skew, datatype, driver, and name (filename). By default, the warp functions keeps most parameters equal to the values of the original source raster, so only parameters that should be changed need to be specified. Note that this includes the driver, so for file-based rasters the warp function will create a new raster on disk. The only parameter that is set differently from the source raster is the name. The default value of the the raster name is the name of the source raster appended with ``'_copy' + source_driver_name``. For file-based rasters it is recommended to provide the file path of the target raster. The resampling algorithm used for warping can be specified with the ``resampling`` argument. The default is ``NearestNeighbor``, and the other allowed values are ``Bilinear``, ``Cubic``, ``CubicSpline``, ``Lanczos``, ``Average``, and ``Mode``. The ``max_error`` argument can be used to specify the maximum error measured in input pixels that is allowed in approximating the transformation. The default is 0.0 for exact calculations. For users familiar with ``GDAL``, this function has a similar functionality to the ``gdalwarp`` command-line utility. For example, the warp function can be used for aggregating a raster to the double of its original pixel scale: >>> rst = GDALRaster({ ... "width": 6, "height": 6, "srid": 3086, ... "origin": [500000, 400000], ... "scale": [100, -100], ... "bands": [{"data": range(36), "nodata_value": 99}] ... }) >>> target = rst.warp({"scale": [200, -200], "width": 3, "height": 3}) >>> target.bands[0].data() array([[ 7., 9., 11.], [ 19., 21., 23.], [ 31., 33., 35.]], dtype=float32) .. method:: transform(srid, driver=None, name=None, resampling='NearestNeighbour', max_error=0.0) .. versionadded:: 1.9 Returns a transformed version of this raster with the specified SRID. This function transforms the current raster into a new spatial reference system that can be specified with an ``srid``. It calculates the bounds and scale of the current raster in the new spatial reference system and warps the raster using the :attr:`~GDALRaster.warp` function. By default, the driver of the source raster is used and the name of the raster is the original name appended with ``'_copy' + source_driver_name``. A different driver or name can be specified with the ``driver`` and ``name`` arguments. The default resampling algorithm is ``NearestNeighbour`` but can be changed using the ``resampling`` argument. The default maximum allowed error for resampling is 0.0 and can be changed using the ``max_error`` argument. Consult the :attr:`~GDALRaster.warp` documentation for detail on those arguments. >>> rst = GDALRaster({ ... "width": 6, "height": 6, "srid": 3086, ... "origin": [500000, 400000], ... "scale": [100, -100], ... "bands": [{"data": range(36), "nodata_value": 99}] ... }) >>> target = rst.transform(4326) >>> target.origin [-82.98492744885776, 27.601924753080144] ``GDALBand`` ------------ Loading Loading @@ -1385,7 +1468,6 @@ blue. [ 8, -77, -66, 11], [ 12, 13, 14, 15]], dtype=int8) Settings ======== Loading
docs/releases/1.9.txt +9 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,15 @@ Minor features It supports automatic spatial index creation and reprojection when saving a model. It does not yet support spatial querying. * The new :meth:`GDALRaster.warp() <django.contrib.gis.gdal.GDALRaster.warp>` method allows warping a raster by specifying target raster properties such as origin, width, height, or pixel size (amongst others). * The new :meth:`GDALRaster.transform() <django.contrib.gis.gdal.GDALRaster.transform>` method allows transforming a raster into a different spatial reference system by specifying a target ``srid``. :mod:`django.contrib.messages` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Loading