Index: apps/gdal_utilities.dox =================================================================== --- apps/gdal_utilities.dox (revision 25484) +++ apps/gdal_utilities.dox (working copy) @@ -128,6 +128,7 @@ 'rw' is read or write (ie. supports CreateCopy); 'rw+' is read, write and update (ie. supports Create). A 'v' is appended for formats supporting virtual IO (/vsimem, /vsigzip, /vsizip, etc). +A 's' is appended for formats supporting subdatasets in read-only mode. Note: The valid formats for the output of gdalwarp are formats that support the Create() method (marked as rw+), not just the CreateCopy() method. Index: doc/gdal_datamodel.dox =================================================================== --- doc/gdal_datamodel.dox (revision 25484) +++ doc/gdal_datamodel.dox (working copy) @@ -174,26 +174,29 @@ The SUBDATASETS domain holds a list of child datasets. Normally this is used to provide pointers to a list of images stored within a single multi -image file (such as HDF or NITF). For instance, an NITF with four images -might have the following subdataset list. +image file. +For example, an NITF with two images might have the following subdataset list. +
   SUBDATASET_1_NAME=NITF_IM:0:multi_1b.ntf
   SUBDATASET_1_DESC=Image 1 of multi_1b.ntf
   SUBDATASET_2_NAME=NITF_IM:1:multi_1b.ntf
   SUBDATASET_2_DESC=Image 2 of multi_1b.ntf
-  SUBDATASET_3_NAME=NITF_IM:2:multi_1b.ntf
-  SUBDATASET_3_DESC=Image 3 of multi_1b.ntf
-  SUBDATASET_4_NAME=NITF_IM:3:multi_1b.ntf
-  SUBDATASET_4_DESC=Image 4 of multi_1b.ntf
-  SUBDATASET_5_NAME=NITF_IM:4:multi_1b.ntf
-  SUBDATASET_5_DESC=Image 5 of multi_1b.ntf
 
