GDAL库扩展Landsat系列MTL文件格式支持

Landsat系列卫星提供的数据,一般都是每个波段一个tif文件,然后外加一个MTL.txt的元数据文件,使用gdal可以直接打开每个波段的tif文件,但是有时候想在打开tif数据的同时能够自动读取MTL文件里面的元数据信息,这个时候就只能自己再解析这个文件了。比较麻烦,下面就是针对这种情况,直接在gdal库里面扩展一种支持landsat的mtl的格式,直接打开mtl文件的同时自动打开tif数据以及元数据。

关于扩展GDAL库可以参考我之前写的CNSDTF格式扩展,以及gdal的官网说明,网址为http://www.gdal.org/gdal_drivertut.html。

首先我们看一下Landsat的数据目录格式,以Landsat8数据为例,如下图所示:

GDAL库扩展Landsat系列MTL文件格式支持_第1张图片

Landsat8一共有11个波段,里面包含12个tif文件和一个txt文件,Landsat8包括两个传感器,分别是OLI和TIRS,其中OLI传感器有9个光谱波段,空间分辨率为15m(全色波段1个)和30m(多光谱波段8个),成像幅宽为185km。 TIRS有2个热红外波段,空间分辨率为30m,所以一共11个波段,此外还有一个BQA的tif不太清楚干啥的。

知道了数据的类别,那么我们可以参考HDF数据的样子,将Landsat8的数据归类为4个子数据集,第一个OLI全色数据,第二个OLI多光谱数据,第三个TIRS数据,第四个就是BQA数据。

下面是Landsat的实现源码,将其放到frmts\landsat目录,然后参考官网的说明编写make文件等,重新编译gdal库即可。

/******************************************************************************
* $Id: landsatdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
*
* Project:  Landsat 7/8 _MTL.TXT Driver
* Purpose:  Implementation of the LandsatDataset class.
* Author:   Minlu Li, [email protected]
*
******************************************************************************
* Copyright (c) 2015, Minlu Li
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
****************************************************************************/

#include "gdal_pam.h"
#include "gdal_proxy.h"
#include "ogr_spatialref.h"
#include "cpl_string.h"
#include "vrtdataset.h"
#include "cpl_multiproc.h"
#include "cplkeywordparser.h"

enum Satellite  // Satellites:
{
	LANDSAT7,	// Landsat 7
	LANDSAT8	// Landsat 8
};

/************************************************************************/
/* ==================================================================== */
/*			                   	LandsatDataset		             		*/
/* ==================================================================== */
/************************************************************************/

class CPL_DLL LandsatDataset : public GDALPamDataset
{
	VRTDataset *poVRTDS;
	std::vector<GDALDataset *> apoTifDS;

protected:
	virtual int         CloseDependentDatasets();

public:
	LandsatDataset();
	~LandsatDataset();

	virtual char **GetFileList(void);

	static GDALDataset *Open( GDALOpenInfo * );
	static int Identify( GDALOpenInfo *poOpenInfo );
	static int ParserLandsat7( const char* pszMtlFile, char **papszMetaInfo, int nSubdataset, LandsatDataset **ppoDS );
	static int ParserLandsat8( const char* pszMtlFile, char **papszMetaInfo, int nSubdataset, LandsatDataset **ppoDS );
};

/************************************************************************/
/* ==================================================================== */
/*                          LandSatRasterBand                           */
/* ==================================================================== */
/************************************************************************/

class LandSatRasterBand : public GDALPamRasterBand
{
	friend class LandsatDataset;

	GDALRasterBand *poVRTBand;

public:
	LandSatRasterBand( LandsatDataset *, int, GDALRasterBand * );
	virtual       ~LandSatRasterBand() {};

	virtual CPLErr IReadBlock( int, int, void * );
	virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
		void *, int, int, GDALDataType,
		int, int );
};

/************************************************************************/
/*                         LandSatRasterBand()                          */
/************************************************************************/

LandSatRasterBand::LandSatRasterBand( LandsatDataset *poTILDS, int nBand, 
									 GDALRasterBand *poVRTBand )

{
	this->poDS = poTILDS;
	this->poVRTBand = poVRTBand;
	this->nBand = nBand;
	this->eDataType = poVRTBand->GetRasterDataType();

	poVRTBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
}

/************************************************************************/
/*                             IReadBlock()                             */
/************************************************************************/

CPLErr LandSatRasterBand::IReadBlock( int iBlockX, int iBlockY, void *pBuffer )

{
	return poVRTBand->ReadBlock( iBlockX, iBlockY, pBuffer );
}

/************************************************************************/
/*                             IRasterIO()                              */
/************************************************************************/

CPLErr LandSatRasterBand::IRasterIO( GDALRWFlag eRWFlag,
									int nXOff, int nYOff, int nXSize, int nYSize,
									void * pData, int nBufXSize, int nBufYSize,
									GDALDataType eBufType,
									int nPixelSpace, int nLineSpace )

{
	if(GetOverviewCount() > 0)
	{
		return GDALPamRasterBand::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
			pData, nBufXSize, nBufYSize, eBufType,
			nPixelSpace, nLineSpace );
	}
	else //if not exist TIL overviews, try to use band source overviews
	{
		return poVRTBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
			pData, nBufXSize, nBufYSize, eBufType,
			nPixelSpace, nLineSpace );
	}
}

/************************************************************************/
/*                           LandsatDataset()                           */
/************************************************************************/

LandsatDataset::LandsatDataset()

{
	poVRTDS = NULL;
}

/************************************************************************/
/*                          ~LandsatDataset()                           */
/************************************************************************/

LandsatDataset::~LandsatDataset()

{
	CloseDependentDatasets();
}

/************************************************************************/
/*                        CloseDependentDatasets()                      */
/************************************************************************/

int LandsatDataset::CloseDependentDatasets()
{
	int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();

	if( poVRTDS )
	{
		bHasDroppedRef = TRUE;
		delete poVRTDS;
		poVRTDS = NULL;
	}

	while( !apoTifDS.empty() )
	{
		GDALClose( (GDALDatasetH) apoTifDS.back() );
		apoTifDS.pop_back();
	}

	return bHasDroppedRef;
}

/************************************************************************/
/*                              Identify()                              */
/************************************************************************/

int LandsatDataset::Identify( GDALOpenInfo *poOpenInfo )

{
	if( EQUALN(poOpenInfo->pszFilename,"LANDSAT:",8) )	//subdataset
		return TRUE;

	const char* pszExt = CPLGetExtension(poOpenInfo->pszFilename);
	if( !EQUAL(pszExt,"TXT") && !EQUAL(pszExt,"MET"))
		return FALSE;

	if( strstr((const char *) poOpenInfo->pabyHeader,"GROUP = L1_METADATA_FILE") == NULL )
		return FALSE;
	else
		return TRUE;
}

