[gdal-dev] Re: a generic options facility for GDAL

Ivan Shmakov ivan at theory.asu.ru
Thu Jan 24 16:10:45 EST 2008


* Preface

	Here I'm posting a proof of concept patch implementing (a part
	of) a generic options facility for GDAL.  The goals of having
	such a facility are as follows (see, e. g., [1, 2]):

	* provide a generic way to obtain the information about a
	  specific dataset from a helper file, either distributed with
	  GDAL, or created by the user; (especially for the information
	  that cannot be obtained by any other means, or needs some
	  complex heuristics to be implemented by the driver);

	* provide an easy to use API for an application developer to
	  pass the options to a GDAL driver;

	* provide a way to specify options for the dataset by encoding
	  them within the dataset name.

	Reaching the first goal will allow for some hard-coded defaults
	and heuristics to be thrown away from the drivers' source and be
	put into a helper file, thus easing the maintenance of the
	driver and offering more flexibility to the user.

	The last goal is so that the extra flexibility will be available
	in a backward compatible way.

	By no means the code or the interface below is of a production
	quality.  I explicitly state that it is not intended for
	inclusion into the official GDAL source.  The code is provided
	so that the people interested in the problem could evaluate the
	approach and (I hope) eventually come up with a solution
	suitable for inclusion into GDAL.

	The added code is in the public domain.

	Use the code at your own risk.

* The interface

	The interface currently implemented allows for the hierarchy of
	options to be specified either with a helper file, or from the
	command line.  E. g.:

$ cat "$GDAL_OPTIONS_FILE" 
{ match "^HDF4_EOS:EOS_GRID:.*:MOD_Grid_BRDF:Albedo\$" } {
    options hdf4 { dims { iy 0 ix 1 iband 2 i4 3 } }
}
{ match "^HDF4_EOS:EOS_GRID:.*:MOD_Grid_BRDF:BRDF_Albedo_Parameters\$" } {
    options hdf4 { dims { iy 0 ix 1 iband 2 i4 3 } }
}
$ file=2006-08-02-brdf-22-3/2006-08-02-brdf.1.hdf
$ dataset="HDF4_EOS:EOS_GRID:\"${file}\":MOD_Grid_BRDF:BRDF_Albedo_Parameters"
$ gdalinfo "${dataset}:OPTIONS:dict create hdf4 { dims { iy 0 ix 1 iband 2 i4 3 } }" 
Driver: HDF4Image/HDF4 Dataset
Size is 1200, 1200
...
Band 1 Block=1200x1 Type=Int16, ColorInterp=Gray
  NoData Value=32767
Band 2 Block=1200x1 Type=Int16, ColorInterp=Gray
  NoData Value=32767
...
Band 29 Block=1200x1 Type=Int16, ColorInterp=Gray
  NoData Value=32767
Band 30 Block=1200x1 Type=Int16, ColorInterp=Gray
  NoData Value=32767
$ 

	Either way the options specified are as follows:

hdf4
 `-- dims
     |-- iy    => 0
     |-- ix    => 1
     |-- iband => 2
     `-- i4    => 3

	The HDF4 driver fails to determine the meaning of the dimensions
	when no options are specified:

$ gdalinfo "${dataset}"
Driver: HDF4Image/HDF4 Dataset
Size is 1200, 1200
...
Band 1 Block=1200x1 Type=Int16, ColorInterp=Gray
  NoData Value=32767
Band 2 Block=1200x1 Type=Int16, ColorInterp=Gray
  NoData Value=32767
...
Band 11999 Block=1200x1 Type=Int16, ColorInterp=Gray
  NoData Value=32767
Band 12000 Block=1200x1 Type=Int16, ColorInterp=Gray
  NoData Value=32767
$ 

	The options support is currently added only to the HDF4 driver
	and only the options in `dims' subspace (namely, `ix', `iy',
	`iband' and `i4') are handled.

	There're no substantial API to be described at the moment.
	Please refer to the source if you need to know the details.

