zoukankan      html  css  js  c++  java
  • 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数据为例,如下图所示:


    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的实现源码,将其放到frmtslandsat目录,然后参考官网的说明编写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, liminlu0314@163.com
    *
    ******************************************************************************
    * 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] = '';
    
    		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] = '';
    
    	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] = '';
    
    		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] = '';
    
    		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] = '';
    
    	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] = '';
    
    		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.
    " );
    		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 != '' && *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.
    ", 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:gdalin>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:gdalin>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:gdalin>gdalinfo.exe F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_MTL.txt
    Driver: LANDSAT/LANDSAT 7/8 GeoTiff with Metadata
    Files: F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_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:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_MTL.txt
      SUBDATASET_1_DESC=LANDSAT:Panchromatic
      SUBDATASET_2_NAME=LANDSAT:1:F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_MTL.txt
      SUBDATASET_2_DESC=LANDSAT:Reflective
      SUBDATASET_3_NAME=LANDSAT:2:F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_MTL.txt
      SUBDATASET_3_DESC=LANDSAT:Thermal
      SUBDATASET_4_NAME=LANDSAT:3:F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_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:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_MTL.txt,下面以这个作为gdalinfo的参数,输出内容如下:

    F:gdalin>gdalinfo.exe LANDSAT:0:F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_MTL.txt
    Driver: LANDSAT/LANDSAT 7/8 GeoTiff with Metadata
    Files: F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_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:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_MTL.txt,由于输出的元数据信息一样,所以使用参数-nomd禁止输出元数据。输出内容如下:

    F:gdalin>gdalinfo.exe -nomd LANDSAT:1:F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_MTL.txt
    Driver: LANDSAT/LANDSAT 7/8 GeoTiff with Metadata
    Files: F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_B1.TIF
           F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_B2.TIF
           F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_B3.TIF
           F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_B4.TIF
           F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_B5.TIF
           F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_B6.TIF
           F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_B7.TIF
           F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_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:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_MTL.txt,输出的信息如下:

    F:gdalin>gdalinfo.exe -nomd LANDSAT:2:F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_MTL.txt
    Driver: LANDSAT/LANDSAT 7/8 GeoTiff with Metadata
    Files: F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_B10.TIF
           F:DataLandSatLC81270562014067LGN00LC81270562014067LGN00_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文件从而自动将数据组合在一起了,在使用的时候也比较方便。希望对大家能有所帮助。

  • 相关阅读:
    贴一段微博上的小知识
    关于编译Qt以及驱动的一点总结吧
    一些服务器客户端的c例子
    android中DatePicker和TimePicker的使用
    Python标准库string模块《未完待续》
    Qt: SQL Programming
    和一个坑爹的项目组的经历
    linux一些杂项整理
    Qt中的QTableWidget
    Linux c学习进程基础学习
  • 原文地址:https://www.cnblogs.com/xiaowangba/p/6313904.html
Copyright © 2011-2022 走看看