使用GDAL读取HDF,NetCDF等数据集中的数据时,一般需要两个步骤,第一,获取数据集中的子数据集;第二,通过第一步获取的子数据集读取图像数据。一般的HDF图像中会有很多个子数据集,比如常用的MODIS数据,使用Envi打开会弹出下面的对话框来让用户选择需要打开的子数据集(如图1)。
图1 Envi打开Modis数据
从图1中可以看出,Envi是把所有的子数据集的波段都进行了列举,不过这点和GDAL读取有点不一样。(这里有个比较疑惑的地方就是,使用GDALInfo获取的子数据一共有46个,而且很多图像大小都不一样,而这里Envi所有的波段图像大小都是1354×2030,希望知道的同学告知一下,难道那些小一点的406×271的都不要了?)。
看完Envi的,我们使用GDALInfo工具查看这个数据的信息,输出的内容如下:
Driver: HDF4/Hierarchical Data Format Release 4
Files: F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf
Size is 512, 512
Coordinate System is `'
Metadata:
% Dead Detector EV Data=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
此处省略NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN多字........................................
SOUTHBOUNDINGCOORDINATE=27.4153536499348
VERSIONID=5
WESTBOUNDINGCOORDINATE=106.240739628195
Subdatasets:
SUBDATASET_1_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:EV_1KM_RefSB
SUBDATASET_1_DESC=[15x2030x1354] EV_1KM_RefSB MODIS_SWATH_Type_L1B (16-bit unsigned integer)
SUBDATASET_2_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:EV_1KM_RefSB_Uncert_Indexes
SUBDATASET_2_DESC=[15x2030x1354] EV_1KM_RefSB_Uncert_Indexes MODIS_SWATH_Type_L1B (8-bit unsigned integer)
SUBDATASET_3_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:EV_1KM_Emissive
SUBDATASET_3_DESC=[16x2030x1354] EV_1KM_Emissive MODIS_SWATH_Type_L1B (16-bit unsigned integer)
SUBDATASET_4_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:EV_1KM_Emissive_Uncert_Indexes
SUBDATASET_4_DESC=[16x2030x1354] EV_1KM_Emissive_Uncert_Indexes MODIS_SWATH_Type_L1B (8-bit unsigned integer)
SUBDATASET_5_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:EV_250_Aggr1km_RefSB
SUBDATASET_5_DESC=[2x2030x1354] EV_250_Aggr1km_RefSB MODIS_SWATH_Type_L1B (16-bit unsigned integer)
SUBDATASET_6_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:EV_250_Aggr1km_RefSB_Uncert_Indexes
SUBDATASET_6_DESC=[2x2030x1354] EV_250_Aggr1km_RefSB_Uncert_Indexes MODIS_SWATH_Type_L1B (8-bit unsigned integer)
SUBDATASET_7_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:EV_250_Aggr1km_RefSB_Samples_Used
SUBDATASET_7_DESC=[2x2030x1354] EV_250_Aggr1km_RefSB_Samples_Used MODIS_SWATH_Type_L1B (8-bit integer)
SUBDATASET_8_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:EV_500_Aggr1km_RefSB
SUBDATASET_8_DESC=[5x2030x1354] EV_500_Aggr1km_RefSB MODIS_SWATH_Type_L1B (16-bit unsigned integer)
SUBDATASET_9_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:EV_500_Aggr1km_RefSB_Uncert_Indexes
SUBDATASET_9_DESC=[5x2030x1354] EV_500_Aggr1km_RefSB_Uncert_Indexes MODIS_SWATH_Type_L1B (8-bit unsigned integer)
SUBDATASET_10_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:EV_500_Aggr1km_RefSB_Samples_Used
SUBDATASET_10_DESC=[5x2030x1354] EV_500_Aggr1km_RefSB_Samples_Used MODIS_SWATH_Type_L1B (8-bit integer)
SUBDATASET_11_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:Height
SUBDATASET_11_DESC=[406x271] Height MODIS_SWATH_Type_L1B (16-bit integer)
SUBDATASET_12_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:SensorZenith
SUBDATASET_12_DESC=[406x271] SensorZenith MODIS_SWATH_Type_L1B (16-bit integer)
SUBDATASET_13_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:SensorAzimuth
SUBDATASET_13_DESC=[406x271] SensorAzimuth MODIS_SWATH_Type_L1B (16-bit integer)
SUBDATASET_14_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:Range
SUBDATASET_14_DESC=[406x271] Range MODIS_SWATH_Type_L1B (16-bit unsigned integer)
SUBDATASET_15_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:SolarZenith
SUBDATASET_15_DESC=[406x271] SolarZenith MODIS_SWATH_Type_L1B (16-bit integer)
SUBDATASET_16_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:SolarAzimuth
SUBDATASET_16_DESC=[406x271] SolarAzimuth MODIS_SWATH_Type_L1B (16-bit integer)
SUBDATASET_17_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:gflags
SUBDATASET_17_DESC=[406x271] gflags MODIS_SWATH_Type_L1B (8-bit unsigned integer)
SUBDATASET_18_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:EV_Band26
SUBDATASET_18_DESC=[2030x1354] EV_Band26 MODIS_SWATH_Type_L1B (16-bit unsigned integer)
SUBDATASET_19_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:EV_Band26_Uncert_Indexes
SUBDATASET_19_DESC=[2030x1354] EV_Band26_Uncert_Indexes MODIS_SWATH_Type_L1B (8-bit unsigned integer)
SUBDATASET_20_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":0
SUBDATASET_20_DESC=[406x271] Latitude (32-bit floating-point)
SUBDATASET_21_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":1
SUBDATASET_21_DESC=[406x271] Longitude (32-bit floating-point)
SUBDATASET_22_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":2
SUBDATASET_22_DESC=[15x2030x1354] EV_1KM_RefSB (16-bit unsigned integer)
SUBDATASET_23_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":3
SUBDATASET_23_DESC=[15x2030x1354] EV_1KM_RefSB_Uncert_Indexes (8-bit unsigned integer)
SUBDATASET_24_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":4
SUBDATASET_24_DESC=[16x2030x1354] EV_1KM_Emissive (16-bit unsigned integer)
SUBDATASET_25_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":5
SUBDATASET_25_DESC=[16x2030x1354] EV_1KM_Emissive_Uncert_Indexes (8-bit unsigned integer)
SUBDATASET_26_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":6
SUBDATASET_26_DESC=[2x2030x1354] EV_250_Aggr1km_RefSB (16-bit unsigned integer)
SUBDATASET_27_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":7
SUBDATASET_27_DESC=[2x2030x1354] EV_250_Aggr1km_RefSB_Uncert_Indexes (8-bit unsigned integer)
SUBDATASET_28_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":8
SUBDATASET_28_DESC=[2x2030x1354] EV_250_Aggr1km_RefSB_Samples_Used (8-bit integer)
SUBDATASET_29_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":9
SUBDATASET_29_DESC=[5x2030x1354] EV_500_Aggr1km_RefSB (16-bit unsigned integer)
SUBDATASET_30_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":10
SUBDATASET_30_DESC=[5x2030x1354] EV_500_Aggr1km_RefSB_Uncert_Indexes (8-bit unsigned integer)
SUBDATASET_31_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":11
SUBDATASET_31_DESC=[5x2030x1354] EV_500_Aggr1km_RefSB_Samples_Used (8-bit integer)
SUBDATASET_32_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":12
SUBDATASET_32_DESC=[406x271] Height (16-bit integer)
SUBDATASET_33_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":13
SUBDATASET_33_DESC=[406x271] SensorZenith (16-bit integer)
SUBDATASET_34_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":14
SUBDATASET_34_DESC=[406x271] SensorAzimuth (16-bit integer)
SUBDATASET_35_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":15
SUBDATASET_35_DESC=[406x271] Range (16-bit unsigned integer)
SUBDATASET_36_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":16
SUBDATASET_36_DESC=[406x271] SolarZenith (16-bit integer)
SUBDATASET_37_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":17
SUBDATASET_37_DESC=[406x271] SolarAzimuth (16-bit integer)
SUBDATASET_38_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":18
SUBDATASET_38_DESC=[406x271] gflags (8-bit unsigned integer)
SUBDATASET_39_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":19
SUBDATASET_39_DESC=[2030x1354] EV_Band26 (16-bit unsigned integer)
SUBDATASET_40_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":20
SUBDATASET_40_DESC=[2030x1354] EV_Band26_Uncert_Indexes (8-bit unsigned integer)
SUBDATASET_41_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":21
SUBDATASET_41_DESC=[16x10] Noise in Thermal Detectors (8-bit unsigned integer)
SUBDATASET_42_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":22
SUBDATASET_42_DESC=[16x10] Change in relative responses of thermal detectors (8-bit unsigned integer)
SUBDATASET_43_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":23
SUBDATASET_43_DESC=[203x16x10] DC Restore Change for Thermal Bands (8-bit integer)
SUBDATASET_44_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":24
SUBDATASET_44_DESC=[203x2x40] DC Restore Change for Reflective 250m Bands (8-bit integer)
SUBDATASET_45_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":25
SUBDATASET_45_DESC=[203x5x20] DC Restore Change for Reflective 500m Bands (8-bit integer)
SUBDATASET_46_NAME=HDF4_SDS:UNKNOWN:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":26
SUBDATASET_46_DESC=[203x15x10] DC Restore Change for Reflective 1km Bands (8-bit integer)
Corner Coordinates:
Upper Left ( 0.0, 0.0)
Lower Left ( 0.0, 512.0)
Upper Right ( 512.0, 0.0)
Lower Right ( 512.0, 512.0)
Center ( 256.0, 256.0)
从上面的输出信息中可以看出,这个HDF数据其实有46个子数据,从上面的Subdatasets开始,一共有46个子数据集,同时GDAL列举了这些数据的描述信息,包括数据大小波段数以及数据类型。下面以第一个子数据集为例说明一下GDAL输出的这个信息的大致意思,第一个子数据集的描述如下:
SUBDATASET_1_NAME=HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:EV_1KM_RefSB
SUBDATASET_1_DESC=[15x2030x1354] EV_1KM_RefSB MODIS_SWATH_Type_L1B (16-bit unsigned integer)
可以看出,一个子数据集由两行组成,第一行表示这个子数据集的“路径”,这里的路径可以认为是这个子数据集存储在HDF文件中的路径。后面使用GDAL读取数据就要使用这个路径。第二行表示的是对这个子数据的描述信息,比如这里的,15×2030×1354就表示这个子数据有15个波段,长和宽分别是2030和1354。周末的EV_1KM_RefSB MODIS_SWATH_Type_L1B表示的是这个数据的处理级别和类型等,接下来的括弧里面的16-bit unsigned integer表示这个子数据集是个16位的无符号整数。
那么接下来如何使用gdal来获取子数据集里面的图像信息呢,我们还是以gdalinfo这个工具来说明。要获取hdf中每个子数据集的信息,首先要获取hdf中子数据集的路径才行,这个路径就需要上面的SUBDATASET_1_NAM来确定了。还是以第一个子数据集为例,使用的命令行如下,截图如图2所示:
gdalinfo.exe HDF4_EOS:EOS_SWATH:"F:\Data\HDF\MOD021KM.A2010287.0250.005.2010287121743.hdf":MODIS_SWATH_Type_L1B:EV_1KM_RefSB
图2 使用gdalinfo查看子数据集的输出信息
由于输出的信息太多,截图不能全部显示,就意思一下,这里就不在贴出来了。有了上面的试验,接下来我们就可以写程序来读取HDF数据了,首先是用gdal打开hdf数据,获取Subdatasets中的子数据集路径,然后再使用gdalopen来打开。至于这个Subdatasets其实就在gdal的元数据里面,可以使用函数,GDALDataset::GetMetadata()函数来获取。示例代码如下:
GDALAllRegister();
const char* pszSrcFile = "F:\\Data\\HDF\\MOD021KM.A2010287.0250.005.2010287121743.hdf";
GDALDataset *pDataSet = (GDALDataset *) GDALOpen( pszSrcFile, GA_ReadOnly );
if (pDataSet == NULL)
{
printf("不能打开该文件,请检查文件是否存在!");
return RE_FILENOTEXIST;
}
char ** papszSUBDATASETS = GDALGetMetadata( (GDALDatasetH)pDataSet, "SUBDATASETS");
这段代码最后一行的papszSUBDATASETS中就是存储的子数据的路径和描述信息。papszSUBDATASETS其实就是个字符串数组,接下来就是解析这个字符串数组,然后从里面获取HDF子数据集的路径和描述信息,这里需要注意的是,如果一个HDF文件获取的子数据集是NULL,也就是papszSUBDATASETS这个变量如果为NULL,说明这个hdf数据本身就是一个单一的数据,里面没有子数据集。接下来的代码就是解析这个子数据集的字符串数组:
vector<string> vSubDataSets, vector<string> vSubDataDesc;
if ( papszSUBDATASETS == NULL )
{
string papszMetadata = GDALGetDriverShortName((GDALDriverH)pDataSet);
vSubDataSets.push_back(papszMetadata);
vSubDataDesc.push_back(papszMetadata);
}
上面的代码中是如果当前的HDF数据没有子数据集,那么其本身就是一个数据集。这里定义了两个vector<string>,分别用来存储子数据集的路径和描述信息。下面的代码就是解析含有子数据集的HDF数据了。这里需要一点点的std::string的函数,主要是用来截取字符串用的substr函数。
else
{
int iCount = CSLCount(papszSUBDATASETS);
if( iCount <= 0 )
{
if(pProcess != NULL)
pProcess->SetMessage("该HDF文件中没有子数据!");
GDALClose((GDALDriverH)pDataSet);
return RE_SUCCESS;
}
for(int i=0; papszSUBDATASETS[i] != NULL; i++ )
{
if(i%2 != 0)
continue;
string tmpstr = string(papszSUBDATASETS[i]);
tmpstr = tmpstr.substr(tmpstr.find_first_of("=") + 1);
const char *tmpc_str = tmpstr.c_str();
string tmpdsc = string(papszSUBDATASETS[i+1]);
tmpdsc = tmpdsc.substr(tmpdsc.find_first_of("=") + 1);
GDALDatasetH hTmpDt = GDALOpen(tmpc_str, GA_ReadOnly);
if(hTmpDt != NULL)
{
vSubDataSets.push_back(tmpstr);
vSubDataDesc.push_back(tmpdsc);
GDALClose(hTmpDt);
}
}//end for
}
GDALClose((GDALDriverH)pDataSet);
对上面的代码稍微解释一下:首先使用CSLCount函数获取这个字符串数组的个数,如果不大于0就说明没有,直接关闭HDF数据返回。如果大于0,遍历这个字符串数组,一般这个字符串数组个数肯定是个偶数,你也可以提前判断一下。如果数组的下标是奇数,直接跳过,也就是说,我们直接取下标是0、2、4的字符串。接下来取出的字符串中是有一个“=”连接起来的(具体可以看上面的例子)。这个等号的左边是描述数据集的顺序,右边是值也就是子数据集的路径。使用substr函数把路径取出来存储到前面定义的vector<string>中,同时获取描述信息也存进去(这个描述信息可以不用,如果需要用户交互的话还是留着的好),接下来使用GDALOpen打开测试一下这个子数据集的路径是否正确,如果可以打开就说明正常。
通过上面的说明,对于HDF的数据(包括HDF4、HDF5、NetCDF等类型的数据)怎么使用GDAL打开就有个了解了吧。下面是我写的一个简单的Demo截图,核心功能就是用的上面这段代码。
首先是打开HDF数据,如图3所示:
图3 打开HDF数据
点击打开之后会弹出一个对话框,如图4所示,会在列表中显示打开的HDF数据中所有的子数据集的描述信息,通过用户选择来指定所要打开的子数据集,这个对话框中的列表显示的内容就是上面代码中解析的描述信息。然后点击确定的时候通过选择的第几个来定位子数据集的路径,然后使用GDAL打开进行显示或者进行其他的处理即可。
图4 打开HDF数据后列举的子数据集描述