GDAL工具箱详解之gdalinfo.exe

来源:互联网 发布:中山大学图书馆 知乎 编辑:程序博客网 时间:2024/05/01 01:28

GDAL工具箱详解之gdalinfo.exe

GDAL自带的工具包含了众多的功能,可以看做是利用该开源库进行的典型开发案例。本节主要介绍其中基本的一项工具——gdalinfo.exe。

  • 该工具箱位于GDAL文件夹下的apps文件夹中,属于命令行可执行程序。

目录

  • GDAL工具箱详解之gdalinfoexe
      • 目录
    • 使用方法
      • 常规项目的内容
      • 典例
    • 源码分析
      • 源码及分析
      • 流程图
      • 参数初始化
      • 读取信息主函数


使用方法

GDAL帮助文件中栅格工具箱里关于gdalinfo.exe的描述如下:

gdalinfo [--help-general] [-json] [-mm] [-stats] [-hist] [-nogcp] [-nomd]         [-norat] [-noct] [-nofl] [-checksum] [-proj4]         [-listmdd] [-mdd domain|`all`]*         [-sd subdataset] [-oo NAME=VALUE]* datasetname
项目 作用 –help 显示帮助 -general 常规项目 -json 标记是否以json形式输出 -mm 标记是否强制计算每波段的MAX及MIN -stats 标记读取图像统计信息(如果没有将从图像中计算) -hist 标记报告所有波段的直方图信息 -nogcp 标记不显示图像包含的地面控制点 -nomd 标记不显示元数据 -norat 标记不显示栅格属性表 -noct 标记不显示色彩表 -checksum 强制计算波段的校验码 -listmdd 列出数据集可获得的所有元数据 -mdd domain 获取特定所属的元数据 -nofl 只显示文件列表中的第一个文件 -sd subdataset 如果数据集包含了子集,该项用于指定要获取的子项。 -proj4 以PROJ4字符串形式显示图像的地理坐标系 -oo NAME=VALUE 打开选项(以“选项名=选项值”进行设定)

常规项目的内容

在命令行界面转到可执行程序目录,输入如下命令:

(Path of gdalinfo.exe)gdalinfo --help-general

得到输出

Generic GDAL utility command options:  --version: report version of GDAL in use.  --license: report GDAL license info.  --formats: report all configured format drivers.  --format [format]: details of one format.  --optfile filename: expand an option file into the argument list.  --config key value: set system configuration option.  --debug [on/off/value]: set debug level.  --pause: wait for user input, time to attach debugger  --locale [locale]: install locale for debugging (i.e. en_US.UTF-8)  --help-general: report detailed help on general options.

典例

下面是使用该程序的一个典型例子:

(Path of gdalinfo.exe)>gdalinfo -proj4 -stats ~\exmaple.tif

得到输出为:

Driver: GTiff/GeoTIFFFiles: E:\exmaple.tifSize is 200, 400Coordinate System is: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"]]PROJ.4 string is:'+proj=longlat +datum=WGS84 +no_defs 'Origin = (116.438654182485010,40.154364985586007)Pixel Size = (0.000018000000000,-0.000018000000000)Metadata:  AREA_OR_POINT=AreaImage Structure Metadata:  INTERLEAVE=PIXELCorner Coordinates:Upper Left  ( 116.4386542,  40.1543650)Lower Left  ( 116.4386542,  40.1471650)Upper Right ( 116.4422542,  40.1543650)Lower Right ( 116.4422542,  40.1471650)Center      ( 116.4404542,  40.1507650)Band 1 Block=200x5 Type=UInt16, ColorInterp=Gray  Minimum=0.000, Maximum=0.000, Mean=0.000, StdDev=0.000  Metadata:    STATISTICS_MAXIMUM=0    STATISTICS_MEAN=0    STATISTICS_MINIMUM=0    STATISTICS_STDDEV=0Band 2 Block=200x5 Type=UInt16, ColorInterp=Undefined  Minimum=0.000, Maximum=0.000, Mean=0.000, StdDev=0.000  Metadata:    STATISTICS_MAXIMUM=0    STATISTICS_MEAN=0    STATISTICS_MINIMUM=0    STATISTICS_STDDEV=0Band 3 Block=200x5 Type=UInt16, ColorInterp=Undefined  Minimum=0.000, Maximum=0.000, Mean=0.000, StdDev=0.000  Metadata:    STATISTICS_MAXIMUM=0    STATISTICS_MEAN=0    STATISTICS_MINIMUM=0    STATISTICS_STDDEV=0Band 4 Block=200x5 Type=UInt16, ColorInterp=Undefined  Minimum=0.000, Maximum=0.000, Mean=0.000, StdDev=0.000  Metadata:    STATISTICS_MAXIMUM=0    STATISTICS_MEAN=0    STATISTICS_MINIMUM=0    STATISTICS_STDDEV=0

这里使用的例子数据是一份实验数据,实际上带有信息的图像的统计信息不会全为0。


源码分析

那么gdalinfo是如何工作的呢,虽然有帮助的提示,我们还有很多选项不知道如何设定,比如:–oo中的NAME=VALUE存在哪些项目和可选项呢?这些选项的默认参数又是什么呢?下面我们就从源码角度来分析该应用程序是如何工作的。

源码及分析

