当前位置:   article > 正文

GDAL工具集(一):gdalinfo工具集_gdalinfo --version提示不是内部命令

gdalinfo --version提示不是内部命令

转载地址:https://blog.csdn.net/hanminaaa/article/details/52204396


目录

 

 


使用方法

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

  1. gdalinfo [--help-general] [-json] [-mm] [-stats] [-hist] [-nogcp] [-nomd]
  2. [-norat] [-noct] [-nofl] [-checksum] [-proj4]
  3. [-listmdd] [-mdd domain|`all`]*
  4. [-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
  • 得到输出
  1. Generic GDAL utility command options:
  2. --version: report version of GDAL in use.
  3. --license: report GDAL license info.
  4. --formats: report all configured format drivers.
  5. --format [format]: details of one format.
  6. --optfile filename: expand an option file into the argument list.
  7. --config key value: set system configuration option.
  8. --debug [on/off/value]: set debug level.
  9. --pause: wait for user input, time to attach debugger
  10. --locale [locale]: install locale for debugging (i.e. en_US.UTF-8)
  11. --help-general: report detailed help on general options.

典例

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

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

得到输出为:

  1. Driver: GTiff/GeoTIFF
  2. Files: E:\exmaple.tif
  3. Size is 200, 400
  4. Coordinate System is:
  5. GEOGCS["WGS 84",
  6. DATUM["WGS_1984",
  7. SPHEROID["WGS 84",6378137,298.257223563,
  8. AUTHORITY["EPSG","7030"]],
  9. AUTHORITY["EPSG","6326"]],
  10. PRIMEM["Greenwich",0],
  11. UNIT["degree",0.0174532925199433],
  12. AUTHORITY["EPSG","4326"]]
  13. PROJ.4 string is:
  14. '+proj=longlat +datum=WGS84 +no_defs '
  15. Origin = (116.438654182485010,40.154364985586007)
  16. Pixel Size = (0.000018000000000,-0.000018000000000)
  17. Metadata:
  18. AREA_OR_POINT=Area
  19. Image Structure Metadata:
  20. INTERLEAVE=PIXEL
  21. Corner Coordinates:
  22. Upper Left ( 116.4386542, 40.1543650)
  23. Lower Left ( 116.4386542, 40.1471650)
  24. Upper Right ( 116.4422542, 40.1543650)
  25. Lower Right ( 116.4422542, 40.1471650)
  26. Center ( 116.4404542, 40.1507650)
  27. Band 1 Block=200x5 Type=UInt16, ColorInterp=Gray
  28. Minimum=0.000, Maximum=0.000, Mean=0.000, StdDev=0.000
  29. Metadata:
  30. STATISTICS_MAXIMUM=0
  31. STATISTICS_MEAN=0
  32. STATISTICS_MINIMUM=0
  33. STATISTICS_STDDEV=0
  34. Band 2 Block=200x5 Type=UInt16, ColorInterp=Undefined
  35. Minimum=0.000, Maximum=0.000, Mean=0.000, StdDev=0.000
  36. Metadata:
  37. STATISTICS_MAXIMUM=0
  38. STATISTICS_MEAN=0
  39. STATISTICS_MINIMUM=0
  40. STATISTICS_STDDEV=0
  41. Band 3 Block=200x5 Type=UInt16, ColorInterp=Undefined
  42. Minimum=0.000, Maximum=0.000, Mean=0.000, StdDev=0.000
  43. Metadata:
  44. STATISTICS_MAXIMUM=0
  45. STATISTICS_MEAN=0
  46. STATISTICS_MINIMUM=0
  47. STATISTICS_STDDEV=0
  48. Band 4 Block=200x5 Type=UInt16, ColorInterp=Undefined
  49. Minimum=0.000, Maximum=0.000, Mean=0.000, StdDev=0.000
  50. Metadata:
  51. STATISTICS_MAXIMUM=0
  52. STATISTICS_MEAN=0
  53. STATISTICS_MINIMUM=0
  54. STATISTICS_STDDEV=0

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


源码分析

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

源码及分析

  1. int main( int argc, char ** argv )
  2. {
  3. EarlySetConfigOptions(argc, argv);//预设置
  4. GDALAllRegister();//注册所有驱动
  5. argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );//命令行参数处理
  6. if( argc < 1 )//如果参数小于1,程序退出
  7. exit( -argc );
  8. for( int i = 0; argv != NULL && argv[i] != NULL; i++ )//参数匹配
  9. {
  10. if( EQUAL(argv[i], "--utility_version") )
  11. {//打印工具版本
  12. printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
  13. argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
  14. CSLDestroy( argv );
  15. return 0;
  16. }
  17. else if( EQUAL(argv[i],"--help") )
  18. {//打印帮助,并退出
  19. Usage();
  20. }
  21. }
  22. argv = CSLAddString(argv, "-stdout");//设置标准输出
  23. GDALInfoOptionsForBinary* psOptionsForBinary = GDALInfoOptionsForBinaryNew();//初始化二值化选项
  24. GDALInfoOptions *psOptions
  25. = GDALInfoOptionsNew(argv + 1, psOptionsForBinary);//**根据字符串数组初始化要显示的信息选项**
  26. if( psOptions == NULL )//如果选项初始化失败,退出
  27. Usage();
  28. if( psOptionsForBinary->pszFilename == NULL )//如果没有指定资源文件,退出
  29. Usage("No datasource specified.");
  30. /* -------------------------------------------------------------------- */
  31. /* 打开数据集. */
  32. /* -------------------------------------------------------------------- */
  33. #ifdef __AFL_HAVE_MANUAL_CONTROL
  34. //**配合下面**
  35. int iIter = 0;
  36. while (__AFL_LOOP(1000)) {
  37. iIter ++;
  38. #endif
  39. GDALDatasetH hDataset
  40. = GDALOpenEx( psOptionsForBinary->pszFilename, GDAL_OF_READONLY | GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR, NULL,
  41. (const char* const* )psOptionsForBinary->papszOpenOptions, NULL );//打开数据集
  42. if( hDataset == NULL )
  43. {
  44. #ifdef __AFL_HAVE_MANUAL_CONTROL
  45. continue;
  46. #else
  47. fprintf( stderr,
  48. "gdalinfo failed - unable to open '%s'.\n",
  49. psOptionsForBinary->pszFilename );
  50. /* -------------------------------------------------------------------- */
  51. /* 如果参数是一个VSI文件, 就打印其内容。 */
  52. /* -------------------------------------------------------------------- */
  53. if ( STARTS_WITH(psOptionsForBinary->pszFilename, "/vsizip/") ||
  54. STARTS_WITH(psOptionsForBinary->pszFilename, "/vsitar/") )
  55. {
  56. char** papszFileList = VSIReadDirRecursive( psOptionsForBinary->pszFilename );
  57. if ( papszFileList )
  58. {
  59. int nCount = CSLCount( papszFileList );
  60. fprintf( stdout,
  61. "Unable to open source `%s' directly.\n"
  62. "The archive contains %d files:\n",
  63. psOptionsForBinary->pszFilename, nCount );
  64. for ( int i = 0; i < nCount; i++ )
  65. {//打印内部文件列表
  66. fprintf( stdout, " %s/%s\n", psOptionsForBinary->pszFilename, papszFileList[i] );
  67. }
  68. CSLDestroy( papszFileList );
  69. }
  70. }
  71. CSLDestroy( argv );//释放参数
  72. GDALInfoOptionsForBinaryFree(psOptionsForBinary);//释放二值化选项
  73. GDALInfoOptionsFree( psOptions );//释放选项占用的内存
  74. GDALDumpOpenDatasets( stderr );//释放打开的数据集
  75. GDALDestroyDriverManager();//释放驱动管理
  76. CPLDumpSharedList( NULL );
  77. exit( 1 );
  78. #endif
  79. }
  80. /* -------------------------------------------------------------------- */
  81. /* 读取特定的文件子数据集. */
  82. /* -------------------------------------------------------------------- */
  83. if ( psOptionsForBinary->nSubdataset > 0 )
  84. {
  85. char **papszSubdatasets = GDALGetMetadata( hDataset, "SUBDATASETS" );
  86. int nSubdatasets = CSLCount( papszSubdatasets );
  87. if ( nSubdatasets > 0 && psOptionsForBinary->nSubdataset <= nSubdatasets )
  88. {
  89. char szKeyName[1024];
  90. char *pszSubdatasetName;
  91. snprintf( szKeyName, sizeof(szKeyName),
  92. "SUBDATASET_%d_NAME", psOptionsForBinary->nSubdataset );
  93. szKeyName[sizeof(szKeyName) - 1] = '\0';
  94. pszSubdatasetName =
  95. CPLStrdup( CSLFetchNameValue( papszSubdatasets, szKeyName ) );
  96. GDALClose( hDataset );//关闭原数据集
  97. hDataset = GDALOpen( pszSubdatasetName, GA_ReadOnly );//打开子数据集
  98. CPLFree( pszSubdatasetName );
  99. }
  100. else
  101. {
  102. fprintf( stderr,
  103. "gdalinfo warning: subdataset %d of %d requested. "
  104. "Reading the main dataset.\n",
  105. psOptionsForBinary->nSubdataset, nSubdatasets );
  106. }
  107. }
  108. char* pszGDALInfoOutput = GDALInfo( hDataset, psOptions );//**核心函数,读取数据集信息**
  109. if( pszGDALInfoOutput )//读取成功则输出
  110. printf( "%s", pszGDALInfoOutput );
  111. CPLFree( pszGDALInfoOutput );//释放输出字符串
  112. GDALClose( hDataset );//关闭数据集
  113. #ifdef __AFL_HAVE_MANUAL_CONTROL
  114. }//**配合上面,组成循环**
  115. #endif
  116. GDALInfoOptionsForBinaryFree(psOptionsForBinary);//释放二值化选项
  117. GDALInfoOptionsFree( psOptions );//释放选项
  118. CSLDestroy( argv );//释放输入参数
  119. GDALDumpOpenDatasets( stderr );//释放打开数据集
  120. GDALDestroyDriverManager();//释放驱动管理
  121. CPLDumpSharedList( NULL );
  122. CPLCleanupTLS();
  123. exit( 0 );
  124. }

