MODIS影像以HDF4或者HDF5格式进行存储。关于如何搭建开发环境,参见Ubuntu下GDAL读取HDF4(MODIS影像)开发环境搭建。
我们可以将HDF数据看做一个容器,容器里面包含了很多具体的Dataset子集,所以我们首先要取出子数据集的地址。元数据信息可以通过GDAL获取,HDF的元数据信息中(将元数据信息保存在一个字符串数组中),奇数索引的信息是子数据集的地址,偶数索引的信息是该子数据集的其它信息(名称等)。 元数据示例如下:
在C++代码中我们只需要读取元数据信息,提取出Dataset子数据集的路径就可以了! 代码如下:(其中用到的readGeoRaster函数用于输出Dataset的一些地理信息,具体实现参见Hello GDAL(简单的GDAL入门程序))
int main(int argc, char* argv[])
{
const char* pszFileName = argv[1]; // 从命令行传入MODIS数据文件路径
GDALAllRegister();
GDALDataset* poDataset = static_cast<GDALDataset*>(GDALOpen(pszFileName, GA_ReadOnly));
if (!poDataset)
{
cout << "影像读取失败:" << pszFileName << "!" << '\n';
return EXIT_FAILURE;
}
char** metadata = poDataset->GetMetadata("SUBDATASETS");
vector<string> vtDatasets;
// 我们可以将HDF数据看做一个容器,容器里面包含了很多具体的子Dataset,所以我们首先要取出子数据集的地址
// 元数据metadata中保存的信息中,奇数索引的信息是子数据的地址,偶数索引的信息是该子数据的其它信息
if (0 < CSLCount(const_cast<const char* const*>(metadata)))
{
for (int i = 0; metadata[i]; i += 2)
{
string strDSName(metadata[i]);
cout << strDSName << '\n';
strDSName = strDSName.substr(strDSName.find_first_of('=') + 1);
vtDatasets.push_back(strDSName);
}
}
GDALClose(poDataset);
for (auto name : vtDatasets)
{
const char* pszDSName = name.c_str();
cout << "数据路径:" << pszDSName << '\n';
readGeoRaster(pszDSName);
}
return EXIT_SUCCESS;
}
输出如下: