前言
Landsat8数据是最常用的免费数据,其具有9个可见光短波红外波段,2个热红外波段,可以反演多个地表、大气参数,包括大气气溶胶、地表温度。然而其下载文件解压后,由多个tif组成多个文件,而不是一个tif中有多个波段,这对GDAL读取造成了一定的困扰,但是莫慌,这里写了一个GDAL接口用来读取Landsat8数据:
具体实现
首先是一个头文件“Landsat8Dataset.h”
#pragma once #include "C:\warmerda\x64\include\gdal_priv.h" #include <vector> #include <string> #include "gdal_utils.h" #include "cplkeywordparser.h" #include <iostream> #include "gdal_pam.h" using namespace std; enum L8DTS { Pan, Mul, QA, Them }; class Landsat8Dataset { public: Landsat8Dataset(); ~Landsat8Dataset(); int nBands = 0; <a href="https://www.ixxin.cn/tag/gdal/" title="查看更多关于GDAL的文章" target="_blank">GDAL</a>Dataset* poVRTDS; <a href="https://www.ixxin.cn/tag/gdal/" title="查看更多关于GDAL的文章" target="_blank">GDAL</a>DatasetH* GetDatasetList(); char** FileList = NULL; <a href="https://www.ixxin.cn/tag/gdal/" title="查看更多关于GDAL的文章" target="_blank">GDAL</a>Dataset* Open(const char* pMTLFile,L8DTS DT); void Close(); protected: <a href="https://www.ixxin.cn/tag/gdal/" title="查看更多关于GDAL的文章" target="_blank">GDAL</a>DatasetH* DatasetList = NULL; };
具体实现文件“Landsat8Dataset.cpp”
#include "Landsat8Dataset.h" Landsat8Dataset::Landsat8Dataset() { poVRTDS = NULL; } Landsat8Dataset::~Landsat8Dataset() { Close(); } GDALDataset* Landsat8Dataset::Open(const char* pMTLFile,L8DTS DT = L8DTS::Mul) { /*初始化参数*/ double dfCellSize = 0.0; int nRasterXSize = 0, nRasterYSize = 0; char **papszRasterName = NULL; int nSubDataset = 1; switch (DT) { case Pan: nSubDataset = 0; break; case Mul: nSubDataset = 1; break; case QA: nSubDataset = 4; break; case Them: nSubDataset = 2; break; default: break; } GDALAllRegister(); /*读取MTL文件*/ VSILFILE *fp = VSIFOpenL(pMTLFile, "r"); if (fp == NULL) { return NULL; } CPLKeywordParser oParser; if (!oParser.Ingest(fp)) { VSIFCloseL(fp); return NULL; } VSIFCloseL(fp); char** papszMetaInfo = oParser.GetAllKeywords(); if (nSubDataset == 0) { dfCellSize = CPLAtof(CSLFetchNameValueDef(papszMetaInfo, "L1_METADATA_FILE.PROJECTION_PARAMETERS.GRID_CELL_SIZE_PANCHROMATIC", "0")); nRasterXSize = atoi(CSLFetchNameValueDef(papszMetaInfo, "L1_METADATA_FILE.PRODUCT_METADATA.PANCHROMATIC_SAMPLES", "0")); nRasterYSize = atoi(CSLFetchNameValueDef(papszMetaInfo, "L1_METADATA_FILE.PRODUCT_METADATA.PANCHROMATIC_LINES", "0")); papszRasterName = CSLAddString(papszRasterName, "BAND_8"); } else if (nSubDataset == 1) { dfCellSize = CPLAtof(CSLFetchNameValueDef(papszMetaInfo, "L1_METADATA_FILE.PROJECTION_PARAMETERS.GRID_CELL_SIZE_REFLECTIVE", "0")); nRasterXSize = atoi(CSLFetchNameValueDef(papszMetaInfo, "L1_METADATA_FILE.PRODUCT_METADATA.REFLECTIVE_SAMPLES", "0")); nRasterYSize = atoi(CSLFetchNameValueDef(papszMetaInfo, "L1_METADATA_FILE.PRODUCT_METADATA.REFLECTIVE_LINES", "0")); papszRasterName = CSLAddString(papszRasterName, "BAND_1"); papszRasterName = CSLAddString(papszRasterName, "BAND_2"); papszRasterName = CSLAddString(papszRasterName, "BAND_3"); papszRasterName = CSLAddString(papszRasterName, "BAND_4"); papszRasterName = CSLAddString(papszRasterName, "BAND_5"); papszRasterName = CSLAddString(papszRasterName, "BAND_6"); papszRasterName = CSLAddString(papszRasterName, "BAND_7"); papszRasterName = CSLAddString(papszRasterName, "BAND_9"); } else if (nSubDataset == 2) { dfCellSize = CPLAtof(CSLFetchNameValueDef(papszMetaInfo, "L1_METADATA_FILE.PROJECTION_PARAMETERS.GRID_CELL_SIZE_THERMAL", "0")); nRasterXSize = atoi(CSLFetchNameValueDef(papszMetaInfo, "L1_METADATA_FILE.PRODUCT_METADATA.THERMAL_SAMPLES", "0")); nRasterYSize = atoi(CSLFetchNameValueDef(papszMetaInfo, "L1_METADATA_FILE.PRODUCT_METADATA.THERMAL_LINES", "0")); papszRasterName = CSLAddString(papszRasterName, "BAND_10"); papszRasterName = CSLAddString(papszRasterName, "BAND_11"); } else { dfCellSize = CPLAtof(CSLFetchNameValueDef(papszMetaInfo, "L1_METADATA_FILE.PROJECTION_PARAMETERS.GRID_CELL_SIZE_THERMAL", "0")); nRasterXSize = atoi(CSLFetchNameValueDef(papszMetaInfo, "L1_METADATA_FILE.PRODUCT_METADATA.THERMAL_SAMPLES", "0")); nRasterYSize = atoi(CSLFetchNameValueDef(papszMetaInfo, "L1_METADATA_FILE.PRODUCT_METADATA.THERMAL_LINES", "0")); papszRasterName = CSLAddString(papszRasterName, "BAND_QUALITY"); } if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize)) { CSLDestroy(papszRasterName); return NULL; } int nBandCount = CSLCount(papszRasterName); nBands = nBandCount; //GDALDatasetH* DatasetS = new GDALDatasetH[nBandCount](); DatasetList = new GDALDatasetH[nBandCount](); std::string sTmpStr; CPLString ostrFileName; const char *pszFilename; const char* pszSubFile; const char* osDirname = CPLGetDirname(pMTLFile); for (int iBand = 0; iBand < nBandCount; iBand++) { //ostrFileName.Printf("L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_%s", papszRasterName[iBand]); sTmpStr = papszRasterName[iBand]; ostrFileName = "L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_" + sTmpStr; pszFilename = CSLFetchNameValue(papszMetaInfo, ostrFileName.c_str()); if (pszFilename == NULL) { CPLError(CE_Failure, CPLE_AppDefined, "Missing %s in .TXT file.", ostrFileName.c_str()); CSLDestroy(papszRasterName); return NULL; } // trim double quotes. if (pszFilename[0] == '"') pszFilename++; if (pszFilename[strlen(pszFilename) - 1] == '"') ((char *)pszFilename)[strlen(pszFilename) - 1] = '\0'; pszSubFile = CPLFormFilename(osDirname, pszFilename, NULL); FileList = CSLAddString(FileList, pszSubFile); GDALDatasetH poBandDS = GDALOpen(pszSubFile, GA_ReadOnly); //DatasetS[iBand] = poBandDS; DatasetList[iBand] = poBandDS; } char** argv = NULL; argv = CSLAddString(argv, "-separate"); argv = CSLAddString(argv, "-srcnodata"); argv = CSLAddString(argv, "0"); argv = CSLAddString(argv, "-vrtnodata"); argv = CSLAddString(argv, "0"); GDALBuildVRTOptions* VRTOptions = GDALBuildVRTOptionsNew(argv, NULL); GDALDataset* VRTDt = (GDALDataset*)GDALBuildVRT(NULL, nBandCount, DatasetList, NULL, VRTOptions, NULL); if (VRTDt == NULL) { std::cout << "VRT Build Error" << endl; GDALBuildVRTOptionsFree(VRTOptions); CSLDestroy(papszRasterName); for (int i = 0; i < nBandCount; i++) { GDALClose(DatasetList[i]); } GDALClose((GDALDatasetH)VRTDt); return NULL; } GDALBuildVRTOptionsFree(VRTOptions); CSLDestroy(papszRasterName); VRTDt->SetMetadata(papszMetaInfo); poVRTDS = VRTDt; return VRTDt; } void Landsat8Dataset::Close() { if (this->poVRTDS != NULL) { GDALClose(GDALDatasetH(this->poVRTDS)); } if (this->DatasetList != NULL) { for (int i = 0; i < nBands; i++) { if (this->DatasetList[i] == NULL) continue; else GDALClose(this->DatasetList[i]); } } if (this->FileList != NULL) { CSLDestroy(this->FileList); } /*归为NULL*/ this->poVRTDS = NULL; this->DatasetList = NULL; this->FileList = NULL; }
读取示例:
#include <iostream> #include "Landsat8Dataset.h" using namespace std; int ReadLandsat8() { const char* pMTLFile = "E:\\Landsat8\\LC81240332013107LGN01\\LC81240332013107LGN01_MTL.txt"; const char* pOLIFile = "E:\\Landsat8\\OLI.tif"; const char* pPANFile = "E:\\Landsat8\\PAN.tif"; Landsat8Dataset* Landsat8 = new Landsat8Dataset(); GDALDataset* GDALLandsatDt = Landsat8->Open(pMTLFile,L8DTS::Pan); int nbands = Landsat8->nBands; char** FileList = Landsat8->FileList; int nFile = CSLCount(FileList); for (int f = 0; f < nFile; f++) { cout << FileList[f] << endl; } GDALDriver* pDstDrive = (GDALDriver*)GDALGetDriverByName("ENVI"); GDALDataset* pDstDs = pDstDrive->CreateCopy(pPANFile, GDALLandsatDt, FALSE, NULL,(GDALProgressFunc)GDALTermProgress, NULL); GDALClose(GDALDatasetH(pDstDs)); /*关闭*/ Landsat8->Close(); if (Landsat8->poVRTDS != NULL) { cout << 1 << endl; } delete Landsat8; cout << "Success" << endl; return 0; }
结尾:
通过此接口就可以直接读取Landsat8 MTL头文件了,是不是很方便?具体实现可以看一下第三段示例代码哦。源代码下载链接:https://download.csdn.net/download/wudixinxin/10636979
,支持博主的点击一下网站头部与底部的广告哦,扫一下支付宝红包。
如有问题,请发邮件到:s_xxin@qq.com