int LandsatDataset::ParserLandsat7( const char* pszMtlFile, char **papszMetaInfo, int nSubdataset, LandsatDataset **ppoDS )
{
	LandsatDataset *poDS = (LandsatDataset*)(*ppoDS);

	double dfCellSize = 0.0;
	char **papszRasterName = NULL;
	if(nSubdataset == 0)
	{
		dfCellSize = CPLAtof(CSLFetchNameValueDef(papszMetaInfo, "PROJECTION_PARAMETERS.GRID_CELL_SIZE_PAN", "0"));
		poDS->nRasterXSize = atoi(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_SAMPLES_PAN","0"));
		poDS->nRasterYSize = atoi(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_LINES_PAN","0"));
		papszRasterName = CSLAddString(papszRasterName, "BAND8");
	}
	else if(nSubdataset ==1)
	{
		dfCellSize = CPLAtof(CSLFetchNameValueDef(papszMetaInfo, "PROJECTION_PARAMETERS.GRID_CELL_SIZE_REF", "0"));
		poDS->nRasterXSize = atoi(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_SAMPLES_REF","0"));
		poDS->nRasterYSize = atoi(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_LINES_REF","0"));
		papszRasterName = CSLAddString(papszRasterName, "BAND1");
		papszRasterName = CSLAddString(papszRasterName, "BAND2");
		papszRasterName = CSLAddString(papszRasterName, "BAND3");
		papszRasterName = CSLAddString(papszRasterName, "BAND4");
		papszRasterName = CSLAddString(papszRasterName, "BAND5");
		papszRasterName = CSLAddString(papszRasterName, "BAND7");
	}
	else
	{
		dfCellSize = CPLAtof(CSLFetchNameValueDef(papszMetaInfo, "PROJECTION_PARAMETERS.GRID_CELL_SIZE_THM", "0"));
		poDS->nRasterXSize = atoi(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_SAMPLES_THM","0"));
		poDS->nRasterYSize = atoi(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_LINES_THM","0"));
		papszRasterName = CSLAddString(papszRasterName, "BAND61");
		papszRasterName = CSLAddString(papszRasterName, "BAND62");
	}

	if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
	{
		CSLDestroy(papszRasterName);
		return FALSE;
	}

	OGRSpatialReference oSRS;
	const char* pszMapProjection = CSLFetchNameValue(papszMetaInfo, "PROJECTION_PARAMETERS.MAP_PROJECTION");
	const char* pszDatum = NULL;
	const char* pszEllipsoid = NULL;
	const char* pszZone = NULL;

	if(strstr(pszMapProjection, "UTM") != NULL)
	{
		pszDatum = CSLFetchNameValue(papszMetaInfo, "PROJECTION_PARAMETERS.REFERENCE_DATUM");
		pszEllipsoid = CSLFetchNameValue(papszMetaInfo, "PROJECTION_PARAMETERS.REFERENCE_ELLIPSOID");
		pszZone = CSLFetchNameValue(papszMetaInfo, "UTM_PARAMETERS.ZONE_NUMBER");

		// trim double quotes. 
		if( pszDatum[0] == '"' )
			pszDatum++;
		if( pszDatum[strlen(pszDatum)-1] == '"' )
			((char *) pszDatum)[strlen(pszDatum)-1] = '\0';

		oSRS.SetWellKnownGeogCS(pszDatum);
		oSRS.SetUTM(atoi(pszZone));
	}

	char *pszWkt = NULL;
	if(oSRS.exportToWkt(&pszWkt) == OGRERR_NONE)
		poDS->SetProjection(pszWkt);

	double dfUL_X = CPLAtof(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_UL_CORNER_MAPX","0"));
	double dfUL_Y = CPLAtof(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_UL_CORNER_MAPY","0"));
	double dfUR_X = CPLAtof(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_UR_CORNER_MAPX","0"));
	double dfUR_Y = CPLAtof(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_UR_CORNER_MAPY","0"));
	double dfLL_X = CPLAtof(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_LL_CORNER_MAPX","0"));
	double dfLL_Y = CPLAtof(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_LL_CORNER_MAPY","0"));
	double dfLR_X = CPLAtof(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_LR_CORNER_MAPX","0"));
	double dfLR_Y = CPLAtof(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_LR_CORNER_MAPY","0"));

	double adfGeoTransform[6] = {dfUL_X, dfCellSize, 0, dfUL_Y, 0, -1*dfCellSize};
	poDS->SetGeoTransform(adfGeoTransform);

	/* -------------------------------------------------------------------- */
	/*      We need to open one of the images in order to establish         */
	/*      details like the band count and types.                          */
	/* -------------------------------------------------------------------- */
	GDALDataset *poTemplateDS = NULL;

	CPLString ostrFileName;
	ostrFileName.Printf( "L1_METADATA_FILE.%s_FILE_NAME", papszRasterName[0] );
	const char *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 FALSE;
	}

	CPLString osDirname = CPLGetDirname(pszMtlFile);

	// trim double quotes. 
	if( pszFilename[0] == '"' )
		pszFilename++;
	if( pszFilename[strlen(pszFilename)-1] == '"' )
		((char *) pszFilename)[strlen(pszFilename)-1] = '\0';

	const char* pszSubFile = CPLFormFilename(osDirname, pszFilename, NULL);
	poTemplateDS = (GDALDataset *) GDALOpen( pszSubFile, GA_ReadOnly );
	if( poTemplateDS == NULL || poTemplateDS->GetRasterCount() == 0)
	{
		if (poTemplateDS != NULL)
			GDALClose( poTemplateDS );

		CSLDestroy(papszRasterName);
		return FALSE;
	}

	poDS->SetProjection(poTemplateDS->GetProjectionRef());
	poTemplateDS->GetGeoTransform(adfGeoTransform);
	poDS->SetGeoTransform(adfGeoTransform);

	GDALRasterBand *poTemplateBand = poTemplateDS->GetRasterBand(1);
	GDALDataType eDT = poTemplateBand->GetRasterDataType();
	int          nBandCount = CSLCount(papszRasterName);

	poTemplateBand = NULL;
	GDALClose( poTemplateDS );

	/* -------------------------------------------------------------------- */
	/*      Create and initialize the corresponding VRT dataset used to     */
	/*      manage the tiled data access.                                   */
	/* -------------------------------------------------------------------- */
	poDS->poVRTDS = new VRTDataset(poDS->nRasterXSize, poDS->nRasterYSize);
	int iBand = 0;
	for( iBand = 0; iBand < nBandCount; iBand++ )
		poDS->poVRTDS->AddBand( eDT, NULL );

	/* Don't try to write a VRT file */
	poDS->poVRTDS->SetWritable(FALSE);

	/* -------------------------------------------------------------------- */
	/*      Create band information objects.                                */
	/* -------------------------------------------------------------------- */
	for( iBand = 0; iBand < nBandCount; iBand++ )
	{
		ostrFileName.Printf( "L1_METADATA_FILE.%s_FILE_NAME", papszRasterName[iBand] );
		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 FALSE;
		}

		// trim double quotes. 
		if( pszFilename[0] == '"' )
			pszFilename++;
		if( pszFilename[strlen(pszFilename)-1] == '"' )
			((char *) pszFilename)[strlen(pszFilename)-1] = '\0';

		pszSubFile = CPLFormFilename(osDirname, pszFilename, NULL);
		GDALDataset *poBandDS = (GDALDataset *) GDALOpen( pszSubFile, GA_ReadOnly );
		if( poBandDS == NULL || poBandDS->GetRasterCount() == 0)
		{
			if (poBandDS != NULL)
				GDALClose( poBandDS );

			CSLDestroy(papszRasterName);
			return FALSE;
		}

		poDS->apoTifDS.push_back( poBandDS );

		GDALRasterBand *pBand = poBandDS->GetRasterBand(1);
		LandSatRasterBand *pLandsatBand = new LandSatRasterBand( poDS, iBand+1, pBand);
		char** papszBandMeta = NULL;
		papszBandMeta = CSLAddString(papszBandMeta, pszFilename);
		pLandsatBand->SetMetadata(papszBandMeta);
		poDS->SetBand( iBand+1, pLandsatBand);
	}

	CSLDestroy(papszRasterName);
	return TRUE;
}

int LandsatDataset::ParserLandsat8( const char* pszMtlFile, char **papszMetaInfo, int nSubdataset, LandsatDataset **ppoDS )
{
	LandsatDataset *poDS = (LandsatDataset*)(*ppoDS);

	double dfCellSize = 0.0;
	char **papszRasterName = NULL;
	if(nSubdataset == 0)
	{
		dfCellSize = CPLAtof(CSLFetchNameValueDef(papszMetaInfo, "L1_METADATA_FILE.PROJECTION_PARAMETERS.GRID_CELL_SIZE_PANCHROMATIC", "0"));
		poDS->nRasterXSize = atoi(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_METADATA.PANCHROMATIC_SAMPLES","0"));
		poDS->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"));
		poDS->nRasterXSize = atoi(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_METADATA.REFLECTIVE_SAMPLES","0"));
		poDS->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"));
		poDS->nRasterXSize = atoi(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_METADATA.THERMAL_SAMPLES","0"));
		poDS->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"));
		poDS->nRasterXSize = atoi(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_METADATA.THERMAL_SAMPLES","0"));
		poDS->nRasterYSize = atoi(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_METADATA.THERMAL_LINES","0"));
		papszRasterName = CSLAddString(papszRasterName, "BAND_QUALITY");
	}

	if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
	{
		CSLDestroy(papszRasterName);
		return FALSE;
	}

	OGRSpatialReference oSRS;
	const char* pszMapProjection = CSLFetchNameValue(papszMetaInfo, "L1_METADATA_FILE.PROJECTION_PARAMETERS.MAP_PROJECTION");
	const char* pszDatum = NULL;
	const char* pszEllipsoid = NULL;
	const char* pszZone = NULL;

	if(strstr(pszMapProjection, "UTM") != NULL)
	{
		pszDatum = CSLFetchNameValue(papszMetaInfo, "L1_METADATA_FILE.PROJECTION_PARAMETERS.DATUM");
		pszEllipsoid = CSLFetchNameValue(papszMetaInfo, "L1_METADATA_FILE.PROJECTION_PARAMETERS.ELLIPSOID");
		pszZone = CSLFetchNameValue(papszMetaInfo, "L1_METADATA_FILE.PROJECTION_PARAMETERS.UTM_ZONE");

		// trim double quotes. 
		if( pszDatum[0] == '"' )
			pszDatum++;
		if( pszDatum[strlen(pszDatum)-1] == '"' )
			((char *) pszDatum)[strlen(pszDatum)-1] = '\0';

		oSRS.SetWellKnownGeogCS(pszDatum);
		oSRS.SetUTM(atoi(pszZone));
	}

	char *pszWkt = NULL;
	if(oSRS.exportToWkt(&pszWkt) == OGRERR_NONE)
		poDS->SetProjection(pszWkt);

	double dfUL_X = CPLAtof(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UL_PROJECTION_X_PRODUCT","0"));
	double dfUL_Y = CPLAtof(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UL_PROJECTION_Y_PRODUCT","0"));
	double dfUR_X = CPLAtof(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UR_PROJECTION_X_PRODUCT","0"));
	double dfUR_Y = CPLAtof(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UR_PROJECTION_Y_PRODUCT","0"));
	double dfLL_X = CPLAtof(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LL_PROJECTION_X_PRODUCT","0"));
	double dfLL_Y = CPLAtof(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LL_PROJECTION_Y_PRODUCT","0"));
	double dfLR_X = CPLAtof(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LR_PROJECTION_X_PRODUCT","0"));
	double dfLR_Y = CPLAtof(CSLFetchNameValueDef(papszMetaInfo,"L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LR_PROJECTION_Y_PRODUCT","0"));

	double adfGeoTransform[6] = {dfUL_X, dfCellSize, 0, dfUL_Y, 0, -1*dfCellSize};
	poDS->SetGeoTransform(adfGeoTransform);

	/* -------------------------------------------------------------------- */
	/*      We need to open one of the images in order to establish         */
	/*      details like the band count and types.                          */
	/* -------------------------------------------------------------------- */
	GDALDataset *poTemplateDS = NULL;
	
	CPLString ostrFileName;
	ostrFileName.Printf( "L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_%s", papszRasterName[0] );
	const char *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 FALSE;
	}

	CPLString osDirname = CPLGetDirname(pszMtlFile);

	// trim double quotes. 
	if( pszFilename[0] == '"' )
		pszFilename++;
	if( pszFilename[strlen(pszFilename)-1] == '"' )
		((char *) pszFilename)[strlen(pszFilename)-1] = '\0';

	const char* pszSubFile = CPLFormFilename(osDirname, pszFilename, NULL);
	poTemplateDS = (GDALDataset *) GDALOpen( pszSubFile, GA_ReadOnly );
	if( poTemplateDS == NULL || poTemplateDS->GetRasterCount() == 0)
	{
		if (poTemplateDS != NULL)
			GDALClose( poTemplateDS );

		CSLDestroy(papszRasterName);
		return FALSE;
	}

	poDS->SetProjection(poTemplateDS->GetProjectionRef());
	poTemplateDS->GetGeoTransform(adfGeoTransform);
	poDS->SetGeoTransform(adfGeoTransform);

	GDALRasterBand *poTemplateBand = poTemplateDS->GetRasterBand(1);
	GDALDataType eDT = poTemplateBand->GetRasterDataType();
	int          nBandCount = CSLCount(papszRasterName);

	poTemplateBand = NULL;
	GDALClose( poTemplateDS );

	/* -------------------------------------------------------------------- */
	/*      Create and initialize the corresponding VRT dataset used to     */
	/*      manage the tiled data access.                                   */
	/* -------------------------------------------------------------------- */
	poDS->poVRTDS = new VRTDataset(poDS->nRasterXSize, poDS->nRasterYSize);
	int iBand = 0;
	for( iBand = 0; iBand < nBandCount; iBand++ )
		poDS->poVRTDS->AddBand( eDT, NULL );

	/* Don't try to write a VRT file */
	poDS->poVRTDS->SetWritable(FALSE);

	/* -------------------------------------------------------------------- */
	/*      Create band information objects.                                */
	/* -------------------------------------------------------------------- */
	for( iBand = 0; iBand < nBandCount; iBand++ )
	{
		ostrFileName.Printf( "L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_%s", papszRasterName[iBand] );
		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 FALSE;
		}

		// trim double quotes. 
		if( pszFilename[0] == '"' )
			pszFilename++;
		if( pszFilename[strlen(pszFilename)-1] == '"' )
			((char *) pszFilename)[strlen(pszFilename)-1] = '\0';

		pszSubFile = CPLFormFilename(osDirname, pszFilename, NULL);
		GDALDataset *poBandDS = (GDALDataset *) GDALOpen( pszSubFile, GA_ReadOnly );
		if( poBandDS == NULL || poBandDS->GetRasterCount() == 0)
		{
			if (poBandDS != NULL)
				GDALClose( poBandDS );

			CSLDestroy(papszRasterName);
			return FALSE;
		}

		poDS->apoTifDS.push_back( poBandDS );

		GDALRasterBand *pBand = poBandDS->GetRasterBand(1);
		LandSatRasterBand *pLandsatBand = new LandSatRasterBand( poDS, iBand+1, pBand);
		char** papszBandMeta = NULL;
		papszBandMeta = CSLAddString(papszBandMeta, pszFilename);
		pLandsatBand->SetMetadata(papszBandMeta);
		poDS->SetBand( iBand+1, pLandsatBand);
	}

	CSLDestroy(papszRasterName);
	return TRUE;
}

/************************************************************************/
/*                                Open()                                */
/************************************************************************/

GDALDataset *LandsatDataset::Open( GDALOpenInfo * poOpenInfo )

{
	if( !Identify( poOpenInfo ) )
		return NULL;

	/* -------------------------------------------------------------------- */
	/*      Confirm the requested access is supported.                      */
	/* -------------------------------------------------------------------- */
	if( poOpenInfo->eAccess == GA_Update )
	{
		CPLError( CE_Failure, CPLE_NotSupported, 
			"The LANDSAT driver does not support update access to existing"
			" datasets.\n" );
		return NULL;
	}

	CPLString osFilename;
	int iSubdatasetIndex = -1;//0:PAN 1:REF 2:THM

	if( EQUALN(poOpenInfo->pszFilename, "LANDSAT:",8) )
	{
		const char *pszRest = poOpenInfo->pszFilename+8;

		iSubdatasetIndex = atoi(pszRest);
		while( *pszRest != '\0' && *pszRest != ':' )
			pszRest++;

		if( *pszRest == ':' )
			pszRest++;

		osFilename = pszRest;
	}
	else
		osFilename = poOpenInfo->pszFilename;

	if(iSubdatasetIndex <-1 || iSubdatasetIndex > 3)
	{
		CPLError( CE_Failure, CPLE_IllegalArg, "The LANDSAT driver does not support %d subdatasets.\n", iSubdatasetIndex );
		return NULL;
	}

	/* -------------------------------------------------------------------- */
	/*      Try to load and parse the .MTL .TXT file.                       */
	/* -------------------------------------------------------------------- */
	VSILFILE *fp = VSIFOpenL( osFilename, "r" );
	if( fp == NULL )
	{
		return NULL;
	}

	CPLKeywordParser oParser;
	if( !oParser.Ingest( fp ) )
	{
		VSIFCloseL( fp );
		return NULL;
	}

	VSIFCloseL( fp );

	char **papszMTL = oParser.GetAllKeywords();
	Satellite sat = LANDSAT7;

	const char* pszSatID = CSLFetchNameValue(papszMTL, "L1_METADATA_FILE.PRODUCT_METADATA.SPACECRAFT_ID");
	if(pszSatID == NULL)
	{
		return NULL;
	}

	if(strstr(pszSatID,"Landsat7") != NULL)
		sat = LANDSAT7;
	else if(strstr(pszSatID,"LANDSAT_8") != NULL)
		sat = LANDSAT8;
	else
	{
		return NULL;
	}

	if(sat == LANDSAT7 && iSubdatasetIndex ==3)	//landsat7 not quality
	{
		return NULL;
	}

	/* -------------------------------------------------------------------- */
	/*      Create a corresponding GDALDataset.                             */
	/* -------------------------------------------------------------------- */
	LandsatDataset 	*poDS;
	poDS = new LandsatDataset();
	poDS->SetMetadata(papszMTL);

	char *papszName[4] = {"PAN", "REF", "THE", "QUA"};
	char *papszDesc[4] = {"Panchromatic", "Reflective", "Thermal", "Quality"};
	if( iSubdatasetIndex == -1 )	//not a subdataset
	{
		int nSubdataset = (sat==LANDSAT7) ? 3 : 4;
		for (int i=0; i<nSubdataset; i++)
		{
			CPLString osKey, osValue;
			osKey.Printf( "SUBDATASET_%d_NAME", i+1 );
			osValue.Printf( "LANDSAT:%d:%s", i, osFilename.c_str() );
			poDS->SetMetadataItem( osKey, osValue, "SUBDATASETS" );

			osKey.Printf( "SUBDATASET_%d_DESC", i+1 );
			osValue.Printf( "LANDSAT:%s", papszDesc[i] );
			poDS->SetMetadataItem( osKey, osValue, "SUBDATASETS" );
		}

		return( poDS );
	}

	int nSuccess = FALSE;
	if(sat == LANDSAT7)
		nSuccess = ParserLandsat7(osFilename.c_str(), papszMTL, iSubdatasetIndex, &poDS);
	else
		nSuccess = ParserLandsat8(osFilename.c_str(), papszMTL, iSubdatasetIndex, &poDS);

	if(!nSuccess)
	{
		delete poDS;
		return NULL;
	}

	const char* pszDirname = CPLGetDirname(osFilename);
	const char* pszBasename = CPLGetBasename(osFilename);
	CPLString osTemp;
	osTemp.Printf("%s_%s", pszBasename, papszName[iSubdatasetIndex]);
	const char* pszSubFile = CPLFormFilename(pszDirname, osTemp, "");

	/* -------------------------------------------------------------------- */
	/*      Initialize any PAM information.                                 */
	/* -------------------------------------------------------------------- */
	poDS->SetDescription( pszSubFile );
	poDS->TryLoadXML();

	/* -------------------------------------------------------------------- */
	/*      Check for overviews.                                            */
	/* -------------------------------------------------------------------- */
	poDS->oOvManager.Initialize( poDS, pszSubFile );

	return( poDS );
}

/************************************************************************/
/*                            GetFileList()                             */
/************************************************************************/

char **LandsatDataset::GetFileList()

{
	unsigned int  i;
	char **papszFileList = GDALPamDataset::GetFileList();

	for( i = 0; i < apoTifDS.size(); i++ )
		papszFileList = CSLAddString( papszFileList, apoTifDS[i]->GetDescription() );

	return papszFileList;
}

/************************************************************************/
/*                         GDALRegister_Landsat()                       */
/************************************************************************/

void GDALRegister_Landsat()

{
	GDALDriver	*poDriver;

	if( GDALGetDriverByName( "LANDSAT" ) == NULL )
	{
		poDriver = new GDALDriver();

		poDriver->SetDescription( "LANDSAT" );
		poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "LANDSAT 7/8 GeoTiff with Metadata" );
		poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_landsat.html" );

		poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );

		poDriver->pfnOpen = LandsatDataset::Open;
		poDriver->pfnIdentify = LandsatDataset::Identify;

		GetGDALDriverManager()->RegisterDriver( poDriver );
	}
}
编译之后,使用gdalinfo命令查看是否编译成功,处理输出如下,可以看到最后一行就是新加的landsat的驱动。

F:\gdal\bin>gdalinfo.exe --formats
Supported Formats:
  ECW (rov): ERDAS Compressed Wavelets (SDK 4.2)
  JP2ECW (rov): ERDAS JPEG2000 (SDK 4.2)
  FITS (rw+): Flexible Image Transport System
  GeoRaster (rw+s): Oracle Spatial GeoRaster
  HDF4 (ros): Hierarchical Data Format Release 4
  HDF4Image (rw+): HDF4 Dataset
  HDF5 (ros): Hierarchical Data Format Release 5
  HDF5Image (ro): HDF5 Dataset
  MG4Lidar (ro): MrSID Generation 4 / Lidar (.sid)
  MrSID (rov): Multi-resolution Seamless Image Database (MrSID)
  JP2MrSID (rov): MrSID JPEG2000
  netCDF (rw+s): Network Common Data Format
  GMT (rw): GMT NetCDF Grid Format
  PostGISRaster (rws): PostGIS Raster driver
  VRT (rw+v): Virtual Raster
  GTiff (rw+vs): GeoTIFF
  NITF (rw+vs): National Imagery Transmission Format
  RPFTOC (rovs): Raster Product Format TOC format
  ECRGTOC (rovs): ECRG TOC format
  HFA (rw+v): Erdas Imagine Images (.img)
  SAR_CEOS (rov): CEOS SAR Image
  CEOS (rov): CEOS Image
  。。。。太多了,删除了一些。。。
  IRIS (rov): IRIS data (.PPI, .CAPPi etc)
  WMTS (rwv): OGC Web Mab Tile Service
  CNSDTF (rwv): China Geospatial Data Transfer Grid Format (.grd)
  LANDSAT (rov): LANDSAT 7/8 GeoTiff with Metadata
再使用gdalinfo --format LANDSAT看看驱动详情

F:\gdal\bin>gdalinfo.exe --format LANDSAT
Format Details:
  Short Name: LANDSAT
  Long Name: LANDSAT 7/8 GeoTiff with Metadata
  Help Topic: frmt_landsat.html
  Supports: Virtual IO - eg. /vsimem/
如果输出上面的信息,说明gdal扩展成功,下面使用gdalinfo打开landsat8的数据试试,上面的驱动在实现的时候同时考虑了Landsat7的数据,所以这两个数据应该都可以支持。使用gdalinfo输出mtl.txt文件之后,输出内容如下:

F:\gdal\bin>gdalinfo.exe F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_MTL.txt
Driver: LANDSAT/LANDSAT 7/8 GeoTiff with Metadata
Files: F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_MTL.txt
Size is 512, 512
Coordinate System is `'
Metadata:
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.CLOUD_COVER=11.95
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.EARTH_SUN_DISTANCE=0.9925442
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.GEOMETRIC_RMSE_MODEL=8.958
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.GEOMETRIC_RMSE_MODEL_X=6.205
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.GEOMETRIC_RMSE_MODEL_Y=6.460
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.GEOMETRIC_RMSE_VERIFY=6.144
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.GROUND_CONTROL_POINTS_MODEL=141
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.GROUND_CONTROL_POINTS_VERIFY=36
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.IMAGE_QUALITY_OLI=9
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.IMAGE_QUALITY_TIRS=9
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.ROLL_ANGLE=-0.001
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.SUN_AZIMUTH=109.94537007
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.SUN_ELEVATION=59.45969108
  L1_METADATA_FILE.METADATA_FILE_INFO.FILE_DATE=2014-03-08T06:54:18Z
  L1_METADATA_FILE.METADATA_FILE_INFO.LANDSAT_SCENE_ID="LC81270562014067LGN00"
  L1_METADATA_FILE.METADATA_FILE_INFO.ORIGIN="Image courtesy of the U.S. Geological Survey"
  L1_METADATA_FILE.METADATA_FILE_INFO.PROCESSING_SOFTWARE_VERSION="LPGS_2.3.0"
  L1_METADATA_FILE.METADATA_FILE_INFO.REQUEST_ID="0501403074153_00047"
  L1_METADATA_FILE.METADATA_FILE_INFO.STATION_ID="LGN"
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_10=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_11=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_1=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_2=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_3=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_4=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_5=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_6=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_7=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_8=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_9=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_10=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_11=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_1=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_2=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_3=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_4=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_5=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_6=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_7=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_8=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_9=1
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_10=22.00180
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_11=22.00180
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_1=771.52448
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_2=790.05048
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_3=728.02478
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_4=613.91150
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_5=375.68323
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_6=93.42900
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_7=31.49057
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_8=694.77887
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_9=146.82552
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_10=0.10033
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_11=0.10033
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_1=-63.71274
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_2=-65.24262
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_3=-60.12052
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_4=-50.69701
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_5=-31.02404
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_6=-7.71540
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_7=-2.60050
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_8=-57.37506
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_9=-12.12490
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_1=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_2=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_3=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_4=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_5=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_6=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_7=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_8=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_9=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_1=-0.099980
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_2=-0.099980
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_3=-0.099980
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_4=-0.099980
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_5=-0.099980
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_6=-0.099980
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_7=-0.099980
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_8=-0.099980
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_9=-0.099980
  L1_METADATA_FILE.PRODUCT_METADATA.BPF_NAME_OLI="LO8BPF20140308030904_20140308035315.01"
  L1_METADATA_FILE.PRODUCT_METADATA.BPF_NAME_TIRS="LT8BPF20140308030510_20140308035408.01"
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LL_LAT_PRODUCT=4.73612
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LL_LON_PRODUCT=100.95098
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LL_PROJECTION_X_PRODUCT=716400.000
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LL_PROJECTION_Y_PRODUCT=523800.000
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LR_LAT_PRODUCT=4.72733
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LR_LON_PRODUCT=102.99592
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LR_PROJECTION_X_PRODUCT=943500.000
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LR_PROJECTION_Y_PRODUCT=523800.000
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UL_LAT_PRODUCT=6.83546
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UL_LON_PRODUCT=100.95819
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UL_PROJECTION_X_PRODUCT=716400.000
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UL_PROJECTION_Y_PRODUCT=756000.000
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UR_LAT_PRODUCT=6.82274
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UR_LON_PRODUCT=103.01065
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UR_PROJECTION_X_PRODUCT=943500.000
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UR_PROJECTION_Y_PRODUCT=756000.000
  L1_METADATA_FILE.PRODUCT_METADATA.CPF_NAME="L8CPF20140101_20140331.03"
  L1_METADATA_FILE.PRODUCT_METADATA.DATA_TYPE="L1T"
  L1_METADATA_FILE.PRODUCT_METADATA.DATE_ACQUIRED=2014-03-08
  L1_METADATA_FILE.PRODUCT_METADATA.ELEVATION_SOURCE="GLS2000"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_10="LC81270562014067LGN00_B10.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_11="LC81270562014067LGN00_B11.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_1="LC81270562014067LGN00_B1.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_2="LC81270562014067LGN00_B2.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_3="LC81270562014067LGN00_B3.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_4="LC81270562014067LGN00_B4.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_5="LC81270562014067LGN00_B5.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_6="LC81270562014067LGN00_B6.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_7="LC81270562014067LGN00_B7.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_8="LC81270562014067LGN00_B8.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_9="LC81270562014067LGN00_B9.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_QUALITY="LC81270562014067LGN00_BQA.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.METADATA_FILE_NAME="LC81270562014067LGN00_MTL.txt"
  L1_METADATA_FILE.PRODUCT_METADATA.NADIR_OFFNADIR="NADIR"
  L1_METADATA_FILE.PRODUCT_METADATA.OUTPUT_FORMAT="GEOTIFF"
  L1_METADATA_FILE.PRODUCT_METADATA.PANCHROMATIC_LINES=15481
  L1_METADATA_FILE.PRODUCT_METADATA.PANCHROMATIC_SAMPLES=15141
  L1_METADATA_FILE.PRODUCT_METADATA.REFLECTIVE_LINES=7741
  L1_METADATA_FILE.PRODUCT_METADATA.REFLECTIVE_SAMPLES=7571
  L1_METADATA_FILE.PRODUCT_METADATA.RLUT_FILE_NAME="L8RLUT20130211_20431231v09.h5"
  L1_METADATA_FILE.PRODUCT_METADATA.SCENE_CENTER_TIME=03:28:21.9117383Z
  L1_METADATA_FILE.PRODUCT_METADATA.SENSOR_ID="OLI_TIRS"
  L1_METADATA_FILE.PRODUCT_METADATA.SPACECRAFT_ID="LANDSAT_8"
  L1_METADATA_FILE.PRODUCT_METADATA.TARGET_WRS_PATH=127
  L1_METADATA_FILE.PRODUCT_METADATA.TARGET_WRS_ROW=56
  L1_METADATA_FILE.PRODUCT_METADATA.THERMAL_LINES=7741
  L1_METADATA_FILE.PRODUCT_METADATA.THERMAL_SAMPLES=7571
  L1_METADATA_FILE.PRODUCT_METADATA.WRS_PATH=127
  L1_METADATA_FILE.PRODUCT_METADATA.WRS_ROW=56
  L1_METADATA_FILE.PROJECTION_PARAMETERS.DATUM="WGS84"
  L1_METADATA_FILE.PROJECTION_PARAMETERS.ELLIPSOID="WGS84"
  L1_METADATA_FILE.PROJECTION_PARAMETERS.GRID_CELL_SIZE_PANCHROMATIC=15.00
  L1_METADATA_FILE.PROJECTION_PARAMETERS.GRID_CELL_SIZE_REFLECTIVE=30.00
  L1_METADATA_FILE.PROJECTION_PARAMETERS.GRID_CELL_SIZE_THERMAL=30.00
  L1_METADATA_FILE.PROJECTION_PARAMETERS.MAP_PROJECTION="UTM"
  L1_METADATA_FILE.PROJECTION_PARAMETERS.ORIENTATION="NORTH_UP"
  L1_METADATA_FILE.PROJECTION_PARAMETERS.RESAMPLING_OPTION="CUBIC_CONVOLUTION"
  L1_METADATA_FILE.PROJECTION_PARAMETERS.UTM_ZONE=47
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_10=0.10000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_11=0.10000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_1=-63.72549
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_2=-65.25568
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_3=-60.13255
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_4=-50.70715
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_5=-31.03025
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_6=-7.71694
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_7=-2.60102
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_8=-57.38654
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_9=-12.12732
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_10=3.3420E-04
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_11=3.3420E-04
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_1=1.2745E-02
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_2=1.3051E-02
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_3=1.2027E-02
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_4=1.0141E-02
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_5=6.2060E-03
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_6=1.5434E-03
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_7=5.2020E-04
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_8=1.1477E-02
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_9=2.4255E-03
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_1=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_2=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_3=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_4=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_5=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_6=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_7=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_8=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_9=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_1=2.0000E-05
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_2=2.0000E-05
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_3=2.0000E-05
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_4=2.0000E-05
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_5=2.0000E-05
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_6=2.0000E-05
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_7=2.0000E-05
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_8=2.0000E-05
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_9=2.0000E-05
  L1_METADATA_FILE.TIRS_THERMAL_CONSTANTS.K1_CONSTANT_BAND_10=774.89
  L1_METADATA_FILE.TIRS_THERMAL_CONSTANTS.K1_CONSTANT_BAND_11=480.89
  L1_METADATA_FILE.TIRS_THERMAL_CONSTANTS.K2_CONSTANT_BAND_10=1321.08
  L1_METADATA_FILE.TIRS_THERMAL_CONSTANTS.K2_CONSTANT_BAND_11=1201.14
Subdatasets:
  SUBDATASET_1_NAME=LANDSAT:0:F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_MTL.txt
  SUBDATASET_1_DESC=LANDSAT:Panchromatic
  SUBDATASET_2_NAME=LANDSAT:1:F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_MTL.txt
  SUBDATASET_2_DESC=LANDSAT:Reflective
  SUBDATASET_3_NAME=LANDSAT:2:F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_MTL.txt
  SUBDATASET_3_DESC=LANDSAT:Thermal
  SUBDATASET_4_NAME=LANDSAT:3:F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_MTL.txt
  SUBDATASET_4_DESC=LANDSAT:Quality
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)
从上面的输出内容可以看出,扩展的驱动可以将MTL中的所有的信息作为元数据进行输出,同时构造了四个subdataset。下面分别输出四个subdataset的信息。首先是subdataset1,也就是全色数据,子数据集的名称为LANDSAT:0:F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_MTL.txt,下面以这个作为gdalinfo的参数,输出内容如下:

F:\gdal\bin>gdalinfo.exe LANDSAT:0:F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_MTL.txt
Driver: LANDSAT/LANDSAT 7/8 GeoTiff with Metadata
Files: F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_B8.TIF
Size is 15141, 15481
Coordinate System is:
PROJCS["WGS 84 / UTM zone 47N",
    GEOGCS["WGS 84",
        DATUM["WGS_1984",
            SPHEROID["WGS 84",6378137,298.257223563,
                AUTHORITY["EPSG","7030"]],
            AUTHORITY["EPSG","6326"]],
        PRIMEM["Greenwich",0],
        UNIT["degree",0.0174532925199433],
        AUTHORITY["EPSG","4326"]],
    PROJECTION["Transverse_Mercator"],
    PARAMETER["latitude_of_origin",0],
    PARAMETER["central_meridian",99],
    PARAMETER["scale_factor",0.9996],
    PARAMETER["false_easting",500000],
    PARAMETER["false_northing",0],
    UNIT["metre",1,
        AUTHORITY["EPSG","9001"]],
    AUTHORITY["EPSG","32647"]]
Origin = (716392.500000000000000,756007.500000000000000)
Pixel Size = (15.000000000000000,-15.000000000000000)
Metadata:
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.CLOUD_COVER=11.95
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.EARTH_SUN_DISTANCE=0.9925442
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.GEOMETRIC_RMSE_MODEL=8.958
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.GEOMETRIC_RMSE_MODEL_X=6.205
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.GEOMETRIC_RMSE_MODEL_Y=6.460
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.GEOMETRIC_RMSE_VERIFY=6.144
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.GROUND_CONTROL_POINTS_MODEL=141
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.GROUND_CONTROL_POINTS_VERIFY=36
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.IMAGE_QUALITY_OLI=9
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.IMAGE_QUALITY_TIRS=9
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.ROLL_ANGLE=-0.001
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.SUN_AZIMUTH=109.94537007
  L1_METADATA_FILE.IMAGE_ATTRIBUTES.SUN_ELEVATION=59.45969108
  L1_METADATA_FILE.METADATA_FILE_INFO.FILE_DATE=2014-03-08T06:54:18Z
  L1_METADATA_FILE.METADATA_FILE_INFO.LANDSAT_SCENE_ID="LC81270562014067LGN00"
  L1_METADATA_FILE.METADATA_FILE_INFO.ORIGIN="Image courtesy of the U.S. Geological Survey"
  L1_METADATA_FILE.METADATA_FILE_INFO.PROCESSING_SOFTWARE_VERSION="LPGS_2.3.0"
  L1_METADATA_FILE.METADATA_FILE_INFO.REQUEST_ID="0501403074153_00047"
  L1_METADATA_FILE.METADATA_FILE_INFO.STATION_ID="LGN"
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_10=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_11=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_1=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_2=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_3=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_4=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_5=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_6=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_7=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_8=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MAX_BAND_9=65535
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_10=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_11=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_1=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_2=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_3=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_4=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_5=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_6=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_7=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_8=1
  L1_METADATA_FILE.MIN_MAX_PIXEL_VALUE.QUANTIZE_CAL_MIN_BAND_9=1
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_10=22.00180
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_11=22.00180
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_1=771.52448
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_2=790.05048
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_3=728.02478
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_4=613.91150
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_5=375.68323
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_6=93.42900
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_7=31.49057
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_8=694.77887
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MAXIMUM_BAND_9=146.82552
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_10=0.10033
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_11=0.10033
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_1=-63.71274
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_2=-65.24262
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_3=-60.12052
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_4=-50.69701
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_5=-31.02404
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_6=-7.71540
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_7=-2.60050
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_8=-57.37506
  L1_METADATA_FILE.MIN_MAX_RADIANCE.RADIANCE_MINIMUM_BAND_9=-12.12490
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_1=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_2=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_3=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_4=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_5=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_6=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_7=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_8=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MAXIMUM_BAND_9=1.210700
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_1=-0.099980
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_2=-0.099980
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_3=-0.099980
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_4=-0.099980
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_5=-0.099980
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_6=-0.099980
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_7=-0.099980
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_8=-0.099980
  L1_METADATA_FILE.MIN_MAX_REFLECTANCE.REFLECTANCE_MINIMUM_BAND_9=-0.099980
  L1_METADATA_FILE.PRODUCT_METADATA.BPF_NAME_OLI="LO8BPF20140308030904_20140308035315.01"
  L1_METADATA_FILE.PRODUCT_METADATA.BPF_NAME_TIRS="LT8BPF20140308030510_20140308035408.01"
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LL_LAT_PRODUCT=4.73612
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LL_LON_PRODUCT=100.95098
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LL_PROJECTION_X_PRODUCT=716400.000
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LL_PROJECTION_Y_PRODUCT=523800.000
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LR_LAT_PRODUCT=4.72733
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LR_LON_PRODUCT=102.99592
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LR_PROJECTION_X_PRODUCT=943500.000
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_LR_PROJECTION_Y_PRODUCT=523800.000
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UL_LAT_PRODUCT=6.83546
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UL_LON_PRODUCT=100.95819
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UL_PROJECTION_X_PRODUCT=716400.000
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UL_PROJECTION_Y_PRODUCT=756000.000
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UR_LAT_PRODUCT=6.82274
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UR_LON_PRODUCT=103.01065
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UR_PROJECTION_X_PRODUCT=943500.000
  L1_METADATA_FILE.PRODUCT_METADATA.CORNER_UR_PROJECTION_Y_PRODUCT=756000.000
  L1_METADATA_FILE.PRODUCT_METADATA.CPF_NAME="L8CPF20140101_20140331.03"
  L1_METADATA_FILE.PRODUCT_METADATA.DATA_TYPE="L1T"
  L1_METADATA_FILE.PRODUCT_METADATA.DATE_ACQUIRED=2014-03-08
  L1_METADATA_FILE.PRODUCT_METADATA.ELEVATION_SOURCE="GLS2000"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_10="LC81270562014067LGN00_B10.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_11="LC81270562014067LGN00_B11.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_1="LC81270562014067LGN00_B1.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_2="LC81270562014067LGN00_B2.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_3="LC81270562014067LGN00_B3.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_4="LC81270562014067LGN00_B4.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_5="LC81270562014067LGN00_B5.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_6="LC81270562014067LGN00_B6.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_7="LC81270562014067LGN00_B7.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_8="LC81270562014067LGN00_B8.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_9="LC81270562014067LGN00_B9.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.FILE_NAME_BAND_QUALITY="LC81270562014067LGN00_BQA.TIF"
  L1_METADATA_FILE.PRODUCT_METADATA.METADATA_FILE_NAME="LC81270562014067LGN00_MTL.txt"
  L1_METADATA_FILE.PRODUCT_METADATA.NADIR_OFFNADIR="NADIR"
  L1_METADATA_FILE.PRODUCT_METADATA.OUTPUT_FORMAT="GEOTIFF"
  L1_METADATA_FILE.PRODUCT_METADATA.PANCHROMATIC_LINES=15481
  L1_METADATA_FILE.PRODUCT_METADATA.PANCHROMATIC_SAMPLES=15141
  L1_METADATA_FILE.PRODUCT_METADATA.REFLECTIVE_LINES=7741
  L1_METADATA_FILE.PRODUCT_METADATA.REFLECTIVE_SAMPLES=7571
  L1_METADATA_FILE.PRODUCT_METADATA.RLUT_FILE_NAME="L8RLUT20130211_20431231v09.h5"
  L1_METADATA_FILE.PRODUCT_METADATA.SCENE_CENTER_TIME=03:28:21.9117383Z
  L1_METADATA_FILE.PRODUCT_METADATA.SENSOR_ID="OLI_TIRS"
  L1_METADATA_FILE.PRODUCT_METADATA.SPACECRAFT_ID="LANDSAT_8"
  L1_METADATA_FILE.PRODUCT_METADATA.TARGET_WRS_PATH=127
  L1_METADATA_FILE.PRODUCT_METADATA.TARGET_WRS_ROW=56
  L1_METADATA_FILE.PRODUCT_METADATA.THERMAL_LINES=7741
  L1_METADATA_FILE.PRODUCT_METADATA.THERMAL_SAMPLES=7571
  L1_METADATA_FILE.PRODUCT_METADATA.WRS_PATH=127
  L1_METADATA_FILE.PRODUCT_METADATA.WRS_ROW=56
  L1_METADATA_FILE.PROJECTION_PARAMETERS.DATUM="WGS84"
  L1_METADATA_FILE.PROJECTION_PARAMETERS.ELLIPSOID="WGS84"
  L1_METADATA_FILE.PROJECTION_PARAMETERS.GRID_CELL_SIZE_PANCHROMATIC=15.00
  L1_METADATA_FILE.PROJECTION_PARAMETERS.GRID_CELL_SIZE_REFLECTIVE=30.00
  L1_METADATA_FILE.PROJECTION_PARAMETERS.GRID_CELL_SIZE_THERMAL=30.00
  L1_METADATA_FILE.PROJECTION_PARAMETERS.MAP_PROJECTION="UTM"
  L1_METADATA_FILE.PROJECTION_PARAMETERS.ORIENTATION="NORTH_UP"
  L1_METADATA_FILE.PROJECTION_PARAMETERS.RESAMPLING_OPTION="CUBIC_CONVOLUTION"
  L1_METADATA_FILE.PROJECTION_PARAMETERS.UTM_ZONE=47
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_10=0.10000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_11=0.10000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_1=-63.72549
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_2=-65.25568
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_3=-60.13255
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_4=-50.70715
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_5=-31.03025
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_6=-7.71694
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_7=-2.60102
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_8=-57.38654
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_ADD_BAND_9=-12.12732
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_10=3.3420E-04
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_11=3.3420E-04
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_1=1.2745E-02
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_2=1.3051E-02
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_3=1.2027E-02
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_4=1.0141E-02
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_5=6.2060E-03
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_6=1.5434E-03
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_7=5.2020E-04
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_8=1.1477E-02
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.RADIANCE_MULT_BAND_9=2.4255E-03
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_1=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_2=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_3=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_4=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_5=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_6=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_7=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_8=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_ADD_BAND_9=-0.100000
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_1=2.0000E-05
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_2=2.0000E-05
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_3=2.0000E-05
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_4=2.0000E-05
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_5=2.0000E-05
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_6=2.0000E-05
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_7=2.0000E-05
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_8=2.0000E-05
  L1_METADATA_FILE.RADIOMETRIC_RESCALING.REFLECTANCE_MULT_BAND_9=2.0000E-05
  L1_METADATA_FILE.TIRS_THERMAL_CONSTANTS.K1_CONSTANT_BAND_10=774.89
  L1_METADATA_FILE.TIRS_THERMAL_CONSTANTS.K1_CONSTANT_BAND_11=480.89
  L1_METADATA_FILE.TIRS_THERMAL_CONSTANTS.K2_CONSTANT_BAND_10=1321.08
  L1_METADATA_FILE.TIRS_THERMAL_CONSTANTS.K2_CONSTANT_BAND_11=1201.14
Corner Coordinates:
Upper Left  (  716392.500,  756007.500) (100d57'29.23"E,  6d50' 7.91"N)
Lower Left  (  716392.500,  523792.500) (100d57' 3.27"E,  4d44' 9.79"N)
Upper Right (  943507.500,  756007.500) (103d 0'38.59"E,  6d49'22.11"N)
Lower Right (  943507.500,  523792.500) (102d59'45.54"E,  4d43'38.14"N)
Center      (  829950.000,  639900.000) (101d58'44.08"E,  5d46'52.89"N)
Band 1 Block=15141x1 Type=UInt16, ColorInterp=Undefined
  Metadata:
    LC81270562014067LGN00_B8.TIF
从上面的输出可以看出,子数据集也将mtl中的元数据信息进行了输出,同时输出的全色数据的投影信息,四角坐标,分辨率等信息。

下面是多光谱数据,子数据集名称为LANDSAT:1:F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_MTL.txt,由于输出的元数据信息一样,所以使用参数-nomd禁止输出元数据。输出内容如下:

F:\gdal\bin>gdalinfo.exe -nomd LANDSAT:1:F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_MTL.txt
Driver: LANDSAT/LANDSAT 7/8 GeoTiff with Metadata
Files: F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_B1.TIF
       F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_B2.TIF
       F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_B3.TIF
       F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_B4.TIF
       F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_B5.TIF
       F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_B6.TIF
       F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_B7.TIF
       F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_B9.TIF
Size is 7571, 7741
Coordinate System is:
PROJCS["WGS 84 / UTM zone 47N",
    GEOGCS["WGS 84",
        DATUM["WGS_1984",
            SPHEROID["WGS 84",6378137,298.257223563,
                AUTHORITY["EPSG","7030"]],
            AUTHORITY["EPSG","6326"]],
        PRIMEM["Greenwich",0],
        UNIT["degree",0.0174532925199433],
        AUTHORITY["EPSG","4326"]],
    PROJECTION["Transverse_Mercator"],
    PARAMETER["latitude_of_origin",0],
    PARAMETER["central_meridian",99],
    PARAMETER["scale_factor",0.9996],
    PARAMETER["false_easting",500000],
    PARAMETER["false_northing",0],
    UNIT["metre",1,
        AUTHORITY["EPSG","9001"]],
    AUTHORITY["EPSG","32647"]]
Origin = (716385.000000000000000,756015.000000000000000)
Pixel Size = (30.000000000000000,-30.000000000000000)
Corner Coordinates:
Upper Left  (  716385.000,  756015.000) (100d57'28.99"E,  6d50' 8.15"N)
Lower Left  (  716385.000,  523785.000) (100d57' 3.03"E,  4d44' 9.55"N)
Upper Right (  943515.000,  756015.000) (103d 0'38.83"E,  6d49'22.36"N)
Lower Right (  943515.000,  523785.000) (102d59'45.78"E,  4d43'37.90"N)
Center      (  829950.000,  639900.000) (101d58'44.08"E,  5d46'52.89"N)
Band 1 Block=7571x1 Type=UInt16, ColorInterp=Undefined
Band 2 Block=7571x1 Type=UInt16, ColorInterp=Undefined
Band 3 Block=7571x1 Type=UInt16, ColorInterp=Undefined
Band 4 Block=7571x1 Type=UInt16, ColorInterp=Undefined
Band 5 Block=7571x1 Type=UInt16, ColorInterp=Undefined
Band 6 Block=7571x1 Type=UInt16, ColorInterp=Undefined
Band 7 Block=7571x1 Type=UInt16, ColorInterp=Undefined
Band 8 Block=7571x1 Type=UInt16, ColorInterp=Undefined
从上面的信息中可以看出,输出的多光谱一共有8个波段,以及空间参考信息,分辨率,四至范围等。

下面输出TIRS的数据,命令行如上,子数据集的名称为LANDSAT:2:F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_MTL.txt,输出的信息如下:

F:\gdal\bin>gdalinfo.exe -nomd LANDSAT:2:F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_MTL.txt
Driver: LANDSAT/LANDSAT 7/8 GeoTiff with Metadata
Files: F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_B10.TIF
       F:\Data\LandSat\LC81270562014067LGN00\LC81270562014067LGN00_B11.TIF
Size is 7571, 7741
Coordinate System is:
PROJCS["WGS 84 / UTM zone 47N",
    GEOGCS["WGS 84",
        DATUM["WGS_1984",
            SPHEROID["WGS 84",6378137,298.257223563,
                AUTHORITY["EPSG","7030"]],
            AUTHORITY["EPSG","6326"]],
        PRIMEM["Greenwich",0],
        UNIT["degree",0.0174532925199433],
        AUTHORITY["EPSG","4326"]],
    PROJECTION["Transverse_Mercator"],
    PARAMETER["latitude_of_origin",0],
    PARAMETER["central_meridian",99],
    PARAMETER["scale_factor",0.9996],
    PARAMETER["false_easting",500000],
    PARAMETER["false_northing",0],
    UNIT["metre",1,
        AUTHORITY["EPSG","9001"]],
    AUTHORITY["EPSG","32647"]]
Origin = (716385.000000000000000,756015.000000000000000)
Pixel Size = (30.000000000000000,-30.000000000000000)
Corner Coordinates:
Upper Left  (  716385.000,  756015.000) (100d57'28.99"E,  6d50' 8.15"N)
Lower Left  (  716385.000,  523785.000) (100d57' 3.03"E,  4d44' 9.55"N)
Upper Right (  943515.000,  756015.000) (103d 0'38.83"E,  6d49'22.36"N)
Lower Right (  943515.000,  523785.000) (102d59'45.78"E,  4d43'37.90"N)
Center      (  829950.000,  639900.000) (101d58'44.08"E,  5d46'52.89"N)
Band 1 Block=7571x1 Type=UInt16, ColorInterp=Undefined
Band 2 Block=7571x1 Type=UInt16, ColorInterp=Undefined
这里有个问题,可以看到输出的TIRS数据的分辨率为30m,但是网上的资料写的TIRS的分辨率都是100m,我直接使用gdalinfo输出了10.tif和11.tif的信息,发现里面的也是30m的分辨率,所以我觉得TIRS的分辨率应该也是30m才对。

有了上面的驱动,就可以直接使用gdal打开mtl文件从而自动将数据组合在一起了,在使用的时候也比较方便。希望对大家能有所帮助。

你可能感兴趣的:(GDAL,dirver,landsat8)