int main( int argc, char ** argv ){    EarlySetConfigOptions(argc, argv);//预设置    GDALAllRegister();//注册所有驱动    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );//命令行参数处理    if( argc < 1 )//如果参数小于1,程序退出        exit( -argc );    for( int i = 0; argv != NULL && argv[i] != NULL; i++ )//参数匹配    {        if( EQUAL(argv[i], "--utility_version") )        {//打印工具版本            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));            CSLDestroy( argv );            return 0;        }        else if( EQUAL(argv[i],"--help") )        {//打印帮助,并退出            Usage();        }    }    argv = CSLAddString(argv, "-stdout");//设置标准输出    GDALInfoOptionsForBinary* psOptionsForBinary = GDALInfoOptionsForBinaryNew();//初始化二值化选项    GDALInfoOptions *psOptions        = GDALInfoOptionsNew(argv + 1, psOptionsForBinary);//**根据字符串数组初始化要显示的信息选项**    if( psOptions == NULL )//如果选项初始化失败,退出        Usage();    if( psOptionsForBinary->pszFilename == NULL )//如果没有指定资源文件,退出        Usage("No datasource specified.");/* -------------------------------------------------------------------- *//*      打开数据集.                                                      *//* -------------------------------------------------------------------- */#ifdef __AFL_HAVE_MANUAL_CONTROL//**配合下面**    int iIter = 0;    while (__AFL_LOOP(1000)) {        iIter ++;#endif    GDALDatasetH hDataset        = GDALOpenEx( psOptionsForBinary->pszFilename, GDAL_OF_READONLY | GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR, NULL,                      (const char* const* )psOptionsForBinary->papszOpenOptions, NULL );//打开数据集    if( hDataset == NULL )    {#ifdef __AFL_HAVE_MANUAL_CONTROL        continue;#else        fprintf( stderr,                 "gdalinfo failed - unable to open '%s'.\n",                 psOptionsForBinary->pszFilename );/* -------------------------------------------------------------------- *//*      如果参数是一个VSI文件, 就打印其内容。                               *//* -------------------------------------------------------------------- */        if ( STARTS_WITH(psOptionsForBinary->pszFilename, "/vsizip/") ||             STARTS_WITH(psOptionsForBinary->pszFilename, "/vsitar/") )        {            char** papszFileList = VSIReadDirRecursive( psOptionsForBinary->pszFilename );            if ( papszFileList )            {                int nCount = CSLCount( papszFileList );                fprintf( stdout,                         "Unable to open source `%s' directly.\n"                         "The archive contains %d files:\n",                         psOptionsForBinary->pszFilename, nCount );                for ( int i = 0; i < nCount; i++ )                {//打印内部文件列表                    fprintf( stdout, "       %s/%s\n", psOptionsForBinary->pszFilename, papszFileList[i] );                }                CSLDestroy( papszFileList );            }        }        CSLDestroy( argv );//释放参数        GDALInfoOptionsForBinaryFree(psOptionsForBinary);//释放二值化选项        GDALInfoOptionsFree( psOptions );//释放选项占用的内存        GDALDumpOpenDatasets( stderr );//释放打开的数据集        GDALDestroyDriverManager();//释放驱动管理        CPLDumpSharedList( NULL );        exit( 1 );#endif    }/* -------------------------------------------------------------------- *//*      读取特定的文件子数据集.                                            *//* -------------------------------------------------------------------- */    if ( psOptionsForBinary->nSubdataset > 0 )    {        char **papszSubdatasets = GDALGetMetadata( hDataset, "SUBDATASETS" );        int nSubdatasets = CSLCount( papszSubdatasets );        if ( nSubdatasets > 0 && psOptionsForBinary->nSubdataset <= nSubdatasets )        {            char szKeyName[1024];            char *pszSubdatasetName;            snprintf( szKeyName, sizeof(szKeyName),                      "SUBDATASET_%d_NAME", psOptionsForBinary->nSubdataset );            szKeyName[sizeof(szKeyName) - 1] = '\0';            pszSubdatasetName =                CPLStrdup( CSLFetchNameValue( papszSubdatasets, szKeyName ) );            GDALClose( hDataset );//关闭原数据集            hDataset = GDALOpen( pszSubdatasetName, GA_ReadOnly );//打开子数据集            CPLFree( pszSubdatasetName );        }        else        {            fprintf( stderr,                     "gdalinfo warning: subdataset %d of %d requested. "                     "Reading the main dataset.\n",                     psOptionsForBinary->nSubdataset, nSubdatasets );        }    }    char* pszGDALInfoOutput = GDALInfo( hDataset, psOptions );//**核心函数,读取数据集信息**    if( pszGDALInfoOutput )//读取成功则输出        printf( "%s", pszGDALInfoOutput );    CPLFree( pszGDALInfoOutput );//释放输出字符串    GDALClose( hDataset );//关闭数据集#ifdef __AFL_HAVE_MANUAL_CONTROL    }//**配合上面,组成循环**#endif    GDALInfoOptionsForBinaryFree(psOptionsForBinary);//释放二值化选项    GDALInfoOptionsFree( psOptions );//释放选项    CSLDestroy( argv );//释放输入参数    GDALDumpOpenDatasets( stderr );//释放打开数据集    GDALDestroyDriverManager();//释放驱动管理    CPLDumpSharedList( NULL );    CPLCleanupTLS();    exit( 0 );}

流程图

这是该程序的主要工作流程
从以上流程图可以看出,本程序的核心函数为GDALInfo(GDALDatasetH hDataset,
const GDALInfoOptions * psOptions )

前面大量的工作用来增强程序对多种输入的适应性构筑信息选项

参数初始化

参数初始化函数GDALInfoOptionsForBinaryNew()以及GDALInfoOptionsNew()是如何设置默认选项的呢,我们定位到函数体:

static GDALInfoOptionsForBinary *GDALInfoOptionsForBinaryNew(void){    return (GDALInfoOptionsForBinary*) CPLCalloc(  1, sizeof(GDALInfoOptionsForBinary) );}

很显然,二值化信息选项只是申请了内存并且返回指针。

GDALInfoOptions *GDALInfoOptionsNew(char** papszArgv,                                    GDALInfoOptionsForBinary* psOptionsForBinary){    bool bGotFilename = false;    GDALInfoOptions *psOptions = static_cast<GDALInfoOptions *>(        CPLCalloc( 1, sizeof(GDALInfoOptions) ) );//申请内存    psOptions->eFormat = GDALINFO_FORMAT_TEXT;//默认以文本形式输出    psOptions->bComputeMinMax = FALSE;//默认不计算最大最小值    psOptions->bReportHistograms = FALSE;//默认不报告直方图    psOptions->bReportProj4 = FALSE;//默认不以PROJ4字符报告    psOptions->bStats = FALSE;//默认不统计波段信息    psOptions->bApproxStats = TRUE;//默认开启粗略统计    psOptions->bSample = FALSE;//默认不采样    psOptions->bComputeChecksum = FALSE;//默认不检校    psOptions->bShowGCPs = TRUE;//默认显示控制点    psOptions->bShowMetadata = TRUE;//默认显示主文件元数据    psOptions->bShowRAT = TRUE;//默认显示栅格属性表    psOptions->bShowColorTable = TRUE;//默认显示颜色表    psOptions->bListMDD = FALSE;//默认不显示元数据列表    psOptions->bShowFileList = TRUE;//默认显示文件列表/* -------------------------------------------------------------------- *//*      传参.                                                *//* -------------------------------------------------------------------- */    for( int i = 0; papszArgv != NULL && papszArgv[i] != NULL; i++ )    {        if( EQUAL(papszArgv[i],"-json") )            psOptions->eFormat = GDALINFO_FORMAT_JSON;        else if( EQUAL(papszArgv[i], "-mm") )            psOptions->bComputeMinMax = TRUE;        else if( EQUAL(papszArgv[i], "-hist") )            psOptions->bReportHistograms = TRUE;        else if( EQUAL(papszArgv[i], "-proj4") )            psOptions->bReportProj4 = TRUE;        else if( EQUAL(papszArgv[i], "-stats") )        {            psOptions->bStats = TRUE;            psOptions->bApproxStats = FALSE;        }        else if( EQUAL(papszArgv[i], "-approx_stats") )        {            psOptions->bStats = TRUE;            psOptions->bApproxStats = TRUE;        }        else if( EQUAL(papszArgv[i], "-sample") )            psOptions->bSample = TRUE;        else if( EQUAL(papszArgv[i], "-checksum") )            psOptions->bComputeChecksum = TRUE;        else if( EQUAL(papszArgv[i], "-nogcp") )            psOptions->bShowGCPs = FALSE;        else if( EQUAL(papszArgv[i], "-nomd") )            psOptions->bShowMetadata = FALSE;        else if( EQUAL(papszArgv[i], "-norat") )            psOptions->bShowRAT = FALSE;        else if( EQUAL(papszArgv[i], "-noct") )            psOptions->bShowColorTable = FALSE;        else if( EQUAL(papszArgv[i], "-listmdd") )            psOptions->bListMDD = TRUE;        /* Not documented: used by gdalinfo_bin.cpp only */        else if( EQUAL(papszArgv[i], "-stdout") )            psOptions->bStdoutOutput = true;        else if( EQUAL(papszArgv[i], "-mdd") && papszArgv[i+1] != NULL )        {//设定要获取的属于该文件的元数据            psOptions->papszExtraMDDomains = CSLAddString(                psOptions->papszExtraMDDomains, papszArgv[++i] );        }        else if( EQUAL(papszArgv[i], "-oo") && papszArgv[i+1] != NULL )        {//设定属性            i++;            if( psOptionsForBinary )            {                psOptionsForBinary->papszOpenOptions = CSLAddString(                     psOptionsForBinary->papszOpenOptions, papszArgv[i] );            }        }        else if( EQUAL(papszArgv[i], "-nofl") )            psOptions->bShowFileList = FALSE;        else if( EQUAL(papszArgv[i], "-sd") && papszArgv[i+1] != NULL )        {//子数据集            i++;            if( psOptionsForBinary )            {                psOptionsForBinary->nSubdataset = atoi(papszArgv[i]);            }        }        else if( papszArgv[i][0] == '-' )        {//错误选项处理            CPLError(CE_Failure, CPLE_NotSupported,                     "Unknown option name '%s'", papszArgv[i]);            GDALInfoOptionsFree(psOptions);            return NULL;        }        else if( !bGotFilename )        {//输入文件名称            bGotFilename = true;            if( psOptionsForBinary )                psOptionsForBinary->pszFilename = CPLStrdup(papszArgv[i]);        }        else        {            CPLError(CE_Failure, CPLE_NotSupported,                     "Too many command options '%s'", papszArgv[i]);            GDALInfoOptionsFree(psOptions);            return NULL;        }    }    return psOptions;}

从上面的源码我们可以得到一些处理命令行程序参数输入的小技巧,如-oo和文件名的指定,也清楚了默认文件打开参数和信息显示选项值。但必须注意的是,这里对于-oo的处理仅是将NMAE=VALUE加入OpenOptions字符串数组中,那么问题就转变成了如何根据这个字符串数组进行有效性判断!
没错,再次将视线转向GDALOpenEx(const char* pszFilename,unsigned int nOpenFlags, const char* const* papszAllowedDrivers, const char* const* papszOpenOptions,const char* const* papszSiblingFiles)函数。注意到帮助里的描述:

 * @param papszOpenOptions NULL, or a NULL terminated list of strings with open * options passed to candidate drivers. An option exists for all drivers, * OVERVIEW_LEVEL=level, to select a particular overview level of a dataset. * The level index starts at 0. The level number can be suffixed by "only" to specify that * only this overview level must be visible, and not sub-levels. * Open options are validated by default, and a warning is emitted in case the * option is not recognized. In some scenarios, it might be not desirable (e.g. * when not knowing which driver will open the file), so the special open option * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings. Alternatively, * since GDAL 2.1, an option name can be preceded by the @ character to indicate * that it may not cause a warning if the driver doesn't declare this option.

经过几步,最后定义到有效性检验函数体:

int GDALValidateOpenOptions( GDALDriverH hDriver,                             const char* const* papszOpenOptions){    VALIDATE_POINTER1( hDriver, "GDALValidateOpenOptions", FALSE );    const char *pszOptionList =        ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_OPENOPTIONLIST );    CPLString osDriver;    osDriver.Printf("driver %s", ((GDALDriver *) hDriver)->GetDescription());    return GDALValidateOptions( pszOptionList, papszOpenOptions,                                "open option",                                osDriver);}

可以看出该打开选项依赖于图像驱动的不同而变化,通过该驱动的GetMetadataItem()方法可以得到驱动所支持的打开选项列表。
这里还存在一个问题,GDAL_DMD_OPENOPTIONLIST 是一个定义项,其值为"DMD_OPENOPTIONLIST",然而在内部进行跟踪时别没有发现它是如何获得选项列表的。不过对帮助进行查看我们发现存在
char ** VRTDriver::GetMetadata ( const char * pszDomain = "" )可以获得驱动的元数据列表,但同样是虚方法,根据具体驱动实现不同。

读取信息主函数

先上源码:

char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions ){    if( hDataset == NULL )        return NULL;    GDALInfoOptions* psOptionsToFree = NULL;    if( psOptions == NULL )    {//初始化信息选项        psOptionsToFree = GDALInfoOptionsNew(NULL, NULL);        psOptions = psOptionsToFree;    }    CPLString osStr;    json_object *poJsonObject = NULL, *poBands = NULL, *poMetadata = NULL;    const bool bJson = psOptions->eFormat == GDALINFO_FORMAT_JSON;//先判断后赋值/* -------------------------------------------------------------------- *//*      报告通常信息.                                                     *//* -------------------------------------------------------------------- */    GDALDriverH hDriver = GDALGetDatasetDriver( hDataset );//获取驱动    if(bJson)    {        json_object *poDescription = json_object_new_string(GDALGetDescription(hDataset));//获取描述        json_object *poDriverShortName = json_object_new_string(GDALGetDriverShortName(hDriver));//驱动简称        json_object *poDriverLongName = json_object_new_string(GDALGetDriverLongName(hDriver));//驱动全称        poJsonObject = json_object_new_object();        poBands = json_object_new_array();        poMetadata = json_object_new_object();        json_object_object_add(poJsonObject, "description", poDescription);        json_object_object_add(poJsonObject, "driverShortName", poDriverShortName);        json_object_object_add(poJsonObject, "driverLongName", poDriverLongName);    }    else    {        Concat( osStr, psOptions->bStdoutOutput, "Driver: %s/%s\n",                GDALGetDriverShortName( hDriver ),                GDALGetDriverLongName( hDriver ) );    }//这是一个链接输出项目形成输出字符串的函数    char **papszFileList = GDALGetFileList( hDataset );    if( papszFileList == NULL || *papszFileList == NULL )    {        if(bJson)        {            json_object *poFiles = json_object_new_array();            json_object_object_add(poJsonObject, "files", poFiles);//文件列表json        }        else            Concat( osStr, psOptions->bStdoutOutput,                    "Files: none associated\n" );    }    else    {        if(bJson)        {            if( psOptions->bShowFileList )            {                json_object *poFiles = json_object_new_array();                for(int i = 0; papszFileList[i] != NULL; i++)                {                    json_object *poFile = json_object_new_string(papszFileList[i]);                    json_object_array_add(poFiles, poFile);                }                json_object_object_add(poJsonObject, "files", poFiles);            }        }        else        {            Concat(osStr, psOptions->bStdoutOutput, "Files: %s\n", papszFileList[0] );            if( psOptions->bShowFileList )            {                for( int i = 1; papszFileList[i] != NULL; i++ )                    Concat(osStr, psOptions->bStdoutOutput, "       %s\n", papszFileList[i] );            }        }    }    CSLDestroy( papszFileList );    if(bJson)    {        json_object *poSize = json_object_new_array();        json_object *poSizeX = json_object_new_int(GDALGetRasterXSize(hDataset));        json_object *poSizeY = json_object_new_int(GDALGetRasterYSize(hDataset));        json_object_array_add(poSize, poSizeX);        json_object_array_add(poSize, poSizeY);        json_object_object_add(poJsonObject, "size", poSize);    }    else        Concat(osStr, psOptions->bStdoutOutput, "Size is %d, %d\n", GDALGetRasterXSize( hDataset ),            GDALGetRasterYSize( hDataset ) );//栅格图像大小/* -------------------------------------------------------------------- *//*      报告投影信息.                                                     *//* -------------------------------------------------------------------- */    if( GDALGetProjectionRef( hDataset ) != NULL )    {        json_object *poCoordinateSystem = NULL;        if(bJson)            poCoordinateSystem = json_object_new_object();        char *pszProjection            = const_cast<char *>( GDALGetProjectionRef( hDataset ) );        OGRSpatialReferenceH hSRS            = OSRNewSpatialReference(NULL);        if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None )//尝试转化OGR参考系        {            char    *pszPrettyWkt = NULL;            OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE );            if(bJson)            {                json_object *poWkt = json_object_new_string(pszPrettyWkt);                json_object_object_add(poCoordinateSystem, "wkt", poWkt);            }            else                Concat( osStr, psOptions->bStdoutOutput,                        "Coordinate System is:\n%s\n",                        pszPrettyWkt );            CPLFree( pszPrettyWkt );        }        else        {            if(bJson)            {                json_object *poWkt = json_object_new_string(GDALGetProjectionRef(hDataset));                json_object_object_add(poCoordinateSystem, "wkt", poWkt);            }            else                Concat( osStr, psOptions->bStdoutOutput,                        "Coordinate System is `%s'\n",                        GDALGetProjectionRef( hDataset ) );//直接输出        }        if ( psOptions->bReportProj4 )        {            char *pszProj4 = NULL;            OSRExportToProj4( hSRS, &pszProj4 );//转换为PROJ4格式            if(bJson)            {                json_object *proj4 = json_object_new_string(pszProj4);                json_object_object_add(poCoordinateSystem, "proj4", proj4);            }            else                Concat(osStr, psOptions->bStdoutOutput, "PROJ.4 string is:\n\'%s\'\n",pszProj4);            CPLFree( pszProj4 );        }        if(bJson)            json_object_object_add(poJsonObject, "coordinateSystem", poCoordinateSystem);        OSRDestroySpatialReference( hSRS );    }/* -------------------------------------------------------------------- *//*      报告地理转换参数.                                                 *//* -------------------------------------------------------------------- */    double adfGeoTransform[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};    if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )//地理转换参数赋值    {        if(bJson)        {            json_object *poGeoTransform = json_object_new_array();            for( int i = 0; i < 6; i++ )            {                json_object *poGeoTransformCoefficient = json_object_new_double_with_precision(adfGeoTransform[i], 16);                json_object_array_add(poGeoTransform, poGeoTransformCoefficient);            }            json_object_object_add(poJsonObject, "geoTransform", poGeoTransform);        }        else        {            if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0 )            {//如果图像未旋转                Concat( osStr, psOptions->bStdoutOutput,                        "Origin = (%.15f,%.15f)\n",                        adfGeoTransform[0], adfGeoTransform[3] );//左上角像元地理坐标                Concat( osStr, psOptions->bStdoutOutput,                        "Pixel Size = (%.15f,%.15f)\n",                        adfGeoTransform[1], adfGeoTransform[5] );//像元大小            }            else                Concat( osStr, psOptions->bStdoutOutput, "GeoTransform =\n"                        "  %.16g, %.16g, %.16g\n"                        "  %.16g, %.16g, %.16g\n",                        adfGeoTransform[0],                        adfGeoTransform[1],                        adfGeoTransform[2],                        adfGeoTransform[3],                        adfGeoTransform[4],                        adfGeoTransform[5] );//顺序输出        }    }/* -------------------------------------------------------------------- *//*      报告地面控制点.                                                   *//* -------------------------------------------------------------------- */    if( psOptions->bShowGCPs && GDALGetGCPCount( hDataset ) > 0 )    {        json_object * const poGCPs = bJson ? json_object_new_object() : NULL;        if (GDALGetGCPProjection(hDataset) != NULL)//获取地面控制点投影        {            json_object *poGCPCoordinateSystem = NULL;            char *pszProjection                = const_cast<char *>( GDALGetGCPProjection( hDataset ) );            OGRSpatialReferenceH hSRS                = OSRNewSpatialReference(NULL);            if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None )            {                char    *pszPrettyWkt = NULL;                OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE );                if(bJson)                {                    json_object *poWkt = json_object_new_string(pszPrettyWkt);                    poGCPCoordinateSystem = json_object_new_object();                    json_object_object_add(poGCPCoordinateSystem, "wkt", poWkt);                }                else                    Concat(osStr, psOptions->bStdoutOutput, "GCP Projection = \n%s\n", pszPrettyWkt );                CPLFree( pszPrettyWkt );            }            else            {                if(bJson)                {                    json_object *poWkt = json_object_new_string(GDALGetGCPProjection(hDataset));                    poGCPCoordinateSystem = json_object_new_object();                    json_object_object_add(poGCPCoordinateSystem, "wkt", poWkt);                }                else                    Concat(osStr, psOptions->bStdoutOutput, "GCP Projection = %s\n",                        GDALGetGCPProjection( hDataset ) );            }            if(bJson)                json_object_object_add(poGCPs, "coordinateSystem", poGCPCoordinateSystem);            OSRDestroySpatialReference( hSRS );        }        json_object * const poGCPList = bJson ? json_object_new_array() : NULL;        for( int i = 0; i < GDALGetGCPCount(hDataset); i++ )        {            const GDAL_GCP *psGCP = GDALGetGCPs( hDataset ) + i;//地面控制点            if(bJson)            {                json_object *poGCP = json_object_new_object();                json_object *poId = json_object_new_string(psGCP->pszId);                json_object *poInfo = json_object_new_string(psGCP->pszInfo);                json_object *poPixel = json_object_new_double_with_precision(psGCP->dfGCPPixel, 15);                json_object *poLine = json_object_new_double_with_precision(psGCP->dfGCPLine, 15);                json_object *poX = json_object_new_double_with_precision(psGCP->dfGCPX, 15);                json_object *poY = json_object_new_double_with_precision(psGCP->dfGCPY, 15);                json_object *poZ = json_object_new_double_with_precision(psGCP->dfGCPZ, 15);                json_object_object_add(poGCP, "id", poId);                json_object_object_add(poGCP, "info", poInfo);                json_object_object_add(poGCP, "pixel", poPixel);                json_object_object_add(poGCP, "line", poLine);                json_object_object_add(poGCP, "x", poX);                json_object_object_add(poGCP, "y", poY);                json_object_object_add(poGCP, "z", poZ);                json_object_array_add(poGCPList, poGCP);            }            else                Concat(osStr, psOptions->bStdoutOutput, "GCP[%3d]: Id=%s, Info=%s\n"                    "          (%.15g,%.15g) -> (%.15g,%.15g,%.15g)\n",                    i, psGCP->pszId, psGCP->pszInfo,                    psGCP->dfGCPPixel, psGCP->dfGCPLine,                    psGCP->dfGCPX, psGCP->dfGCPY, psGCP->dfGCPZ );//控制点信息输出        }        if(bJson)        {            json_object_object_add(poGCPs, "gcpList", poGCPList);            json_object_object_add(poJsonObject, "gcps", poGCPs);        }    }/* -------------------------------------------------------------------- *//*      报告数据集元数据.                                                 *//* -------------------------------------------------------------------- */    GDALInfoReportMetadata( psOptions, hDataset, false, bJson, poMetadata, osStr );//元数据信息获取函数(数据集)    if(bJson)    {        if( psOptions->bShowMetadata )            json_object_object_add( poJsonObject, "metadata", poMetadata );        else            json_object_put(poMetadata);    }/* -------------------------------------------------------------------- *//*      如果合适,设置经纬度投影转换.                                       *//* -------------------------------------------------------------------- */    const char  *pszProjection = NULL;    if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )        pszProjection = GDALGetProjectionRef(hDataset);    OGRCoordinateTransformationH hTransform = NULL;    OGRCoordinateTransformationH hTransformWGS84 = NULL;    if( pszProjection != NULL && strlen(pszProjection) > 0 )    {        OGRSpatialReferenceH hProj, hLatLong = NULL, hLatLongWGS84 = NULL;        hProj = OSRNewSpatialReference( pszProjection );        if( hProj != NULL )        {            hLatLong = OSRCloneGeogCS( hProj );            if(bJson)            {                hLatLongWGS84 = OSRNewSpatialReference( NULL );                OSRSetWellKnownGeogCS( hLatLongWGS84, "WGS84" );            }        }        if( hLatLong != NULL )        {            CPLPushErrorHandler( CPLQuietErrorHandler );            hTransform = OCTNewCoordinateTransformation( hProj, hLatLong );//坐标转换信息            CPLPopErrorHandler();            OSRDestroySpatialReference( hLatLong );        }        if( hLatLongWGS84 != NULL )        {            CPLPushErrorHandler( CPLQuietErrorHandler );            hTransformWGS84 = OCTNewCoordinateTransformation( hProj, hLatLongWGS84 );            CPLPopErrorHandler();            OSRDestroySpatialReference( hLatLongWGS84 );        }        if( hProj != NULL )            OSRDestroySpatialReference( hProj );    }/* -------------------------------------------------------------------- *//*      报告边角信息.                                                     *//* -------------------------------------------------------------------- */    if(bJson)    {        json_object *poLinearRing = json_object_new_array();        json_object *poCornerCoordinates = json_object_new_object();        json_object *poWGS84Extent = json_object_new_object();        json_object *poWGS84ExtentType = json_object_new_string("Polygon");        json_object *poWGS84ExtentCoordinates = json_object_new_array();        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "upperLeft",                              0.0, 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );//边角报告函数        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "lowerLeft",                              0.0, GDALGetRasterYSize(hDataset), bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "upperRight",                              GDALGetRasterXSize(hDataset), 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "lowerRight",                              GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset),                              bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "center",                              GDALGetRasterXSize(hDataset)/2.0, GDALGetRasterYSize(hDataset)/2.0,                              bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "upperLeft",                              0.0, 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );        json_object_object_add( poJsonObject, "cornerCoordinates", poCornerCoordinates );        json_object_object_add( poWGS84Extent, "type", poWGS84ExtentType );        json_object_array_add( poLinearRing, poWGS84ExtentCoordinates );        json_object_object_add( poWGS84Extent, "coordinates", poLinearRing );        json_object_object_add( poJsonObject, "wgs84Extent", poWGS84Extent );    }    else    {        Concat(osStr, psOptions->bStdoutOutput, "Corner Coordinates:\n" );        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Upper Left",                              0.0, 0.0, bJson, NULL, NULL, osStr );        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Lower Left",                              0.0, GDALGetRasterYSize(hDataset), bJson, NULL, NULL, osStr );        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Upper Right",                              GDALGetRasterXSize(hDataset), 0.0, bJson, NULL, NULL, osStr );        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Lower Right",                              GDALGetRasterXSize(hDataset),                              GDALGetRasterYSize(hDataset), bJson, NULL, NULL, osStr );        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Center",                              GDALGetRasterXSize(hDataset)/2.0,                              GDALGetRasterYSize(hDataset)/2.0, bJson, NULL, NULL, osStr );    }    if( hTransform != NULL )    {        OCTDestroyCoordinateTransformation( hTransform );        hTransform = NULL;    }    if( hTransformWGS84 != NULL )    {        OCTDestroyCoordinateTransformation( hTransformWGS84 );        hTransformWGS84 = NULL;    }/* ==================================================================== *//*      循环处理波段.                                                     *//* ==================================================================== */    for( int iBand = 0; iBand < GDALGetRasterCount( hDataset ); iBand++ )    {        json_object *poBand = NULL;        json_object *poBandMetadata = NULL;        if(bJson)        {            poBand = json_object_new_object();            poBandMetadata = json_object_new_object();        }        GDALRasterBandH const hBand = GDALGetRasterBand( hDataset, iBand+1 );//获取波段        if( psOptions->bSample )        {//采样统计判断            vector<float> ofSample(10000, 0);            float * const pafSample = &ofSample[0];            const int nCount =                GDALGetRandomRasterSample( hBand, 10000, pafSample );//采样            if(!bJson)                Concat( osStr, psOptions->bStdoutOutput,                        "Got %d samples.\n", nCount );        }        int nBlockXSize = 0;        int nBlockYSize = 0;        GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );//获取波段数据块大小        if(bJson)        {            json_object *poBandNumber = json_object_new_int(iBand+1);            json_object *poBlock = json_object_new_array();            json_object *poType = json_object_new_string(GDALGetDataTypeName(GDALGetRasterDataType(hBand)));//获取数据类型说明            json_object *poColorInterp = json_object_new_string(GDALGetColorInterpretationName(                GDALGetRasterColorInterpretation(hBand)));//获取波段说明            json_object_array_add(poBlock, json_object_new_int(nBlockXSize));            json_object_array_add(poBlock, json_object_new_int(nBlockYSize));            json_object_object_add(poBand, "band", poBandNumber);            json_object_object_add(poBand, "block", poBlock);            json_object_object_add(poBand, "type", poType);            json_object_object_add(poBand, "colorInterpretation", poColorInterp);        }        else            Concat( osStr, psOptions->bStdoutOutput,                    "Band %d Block=%dx%d Type=%s, ColorInterp=%s\n",                    iBand+1,                    nBlockXSize, nBlockYSize,                    GDALGetDataTypeName(                        GDALGetRasterDataType(hBand)),                    GDALGetColorInterpretationName(                        GDALGetRasterColorInterpretation(hBand)) );        if( GDALGetDescription( hBand ) != NULL            && strlen(GDALGetDescription( hBand )) > 0 )        {            if(bJson)            {                json_object *poBandDescription = json_object_new_string(GDALGetDescription(hBand));                json_object_object_add(poBand, "description", poBandDescription);            }            else                Concat( osStr, psOptions->bStdoutOutput, "  Description = %s\n",                        GDALGetDescription(hBand) );//波段说明        }        {            int bGotMin = FALSE;            int bGotMax = FALSE;            const double dfMin = GDALGetRasterMinimum( hBand, &bGotMin );//获取波段最小值            const double dfMax = GDALGetRasterMaximum( hBand, &bGotMax );//获取波段最大值            if( bGotMin || bGotMax || psOptions->bComputeMinMax )            {                if(!bJson)                    Concat(osStr, psOptions->bStdoutOutput, "  " );                if( bGotMin )                {                    if(bJson)                    {                        json_object *poMin = json_object_new_double_with_precision(dfMin, 3);                        json_object_object_add(poBand, "min", poMin);                    }                    else                        Concat(osStr, psOptions->bStdoutOutput, "Min=%.3f ", dfMin );                }                if( bGotMax )                {                    if(bJson)                    {                        json_object *poMax = json_object_new_double_with_precision(dfMax, 3);                        json_object_object_add(poBand, "max", poMax);                    }                    else                        Concat(osStr, psOptions->bStdoutOutput, "Max=%.3f ", dfMax );                }                if( psOptions->bComputeMinMax )                {                    CPLErrorReset();                    double adfCMinMax[2] = {0.0, 0.0};                    GDALComputeRasterMinMax( hBand, FALSE, adfCMinMax );//强制计算波段最大最小值                    if (CPLGetLastErrorType() == CE_None)                    {                        if(bJson)                        {                            json_object *poComputedMin = json_object_new_double_with_precision(adfCMinMax[0], 3);                            json_object *poComputedMax = json_object_new_double_with_precision(adfCMinMax[1], 3);                            json_object_object_add(poBand, "computedMin", poComputedMin);                            json_object_object_add(poBand, "computedMax", poComputedMax);                        }                        else                            Concat(osStr, psOptions->bStdoutOutput, "  Computed Min/Max=%.3f,%.3f",                              adfCMinMax[0], adfCMinMax[1] );                    }                }                if(!bJson)                    Concat(osStr, psOptions->bStdoutOutput, "\n" );            }        }        double dfMinStat = 0.0;        double dfMaxStat = 0.0;        double dfMean = 0.0;        double dfStdDev = 0.0;        CPLErr eErr = GDALGetRasterStatistics( hBand, psOptions->bApproxStats,                                               psOptions->bStats,                                               &dfMinStat, &dfMaxStat,                                               &dfMean, &dfStdDev );//波段统计        if( eErr == CE_None )        {            if(bJson)            {                json_object *poMinimum = json_object_new_double_with_precision(dfMinStat, 3);                json_object *poMaximum = json_object_new_double_with_precision(dfMaxStat, 3);                json_object *poMean = json_object_new_double_with_precision(dfMean, 3);                json_object *poStdDev = json_object_new_double_with_precision(dfStdDev, 3);                json_object_object_add(poBand, "minimum", poMinimum);                json_object_object_add(poBand, "maximum", poMaximum);                json_object_object_add(poBand, "mean", poMean);                json_object_object_add(poBand, "stdDev", poStdDev);            }            else                Concat(osStr, psOptions->bStdoutOutput, "  Minimum=%.3f, Maximum=%.3f, Mean=%.3f, StdDev=%.3f\n",                    dfMinStat, dfMaxStat, dfMean, dfStdDev );        }        if( psOptions->bReportHistograms )        {            int nBucketCount;            GUIntBig *panHistogram = NULL;            if(bJson)                eErr = GDALGetDefaultHistogramEx( hBand, &dfMinStat, &dfMaxStat,                                                  &nBucketCount, &panHistogram,                                                  TRUE, GDALDummyProgress,                                                  NULL );//获得默认直方图            else                eErr = GDALGetDefaultHistogramEx( hBand, &dfMinStat, &dfMaxStat,                                                  &nBucketCount, &panHistogram,                                                  TRUE, GDALTermProgress,                                                  NULL );            if( eErr == CE_None )            {                json_object *poHistogram = NULL, *poBuckets = NULL;                if(bJson)                {                    json_object *poCount = json_object_new_int(nBucketCount);                    json_object *poMin = json_object_new_double(dfMinStat);                    json_object *poMax = json_object_new_double(dfMaxStat);                    poBuckets = json_object_new_array();                    poHistogram = json_object_new_object();                    json_object_object_add(poHistogram, "count", poCount);                    json_object_object_add(poHistogram, "min", poMin);                    json_object_object_add(poHistogram, "max", poMax);                }                else                    Concat(osStr, psOptions->bStdoutOutput, "  %d buckets from %g to %g:\n  ",                        nBucketCount, dfMinStat, dfMaxStat );                for( int iBucket = 0; iBucket < nBucketCount; iBucket++ )                {//循环显示条带信息                    if(bJson)                    {                        json_object *poBucket = json_object_new_int64(panHistogram[iBucket]);                        json_object_array_add(poBuckets, poBucket);                    }                    else                        Concat(osStr, psOptions->bStdoutOutput, CPL_FRMT_GUIB " ", panHistogram[iBucket] );                }                if(bJson)                {                    json_object_object_add(poHistogram, "buckets", poBuckets);                    json_object_object_add(poBand, "histogram", poHistogram);                }                else                    Concat(osStr, psOptions->bStdoutOutput, "\n" );                CPLFree( panHistogram );            }        }        if ( psOptions->bComputeChecksum)        {            int nBandChecksum = GDALChecksumImage(hBand, 0, 0,                                      GDALGetRasterXSize(hDataset),                                      GDALGetRasterYSize(hDataset));//检校波段            if(bJson)            {                json_object *poChecksum = json_object_new_int(nBandChecksum);                json_object_object_add(poBand, "checksum", poChecksum);            }            else                Concat(osStr, psOptions->bStdoutOutput, "  Checksum=%d\n", nBandChecksum );        }        int bGotNodata = FALSE;        const double dfNoData = GDALGetRasterNoDataValue( hBand, &bGotNodata );//无数据处像素值        if( bGotNodata )        {            if (CPLIsNan(dfNoData))            {                if(bJson)                {                    json_object *poNoDataValue = json_object_new_string("nan");                    json_object_object_add(poBand, "noDataValue", poNoDataValue);                }                else                    Concat(osStr, psOptions->bStdoutOutput, "  NoData Value=nan\n" );            }            else            {                if(bJson)                {                    json_object *poNoDataValue = json_object_new_double_with_precision(dfNoData, 18);                    json_object_object_add(poBand, "noDataValue", poNoDataValue);                }                else                    Concat(osStr, psOptions->bStdoutOutput, "  NoData Value=%.18g\n", dfNoData );            }        }        if( GDALGetOverviewCount(hBand) > 0 )//影像金字塔        {            json_object *poOverviews = NULL;            if(bJson)                poOverviews = json_object_new_array();            else                Concat(osStr, psOptions->bStdoutOutput, "  Overviews: " );            for( int iOverview = 0;                 iOverview < GDALGetOverviewCount(hBand);//####                 iOverview++ )            {                if(!bJson)                    if( iOverview != 0 )                        Concat(osStr, psOptions->bStdoutOutput, ", " );                GDALRasterBandH hOverview = GDALGetOverview( hBand, iOverview );                if (hOverview != NULL)                {                    if(bJson)                    {                        json_object *poOverviewSize = json_object_new_array();                        json_object *poOverviewSizeX = json_object_new_int( GDALGetRasterBandXSize( hOverview) );                        json_object *poOverviewSizeY = json_object_new_int( GDALGetRasterBandYSize( hOverview) );                        json_object *poOverview = json_object_new_object();                        json_object_array_add( poOverviewSize, poOverviewSizeX );                        json_object_array_add( poOverviewSize, poOverviewSizeY );                        json_object_object_add( poOverview, "size", poOverviewSize );                        if(psOptions->bComputeChecksum)                        {                            int nOverviewChecksum = GDALChecksumImage(hOverview, 0, 0,                                        GDALGetRasterBandXSize(hOverview),                                        GDALGetRasterBandYSize(hOverview));                            json_object *poOverviewChecksum = json_object_new_int(nOverviewChecksum);                            json_object_object_add(poOverview, "checksum", poOverviewChecksum);                        }                        json_object_array_add(poOverviews, poOverview);                    }                    else                        Concat(osStr, psOptions->bStdoutOutput, "%dx%d",                            GDALGetRasterBandXSize( hOverview ),                            GDALGetRasterBandYSize( hOverview ) );                    const char *pszResampling                        = GDALGetMetadataItem( hOverview, "RESAMPLING", "" );//元数据项目                    if( pszResampling != NULL && !bJson                        && STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") )                        Concat(osStr, psOptions->bStdoutOutput, "*" );                }                else                    if(!bJson)                        Concat(osStr, psOptions->bStdoutOutput, "(null)" );            }            if(bJson)                json_object_object_add(poBand, "overviews", poOverviews);            else                Concat(osStr, psOptions->bStdoutOutput, "\n" );            if ( psOptions->bComputeChecksum && !bJson )            {                Concat(osStr, psOptions->bStdoutOutput, "  Overviews checksum: " );                for( int iOverview = 0;                     iOverview < GDALGetOverviewCount(hBand);                     iOverview++ )                {                    GDALRasterBandH hOverview;                    if( iOverview != 0 )                        Concat(osStr, psOptions->bStdoutOutput, ", " );                    hOverview = GDALGetOverview( hBand, iOverview );                    if (hOverview)                    {                        Concat(osStr, psOptions->bStdoutOutput, "%d",                                GDALChecksumImage(hOverview, 0, 0,                                        GDALGetRasterBandXSize(hOverview),                                        GDALGetRasterBandYSize(hOverview)));                    }                    else                    {                        Concat(osStr, psOptions->bStdoutOutput, "(null)" );                    }                }                Concat(osStr, psOptions->bStdoutOutput, "\n" );            }        }        if( GDALHasArbitraryOverviews( hBand ) && !bJson )//判断是否存在预览        {            Concat(osStr, psOptions->bStdoutOutput, "  Overviews: arbitrary\n" );        }        const int nMaskFlags = GDALGetMaskFlags( hBand );//获取掩膜标识        if( (nMaskFlags & (GMF_NODATA|GMF_ALL_VALID)) == 0 )        {            GDALRasterBandH hMaskBand = GDALGetMaskBand(hBand) ;//获取掩膜            json_object *poMask = NULL, *poFlags = NULL, *poMaskOverviews = NULL;            if(bJson)            {                poMask = json_object_new_object();                poFlags = json_object_new_array();            }            else                Concat(osStr, psOptions->bStdoutOutput, "  Mask Flags: " );            if( nMaskFlags & GMF_PER_DATASET )            {                if(bJson)                {                    json_object *poFlag = json_object_new_string( "PER_DATASET" );                    json_object_array_add( poFlags, poFlag );                }                else                    Concat(osStr, psOptions->bStdoutOutput, "PER_DATASET " );            }            if( nMaskFlags & GMF_ALPHA )            {                if(bJson)                {                    json_object *poFlag = json_object_new_string( "ALPHA" );                    json_object_array_add( poFlags, poFlag );                }                else                    Concat(osStr, psOptions->bStdoutOutput, "ALPHA " );            }            if( nMaskFlags & GMF_NODATA )            {                if(bJson)                {                    json_object *poFlag = json_object_new_string( "NODATA" );                    json_object_array_add( poFlags, poFlag );                }                else                    Concat(osStr, psOptions->bStdoutOutput, "NODATA " );            }            if( nMaskFlags & GMF_ALL_VALID )            {                if(bJson)                {                    json_object *poFlag = json_object_new_string( "ALL_VALID" );                    json_object_array_add( poFlags, poFlag );                }                else                    Concat(osStr, psOptions->bStdoutOutput, "ALL_VALID " );            }            if(bJson)                json_object_object_add( poMask, "flags", poFlags );            else                Concat(osStr, psOptions->bStdoutOutput, "\n" );            if(bJson)                poMaskOverviews = json_object_new_array();            if( hMaskBand != NULL &&                GDALGetOverviewCount(hMaskBand) > 0 )            {//获取掩膜预览                if(!bJson)                    Concat(osStr, psOptions->bStdoutOutput, "  Overviews of mask band: " );                for( int iOverview = 0;                     iOverview < GDALGetOverviewCount(hMaskBand);                     iOverview++ )                {                    GDALRasterBandH hOverview;                    json_object *poMaskOverview = NULL;                    json_object *poMaskOverviewSize = NULL;                    if(bJson)                    {                        poMaskOverview = json_object_new_object();                        poMaskOverviewSize = json_object_new_array();                    }                    else                    {                        if( iOverview != 0 )                            Concat(osStr, psOptions->bStdoutOutput, ", " );                    }                    hOverview = GDALGetOverview( hMaskBand, iOverview );                    if(bJson)                    {                        json_object *poMaskOverviewSizeX =                            json_object_new_int(GDALGetRasterBandXSize(hOverview));                        json_object *poMaskOverviewSizeY =                            json_object_new_int(GDALGetRasterBandYSize(hOverview));                        json_object_array_add(poMaskOverviewSize, poMaskOverviewSizeX);                        json_object_array_add(poMaskOverviewSize, poMaskOverviewSizeY);                        json_object_object_add(poMaskOverview, "size", poMaskOverviewSize);                        json_object_array_add(poMaskOverviews, poMaskOverview);                    }                    else                        Concat( osStr, psOptions->bStdoutOutput, "%dx%d",                                GDALGetRasterBandXSize( hOverview ),                                GDALGetRasterBandYSize( hOverview ) );                }                if(!bJson)                    Concat(osStr, psOptions->bStdoutOutput, "\n" );            }            if(bJson)            {                json_object_object_add(poMask, "overviews", poMaskOverviews);                json_object_object_add(poBand, "mask", poMask);            }        }        if( strlen(GDALGetRasterUnitType(hBand)) > 0 )        {            if(bJson)            {                json_object *poUnit = json_object_new_string(GDALGetRasterUnitType(hBand));                json_object_object_add(poBand, "unit", poUnit);            }            else                Concat(osStr, psOptions->bStdoutOutput, "  Unit Type: %s\n", GDALGetRasterUnitType(hBand) );//获取栅格单元类型        }        if( GDALGetRasterCategoryNames(hBand) != NULL )        {//获取栅格种类名            char **papszCategories = GDALGetRasterCategoryNames(hBand);            json_object *poCategories = NULL;            if(bJson)                poCategories = json_object_new_array();            else                Concat(osStr, psOptions->bStdoutOutput, "  Categories:\n" );            for( int i = 0; papszCategories[i] != NULL; i++ )            {                if(bJson)                {                    json_object *poCategoryName = json_object_new_string(papszCategories[i]);                    json_object_array_add(poCategories, poCategoryName);                }                else                    Concat(osStr, psOptions->bStdoutOutput, "    %3d: %s\n", i, papszCategories[i] );            }            if(bJson)                json_object_object_add(poBand, "categories", poCategories);        }        int bSuccess = FALSE;        if( GDALGetRasterScale( hBand, &bSuccess ) != 1.0            || GDALGetRasterOffset( hBand, &bSuccess ) != 0.0 )//获取栅格比例尺和偏移量        {            if(bJson)            {                json_object *poOffset = json_object_new_double_with_precision(                    GDALGetRasterOffset(hBand, &bSuccess), 15);                json_object *poScale = json_object_new_double_with_precision(                    GDALGetRasterScale(hBand, &bSuccess), 15);                json_object_object_add(poBand, "offset", poOffset);                json_object_object_add(poBand, "scale", poScale);            }            else                Concat(osStr, psOptions->bStdoutOutput, "  Offset: %.15g,   Scale:%.15g\n",                    GDALGetRasterOffset( hBand, &bSuccess ),                    GDALGetRasterScale( hBand, &bSuccess ) );        }        GDALInfoReportMetadata( psOptions, hBand, true, bJson, poBandMetadata, osStr );//报告波段元数据        if(bJson)        {            if (psOptions->bShowMetadata)                json_object_object_add( poBand, "metadata", poBandMetadata );            else                json_object_put(poBandMetadata);        }        GDALColorTableH hTable;        if( GDALGetRasterColorInterpretation(hBand) == GCI_PaletteIndex            && (hTable = GDALGetRasterColorTable( hBand )) != NULL )//获得颜色索引及色彩表        {            if(!bJson)                Concat( osStr, psOptions->bStdoutOutput,                        "  Color Table (%s with %d entries)\n",                        GDALGetPaletteInterpretationName(                            GDALGetPaletteInterpretation( hTable )),                        GDALGetColorEntryCount( hTable ) );            if (psOptions->bShowColorTable)            {                json_object *poEntries = NULL;                if(bJson)                {                    json_object *poPalette = json_object_new_string(GDALGetPaletteInterpretationName(                        GDALGetPaletteInterpretation(hTable)));                    json_object *poCount = json_object_new_int(GDALGetColorEntryCount(hTable));                    json_object *poColorTable = json_object_new_object();                    json_object_object_add(poColorTable, "palette", poPalette);                    json_object_object_add(poColorTable, "count", poCount);                    poEntries = json_object_new_array();                    json_object_object_add(poColorTable, "entries", poEntries);                    json_object_object_add(poBand, "colorTable", poColorTable);                }                for( int i = 0; i < GDALGetColorEntryCount( hTable ); i++ )//获取颜色记录                {                    GDALColorEntry  sEntry;                    GDALGetColorEntryAsRGB( hTable, i, &sEntry );                    if(bJson)                    {                        json_object *poEntry = json_object_new_array();                        json_object *poC1 = json_object_new_int(sEntry.c1);                        json_object *poC2 = json_object_new_int(sEntry.c2);                        json_object *poC3 = json_object_new_int(sEntry.c3);                        json_object *poC4 = json_object_new_int(sEntry.c4);                        json_object_array_add(poEntry, poC1);                        json_object_array_add(poEntry, poC2);                        json_object_array_add(poEntry, poC3);                        json_object_array_add(poEntry, poC4);                        json_object_array_add(poEntries, poEntry);                    }                    else                        Concat(osStr, psOptions->bStdoutOutput, "  %3d: %d,%d,%d,%d\n",                            i,                            sEntry.c1,                            sEntry.c2,                            sEntry.c3,                            sEntry.c4 );                }            }        }        if( psOptions->bShowRAT && GDALGetDefaultRAT( hBand ) != NULL )        {            GDALRasterAttributeTableH hRAT = GDALGetDefaultRAT( hBand );//获取栅格属性表            if(bJson)            {                json_object *poRAT = (json_object*) GDALRATSerializeJSON( hRAT );                json_object_object_add( poJsonObject, "rat", poRAT );            }            else            {//获取属性表并转化为xml树状信息                CPLXMLNode *psTree = ((GDALRasterAttributeTable *) hRAT)->Serialize();                char *pszXMLText = CPLSerializeXMLTree( psTree );                CPLDestroyXMLNode( psTree );                Concat(osStr, psOptions->bStdoutOutput, "%s\n", pszXMLText );                CPLFree( pszXMLText );            }        }        if(bJson)            json_object_array_add(poBands, poBand);    }    if(bJson)    {        json_object_object_add(poJsonObject, "bands", poBands);        Concat(osStr, psOptions->bStdoutOutput, "%s", json_object_to_json_string_ext(poJsonObject, JSON_C_TO_STRING_PRETTY));        json_object_put(poJsonObject);    }    if( psOptionsToFree != NULL )        GDALInfoOptionsFree(psOptionsToFree);    return VSI_STRDUP_VERBOSE(osStr);}

根据函数名称,我们基本能够推断出函数的作用,从获取关联文件到栅格属性表等等。研究本源码文件更多地是向我们展示了GDAL库设计者们对于库函数的使用范本。

0 0
原创粉丝点击