流程图

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

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

参数初始化

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

  1. static GDALInfoOptionsForBinary *GDALInfoOptionsForBinaryNew(void)
  2. {
  3. return (GDALInfoOptionsForBinary*) CPLCalloc( 1, sizeof(GDALInfoOptionsForBinary) );
  4. }

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

  1. GDALInfoOptions *GDALInfoOptionsNew(char** papszArgv,
  2. GDALInfoOptionsForBinary* psOptionsForBinary)
  3. {
  4. bool bGotFilename = false;
  5. GDALInfoOptions *psOptions = static_cast<GDALInfoOptions *>(
  6. CPLCalloc( 1, sizeof(GDALInfoOptions) ) );//申请内存
  7. psOptions->eFormat = GDALINFO_FORMAT_TEXT;//默认以文本形式输出
  8. psOptions->bComputeMinMax = FALSE;//默认不计算最大最小值
  9. psOptions->bReportHistograms = FALSE;//默认不报告直方图
  10. psOptions->bReportProj4 = FALSE;//默认不以PROJ4字符报告
  11. psOptions->bStats = FALSE;//默认不统计波段信息
  12. psOptions->bApproxStats = TRUE;//默认开启粗略统计
  13. psOptions->bSample = FALSE;//默认不采样
  14. psOptions->bComputeChecksum = FALSE;//默认不检校
  15. psOptions->bShowGCPs = TRUE;//默认显示控制点
  16. psOptions->bShowMetadata = TRUE;//默认显示主文件元数据
  17. psOptions->bShowRAT = TRUE;//默认显示栅格属性表
  18. psOptions->bShowColorTable = TRUE;//默认显示颜色表
  19. psOptions->bListMDD = FALSE;//默认不显示元数据列表
  20. psOptions->bShowFileList = TRUE;//默认显示文件列表
  21. /* -------------------------------------------------------------------- */
  22. /* 传参. */
  23. /* -------------------------------------------------------------------- */
  24. for( int i = 0; papszArgv != NULL && papszArgv[i] != NULL; i++ )
  25. {
  26. if( EQUAL(papszArgv[i],"-json") )
  27. psOptions->eFormat = GDALINFO_FORMAT_JSON;
  28. else if( EQUAL(papszArgv[i], "-mm") )
  29. psOptions->bComputeMinMax = TRUE;
  30. else if( EQUAL(papszArgv[i], "-hist") )
  31. psOptions->bReportHistograms = TRUE;
  32. else if( EQUAL(papszArgv[i], "-proj4") )
  33. psOptions->bReportProj4 = TRUE;
  34. else if( EQUAL(papszArgv[i], "-stats") )
  35. {
  36. psOptions->bStats = TRUE;
  37. psOptions->bApproxStats = FALSE;
  38. }
  39. else if( EQUAL(papszArgv[i], "-approx_stats") )
  40. {
  41. psOptions->bStats = TRUE;
  42. psOptions->bApproxStats = TRUE;
  43. }
  44. else if( EQUAL(papszArgv[i], "-sample") )
  45. psOptions->bSample = TRUE;
  46. else if( EQUAL(papszArgv[i], "-checksum") )
  47. psOptions->bComputeChecksum = TRUE;
  48. else if( EQUAL(papszArgv[i], "-nogcp") )
  49. psOptions->bShowGCPs = FALSE;
  50. else if( EQUAL(papszArgv[i], "-nomd") )
  51. psOptions->bShowMetadata = FALSE;
  52. else if( EQUAL(papszArgv[i], "-norat") )
  53. psOptions->bShowRAT = FALSE;
  54. else if( EQUAL(papszArgv[i], "-noct") )
  55. psOptions->bShowColorTable = FALSE;
  56. else if( EQUAL(papszArgv[i], "-listmdd") )
  57. psOptions->bListMDD = TRUE;
  58. /* Not documented: used by gdalinfo_bin.cpp only */
  59. else if( EQUAL(papszArgv[i], "-stdout") )
  60. psOptions->bStdoutOutput = true;
  61. else if( EQUAL(papszArgv[i], "-mdd") && papszArgv[i+1] != NULL )
  62. {//设定要获取的属于该文件的元数据
  63. psOptions->papszExtraMDDomains = CSLAddString(
  64. psOptions->papszExtraMDDomains, papszArgv[++i] );
  65. }
  66. else if( EQUAL(papszArgv[i], "-oo") && papszArgv[i+1] != NULL )
  67. {//设定属性
  68. i++;
  69. if( psOptionsForBinary )
  70. {
  71. psOptionsForBinary->papszOpenOptions = CSLAddString(
  72. psOptionsForBinary->papszOpenOptions, papszArgv[i] );
  73. }
  74. }
  75. else if( EQUAL(papszArgv[i], "-nofl") )
  76. psOptions->bShowFileList = FALSE;
  77. else if( EQUAL(papszArgv[i], "-sd") && papszArgv[i+1] != NULL )
  78. {//子数据集
  79. i++;
  80. if( psOptionsForBinary )
  81. {
  82. psOptionsForBinary->nSubdataset = atoi(papszArgv[i]);
  83. }
  84. }
  85. else if( papszArgv[i][0] == '-' )
  86. {//错误选项处理
  87. CPLError(CE_Failure, CPLE_NotSupported,
  88. "Unknown option name '%s'", papszArgv[i]);
  89. GDALInfoOptionsFree(psOptions);
  90. return NULL;
  91. }
  92. else if( !bGotFilename )
  93. {//输入文件名称
  94. bGotFilename = true;
  95. if( psOptionsForBinary )
  96. psOptionsForBinary->pszFilename = CPLStrdup(papszArgv[i]);
  97. }
  98. else
  99. {
  100. CPLError(CE_Failure, CPLE_NotSupported,
  101. "Too many command options '%s'", papszArgv[i]);
  102. GDALInfoOptionsFree(psOptions);
  103. return NULL;
  104. }
  105. }
  106. return psOptions;
  107. }

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

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

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

  1. int GDALValidateOpenOptions( GDALDriverH hDriver,
  2. const char* const* papszOpenOptions)
  3. {
  4. VALIDATE_POINTER1( hDriver, "GDALValidateOpenOptions", FALSE );
  5. const char *pszOptionList =
  6. ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_OPENOPTIONLIST );
  7. CPLString osDriver;
  8. osDriver.Printf("driver %s", ((GDALDriver *) hDriver)->GetDescription());
  9. return GDALValidateOptions( pszOptionList, papszOpenOptions,
  10. "open option",
  11. osDriver);
  12. }

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