* The implementation

	In order not to invent either a string representation or a
	simple hierarchial database, I've chosen to use the facilities
	provided by Tcl [3] -- the language notable for its ``everything
	is a string'' concept.  In particular, I've used the
	``dictionaries'' facility [4] introduced in Tcl version 8.5.

	Using of a programming language here also allows for different
	strategies for the options processing to be easily evaluated.
	In particular, the `GDAL_OPTIONS_FILE' support is currently
	implemented in pure Tcl:

$ cat gdal-options.tcl 

proc merge-in { args } {
    global GDALdict
    ## .
    set GDALdict [ uplevel \#0 { dict merge } [ list $GDALdict ] $args ]
}

proc match { regexp } {
    global GDALinfo
    ## .
    regexp -- $regexp $GDALinfo
}

proc options { args } {
    ## .
    merge-in [ uplevel \#0 { dict create } $args ]
}

set varn env(GDAL_OPTIONS_FILE)
if { [ info exists $varn ]
     && [ file exists [ set $varn ] ] } {
    set chan [ open [ set $varn ] "r" ]
    foreach { condition body } [ read $chan ] {
        if { [ uplevel \#0 $condition ] } {
            uplevel \#0 $body
        }
    }
    close $chan
}

## .
set GDALdict
$ 

	In order to use such a file, the Tcl `source' [5] command may be
	specified in the `:OPTIONS:' part, e. g. (provided that
	`$GDAL_OPTIONS_FILE' points to a suitable file):

$ gdalinfo "${dataset}:OPTIONS:source gdal-options.tcl" 
Driver: HDF4Image/HDF4 Dataset
Size is 1200, 1200
...
Band 1 Block=1200x1 Type=Int16, ColorInterp=Gray
  NoData Value=32767
Band 2 Block=1200x1 Type=Int16, ColorInterp=Gray
  NoData Value=32767
...
Band 29 Block=1200x1 Type=Int16, ColorInterp=Gray
  NoData Value=32767
Band 30 Block=1200x1 Type=Int16, ColorInterp=Gray
  NoData Value=32767
$ 

	Using both the helper file and the dataset name is also
	possible, e. g.:

HDF4_EOS:EOS_GRID:"FILE.hdf":Foo_Grid:Bar_Field:OPTIONS:source gdal-options.tcl; options hdf4 { subspace { option-1 value-1 } }

[1] http://lists.osgeo.org/pipermail/gdal-dev/2007-November/014853.html
[2] http://lists.osgeo.org/pipermail/gdal-dev/2007-December/015343.html
[3] http://www.tcl.tk/
[4] http://www.tcl.tk/man/tcl8.5/TclCmd/dict.htm
[5] http://www.tcl.tk/man/tcl8.5/TclCmd/source.htm

	The changes were made against SVN r13584.  The short description
	is as follows.

    * patch #2 -- options support for the HDF4 driver

    frmts/hdf4/hdf4imagedataset.cpp
    (HDF4ImageDataset::go_dims): New member.
    (HDF4ImageDataset::go_geoloc): Likewise.
    (HDF4ImageDataset::HDF4ImageDataset): Initialize `go_dims' and
    `go_geoloc' with a null pointer.
    (HDF4ImageDataset::GetImageDimensions): Override guessing if the
    dimensions indices were specified explicitly via the options.
    (HDF4ImageDataset::Open): Initialize `go_dims' and `go_geoloc' using
    the `options' field of the `GDALOpenInfo' object passed.

    * patch #1 -- generic options facility, proof of concept

    gcore/gdal_priv.h
    (tcl8.5/tcl.h): Include it.
    (struct gdal_options): New type.
    (gdal_options_process_string): New function declaration.
    (gdal_options_sub): Likewise.
    (gdal_option_get): Likewise.
    (gdal_option_put): Likewise.
    (GDALOpenInfo::GDALOpenInfo): Allow for optional `go_override' argument.
    (GDALOpenInfo::options): New member.

    gcore/gdalopeninfo.cpp
    (GDALOpenInfo::GDALOpenInfo): Added `go_override' argument; initialize
    the `options' member; implemented `:OPTIONS:' handling.
    (GDALOpenInfo::~GDALOpenInfo): Call `gdal_options_free' on `options'.
    (assert.h): Include it.
    (MALLOC_VAR): New macro.
    (MALLOC_ARY): Likewise.
    (tclobjs_from_strings): New function.
    (tclobjs_decrement_refcount): Likewise.
    (dict_get): Likewise.
    (gdal_options_new): Likewise.
    (gdal_options_free): Likewise.
    (gdal_options_process_string): Likewise.
    (gdal_options_sub): Likewise.
    (gdal_option_get): Likewise.
    (gdal_option_put): Likewise.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch-1.diff.gz
Type: text/x-diff
Size: 10430 bytes
Desc: patch #1 -- generic options facility, proof of concept
Url : http://lists.osgeo.org/pipermail/gdal-dev/attachments/20080125/b0aeda79/patch-1.diff-0001.bin
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch-2.diff.gz
Type: text/x-diff
Size: 4871 bytes
Desc: patch #2 -- options support for the HDF4 driver
Url : http://lists.osgeo.org/pipermail/gdal-dev/attachments/20080125/b0aeda79/patch-2.diff-0001.bin


More information about the gdal-dev mailing list