Fixed #28288 -- Allowed passing papsz options to GDALRaster initialization.
This commit is contained in:
parent
0c3c37a376
commit
fe5e34a295
|
@ -1,6 +1,6 @@
|
|||
import json
|
||||
import os
|
||||
from ctypes import addressof, byref, c_double, c_void_p
|
||||
from ctypes import addressof, byref, c_char_p, c_double, c_void_p
|
||||
|
||||
from django.contrib.gis.gdal.driver import Driver
|
||||
from django.contrib.gis.gdal.error import GDALException
|
||||
|
@ -92,6 +92,16 @@ class GDALRaster(GDALRasterBase):
|
|||
if 'srid' not in ds_input:
|
||||
raise GDALException('Specify srid for JSON or dict input.')
|
||||
|
||||
# Create null terminated gdal options array.
|
||||
papsz_options = []
|
||||
for key, val in ds_input.get('papsz_options', {}).items():
|
||||
option = '{}={}'.format(key, val)
|
||||
papsz_options.append(option.upper().encode())
|
||||
papsz_options.append(None)
|
||||
|
||||
# Convert papszlist to ctypes array.
|
||||
papsz_options = (c_char_p * len(papsz_options))(*papsz_options)
|
||||
|
||||
# Create GDAL Raster
|
||||
self._ptr = capi.create_ds(
|
||||
driver._ptr,
|
||||
|
@ -100,7 +110,7 @@ class GDALRaster(GDALRasterBase):
|
|||
ds_input['height'],
|
||||
ds_input.get('nr_of_bands', len(ds_input.get('bands', []))),
|
||||
ds_input.get('datatype', 6),
|
||||
None
|
||||
byref(papsz_options),
|
||||
)
|
||||
|
||||
# Set band data if provided
|
||||
|
|
|
@ -1619,21 +1619,22 @@ the others are described below.
|
|||
The following table describes all keys that can be set in the ``ds_input``
|
||||
dictionary.
|
||||
|
||||
=============== ======== ==================================================
|
||||
Key Default Usage
|
||||
=============== ======== ==================================================
|
||||
``srid`` required Mapped to the :attr:`~GDALRaster.srid` attribute
|
||||
``width`` required Mapped to the :attr:`~GDALRaster.width` attribute
|
||||
``height`` required Mapped to the :attr:`~GDALRaster.height` attribute
|
||||
``driver`` ``MEM`` Mapped to the :attr:`~GDALRaster.driver` attribute
|
||||
``name`` ``''`` See below
|
||||
``origin`` ``0`` Mapped to the :attr:`~GDALRaster.origin` attribute
|
||||
``scale`` ``0`` Mapped to the :attr:`~GDALRaster.scale` attribute
|
||||
``skew`` ``0`` Mapped to the :attr:`~GDALRaster.width` attribute
|
||||
``bands`` ``[]`` See below
|
||||
``nr_of_bands`` ``0`` See below
|
||||
``datatype`` ``6`` See below
|
||||
=============== ======== ==================================================
|
||||
================= ======== ==================================================
|
||||
Key Default Usage
|
||||
================= ======== ==================================================
|
||||
``srid`` required Mapped to the :attr:`~GDALRaster.srid` attribute
|
||||
``width`` required Mapped to the :attr:`~GDALRaster.width` attribute
|
||||
``height`` required Mapped to the :attr:`~GDALRaster.height` attribute
|
||||
``driver`` ``MEM`` Mapped to the :attr:`~GDALRaster.driver` attribute
|
||||
``name`` ``''`` See below
|
||||
``origin`` ``0`` Mapped to the :attr:`~GDALRaster.origin` attribute
|
||||
``scale`` ``0`` Mapped to the :attr:`~GDALRaster.scale` attribute
|
||||
``skew`` ``0`` Mapped to the :attr:`~GDALRaster.width` attribute
|
||||
``bands`` ``[]`` See below
|
||||
``nr_of_bands`` ``0`` See below
|
||||
``datatype`` ``6`` See below
|
||||
``papsz_options`` ``{}`` See below
|
||||
================= ======== ==================================================
|
||||
|
||||
.. object:: name
|
||||
|
||||
|
@ -1673,6 +1674,41 @@ Key Default Usage
|
|||
raster bands values are instantiated as an array of zeros and the "no
|
||||
data" value is set to ``None``.
|
||||
|
||||
.. object:: papsz_options
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
A dictionary with raster creation options. The key-value pairs of the
|
||||
input dictionary are passed to the driver on creation of the raster.
|
||||
|
||||
The available options are driver-specific and are described in the
|
||||
documentation of each driver.
|
||||
|
||||
The values in the dictionary are not case-sensitive and are automatically
|
||||
converted to the correct string format upon creation.
|
||||
|
||||
The following example uses some of the options available for the
|
||||
`GTiff driver`__. The result is a compressed signed byte raster with an
|
||||
internal tiling scheme. The internal tiles have a block size of 23 by 23::
|
||||
|
||||
>>> GDALRaster({
|
||||
... 'driver': 'GTiff',
|
||||
... 'name': '/path/to/new/file.tif',
|
||||
... 'srid': 4326,
|
||||
... 'width': 255,
|
||||
... 'height': 255,
|
||||
... 'nr_of_bands': 1,
|
||||
... 'papsz_options': {
|
||||
... 'compress': 'packbits',
|
||||
... 'pixeltype': 'signedbyte',
|
||||
... 'tiled': 'yes',
|
||||
... 'blockxsize': 23,
|
||||
... 'blockysize': 23,
|
||||
... }
|
||||
... })
|
||||
|
||||
__ http://www.gdal.org/frmt_gtiff.html
|
||||
|
||||
The ``band_input`` dictionary
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -83,6 +83,9 @@ Minor features
|
|||
:attr:`~django.contrib.gis.gdal.GDALRaster.info`, and
|
||||
:attr:`~django.contrib.gis.gdal.GDALBand.metadata` attributes.
|
||||
|
||||
* Allowed passing driver-specific creation options to
|
||||
:class:`~django.contrib.gis.gdal.GDALRaster` objects using ``papsz_options``.
|
||||
|
||||
:mod:`django.contrib.messages`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -310,6 +310,44 @@ class GDALRasterTests(SimpleTestCase):
|
|||
info_ref = [line.strip() for line in gdalinfo.split('\n') if line.strip() != '']
|
||||
self.assertEqual(info_dyn, info_ref)
|
||||
|
||||
def test_compressed_file_based_raster_creation(self):
|
||||
rstfile = tempfile.NamedTemporaryFile(suffix='.tif')
|
||||
# Make a compressed copy of an existing raster.
|
||||
compressed = self.rs.warp({'papsz_options': {'compress': 'packbits'}, 'name': rstfile.name})
|
||||
# Check physically if compression worked.
|
||||
self.assertLess(os.path.getsize(compressed.name), os.path.getsize(self.rs.name))
|
||||
if GDAL_VERSION > (1, 11):
|
||||
# Create file-based raster with options from scratch.
|
||||
compressed = GDALRaster({
|
||||
'datatype': 1,
|
||||
'driver': 'tif',
|
||||
'name': rstfile.name,
|
||||
'width': 40,
|
||||
'height': 40,
|
||||
'srid': 3086,
|
||||
'origin': (500000, 400000),
|
||||
'scale': (100, -100),
|
||||
'skew': (0, 0),
|
||||
'bands': [{
|
||||
'data': range(40 ^ 2),
|
||||
'nodata_value': 255,
|
||||
}],
|
||||
'papsz_options': {
|
||||
'compress': 'packbits',
|
||||
'pixeltype': 'signedbyte',
|
||||
'blockxsize': 23,
|
||||
'blockysize': 23,
|
||||
}
|
||||
})
|
||||
# Check if options used on creation are stored in metadata.
|
||||
# Reopening the raster ensures that all metadata has been written
|
||||
# to the file.
|
||||
compressed = GDALRaster(compressed.name)
|
||||
self.assertEqual(compressed.metadata['IMAGE_STRUCTURE']['COMPRESSION'], 'PACKBITS',)
|
||||
self.assertEqual(compressed.bands[0].metadata['IMAGE_STRUCTURE']['PIXELTYPE'], 'SIGNEDBYTE')
|
||||
if GDAL_VERSION >= (2, 1):
|
||||
self.assertIn('Block=40x23', compressed.info)
|
||||
|
||||
def test_raster_warp(self):
|
||||
# Create in memory raster
|
||||
source = GDALRaster({
|
||||
|
|
Loading…
Reference in New Issue