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 json
|
||||||
import os
|
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.driver import Driver
|
||||||
from django.contrib.gis.gdal.error import GDALException
|
from django.contrib.gis.gdal.error import GDALException
|
||||||
@ -92,6 +92,16 @@ class GDALRaster(GDALRasterBase):
|
|||||||
if 'srid' not in ds_input:
|
if 'srid' not in ds_input:
|
||||||
raise GDALException('Specify srid for JSON or dict 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
|
# Create GDAL Raster
|
||||||
self._ptr = capi.create_ds(
|
self._ptr = capi.create_ds(
|
||||||
driver._ptr,
|
driver._ptr,
|
||||||
@ -100,7 +110,7 @@ class GDALRaster(GDALRasterBase):
|
|||||||
ds_input['height'],
|
ds_input['height'],
|
||||||
ds_input.get('nr_of_bands', len(ds_input.get('bands', []))),
|
ds_input.get('nr_of_bands', len(ds_input.get('bands', []))),
|
||||||
ds_input.get('datatype', 6),
|
ds_input.get('datatype', 6),
|
||||||
None
|
byref(papsz_options),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Set band data if provided
|
# Set band data if provided
|
||||||
|
@ -1619,9 +1619,9 @@ the others are described below.
|
|||||||
The following table describes all keys that can be set in the ``ds_input``
|
The following table describes all keys that can be set in the ``ds_input``
|
||||||
dictionary.
|
dictionary.
|
||||||
|
|
||||||
=============== ======== ==================================================
|
================= ======== ==================================================
|
||||||
Key Default Usage
|
Key Default Usage
|
||||||
=============== ======== ==================================================
|
================= ======== ==================================================
|
||||||
``srid`` required Mapped to the :attr:`~GDALRaster.srid` attribute
|
``srid`` required Mapped to the :attr:`~GDALRaster.srid` attribute
|
||||||
``width`` required Mapped to the :attr:`~GDALRaster.width` attribute
|
``width`` required Mapped to the :attr:`~GDALRaster.width` attribute
|
||||||
``height`` required Mapped to the :attr:`~GDALRaster.height` attribute
|
``height`` required Mapped to the :attr:`~GDALRaster.height` attribute
|
||||||
@ -1633,7 +1633,8 @@ Key Default Usage
|
|||||||
``bands`` ``[]`` See below
|
``bands`` ``[]`` See below
|
||||||
``nr_of_bands`` ``0`` See below
|
``nr_of_bands`` ``0`` See below
|
||||||
``datatype`` ``6`` See below
|
``datatype`` ``6`` See below
|
||||||
=============== ======== ==================================================
|
``papsz_options`` ``{}`` See below
|
||||||
|
================= ======== ==================================================
|
||||||
|
|
||||||
.. object:: name
|
.. object:: name
|
||||||
|
|
||||||
@ -1673,6 +1674,41 @@ Key Default Usage
|
|||||||
raster bands values are instantiated as an array of zeros and the "no
|
raster bands values are instantiated as an array of zeros and the "no
|
||||||
data" value is set to ``None``.
|
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
|
The ``band_input`` dictionary
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -83,6 +83,9 @@ Minor features
|
|||||||
:attr:`~django.contrib.gis.gdal.GDALRaster.info`, and
|
:attr:`~django.contrib.gis.gdal.GDALRaster.info`, and
|
||||||
:attr:`~django.contrib.gis.gdal.GDALBand.metadata` attributes.
|
: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`
|
:mod:`django.contrib.messages`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -310,6 +310,44 @@ class GDALRasterTests(SimpleTestCase):
|
|||||||
info_ref = [line.strip() for line in gdalinfo.split('\n') if line.strip() != '']
|
info_ref = [line.strip() for line in gdalinfo.split('\n') if line.strip() != '']
|
||||||
self.assertEqual(info_dyn, info_ref)
|
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):
|
def test_raster_warp(self):
|
||||||
# Create in memory raster
|
# Create in memory raster
|
||||||
source = GDALRaster({
|
source = GDALRaster({
|
||||||
|
Loading…
x
Reference in New Issue
Block a user