GDAL工具箱详解之gdalinfo.exe
GDAL自带的工具包含了众多的功能,可以看做是利用该开源库进行的典型开发案例。本节主要介绍其中基本的一项工具——gdalinfo.exe。
- 该工具箱位于GDAL文件夹下的apps文件夹中,属于命令行可执行程序。
目录
使用方法
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/GeoTIFF
Files: E:\exmaple.tif
Size is 200, 400
Coordinate 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=Area
Image Structure Metadata:
INTERLEAVE=PIXEL
Corner 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=0
Band 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=0
Band 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=0
Band 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