RFC 43: GDALMajorObject::GetMetadataDomainList

Author: Even Rouault

Contact: even dot rouault at spatialys.com

Summary

This (mini)RFC proposes a new virtual method, GetMetadataDomainList(), in the GDALMajorObject class (and a C API) to return the list of all available metadata domains.

Background

GDALMajorObject currently offers the GetMetadata() and GetMetadataItem() methods that both accept a metadata domain argument. But there is no way to auto-discover which metadata domains are valid for a given GDALMajorObject (i.e. a dataset or raster band). This make it impossible to have generic code that can exhaustively discover all metadata in a dataset/raster band.

Implementation

The base implementation in GDALMajorObject just calls GetDomainList() on the internal oMDMD member.

/************************************************************************/
/*                      GetMetadataDomainList()                         */
/************************************************************************/

/**
 * \brief Fetch list of metadata domains.
 *
 * The returned string list is the list of (non-empty) metadata domains.
 *
 * This method does the same thing as the C function GDALGetMetadataDomainList().
 *
 * @return NULL or a string list. Must be freed with CSLDestroy()
 *
 * @since GDAL 1.11
 */

char **GDALMajorObject::GetMetadataDomainList()
{
    return CSLDuplicate(oMDMD.GetDomainList());
}

This method is also available in the C API ( char ** CPL_STDCALL GDALGetMetadataDomainList( GDALMajorObjectH hObject) ) and Swig bindings.

Impacted drivers

Drivers that have custom implementations of GetMetadata() and/or GetMetadataItem() will generally have to also implement GetMetadataDomainList(), when they don't modify the oMDMD member.

To make it easy to implement the specialized GetMetadataDomainList(), GDALMajorObject will offer a protected BuildMetadataDomainList() method that can be used like the following :

/************************************************************************/
/*                      GetMetadataDomainList()                         */
/************************************************************************/

char **NITFDataset::GetMetadataDomainList()
{
    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
                                   TRUE,
                                   "NITF_METADATA", "NITF_DES", "NITF_DES_METADATA",
                                   "NITF_FILE_HEADER_TRES", "NITF_IMAGE_SEGMENT_TRES",
                                   "CGM", "TEXT", "TRE", "xml:TRE", "OVERVIEWS", NULL);
}

The TRUE parameter means that the list of domains that follows are potential domains, and thus BuildMetadataDomainList() will check for each one that GetMetadata() returns a non-NULL value.

An exhaustive search in GDAL drivers has been made and all drivers that needed to be updated to implement GetMetadataDomainList() have been updated: ADRG, BAG, CEOS2, DIMAP, ECW, ENVISAT, ERS, GeoRaster (cannot check myself that it compiles), GIF, GTiff, HDF4, JPEG, MBTILES, netCDF, NITF, OGDI, PCIDSK, PDF, PNG, PostgisRaster, RasterLite, RS2, VRT, WCS, WebP, WMS.

A few caveats :

  • For MBTiles, WMS and VRT, GetMetadataDomainList(), at the band level, will return "LocationInfo" as a valid metadata domain (used by the gdallocationinfo utility), even if GetMetadata("LocationInfo") itself does not return metadata : you have to call GetMetadataItem("Pixel_someX_someY", "LocationInfo") or GetMetadataItem("GeoPixel_someX_someY", "LocationInfo").

  • For CEOS2 and ENVISAT, the list of metadata domains cannot be established easily. GetMetadataDomainList() will return the pattern of accepted domain names.

Impacted utilities

The gdalinfo utility is extended to accept :

  • a "-listmdd" option that will print the metadata domains available,

$ gdalinfo ../autotest/gdrivers/data/byte_with_xmp.jpg -listmdd

Driver: JPEG/JPEG JFIF
Files: ../autotest/gdrivers/data/byte_with_xmp.jpg
Size is 20, 20
Coordinate System is `'
Metadata domains:
  xml:XMP
Corner Coordinates:
Upper Left  (    0.0,    0.0)
Lower Left  (    0.0,   20.0)
Upper Right (   20.0,    0.0)
Lower Right (   20.0,   20.0)
Center      (   10.0,   10.0)
Band 1 Block=20x1 Type=Byte, ColorInterp=Gray
  Metadata domains:
    IMAGE_STRUCTURE
  Image Structure Metadata:
    COMPRESSION=JPEG
  • and "-mdd all" will display the content of all metadata domains.

$ gdalinfo ../autotest/gdrivers/data/byte_with_xmp.jpg -mdd all

Driver: JPEG/JPEG JFIF
Files: ../autotest/gdrivers/data/byte_with_xmp.jpg
Size is 20, 20
Coordinate System is `'
Metadata (xml:XMP):
<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 7.89'>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>

 <rdf:Description rdf:about=''
  xmlns:dc='http://purl.org/dc/elements/1.1/'>
  <dc:description>
   <rdf:Alt>
    <rdf:li xml:lang='x-default'>Description</rdf:li>
   </rdf:Alt>
  </dc:description>
  <dc:subject>
   <rdf:Bag>
    <rdf:li>XMP</rdf:li>
    <rdf:li>Test</rdf:li>
   </rdf:Bag>
  </dc:subject>
  <dc:title>
   </rdf:Alt>
  </dc:title>
 </rdf:Description>

 <rdf:Description rdf:about=''
  xmlns:tiff='http://ns.adobe.com/tiff/1.0/'>
  <tiff:BitsPerSample>
   <rdf:Seq>
    <rdf:li>8</rdf:li>
   </rdf:Seq>
  </tiff:BitsPerSample>
  <tiff:Compression>1</tiff:Compression>
  <tiff:ImageLength>20</tiff:ImageLength>
  <tiff:ImageWidth>20</tiff:ImageWidth>
  <tiff:PhotometricInterpretation>1</tiff:PhotometricInterpretation>
  <tiff:PlanarConfiguration>1</tiff:PlanarConfiguration>
  <tiff:SamplesPerPixel>1</tiff:SamplesPerPixel>
 </rdf:Description>
</rdf:RDF>
</x:xmpmeta>
























<?xpacket end='w'?>
Corner Coordinates:
Upper Left  (    0.0,    0.0)
Lower Left  (    0.0,   20.0)
Upper Right (   20.0,    0.0)
Lower Right (   20.0,   20.0)
Center      (   10.0,   10.0)
Band 1 Block=20x1 Type=Byte, ColorInterp=Gray
  Image Structure Metadata:
    COMPRESSION=JPEG

Backward Compatibility

This change has no impact on backward compatibility at the C API/ABI and C++ API levels. But it impacts C++ ABI, so it requires a full rebuild of all GDAL drivers.

Testing

The Python autotest suite will be extended to test the new API in a few drivers.

Ticket

Ticket #5275 has been opened to track the progress of this RFC.

The implementation is available in an attachment to ticket 5275.

Voting history

+1 from EvenR, DanielM and JukkaR