读取信息主函数

先上源码:

  1. char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
  2. {
  3. if( hDataset == NULL )
  4. return NULL;
  5. GDALInfoOptions* psOptionsToFree = NULL;
  6. if( psOptions == NULL )
  7. {//初始化信息选项
  8. psOptionsToFree = GDALInfoOptionsNew(NULL, NULL);
  9. psOptions = psOptionsToFree;
  10. }
  11. CPLString osStr;
  12. json_object *poJsonObject = NULL, *poBands = NULL, *poMetadata = NULL;
  13. const bool bJson = psOptions->eFormat == GDALINFO_FORMAT_JSON;//先判断后赋值
  14. /* -------------------------------------------------------------------- */
  15. /* 报告通常信息. */
  16. /* -------------------------------------------------------------------- */
  17. GDALDriverH hDriver = GDALGetDatasetDriver( hDataset );//获取驱动
  18. if(bJson)
  19. {
  20. json_object *poDescription = json_object_new_string(GDALGetDescription(hDataset));//获取描述
  21. json_object *poDriverShortName = json_object_new_string(GDALGetDriverShortName(hDriver));//驱动简称
  22. json_object *poDriverLongName = json_object_new_string(GDALGetDriverLongName(hDriver));//驱动全称
  23. poJsonObject = json_object_new_object();
  24. poBands = json_object_new_array();
  25. poMetadata = json_object_new_object();
  26. json_object_object_add(poJsonObject, "description", poDescription);
  27. json_object_object_add(poJsonObject, "driverShortName", poDriverShortName);
  28. json_object_object_add(poJsonObject, "driverLongName", poDriverLongName);
  29. }
  30. else
  31. {
  32. Concat( osStr, psOptions->bStdoutOutput, "Driver: %s/%s\n",
  33. GDALGetDriverShortName( hDriver ),
  34. GDALGetDriverLongName( hDriver ) );
  35. }//这是一个链接输出项目形成输出字符串的函数
  36. char **papszFileList = GDALGetFileList( hDataset );
  37. if( papszFileList == NULL || *papszFileList == NULL )
  38. {
  39. if(bJson)
  40. {
  41. json_object *poFiles = json_object_new_array();
  42. json_object_object_add(poJsonObject, "files", poFiles);//文件列表json
  43. }
  44. else
  45. Concat( osStr, psOptions->bStdoutOutput,
  46. "Files: none associated\n" );
  47. }
  48. else
  49. {
  50. if(bJson)
  51. {
  52. if( psOptions->bShowFileList )
  53. {
  54. json_object *poFiles = json_object_new_array();
  55. for(int i = 0; papszFileList[i] != NULL; i++)
  56. {
  57. json_object *poFile = json_object_new_string(papszFileList[i]);
  58. json_object_array_add(poFiles, poFile);
  59. }
  60. json_object_object_add(poJsonObject, "files", poFiles);
  61. }
  62. }
  63. else
  64. {
  65. Concat(osStr, psOptions->bStdoutOutput, "Files: %s\n", papszFileList[0] );
  66. if( psOptions->bShowFileList )
  67. {
  68. for( int i = 1; papszFileList[i] != NULL; i++ )
  69. Concat(osStr, psOptions->bStdoutOutput, " %s\n", papszFileList[i] );
  70. }
  71. }
  72. }
  73. CSLDestroy( papszFileList );
  74. if(bJson)
  75. {
  76. json_object *poSize = json_object_new_array();
  77. json_object *poSizeX = json_object_new_int(GDALGetRasterXSize(hDataset));
  78. json_object *poSizeY = json_object_new_int(GDALGetRasterYSize(hDataset));
  79. json_object_array_add(poSize, poSizeX);
  80. json_object_array_add(poSize, poSizeY);
  81. json_object_object_add(poJsonObject, "size", poSize);
  82. }
  83. else
  84. Concat(osStr, psOptions->bStdoutOutput, "Size is %d, %d\n", GDALGetRasterXSize( hDataset ),
  85. GDALGetRasterYSize( hDataset ) );//栅格图像大小
  86. /* -------------------------------------------------------------------- */
  87. /* 报告投影信息. */
  88. /* -------------------------------------------------------------------- */
  89. if( GDALGetProjectionRef( hDataset ) != NULL )
  90. {
  91. json_object *poCoordinateSystem = NULL;
  92. if(bJson)
  93. poCoordinateSystem = json_object_new_object();
  94. char *pszProjection
  95. = const_cast<char *>( GDALGetProjectionRef( hDataset ) );
  96. OGRSpatialReferenceH hSRS
  97. = OSRNewSpatialReference(NULL);
  98. if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None )//尝试转化OGR参考系
  99. {
  100. char *pszPrettyWkt = NULL;
  101. OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE );
  102. if(bJson)
  103. {
  104. json_object *poWkt = json_object_new_string(pszPrettyWkt);
  105. json_object_object_add(poCoordinateSystem, "wkt", poWkt);
  106. }
  107. else
  108. Concat( osStr, psOptions->bStdoutOutput,
  109. "Coordinate System is:\n%s\n",
  110. pszPrettyWkt );
  111. CPLFree( pszPrettyWkt );
  112. }
  113. else
  114. {
  115. if(bJson)
  116. {
  117. json_object *poWkt = json_object_new_string(GDALGetProjectionRef(hDataset));
  118. json_object_object_add(poCoordinateSystem, "wkt", poWkt);
  119. }
  120. else
  121. Concat( osStr, psOptions->bStdoutOutput,
  122. "Coordinate System is `%s'\n",
  123. GDALGetProjectionRef( hDataset ) );//直接输出
  124. }
  125. if ( psOptions->bReportProj4 )
  126. {
  127. char *pszProj4 = NULL;
  128. OSRExportToProj4( hSRS, &pszProj4 );//转换为PROJ4格式
  129. if(bJson)
  130. {
  131. json_object *proj4 = json_object_new_string(pszProj4);
  132. json_object_object_add(poCoordinateSystem, "proj4", proj4);
  133. }
  134. else
  135. Concat(osStr, psOptions->bStdoutOutput, "PROJ.4 string is:\n\'%s\'\n",pszProj4);
  136. CPLFree( pszProj4 );
  137. }
  138. if(bJson)
  139. json_object_object_add(poJsonObject, "coordinateSystem", poCoordinateSystem);
  140. OSRDestroySpatialReference( hSRS );
  141. }
  142. /* -------------------------------------------------------------------- */
  143. /* 报告地理转换参数. */
  144. /* -------------------------------------------------------------------- */
  145. double adfGeoTransform[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
  146. if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )//地理转换参数赋值
  147. {
  148. if(bJson)
  149. {
  150. json_object *poGeoTransform = json_object_new_array();
  151. for( int i = 0; i < 6; i++ )
  152. {
  153. json_object *poGeoTransformCoefficient = json_object_new_double_with_precision(adfGeoTransform[i], 16);
  154. json_object_array_add(poGeoTransform, poGeoTransformCoefficient);
  155. }
  156. json_object_object_add(poJsonObject, "geoTransform", poGeoTransform);
  157. }
  158. else
  159. {
  160. if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0 )
  161. {//如果图像未旋转
  162. Concat( osStr, psOptions->bStdoutOutput,
  163. "Origin = (%.15f,%.15f)\n",
  164. adfGeoTransform[0], adfGeoTransform[3] );//左上角像元地理坐标
  165. Concat( osStr, psOptions->bStdoutOutput,
  166. "Pixel Size = (%.15f,%.15f)\n",
  167. adfGeoTransform[1], adfGeoTransform[5] );//像元大小
  168. }
  169. else
  170. Concat( osStr, psOptions->bStdoutOutput, "GeoTransform =\n"
  171. " %.16g, %.16g, %.16g\n"
  172. " %.16g, %.16g, %.16g\n",
  173. adfGeoTransform[0],
  174. adfGeoTransform[1],
  175. adfGeoTransform[2],
  176. adfGeoTransform[3],
  177. adfGeoTransform[4],
  178. adfGeoTransform[5] );//顺序输出
  179. }
  180. }
  181. /* -------------------------------------------------------------------- */
  182. /* 报告地面控制点. */
  183. /* -------------------------------------------------------------------- */
  184. if( psOptions->bShowGCPs && GDALGetGCPCount( hDataset ) > 0 )
  185. {
  186. json_object * const poGCPs = bJson ? json_object_new_object() : NULL;
  187. if (GDALGetGCPProjection(hDataset) != NULL)//获取地面控制点投影
  188. {
  189. json_object *poGCPCoordinateSystem = NULL;
  190. char *pszProjection
  191. = const_cast<char *>( GDALGetGCPProjection( hDataset ) );
  192. OGRSpatialReferenceH hSRS
  193. = OSRNewSpatialReference(NULL);
  194. if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None )
  195. {
  196. char *pszPrettyWkt = NULL;
  197. OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE );
  198. if(bJson)
  199. {
  200. json_object *poWkt = json_object_new_string(pszPrettyWkt);
  201. poGCPCoordinateSystem = json_object_new_object();
  202. json_object_object_add(poGCPCoordinateSystem, "wkt", poWkt);
  203. }
  204. else
  205. Concat(osStr, psOptions->bStdoutOutput, "GCP Projection = \n%s\n", pszPrettyWkt );
  206. CPLFree( pszPrettyWkt );
  207. }
  208. else
  209. {
  210. if(bJson)
  211. {
  212. json_object *poWkt = json_object_new_string(GDALGetGCPProjection(hDataset));
  213. poGCPCoordinateSystem = json_object_new_object();
  214. json_object_object_add(poGCPCoordinateSystem, "wkt", poWkt);
  215. }
  216. else
  217. Concat(osStr, psOptions->bStdoutOutput, "GCP Projection = %s\n",
  218. GDALGetGCPProjection( hDataset ) );
  219. }
  220. if(bJson)
  221. json_object_object_add(poGCPs, "coordinateSystem", poGCPCoordinateSystem);
  222. OSRDestroySpatialReference( hSRS );
  223. }
  224. json_object * const poGCPList = bJson ? json_object_new_array() : NULL;
  225. for( int i = 0; i < GDALGetGCPCount(hDataset); i++ )
  226. {
  227. const GDAL_GCP *psGCP = GDALGetGCPs( hDataset ) + i;//地面控制点
  228. if(bJson)
  229. {
  230. json_object *poGCP = json_object_new_object();
  231. json_object *poId = json_object_new_string(psGCP->pszId);
  232. json_object *poInfo = json_object_new_string(psGCP->pszInfo);
  233. json_object *poPixel = json_object_new_double_with_precision(psGCP->dfGCPPixel, 15);
  234. json_object *poLine = json_object_new_double_with_precision(psGCP->dfGCPLine, 15);
  235. json_object *poX = json_object_new_double_with_precision(psGCP->dfGCPX, 15);
  236. json_object *poY = json_object_new_double_with_precision(psGCP->dfGCPY, 15);
  237. json_object *poZ = json_object_new_double_with_precision(psGCP->dfGCPZ, 15);
  238. json_object_object_add(poGCP, "id", poId);
  239. json_object_object_add(poGCP, "info", poInfo);
  240. json_object_object_add(poGCP, "pixel", poPixel);
  241. json_object_object_add(poGCP, "line", poLine);
  242. json_object_object_add(poGCP, "x", poX);
  243. json_object_object_add(poGCP, "y", poY);
  244. json_object_object_add(poGCP, "z", poZ);
  245. json_object_array_add(poGCPList, poGCP);
  246. }
  247. else
  248. Concat(osStr, psOptions->bStdoutOutput, "GCP[%3d]: Id=%s, Info=%s\n"
  249. " (%.15g,%.15g) -> (%.15g,%.15g,%.15g)\n",
  250. i, psGCP->pszId, psGCP->pszInfo,
  251. psGCP->dfGCPPixel, psGCP->dfGCPLine,
  252. psGCP->dfGCPX, psGCP->dfGCPY, psGCP->dfGCPZ );//控制点信息输出
  253. }
  254. if(bJson)
  255. {
  256. json_object_object_add(poGCPs, "gcpList", poGCPList);
  257. json_object_object_add(poJsonObject, "gcps", poGCPs);
  258. }
  259. }
  260. /* -------------------------------------------------------------------- */
  261. /* 报告数据集元数据. */
  262. /* -------------------------------------------------------------------- */
  263. GDALInfoReportMetadata( psOptions, hDataset, false, bJson, poMetadata, osStr );//元数据信息获取函数(数据集)
  264. if(bJson)
  265. {
  266. if( psOptions->bShowMetadata )
  267. json_object_object_add( poJsonObject, "metadata", poMetadata );
  268. else
  269. json_object_put(poMetadata);
  270. }
  271. /* -------------------------------------------------------------------- */
  272. /* 如果合适,设置经纬度投影转换. */
  273. /* -------------------------------------------------------------------- */
  274. const char *pszProjection = NULL;
  275. if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
  276. pszProjection = GDALGetProjectionRef(hDataset);
  277. OGRCoordinateTransformationH hTransform = NULL;
  278. OGRCoordinateTransformationH hTransformWGS84 = NULL;
  279. if( pszProjection != NULL && strlen(pszProjection) > 0 )
  280. {
  281. OGRSpatialReferenceH hProj, hLatLong = NULL, hLatLongWGS84 = NULL;
  282. hProj = OSRNewSpatialReference( pszProjection );
  283. if( hProj != NULL )
  284. {
  285. hLatLong = OSRCloneGeogCS( hProj );
  286. if(bJson)
  287. {
  288. hLatLongWGS84 = OSRNewSpatialReference( NULL );
  289. OSRSetWellKnownGeogCS( hLatLongWGS84, "WGS84" );
  290. }
  291. }
  292. if( hLatLong != NULL )
  293. {
  294. CPLPushErrorHandler( CPLQuietErrorHandler );
  295. hTransform = OCTNewCoordinateTransformation( hProj, hLatLong );//坐标转换信息
  296. CPLPopErrorHandler();
  297. OSRDestroySpatialReference( hLatLong );
  298. }
  299. if( hLatLongWGS84 != NULL )
  300. {
  301. CPLPushErrorHandler( CPLQuietErrorHandler );
  302. hTransformWGS84 = OCTNewCoordinateTransformation( hProj, hLatLongWGS84 );
  303. CPLPopErrorHandler();
  304. OSRDestroySpatialReference( hLatLongWGS84 );
  305. }
  306. if( hProj != NULL )
  307. OSRDestroySpatialReference( hProj );
  308. }
  309. /* -------------------------------------------------------------------- */
  310. /* 报告边角信息. */
  311. /* -------------------------------------------------------------------- */
  312. if(bJson)
  313. {
  314. json_object *poLinearRing = json_object_new_array();
  315. json_object *poCornerCoordinates = json_object_new_object();
  316. json_object *poWGS84Extent = json_object_new_object();
  317. json_object *poWGS84ExtentType = json_object_new_string("Polygon");
  318. json_object *poWGS84ExtentCoordinates = json_object_new_array();
  319. GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "upperLeft",
  320. 0.0, 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );//边角报告函数
  321. GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "lowerLeft",
  322. 0.0, GDALGetRasterYSize(hDataset), bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
  323. GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "upperRight",
  324. GDALGetRasterXSize(hDataset), 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
  325. GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "lowerRight",
  326. GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset),
  327. bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
  328. GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "center",
  329. GDALGetRasterXSize(hDataset)/2.0, GDALGetRasterYSize(hDataset)/2.0,
  330. bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
  331. GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "upperLeft",
  332. 0.0, 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
  333. json_object_object_add( poJsonObject, "cornerCoordinates", poCornerCoordinates );
  334. json_object_object_add( poWGS84Extent, "type", poWGS84ExtentType );
  335. json_object_array_add( poLinearRing, poWGS84ExtentCoordinates );
  336. json_object_object_add( poWGS84Extent, "coordinates", poLinearRing );
  337. json_object_object_add( poJsonObject, "wgs84Extent", poWGS84Extent );
  338. }
  339. else
  340. {
  341. Concat(osStr, psOptions->bStdoutOutput, "Corner Coordinates:\n" );
  342. GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Upper Left",
  343. 0.0, 0.0, bJson, NULL, NULL, osStr );
  344. GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Lower Left",
  345. 0.0, GDALGetRasterYSize(hDataset), bJson, NULL, NULL, osStr );
  346. GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Upper Right",
  347. GDALGetRasterXSize(hDataset), 0.0, bJson, NULL, NULL, osStr );
  348. GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Lower Right",
  349. GDALGetRasterXSize(hDataset),
  350. GDALGetRasterYSize(hDataset), bJson, NULL, NULL, osStr );
  351. GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Center",
  352. GDALGetRasterXSize(hDataset)/2.0,
  353. GDALGetRasterYSize(hDataset)/2.0, bJson, NULL, NULL, osStr );
  354. }
  355. if( hTransform != NULL )
  356. {
  357. OCTDestroyCoordinateTransformation( hTransform );
  358. hTransform = NULL;
  359. }
  360. if( hTransformWGS84 != NULL )
  361. {
  362. OCTDestroyCoordinateTransformation( hTransformWGS84 );
  363. hTransformWGS84 = NULL;
  364. }
  365. /* ==================================================================== */
  366. /* 循环处理波段. */
  367. /* ==================================================================== */
  368. for( int iBand = 0; iBand < GDALGetRasterCount( hDataset ); iBand++ )
  369. {
  370. json_object *poBand = NULL;
  371. json_object *poBandMetadata = NULL;
  372. if(bJson)
  373. {
  374. poBand = json_object_new_object();
  375. poBandMetadata = json_object_new_object();
  376. }
  377. GDALRasterBandH const hBand = GDALGetRasterBand( hDataset, iBand+1 );
  378. //获取波段
  379. if( psOptions->bSample )
  380. {//采样统计判断
  381. vector<float> ofSample(10000, 0);
  382. float * const pafSample = &ofSample[0];
  383. const int nCount =
  384. GDALGetRandomRasterSample( hBand, 10000, pafSample );//采样
  385. if(!bJson)
  386. Concat( osStr, psOptions->bStdoutOutput,
  387. "Got %d samples.\n", nCount );
  388. }
  389. int nBlockXSize = 0;
  390. int nBlockYSize = 0;
  391. GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );//获取波段数据块大小
  392. if(bJson)
  393. {
  394. json_object *poBandNumber = json_object_new_int(iBand+1);
  395. json_object *poBlock = json_object_new_array();
  396. json_object *poType = json_object_new_string(GDALGetDataTypeName(GDALGetRasterDataType(hBand)));//获取数据类型说明
  397. json_object *poColorInterp = json_object_new_string(GDALGetColorInterpretationName(
  398. GDALGetRasterColorInterpretation(hBand)));//获取波段说明
  399. json_object_array_add(poBlock, json_object_new_int(nBlockXSize));
  400. json_object_array_add(poBlock, json_object_new_int(nBlockYSize));
  401. json_object_object_add(poBand, "band", poBandNumber);
  402. json_object_object_add(poBand, "block", poBlock);
  403. json_object_object_add(poBand, "type", poType);
  404. json_object_object_add(poBand, "colorInterpretation", poColorInterp);
  405. }
  406. else
  407. Concat( osStr, psOptions->bStdoutOutput,
  408. "Band %d Block=%dx%d Type=%s, ColorInterp=%s\n",
  409. iBand+1,
  410. nBlockXSize, nBlockYSize,
  411. GDALGetDataTypeName(
  412. GDALGetRasterDataType(hBand)),
  413. GDALGetColorInterpretationName(
  414. GDALGetRasterColorInterpretation(hBand)) );
  415. if( GDALGetDescription( hBand ) != NULL
  416. && strlen(GDALGetDescription( hBand )) > 0 )
  417. {
  418. if(bJson)
  419. {
  420. json_object *poBandDescription = json_object_new_string(GDALGetDescription(hBand));
  421. json_object_object_add(poBand, "description", poBandDescription);
  422. }
  423. else
  424. Concat( osStr, psOptions->bStdoutOutput, " Description = %s\n",
  425. GDALGetDescription(hBand) );//波段说明
  426. }
  427. {
  428. int bGotMin = FALSE;
  429. int bGotMax = FALSE;
  430. const double dfMin = GDALGetRasterMinimum( hBand, &bGotMin );//获取波段最小值
  431. const double dfMax = GDALGetRasterMaximum( hBand, &bGotMax );//获取波段最大值
  432. if( bGotMin || bGotMax || psOptions->bComputeMinMax )
  433. {
  434. if(!bJson)
  435. Concat(osStr, psOptions->bStdoutOutput, " " );
  436. if( bGotMin )
  437. {
  438. if(bJson)
  439. {
  440. json_object *poMin = json_object_new_double_with_precision(dfMin, 3);
  441. json_object_object_add(poBand, "min", poMin);
  442. }
  443. else
  444. Concat(osStr, psOptions->bStdoutOutput, "Min=%.3f ", dfMin );
  445. }
  446. if( bGotMax )
  447. {
  448. if(bJson)
  449. {
  450. json_object *poMax = json_object_new_double_with_precision(dfMax, 3);
  451. json_object_object_add(poBand, "max", poMax);
  452. }
  453. else
  454. Concat(osStr, psOptions->bStdoutOutput, "Max=%.3f ", dfMax );
  455. }
  456. if( psOptions->bComputeMinMax )
  457. {
  458. CPLErrorReset();
  459. double adfCMinMax[2] = {0.0, 0.0};
  460. GDALComputeRasterMinMax( hBand, FALSE, adfCMinMax );//强制计算波段最大最小值
  461. if (CPLGetLastErrorType() == CE_None)
  462. {
  463. if(bJson)
  464. {
  465. json_object *poComputedMin = json_object_new_double_with_precision(adfCMinMax[0], 3);
  466. json_object *poComputedMax = json_object_new_double_with_precision(adfCMinMax[1], 3);
  467. json_object_object_add(poBand, "computedMin", poComputedMin);
  468. json_object_object_add(poBand, "computedMax", poComputedMax);
  469. }
  470. else
  471. Concat(osStr, psOptions->bStdoutOutput, " Computed Min/Max=%.3f,%.3f",
  472. adfCMinMax[0], adfCMinMax[1] );
  473. }
  474. }
  475. if(!bJson)
  476. Concat(osStr, psOptions->bStdoutOutput, "\n" );
  477. }
  478. }
  479. double dfMinStat = 0.0;
  480. double dfMaxStat = 0.0;
  481. double dfMean = 0.0;
  482. double dfStdDev = 0.0;
  483. CPLErr eErr = GDALGetRasterStatistics( hBand, psOptions->bApproxStats,
  484. psOptions->bStats,
  485. &dfMinStat, &dfMaxStat,
  486. &dfMean, &dfStdDev );//波段统计
  487. if( eErr == CE_None )
  488. {
  489. if(bJson)
  490. {
  491. json_object *poMinimum = json_object_new_double_with_precision(dfMinStat, 3);
  492. json_object *poMaximum = json_object_new_double_with_precision(dfMaxStat, 3);
  493. json_object *poMean = json_object_new_double_with_precision(dfMean, 3);
  494. json_object *poStdDev = json_object_new_double_with_precision(dfStdDev, 3);
  495. json_object_object_add(poBand, "minimum", poMinimum);
  496. json_object_object_add(poBand, "maximum", poMaximum);
  497. json_object_object_add(poBand, "mean", poMean);
  498. json_object_object_add(poBand, "stdDev", poStdDev);
  499. }
  500. else
  501. Concat(osStr, psOptions->bStdoutOutput, " Minimum=%.3f, Maximum=%.3f, Mean=%.3f, StdDev=%.3f\n",
  502. dfMinStat, dfMaxStat, dfMean, dfStdDev );
  503. }
  504. if( psOptions->bReportHistograms )
  505. {
  506. int nBucketCount;
  507. GUIntBig *panHistogram = NULL;
  508. if(bJson)
  509. eErr = GDALGetDefaultHistogramEx( hBand, &dfMinStat, &dfMaxStat,
  510. &nBucketCount, &panHistogram,
  511. TRUE, GDALDummyProgress,
  512. NULL );//获得默认直方图
  513. else
  514. eErr = GDALGetDefaultHistogramEx( hBand, &dfMinStat, &dfMaxStat,
  515. &nBucketCount, &panHistogram,
  516. TRUE, GDALTermProgress,
  517. NULL );
  518. if( eErr == CE_None )
  519. {
  520. json_object *poHistogram = NULL, *poBuckets = NULL;
  521. if(bJson)
  522. {
  523. json_object *poCount = json_object_new_int(nBucketCount);
  524. json_object *poMin = json_object_new_double(dfMinStat);
  525. json_object *poMax = json_object_new_double(dfMaxStat);
  526. poBuckets = json_object_new_array();
  527. poHistogram = json_object_new_object();
  528. json_object_object_add(poHistogram, "count", poCount);
  529. json_object_object_add(poHistogram, "min", poMin);
  530. json_object_object_add(poHistogram, "max", poMax);
  531. }
  532. else
  533. Concat(osStr, psOptions->bStdoutOutput, " %d buckets from %g to %g:\n ",
  534. nBucketCount, dfMinStat, dfMaxStat );
  535. for( int iBucket = 0; iBucket < nBucketCount; iBucket++ )
  536. {//循环显示条带信息
  537. if(bJson)
  538. {
  539. json_object *poBucket = json_object_new_int64(panHistogram[iBucket]);
  540. json_object_array_add(poBuckets, poBucket);
  541. }
  542. else
  543. Concat(osStr, psOptions->bStdoutOutput, CPL_FRMT_GUIB " ", panHistogram[iBucket] );
  544. }
  545. if(bJson)
  546. {
  547. json_object_object_add(poHistogram, "buckets", poBuckets);
  548. json_object_object_add(poBand, "histogram", poHistogram);
  549. }
  550. else
  551. Concat(osStr, psOptions->bStdoutOutput, "\n" );
  552. CPLFree( panHistogram );
  553. }
  554. }
  555. if ( psOptions->bComputeChecksum)
  556. {
  557. int nBandChecksum = GDALChecksumImage(hBand, 0, 0,
  558. GDALGetRasterXSize(hDataset),
  559. GDALGetRasterYSize(hDataset));//检校波段
  560. if(bJson)
  561. {
  562. json_object *poChecksum = json_object_new_int(nBandChecksum);
  563. json_object_object_add(poBand, "checksum", poChecksum);
  564. }
  565. else
  566. Concat(osStr, psOptions->bStdoutOutput, " Checksum=%d\n", nBandChecksum );
  567. }
  568. int bGotNodata = FALSE;
  569. const double dfNoData = GDALGetRasterNoDataValue( hBand, &bGotNodata );//无数据处像素值
  570. if( bGotNodata )
  571. {
  572. if (CPLIsNan(dfNoData))
  573. {
  574. if(bJson)
  575. {
  576. json_object *poNoDataValue = json_object_new_string("nan");
  577. json_object_object_add(poBand, "noDataValue", poNoDataValue);
  578. }
  579. else
  580. Concat(osStr, psOptions->bStdoutOutput, " NoData Value=nan\n" );
  581. }
  582. else
  583. {
  584. if(bJson)
  585. {
  586. json_object *poNoDataValue = json_object_new_double_with_precision(dfNoData, 18);
  587. json_object_object_add(poBand, "noDataValue", poNoDataValue);
  588. }
  589. else
  590. Concat(osStr, psOptions->bStdoutOutput, " NoData Value=%.18g\n", dfNoData );
  591. }
  592. }
  593. if( GDALGetOverviewCount(hBand) > 0 )//影像金字塔
  594. {
  595. json_object *poOverviews = NULL;
  596. if(bJson)
  597. poOverviews = json_object_new_array();
  598. else
  599. Concat(osStr, psOptions->bStdoutOutput, " Overviews: " );
  600. for( int iOverview = 0;
  601. iOverview < GDALGetOverviewCount(hBand);//####
  602. iOverview++ )
  603. {
  604. if(!bJson)
  605. if( iOverview != 0 )
  606. Concat(osStr, psOptions->bStdoutOutput, ", " );
  607. GDALRasterBandH hOverview = GDALGetOverview( hBand, iOverview );
  608. if (hOverview != NULL)
  609. {
  610. if(bJson)
  611. {
  612. json_object *poOverviewSize = json_object_new_array();
  613. json_object *poOverviewSizeX = json_object_new_int( GDALGetRasterBandXSize( hOverview) );
  614. json_object *poOverviewSizeY = json_object_new_int( GDALGetRasterBandYSize( hOverview) );
  615. json_object *poOverview = json_object_new_object();
  616. json_object_array_add( poOverviewSize, poOverviewSizeX );
  617. json_object_array_add( poOverviewSize, poOverviewSizeY );
  618. json_object_object_add( poOverview, "size", poOverviewSize );
  619. if(psOptions->bComputeChecksum)
  620. {
  621. int nOverviewChecksum = GDALChecksumImage(hOverview, 0, 0,
  622. GDALGetRasterBandXSize(hOverview),
  623. GDALGetRasterBandYSize(hOverview));
  624. json_object *poOverviewChecksum = json_object_new_int(nOverviewChecksum);
  625. json_object_object_add(poOverview, "checksum", poOverviewChecksum);
  626. }
  627. json_object_array_add(poOverviews, poOverview);
  628. }
  629. else
  630. Concat(osStr, psOptions->bStdoutOutput, "%dx%d",
  631. GDALGetRasterBandXSize( hOverview ),
  632. GDALGetRasterBandYSize( hOverview ) );
  633. const char *pszResampling
  634. = GDALGetMetadataItem( hOverview, "RESAMPLING", "" );//元数据项目
  635. if( pszResampling != NULL && !bJson
  636. && STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") )
  637. Concat(osStr, psOptions->bStdoutOutput, "*" );
  638. }
  639. else
  640. if(!bJson)
  641. Concat(osStr, psOptions->bStdoutOutput, "(null)" );
  642. }
  643. if(bJson)
  644. json_object_object_add(poBand, "overviews", poOverviews);
  645. else
  646. Concat(osStr, psOptions->bStdoutOutput, "\n" );
  647. if ( psOptions->bComputeChecksum && !bJson )
  648. {
  649. Concat(osStr, psOptions->bStdoutOutput, " Overviews checksum: " );
  650. for( int iOverview = 0;
  651. iOverview < GDALGetOverviewCount(hBand);
  652. iOverview++ )
  653. {
  654. GDALRasterBandH hOverview;
  655. if( iOverview != 0 )
  656. Concat(osStr, psOptions->bStdoutOutput, ", " );
  657. hOverview = GDALGetOverview( hBand, iOverview );
  658. if (hOverview)
  659. {
  660. Concat(osStr, psOptions->bStdoutOutput, "%d",
  661. GDALChecksumImage(hOverview, 0, 0,
  662. GDALGetRasterBandXSize(hOverview),
  663. GDALGetRasterBandYSize(hOverview)));
  664. }
  665. else
  666. {
  667. Concat(osStr, psOptions->bStdoutOutput, "(null)" );
  668. }
  669. }
  670. Concat(osStr, psOptions->bStdoutOutput, "\n" );
  671. }
  672. }
  673. if( GDALHasArbitraryOverviews( hBand ) && !bJson )//判断是否存在预览
  674. {
  675. Concat(osStr, psOptions->bStdoutOutput, " Overviews: arbitrary\n" );
  676. }
  677. const int nMaskFlags = GDALGetMaskFlags( hBand );//获取掩膜标识
  678. if( (nMaskFlags & (GMF_NODATA|GMF_ALL_VALID)) == 0 )
  679. {
  680. GDALRasterBandH hMaskBand = GDALGetMaskBand(hBand) ;//获取掩膜
  681. json_object *poMask = NULL, *poFlags = NULL, *poMaskOverviews = NULL;
  682. if(bJson)
  683. {
  684. poMask = json_object_new_object();
  685. poFlags = json_object_new_array();
  686. }
  687. else
  688. Concat(osStr, psOptions->bStdoutOutput, " Mask Flags: " );
  689. if( nMaskFlags & GMF_PER_DATASET )
  690. {
  691. if(bJson)
  692. {
  693. json_object *poFlag = json_object_new_string( "PER_DATASET" );
  694. json_object_array_add( poFlags, poFlag );
  695. }
  696. else
  697. Concat(osStr, psOptions->bStdoutOutput, "PER_DATASET " );
  698. }
  699. if( nMaskFlags & GMF_ALPHA )
  700. {
  701. if(bJson)
  702. {
  703. json_object *poFlag = json_object_new_string( "ALPHA" );
  704. json_object_array_add( poFlags, poFlag );
  705. }
  706. else
  707. Concat(osStr, psOptions->bStdoutOutput, "ALPHA " );
  708. }
  709. if( nMaskFlags & GMF_NODATA )
  710. {
  711. if(bJson)
  712. {
  713. json_object *poFlag = json_object_new_string( "NODATA" );
  714. json_object_array_add( poFlags, poFlag );
  715. }
  716. else
  717. Concat(osStr, psOptions->bStdoutOutput, "NODATA " );
  718. }
  719. if( nMaskFlags & GMF_ALL_VALID )
  720. {
  721. if(bJson)
  722. {
  723. json_object *poFlag = json_object_new_string( "ALL_VALID" );
  724. json_object_array_add( poFlags, poFlag );
  725. }
  726. else
  727. Concat(osStr, psOptions->bStdoutOutput, "ALL_VALID " );
  728. }
  729. if(bJson)
  730. json_object_object_add( poMask, "flags", poFlags );
  731. else
  732. Concat(osStr, psOptions->bStdoutOutput, "\n" );
  733. if(bJson)
  734. poMaskOverviews = json_object_new_array();
  735. if( hMaskBand != NULL &&
  736. GDALGetOverviewCount(hMaskBand) > 0 )
  737. {//获取掩膜预览
  738. if(!bJson)
  739. Concat(osStr, psOptions->bStdoutOutput, " Overviews of mask band: " );
  740. for( int iOverview = 0;
  741. iOverview < GDALGetOverviewCount(hMaskBand);
  742. iOverview++ )
  743. {
  744. GDALRasterBandH hOverview;
  745. json_object *poMaskOverview = NULL;
  746. json_object *poMaskOverviewSize = NULL;
  747. if(bJson)
  748. {
  749. poMaskOverview = json_object_new_object();
  750. poMaskOverviewSize = json_object_new_array();
  751. }
  752. else
  753. {
  754. if( iOverview != 0 )
  755. Concat(osStr, psOptions->bStdoutOutput, ", " );
  756. }
  757. hOverview = GDALGetOverview( hMaskBand, iOverview );
  758. if(bJson)
  759. {
  760. json_object *poMaskOverviewSizeX =
  761. json_object_new_int(GDALGetRasterBandXSize(hOverview));
  762. json_object *poMaskOverviewSizeY =
  763. json_object_new_int(GDALGetRasterBandYSize(hOverview));
  764. json_object_array_add(poMaskOverviewSize, poMaskOverviewSizeX);
  765. json_object_array_add(poMaskOverviewSize, poMaskOverviewSizeY);
  766. json_object_object_add(poMaskOverview, "size", poMaskOverviewSize);
  767. json_object_array_add(poMaskOverviews, poMaskOverview);
  768. }
  769. else
  770. Concat( osStr, psOptions->bStdoutOutput, "%dx%d",
  771. GDALGetRasterBandXSize( hOverview ),
  772. GDALGetRasterBandYSize( hOverview ) );
  773. }
  774. if(!bJson)
  775. Concat(osStr, psOptions->bStdoutOutput, "\n" );
  776. }
  777. if(bJson)
  778. {
  779. json_object_object_add(poMask, "overviews", poMaskOverviews);
  780. json_object_object_add(poBand, "mask", poMask);
  781. }
  782. }
  783. if( strlen(GDALGetRasterUnitType(hBand)) > 0 )
  784. {
  785. if(bJson)
  786. {
  787. json_object *poUnit = json_object_new_string(GDALGetRasterUnitType(hBand));
  788. json_object_object_add(poBand, "unit", poUnit);
  789. }
  790. else
  791. Concat(osStr, psOptions->bStdoutOutput, " Unit Type: %s\n", GDALGetRasterUnitType(hBand) );//获取栅格单元类型
  792. }
  793. if( GDALGetRasterCategoryNames(hBand) != NULL )
  794. {//获取栅格种类名
  795. char **papszCategories = GDALGetRasterCategoryNames(hBand);
  796. json_object *poCategories = NULL;
  797. if(bJson)
  798. poCategories = json_object_new_array();
  799. else
  800. Concat(osStr, psOptions->bStdoutOutput, " Categories:\n" );
  801. for( int i = 0; papszCategories[i] != NULL; i++ )
  802. {
  803. if(bJson)
  804. {
  805. json_object *poCategoryName = json_object_new_string(papszCategories[i]);
  806. json_object_array_add(poCategories, poCategoryName);
  807. }
  808. else
  809. Concat(osStr, psOptions->bStdoutOutput, " %3d: %s\n", i, papszCategories[i] );
  810. }
  811. if(bJson)
  812. json_object_object_add(poBand, "categories", poCategories);
  813. }
  814. int bSuccess = FALSE;
  815. if( GDALGetRasterScale( hBand, &bSuccess ) != 1.0
  816. || GDALGetRasterOffset( hBand, &bSuccess ) != 0.0 )//获取栅格比例尺和偏移量
  817. {
  818. if(bJson)
  819. {
  820. json_object *poOffset = json_object_new_double_with_precision(
  821. GDALGetRasterOffset(hBand, &bSuccess), 15);
  822. json_object *poScale = json_object_new_double_with_precision(
  823. GDALGetRasterScale(hBand, &bSuccess), 15);
  824. json_object_object_add(poBand, "offset", poOffset);
  825. json_object_object_add(poBand, "scale", poScale);
  826. }
  827. else
  828. Concat(osStr, psOptions->bStdoutOutput, " Offset: %.15g, Scale:%.15g\n",
  829. GDALGetRasterOffset( hBand, &bSuccess ),
  830. GDALGetRasterScale( hBand, &bSuccess ) );
  831. }
  832. GDALInfoReportMetadata( psOptions, hBand, true, bJson, poBandMetadata, osStr );//报告波段元数据
  833. if(bJson)
  834. {
  835. if (psOptions->bShowMetadata)
  836. json_object_object_add( poBand, "metadata", poBandMetadata );
  837. else
  838. json_object_put(poBandMetadata);
  839. }
  840. GDALColorTableH hTable;
  841. if( GDALGetRasterColorInterpretation(hBand) == GCI_PaletteIndex
  842. && (hTable = GDALGetRasterColorTable( hBand )) != NULL )//获得颜色索引及色彩表
  843. {
  844. if(!bJson)
  845. Concat( osStr, psOptions->bStdoutOutput,
  846. " Color Table (%s with %d entries)\n",
  847. GDALGetPaletteInterpretationName(
  848. GDALGetPaletteInterpretation( hTable )),
  849. GDALGetColorEntryCount( hTable ) );
  850. if (psOptions->bShowColorTable)
  851. {
  852. json_object *poEntries = NULL;
  853. if(bJson)
  854. {
  855. json_object *poPalette = json_object_new_string(GDALGetPaletteInterpretationName(
  856. GDALGetPaletteInterpretation(hTable)));
  857. json_object *poCount = json_object_new_int(GDALGetColorEntryCount(hTable));
  858. json_object *poColorTable = json_object_new_object();
  859. json_object_object_add(poColorTable, "palette", poPalette);
  860. json_object_object_add(poColorTable, "count", poCount);
  861. poEntries = json_object_new_array();
  862. json_object_object_add(poColorTable, "entries", poEntries);
  863. json_object_object_add(poBand, "colorTable", poColorTable);
  864. }
  865. for( int i = 0; i < GDALGetColorEntryCount( hTable ); i++ )//获取颜色记录
  866. {
  867. GDALColorEntry sEntry;
  868. GDALGetColorEntryAsRGB( hTable, i, &sEntry );
  869. if(bJson)
  870. {
  871. json_object *poEntry = json_object_new_array();
  872. json_object *poC1 = json_object_new_int(sEntry.c1);
  873. json_object *poC2 = json_object_new_int(sEntry.c2);
  874. json_object *poC3 = json_object_new_int(sEntry.c3);
  875. json_object *poC4 = json_object_new_int(sEntry.c4);
  876. json_object_array_add(poEntry, poC1);
  877. json_object_array_add(poEntry, poC2);
  878. json_object_array_add(poEntry, poC3);
  879. json_object_array_add(poEntry, poC4);
  880. json_object_array_add(poEntries, poEntry);
  881. }
  882. else
  883. Concat(osStr, psOptions->bStdoutOutput, " %3d: %d,%d,%d,%d\n",
  884. i,
  885. sEntry.c1,
  886. sEntry.c2,
  887. sEntry.c3,
  888. sEntry.c4 );
  889. }
  890. }
  891. }
  892. if( psOptions->bShowRAT && GDALGetDefaultRAT( hBand ) != NULL )
  893. {
  894. GDALRasterAttributeTableH hRAT = GDALGetDefaultRAT( hBand );//获取栅格属性表
  895. if(bJson)
  896. {
  897. json_object *poRAT = (json_object*) GDALRATSerializeJSON( hRAT );
  898. json_object_object_add( poJsonObject, "rat", poRAT );
  899. }
  900. else
  901. {//获取属性表并转化为xml树状信息
  902. CPLXMLNode *psTree = ((GDALRasterAttributeTable *) hRAT)->Serialize();
  903. char *pszXMLText = CPLSerializeXMLTree( psTree );
  904. CPLDestroyXMLNode( psTree );
  905. Concat(osStr, psOptions->bStdoutOutput, "%s\n", pszXMLText );
  906. CPLFree( pszXMLText );
  907. }
  908. }
  909. if(bJson)
  910. json_object_array_add(poBands, poBand);
  911. }
  912. if(bJson)
  913. {
  914. json_object_object_add(poJsonObject, "bands", poBands);
  915. Concat(osStr, psOptions->bStdoutOutput, "%s", json_object_to_json_string_ext(poJsonObject, JSON_C_TO_STRING_PRETTY));
  916. json_object_put(poJsonObject);
  917. }
  918. if( psOptionsToFree != NULL )
  919. GDALInfoOptionsFree(psOptionsToFree);
  920. return VSI_STRDUP_VERBOSE(osStr);
  921. }

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/329915
推荐阅读
相关标签
  

闽ICP备14008679号