Commit 00fa1474 authored by Claude Paroz's avatar Claude Paroz
Browse files

Added raster support for GDAL Driver class

Based on Daniel Wiesmann's work. Refs #23804.
parent ac51496c
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -67,10 +67,7 @@ class DataSource(GDALBase):
        # See also http://trac.osgeo.org/gdal/wiki/rfc23_ogr_unicode
        self.encoding = encoding

        # Registering all the drivers, this needs to be done
        #  _before_ we try to open up a data source.
        if not capi.get_driver_count():
            capi.register_all()
        Driver.ensure_registered()

        if isinstance(ds_input, six.string_types):
            # The data source driver is a void pointer.
+66 −39
Original line number Diff line number Diff line
# prerequisites imports
from ctypes import c_void_p
from django.contrib.gis.gdal.base import GDALBase
from django.contrib.gis.gdal.error import OGRException
from django.contrib.gis.gdal.prototypes import ds as capi
from django.contrib.gis.gdal.prototypes import ds as vcapi, raster as rcapi

from django.utils import six
from django.utils.encoding import force_bytes
from django.utils.encoding import force_bytes, force_text


# For more information, see the OGR C API source code:
#  http://www.gdal.org/ogr/ogr__api_8h.html
#
# The OGR_Dr_* routines are relevant here.
class Driver(GDALBase):
    "Wraps an OGR Data Source Driver."
    """
    Wraps a GDAL/OGR Data Source Driver.
    For more information, see the C API source code:
    http://www.gdal.org/gdal_8h.html - http://www.gdal.org/ogr__api_8h.html
    """

    # Case-insensitive aliases for OGR Drivers.
    _alias = {'esri': 'ESRI Shapefile',
    # Case-insensitive aliases for some GDAL/OGR Drivers.
    # For a complete list of original driver names see
    # http://www.gdal.org/ogr_formats.html (vector)
    # http://www.gdal.org/formats_list.html (raster)
    _alias = {
        # vector
        'esri': 'ESRI Shapefile',
        'shp': 'ESRI Shapefile',
        'shape': 'ESRI Shapefile',
        'tiger': 'TIGER',
        'tiger/line': 'TIGER',
        # raster
        'tiff': 'GTiff',
        'tif': 'GTiff',
        'jpeg': 'JPEG',
        'jpg': 'JPEG',
    }

    def __init__(self, dr_input):
        "Initializes an OGR driver on either a string or integer input."

        """
        Initializes an GDAL/OGR driver on either a string or integer input.
        """
        if isinstance(dr_input, six.string_types):
            # If a string name of the driver was passed in
            self._register()
            self.ensure_registered()

            # Checking the alias dictionary (case-insensitive) to see if an alias
            #  exists for the given driver.
            # Checking the alias dictionary (case-insensitive) to see if an
            # alias exists for the given driver.
            if dr_input.lower() in self._alias:
                name = self._alias[dr_input.lower()]
            else:
                name = dr_input

            # Attempting to get the OGR driver by the string name.
            dr = capi.get_driver_by_name(force_bytes(name))
            # Attempting to get the GDAL/OGR driver by the string name.
            for iface in (vcapi, rcapi):
                driver = iface.get_driver_by_name(force_bytes(name))
                if driver:
                    break
        elif isinstance(dr_input, int):
            self._register()
            dr = capi.get_driver(dr_input)
            self.ensure_registered()
            for iface in (vcapi, rcapi):
                driver = iface.get_driver(dr_input)
                if driver:
                    break
        elif isinstance(dr_input, c_void_p):
            dr = dr_input
            driver = dr_input
        else:
            raise OGRException('Unrecognized input type for OGR Driver: %s' % str(type(dr_input)))
            raise OGRException('Unrecognized input type for GDAL/OGR Driver: %s' % str(type(dr_input)))

        # Making sure we get a valid pointer to the OGR Driver
        if not dr:
            raise OGRException('Could not initialize OGR Driver on input: %s' % str(dr_input))
        self.ptr = dr
        if not driver:
            raise OGRException('Could not initialize GDAL/OGR Driver on input: %s' % str(dr_input))
        self.ptr = driver

    def __str__(self):
        "Returns the string name of the OGR Driver."
        return capi.get_driver_name(self.ptr)
        return self.name

    def _register(self):
        "Attempts to register all the data source drivers."
    @classmethod
    def ensure_registered(cls):
        """
        Attempts to register all the data source drivers.
        """
        # Only register all if the driver count is 0 (or else all drivers
        # will be registered over and over again)
        if not self.driver_count:
            capi.register_all()
        if not cls.driver_count():
            vcapi.register_all()
            rcapi.register_all()

    @classmethod
    def driver_count(cls):
        """
        Returns the number of GDAL/OGR data source drivers registered.
        """
        return vcapi.get_driver_count() + rcapi.get_driver_count()

    # Driver properties
    @property
    def driver_count(self):
        "Returns the number of OGR data source drivers registered."
        return capi.get_driver_count()
    def name(self):
        """
        Returns description/name string for this driver.
        """
        return force_text(rcapi.get_driver_description(self.ptr))
+1 −1
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@ c_int_p = POINTER(c_int) # shortcut type
register_all = void_output(lgdal.OGRRegisterAll, [], errcheck=False)
cleanup_all = void_output(lgdal.OGRCleanupAll, [], errcheck=False)
get_driver = voidptr_output(lgdal.OGRGetDriver, [c_int])
get_driver_by_name = voidptr_output(lgdal.OGRGetDriverByName, [c_char_p])
get_driver_by_name = voidptr_output(lgdal.OGRGetDriverByName, [c_char_p], errcheck=False)
get_driver_count = int_output(lgdal.OGRGetDriverCount, [])
get_driver_name = const_string_output(lgdal.OGR_Dr_GetName, [c_void_p], decoding='ascii')

+21 −12
Original line number Diff line number Diff line
import unittest
from unittest import skipUnless

from django.contrib.gis.gdal import HAS_GDAL

@@ -7,29 +6,39 @@ if HAS_GDAL:
    from django.contrib.gis.gdal import Driver, OGRException


valid_drivers = ('ESRI Shapefile', 'MapInfo File', 'TIGER', 'S57', 'DGN',
                 'Memory', 'CSV', 'GML', 'KML')
valid_drivers = (
    # vector
    'ESRI Shapefile', 'MapInfo File', 'TIGER', 'S57', 'DGN', 'Memory', 'CSV',
    'GML', 'KML',
    # raster
    'GTiff', 'JPEG', 'netCDF', 'MEM', 'PNG',
)

invalid_drivers = ('Foo baz', 'clucka', 'ESRI Shp')
invalid_drivers = ('Foo baz', 'clucka', 'ESRI Shp', 'ESRI rast')

aliases = {'eSrI': 'ESRI Shapefile',
aliases = {
    'eSrI': 'ESRI Shapefile',
    'TigER/linE': 'TIGER',
    'SHAPE': 'ESRI Shapefile',
    'sHp': 'ESRI Shapefile',
    'tiFf': 'GTiff',
    'tIf': 'GTiff',
    'jPEg': 'JPEG',
    'jpG': 'JPEG',
}


@skipUnless(HAS_GDAL, "GDAL is required")
@unittest.skipUnless(HAS_GDAL, "GDAL is required")
class DriverTest(unittest.TestCase):

    def test01_valid_driver(self):
        "Testing valid OGR Data Source Drivers."
        "Testing valid GDAL/OGR Data Source Drivers."
        for d in valid_drivers:
            dr = Driver(d)
            self.assertEqual(d, str(dr))

    def test02_invalid_driver(self):
        "Testing invalid OGR Data Source Drivers."
        "Testing invalid GDAL/OGR Data Source Drivers."
        for i in invalid_drivers:
            self.assertRaises(OGRException, Driver, i)