The value of the _NAME is the string that can be passed to GDALOpen() to access the file. The _DESC value is intended to be a more user friendly string that can be displayed to the user in a selector. +Drivers which support subdatasets in read-only mode advertize +the DMD_SUBDATASETS capability. This information is reported when the +\-\-format and \-\-formats options are passed to the commandline utilities. + +Currently, drivers which support subdatasets are: +ADRG, ECRGTOC, GEORASTER, GTiff, HDF4, HDF5, netCDF, NITF, NTv2, OGDI, PDF, +PostGISRaster, Rasterlite, RPFTOC, RS2, WCS, and WMS. + \subsubsection gdal_datamodel_image_structure IMAGE_STRUCTURE Domain Metadata in the default domain is intended to be related to the Index: frmts/wms/wmsdriver.cpp =================================================================== --- frmts/wms/wmsdriver.cpp (revision 25488) +++ frmts/wms/wmsdriver.cpp (working copy) @@ -860,14 +860,18 @@ GDALDriver *driver; if (GDALGetDriverByName("WMS") == NULL) { driver = new GDALDriver(); + driver->SetDescription("WMS"); driver->SetMetadataItem(GDAL_DMD_LONGNAME, "OGC Web Map Service"); driver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_wms.html"); driver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" ); + driver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" ); + driver->pfnOpen = GDALWMSDataset::Open; driver->pfnIdentify = GDALWMSDataset::Identify; driver->pfnUnloadDriver = GDALDeregister_WMS; driver->pfnCreateCopy = GDALWMSDataset::CreateCopy; + GetGDALDriverManager()->RegisterDriver(driver); GDALWMSMiniDriverManager *const mdm = GetGDALWMSMiniDriverManager(); Index: frmts/pdf/pdfdataset.cpp =================================================================== --- frmts/pdf/pdfdataset.cpp (revision 25488) +++ frmts/pdf/pdfdataset.cpp (working copy) @@ -4809,6 +4809,7 @@ poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "pdf" ); poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" ); + poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" ); #ifdef HAVE_POPPLER poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" ); poDriver->SetMetadataItem( "HAVE_POPPLER", "YES" ); Index: frmts/adrg/adrgdataset.cpp =================================================================== --- frmts/adrg/adrgdataset.cpp (revision 25488) +++ frmts/adrg/adrgdataset.cpp (working copy) @@ -2372,7 +2372,7 @@ poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gen" ); poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" ); - + poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" ); poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" ); poDriver->pfnOpen = ADRGDataset::Open; Index: frmts/raw/ntv2dataset.cpp =================================================================== --- frmts/raw/ntv2dataset.cpp (revision 25488) +++ frmts/raw/ntv2dataset.cpp (working copy) @@ -870,7 +870,7 @@ "NTv2 Datum Grid Shift" ); poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gsb" ); poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" ); - + poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" ); poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Float32" ); Index: frmts/georaster/georaster_dataset.cpp =================================================================== --- frmts/georaster/georaster_dataset.cpp (revision 25488) +++ frmts/georaster/georaster_dataset.cpp (working copy) @@ -1864,6 +1864,7 @@ poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Oracle Spatial GeoRaster" ); poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_georaster.html" ); + poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" ); poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte UInt16 Int16 UInt32 Int32 Float32 " "Float64 CFloat32 CFloat64" ); Index: frmts/netcdf/netcdfdataset.cpp =================================================================== --- frmts/netcdf/netcdfdataset.cpp (revision 25488) +++ frmts/netcdf/netcdfdataset.cpp (working copy) @@ -5625,6 +5625,7 @@ poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "nc" ); poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, szCreateOptions ); + poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" ); /* make driver config and capabilities available */ poDriver->SetMetadataItem( "NETCDF_VERSION", nc_inq_libvers() ); Index: frmts/rs2/rs2dataset.cpp =================================================================== --- frmts/rs2/rs2dataset.cpp (revision 25488) +++ frmts/rs2/rs2dataset.cpp (working copy) @@ -1472,6 +1472,7 @@ poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "RadarSat 2 XML Product" ); poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_rs2.html" ); + poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" ); poDriver->pfnOpen = RS2Dataset::Open; poDriver->pfnIdentify = RS2Dataset::Identify; Index: frmts/rasterlite/rasterlitedataset.cpp =================================================================== --- frmts/rasterlite/rasterlitedataset.cpp (revision 25488) +++ frmts/rasterlite/rasterlitedataset.cpp (working copy) @@ -1343,6 +1343,7 @@ poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_rasterlite.html" ); poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sqlite" ); + poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" ); poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte UInt16 Int16 UInt32 Int32 Float32 " "Float64 CInt16 CInt32 CFloat32 CFloat64" ); Index: frmts/ogdi/ogdidataset.cpp =================================================================== --- frmts/ogdi/ogdidataset.cpp (revision 25488) +++ frmts/ogdi/ogdidataset.cpp (working copy) @@ -966,6 +966,7 @@ "OGDI Bridge" ); poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_ogdi.html" ); + poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" ); poDriver->pfnOpen = OGDIDataset::Open; Index: frmts/gtiff/geotiff.cpp =================================================================== --- frmts/gtiff/geotiff.cpp (revision 25488) +++ frmts/gtiff/geotiff.cpp (working copy) @@ -9834,7 +9834,7 @@ "Float64 CInt16 CInt32 CFloat32 CFloat64" ); poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, szCreateOptions ); - + poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" ); poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" ); poDriver->pfnOpen = GTiffDataset::Open; Index: frmts/postgisraster/postgisrasterdataset.cpp =================================================================== --- frmts/postgisraster/postgisrasterdataset.cpp (revision 25488) +++ frmts/postgisraster/postgisrasterdataset.cpp (working copy) @@ -2049,6 +2049,7 @@ poDriver->SetDescription("PostGISRaster"); poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "PostGIS Raster driver"); + poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" ); poDriver->pfnOpen = PostGISRasterDataset::Open; poDriver->pfnCreateCopy = PostGISRasterDataset::CreateCopy; Index: frmts/nitf/rpftocdataset.cpp =================================================================== --- frmts/nitf/rpftocdataset.cpp (revision 25488) +++ frmts/nitf/rpftocdataset.cpp (working copy) @@ -1280,6 +1280,7 @@ "frmt_various.html#RPFTOC" ); poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "toc" ); poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" ); + poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" ); GetGDALDriverManager()->RegisterDriver( poDriver ); } Index: frmts/nitf/ecrgtocdataset.cpp =================================================================== --- frmts/nitf/ecrgtocdataset.cpp (revision 25488) +++ frmts/nitf/ecrgtocdataset.cpp (working copy) @@ -1049,6 +1049,7 @@ "frmt_various.html#ECRGTOC" ); poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "xml" ); poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" ); + poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" ); GetGDALDriverManager()->RegisterDriver( poDriver ); } Index: frmts/nitf/nitfdataset.cpp =================================================================== --- frmts/nitf/nitfdataset.cpp (revision 25488) +++ frmts/nitf/nitfdataset.cpp (working copy) @@ -5649,6 +5649,7 @@ poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_nitf.html" ); poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ntf" ); + poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" ); poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte UInt16 Int16 UInt32 Int32 Float32" ); Index: frmts/wcs/wcsdataset.cpp =================================================================== --- frmts/wcs/wcsdataset.cpp (revision 25488) +++ frmts/wcs/wcsdataset.cpp (working copy) @@ -2389,6 +2389,7 @@ poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_wcs.html" ); poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" ); + poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" ); poDriver->pfnOpen = WCSDataset::Open; poDriver->pfnIdentify = WCSDataset::Identify; Index: frmts/hdf4/hdf4dataset.cpp =================================================================== --- frmts/hdf4/hdf4dataset.cpp (revision 25488) +++ frmts/hdf4/hdf4dataset.cpp (working copy) @@ -1151,7 +1151,8 @@ "Hierarchical Data Format Release 4" ); poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_hdf4.html" ); - poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "hdf"); + poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "hdf" ); + poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" ); poDriver->pfnOpen = HDF4Dataset::Open; poDriver->pfnIdentify = HDF4Dataset::Identify; Index: frmts/hdf5/hdf5dataset.cpp =================================================================== --- frmts/hdf5/hdf5dataset.cpp (revision 25488) +++ frmts/hdf5/hdf5dataset.cpp (working copy) @@ -69,6 +69,7 @@ poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_hdf5.html"); poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "hdf5"); + poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES"); poDriver->pfnOpen = HDF5Dataset::Open; poDriver->pfnIdentify = HDF5Dataset::Identify; GetGDALDriverManager()->RegisterDriver(poDriver); Index: gcore/gdal.h =================================================================== --- gcore/gdal.h (revision 25484) +++ gcore/gdal.h (working copy) @@ -212,6 +212,7 @@ #define GDAL_DMD_EXTENSION "DMD_EXTENSION" #define GDAL_DMD_CREATIONOPTIONLIST "DMD_CREATIONOPTIONLIST" #define GDAL_DMD_CREATIONDATATYPES "DMD_CREATIONDATATYPES" +#define GDAL_DMD_SUBDATASETS "DMD_SUBDATASETS" #define GDAL_DCAP_CREATE "DCAP_CREATE" #define GDAL_DCAP_CREATECOPY "DCAP_CREATECOPY" Index: gcore/gdal_misc.cpp =================================================================== --- gcore/gdal_misc.cpp (revision 25484) +++ gcore/gdal_misc.cpp (working copy) @@ -2552,7 +2552,7 @@ for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ ) { GDALDriverH hDriver = GDALGetDriver(iDr); - const char *pszRWFlag, *pszVirtualIO; + const char *pszRWFlag, *pszVirtualIO, *pszSubdatasets; if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) ) pszRWFlag = "rw+"; @@ -2567,9 +2567,15 @@ else pszVirtualIO = ""; - printf( " %s (%s%s): %s\n", + pszSubdatasets = GDALGetMetadataItem( hDriver, GDAL_DMD_SUBDATASETS, NULL ); + if( pszSubdatasets && CSLTestBoolean( pszSubdatasets ) ) + pszSubdatasets = "s"; + else + pszSubdatasets = ""; + + printf( " %s (%s%s%s): %s\n", GDALGetDriverShortName( hDriver ), - pszRWFlag, pszVirtualIO, + pszRWFlag, pszVirtualIO, pszSubdatasets, GDALGetDriverLongName( hDriver ) ); } @@ -2621,6 +2627,8 @@ printf( " Help Topic: %s\n", CSLFetchNameValue( papszMD, GDAL_DMD_HELPTOPIC ) ); + if( CSLFetchBoolean( papszMD, GDAL_DMD_SUBDATASETS, FALSE ) ) + printf( " Supports: Subdatasets\n" ); if( CSLFetchBoolean( papszMD, GDAL_DCAP_CREATE, FALSE ) ) printf( " Supports: Create() - Create writeable dataset.\n" ); if( CSLFetchBoolean( papszMD, GDAL_DCAP_CREATECOPY, FALSE ) ) Index: swig/include/gdalconst.i =================================================================== --- swig/include/gdalconst.i (revision 25484) +++ swig/include/gdalconst.i (working copy) @@ -151,6 +151,7 @@ #define GDAL_DMD_EXTENSION "DMD_EXTENSION" #define GDAL_DMD_CREATIONOPTIONLIST "DMD_CREATIONOPTIONLIST" #define GDAL_DMD_CREATIONDATATYPES "DMD_CREATIONDATATYPES" +#define GDAL_DMD_SUBDATASETS "DMD_SUBDATASETS" #define GDAL_DCAP_CREATE "DCAP_CREATE" #define GDAL_DCAP_CREATECOPY "DCAP_CREATECOPY"