GDAL 2.1.0工具开发之gdal_translate(图像裁剪、缩放、拉伸、赋坐标投影、格式转换等)
2016-06-12 13:30
531 查看
为便于在自己的程序中使用GDAL的示例代码提供的那些强大功能,计划建立一个动态库,在动态库中模拟实现gdal的demo的功能。
初步想法是建立一个类CGdalTools,类的成员即是这些demo的名字。实现与demo一样的功能。
下面的例子是以gdal_translate为例。
找到gdal_translate_bin.cpp(该文件已经相当简单,加上各种注释仅300行出头),复制其中的main函数内容到一个单独的gdal_translate函数中,函数参数与main函数同,返回值与其核心函数GDALTranslate的返回值同,为GDALDatasetH,如下:
复制过来的代码不同直接使用,需要做一些修改:
继续复制GDALTranslateOptionsForBinaryNew和GDALTranslateOptionsForBinaryFree
Gdal驱动的注册改为在CGdalTools类的构建函数中进行,而销毁则放在析构函数中。
删除EarlySetConfigOptions函数调用。
exit函数全部改为return null;
认为不必要的地方,可以直接删除。比如输出使用说明、帮助信息、版本信息等地方。
有些输出Usage函数的地方,改为return NULL;
函数最后删除GDALClose(hOutDS); return nRetCode;改为return hOutDS;
找不到GDALTranslateOptionsForBinary类,经检查,该类其实定义于gdal_utils_priv.h中,该定义主要是用来演示DEMO的使用而添加,并不是GDAL的核心功能,因此,GDAL的编译并没有将它导出。为便于开发,最简单的方法是将该文件复制到gdal开发版本的include目录下,然后在所有结构体的定义前加CPL_DLL即可。
修改后的代码已经可以运行了,其输入参数与在命令行中调用gdal_translate完全相同。代码示例如下,需要注意的是输出的GDALDatasetH须在外面关闭,也就是调用在上面的第7步中删除的GDALClose(hOutDS);
继续对该函数进行改造。上面的代码中,变化最大的当属第8步,需要变更GDAL的源文件,gdal_utils_priv.h文件。实际上,GDALTranslateOptionsForBinaryNew只是用作GDALTranslateOptionsNew的构建参数,也就是在GDALTranslateOptionsNew中将某些参数输出给GDALTranslateOptionsForBinaryNew,具体内容可以参看GDALTranslateOptionsForBinaryNew的定义,在gdal_utils_priv.h的第52行,具体内容不展开。需要注意的是在GDALTranslateOptionsNew是如何添加GDALTranslateOptionsForBinaryNew信息的。
在gdal_translate_lib.cpp中,第1674行,能看到GDALTranslateOptionsNew函数。里面与GDALTranslateOptionsForBinaryNew相关的内容如下:
回到上文,不进行第8步,也就是不变动gdal_utils_priv.h文件,也就是在函数外自行构建并管理GDALTranslateOptionsForBinaryNew里的信息。因此,上面的8步中,第1步也不需要。为保证输入文件与输出文件信息,变更函数声明如下:
为保证程序调用时传入GDALDatasetH也可以完成相关工作,这里加一个重载函数
前者详细如下:
后者详细如下:
现在编写一个主程序,对上述代码进行测试,
经测试,程序运行界面如下
初步想法是建立一个类CGdalTools,类的成员即是这些demo的名字。实现与demo一样的功能。
下面的例子是以gdal_translate为例。
找到gdal_translate_bin.cpp(该文件已经相当简单,加上各种注释仅300行出头),复制其中的main函数内容到一个单独的gdal_translate函数中,函数参数与main函数同,返回值与其核心函数GDALTranslate的返回值同,为GDALDatasetH,如下:
GDALDatasetH Gdal_Translate(int argc, char** argv) ;
复制过来的代码不同直接使用,需要做一些修改:
继续复制GDALTranslateOptionsForBinaryNew和GDALTranslateOptionsForBinaryFree
Gdal驱动的注册改为在CGdalTools类的构建函数中进行,而销毁则放在析构函数中。
删除EarlySetConfigOptions函数调用。
exit函数全部改为return null;
认为不必要的地方,可以直接删除。比如输出使用说明、帮助信息、版本信息等地方。
有些输出Usage函数的地方,改为return NULL;
函数最后删除GDALClose(hOutDS); return nRetCode;改为return hOutDS;
找不到GDALTranslateOptionsForBinary类,经检查,该类其实定义于gdal_utils_priv.h中,该定义主要是用来演示DEMO的使用而添加,并不是GDAL的核心功能,因此,GDAL的编译并没有将它导出。为便于开发,最简单的方法是将该文件复制到gdal开发版本的include目录下,然后在所有结构体的定义前加CPL_DLL即可。
修改后的代码已经可以运行了,其输入参数与在命令行中调用gdal_translate完全相同。代码示例如下,需要注意的是输出的GDALDatasetH须在外面关闭,也就是调用在上面的第7步中删除的GDALClose(hOutDS);
GDALDatasetH CGdalTools::Gdal_Translate(int argc, char** argv) { GDALDatasetH hDataset, hOutDS; int bUsageError; argc = GDALGeneralCmdLineProcessor(argc, &argv, 0); if (argc < 1) return NULL; if (CPLGetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", NULL) == NULL) { CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "450"); } GDALTranslateOptionsForBinary* psOptionsForBinary = GDALTranslateOptionsForBinaryNew(); GDALTranslateOptions *psOptions = GDALTranslateOptionsNew(argv + 1, psOptionsForBinary); CSLDestroy(argv); if (psOptions == NULL) { return NULL; } if (psOptionsForBinary->pszSource == NULL) { return NULL; } if (psOptionsForBinary->pszDest == NULL) { return NULL; } if (strcmp(psOptionsForBinary->pszDest, "/vsistdout/") == 0) { psOptionsForBinary->bQuiet = TRUE; } if (!(psOptionsForBinary->bQuiet)) { GDALTranslateOptionsSetProgress(psOptions, GDALTermProgress, NULL); } if (!psOptionsForBinary->bQuiet && !psOptionsForBinary->bFormatExplicitlySet) CheckExtensionConsistency(psOptionsForBinary->pszDest, psOptionsForBinary->pszFormat); /* -------------------------------------------------------------------- */ /* Attempt to open source file. */ /* -------------------------------------------------------------------- */ hDataset = GDALOpenEx(psOptionsForBinary->pszSource, GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR, NULL, (const char* const*)psOptionsForBinary->papszOpenOptions, NULL); if (hDataset == NULL) { return NULL; } /* -------------------------------------------------------------------- */ /* Handle subdatasets. */ /* -------------------------------------------------------------------- */ if (!psOptionsForBinary->bCopySubDatasets && CSLCount(GDALGetMetadata(hDataset, "SUBDATASETS")) > 0 && GDALGetRasterCount(hDataset) == 0) { fprintf(stderr, "Input file contains subdatasets. Please, select one of them for reading.\n"); GDALClose(hDataset); return NULL; } if (CSLCount(GDALGetMetadata(hDataset, "SUBDATASETS")) > 0 && psOptionsForBinary->bCopySubDatasets) { char **papszSubdatasets = GDALGetMetadata(hDataset, "SUBDATASETS"); char *pszSubDest = (char *)CPLMalloc(strlen(psOptionsForBinary->pszDest) + 32); int i; CPLString osPath = CPLGetPath(psOptionsForBinary->pszDest); CPLString osBasename = CPLGetBasename(psOptionsForBinary->pszDest); CPLString osExtension = CPLGetExtension(psOptionsForBinary->pszDest); CPLString osTemp; const char* pszFormat = NULL; if (CSLCount(papszSubdatasets) / 2 < 10) { pszFormat = "%s_%d"; } else if (CSLCount(papszSubdatasets) / 2 < 100) { pszFormat = "%s_%002d"; } else { pszFormat = "%s_%003d"; } const char* pszDest = pszSubDest; for (i = 0; papszSubdatasets[i] != NULL; i += 2) { char* pszSource = CPLStrdup(strstr(papszSubdatasets[i], "=") + 1); osTemp = CPLSPrintf(pszFormat, osBasename.c_str(), i / 2 + 1); osTemp = CPLFormFilename(osPath, osTemp, osExtension); strcpy(pszSubDest, osTemp.c_str()); hDataset = GDALOpenEx(pszSource, GDAL_OF_RASTER, NULL, (const char* const*)psOptionsForBinary->papszOpenOptions, NULL); CPLFree(pszSource); if (!psOptionsForBinary->bQuiet) printf("Input file size is %d, %d\n", GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset)); hOutDS = GDALTranslate(pszDest, hDataset, psOptions, &bUsageError); if (bUsageError == TRUE) return NULL; if (hOutDS == NULL) break; GDALClose(hOutDS); } GDALClose(hDataset); GDALTranslateOptionsFree(psOptions); GDALTranslateOptionsForBinaryFree(psOptionsForBinary); CPLFree(pszSubDest); GDALDestroyDriverManager(); return 0; } if (!psOptionsForBinary->bQuiet) printf("Input file size is %d, %d\n", GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset)); hOutDS = GDALTranslate(psOptionsForBinary->pszDest, hDataset, psOptions, &bUsageError); if (bUsageError == TRUE) return NULL; int nRetCode = (hOutDS) ? 0 : 1; /* Close hOutDS before hDataset for the -f VRT case */ //GDALClose(hOutDS); GDALClose(hDataset); GDALTranslateOptionsFree(psOptions); GDALTranslateOptionsForBinaryFree(psOptionsForBinary); return hOutDS; }
继续对该函数进行改造。上面的代码中,变化最大的当属第8步,需要变更GDAL的源文件,gdal_utils_priv.h文件。实际上,GDALTranslateOptionsForBinaryNew只是用作GDALTranslateOptionsNew的构建参数,也就是在GDALTranslateOptionsNew中将某些参数输出给GDALTranslateOptionsForBinaryNew,具体内容可以参看GDALTranslateOptionsForBinaryNew的定义,在gdal_utils_priv.h的第52行,具体内容不展开。需要注意的是在GDALTranslateOptionsNew是如何添加GDALTranslateOptionsForBinaryNew信息的。
在gdal_translate_lib.cpp中,第1674行,能看到GDALTranslateOptionsNew函数。里面与GDALTranslateOptionsForBinaryNew相关的内容如下:
if( EQUAL(papszArgv[i],"-of") && i < argc-1 ) { ++i; CPLFree(psOptions->pszFormat); psOptions->pszFormat = CPLStrdup(papszArgv[i]); if( psOptionsForBinary ) { psOptionsForBinary->bFormatExplicitlySet = TRUE; } } else if( EQUAL(papszArgv[i],"-q") || EQUAL(papszArgv[i],"-quiet") ) { if( psOptionsForBinary ) psOptionsForBinary->bQuiet = TRUE; } else if( EQUAL(papszArgv[i],"-sds") ) { if( psOptionsForBinary ) psOptionsForBinary->bCopySubDatasets = TRUE; } else if( EQUAL(papszArgv[i], "-oo") && i+1 < argc ) { i++; if( psOptionsForBinary ) { psOptionsForBinary->papszOpenOptions = CSLAddString( psOptionsForBinary->papszOpenOptions, papszArgv[i] ); } } else if( !bGotSourceFilename ) { bGotSourceFilename = true; if( psOptionsForBinary ) psOptionsForBinary->pszSource = CPLStrdup(papszArgv[i]); } else if( !bGotDestFilename ) { bGotDestFilename = true; if( psOptionsForBinary ) psOptionsForBinary->pszDest = CPLStrdup(papszArgv[i]); } if( psOptionsForBinary ) { psOptionsForBinary->pszFormat = CPLStrdup(psOptions->pszFormat); }
回到上文,不进行第8步,也就是不变动gdal_utils_priv.h文件,也就是在函数外自行构建并管理GDALTranslateOptionsForBinaryNew里的信息。因此,上面的8步中,第1步也不需要。为保证输入文件与输出文件信息,变更函数声明如下:
GDALDatasetH Gdal_Translate(char ** argv, char* srcFile, char* dstFile);
为保证程序调用时传入GDALDatasetH也可以完成相关工作,这里加一个重载函数
GDALDatasetH Gdal_Translate(char ** argv, GDALDatasetH hDataset, char* dstFile);
前者详细如下:
GDALDatasetH CGdalTools::Gdal_Translate(char** argv, char* srcFile, char* dstFile) { if (srcFile == NULL) { return NULL; } char** papszOpenOptions=nullptr; int argc = CSLCount(argv); for (int i = 0; i < argc; i++) { if (EQUAL(argv[i], "-oo") && i + 1 < argc) { i++; papszOpenOptions = CSLAddString(papszOpenOptions, argv[i]); } } GDALDatasetH hDataset; hDataset = GDALOpenEx(srcFile, GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR, NULL, (const char* const*)papszOpenOptions, NULL); if (hDataset == NULL) { return NULL; } GDALDatasetH hOutDs = Gdal_Translate(argv, hDataset, dstFile); GDALClose(hDataset); return hOutDs; }
后者详细如下:
GDALDatasetH CGdalTools::Gdal_Translate(char** argv, GDALDatasetH hDataset, char* dstFile) { if (hDataset == NULL) { return NULL; } if (dstFile == NULL) { return NULL; } bool bQuiet = false, bCopySubDatasets = false, bFormatExplicitlySet = false; char* pszFormat = NULL; char** papszOpenOptions=nullptr; int argc = CSLCount(argv); for (int i = 0; i < argc; i++) { if (EQUAL(argv[i], "-of") && i < argc - 1) { ++i; pszFormat = CPLStrdup(argv[i]); bFormatExplicitlySet = TRUE; } else if (EQUAL(argv[i], "-q") || EQUAL(argv[i], "-quiet")) { bQuiet = TRUE; } else if (EQUAL(argv[i], "-sds")) { bCopySubDatasets = TRUE; } else if (EQUAL(argv[i], "-oo") && i + 1 < argc) { i++; papszOpenOptions = CSLAddString(papszOpenOptions, argv[i]); } } GDALDatasetH hOutDS; int bUsageError; argc = GDALGeneralCmdLineProcessor(argc, &argv, 0); if (argc < 1) return NULL; if (CPLGetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", NULL) == NULL) { CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "450"); } GDALTranslateOptions *psOptions = GDALTranslateOptionsNew(argv + 1, NULL); CSLDestroy(argv); if (strcmp(dstFile, "/vsistdout/") == 0) { bQuiet = TRUE; } if (!bQuiet) { GDALTranslateOptionsSetProgress(psOptions, GDALTermProgress, NULL); } if (!bQuiet && !bFormatExplicitlySet) CheckExtensionConsistency(dstFile, pszFormat); /* -------------------------------------------------------------------- */ /* Handle subdatasets. */ /* -------------------------------------------------------------------- */ if (!bCopySubDatasets && CSLCount(GDALGetMetadata(hDataset, "SUBDATASETS")) > 0 && GDALGetRasterCount(hDataset) == 0) { fprintf(stderr, "Input file contains subdatasets. Please, select one of them for reading.\n"); return NULL; } if (CSLCount(GDALGetMetadata(hDataset, "SUBDATASETS")) > 0 && bCopySubDatasets) { char **papszSubdatasets = GDALGetMetadata(hDataset, "SUBDATASETS"); char *pszSubDest = (char *)CPLMalloc(strlen(dstFile) + 32); int i; CPLString osPath = CPLGetPath(dstFile); CPLString osBasename = CPLGetBasename(dstFile); CPLString osExtension = CPLGetExtension(dstFile); CPLString osTemp; const char* pszFormat = NULL; if (CSLCount(papszSubdatasets) / 2 < 10) { pszFormat = "%s_%d"; } else if (CSLCount(papszSubdatasets) / 2 < 100) { pszFormat = "%s_%002d"; } else { pszFormat = "%s_%003d"; } const char* pszDest = pszSubDest; for (i = 0; papszSubdatasets[i] != NULL; i += 2) { char* pszSource = CPLStrdup(strstr(papszSubdatasets[i], "=") + 1); osTemp = CPLSPrintf(pszFormat, osBasename.c_str(), i / 2 + 1); osTemp = CPLFormFilename(osPath, osTemp, osExtension); strcpy(pszSubDest, osTemp.c_str()); hDataset = GDALOpenEx(pszSource, GDAL_OF_RASTER, NULL, (const char* const*)papszOpenOptions, NULL); CPLFree(pszSource); if (!bQuiet) printf("Input file size is %d, %d\n", GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset)); hOutDS = GDALTranslate(pszDest, hDataset, psOptions, &bUsageError); if (bUsageError == TRUE) return NULL; if (hOutDS == NULL) break; GDALClose(hOutDS); } GDALTranslateOptionsFree(psOptions); CPLFree(pszSubDest); return NULL; } if (!bQuiet) printf("Input file size is %d, %d\n", GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset)); hOutDS = GDALTranslate(dstFile, hDataset, psOptions, &bUsageError); if (bUsageError == TRUE) { GDALClose(hOutDS); hOutDS = NULL; } GDALTranslateOptionsFree(psOptions); return hOutDS; }
现在编写一个主程序,对上述代码进行测试,
char** pszInfo = NULL; pszInfo = CSLAddString(pszInfo, "change_format"); pszInfo = CSLAddString(pszInfo, "-of"); pszInfo = CSLAddString(pszInfo, "JPEG"); gt.Gdal_Translate( pszInfo, "G:\\sss.tif", "G:\\sss.jpg");
经测试,程序运行界面如下
相关文章推荐
- Spring 中的SpEL
- Type Project has no default.properties file! Edit the project properties to set one.
- 阶乘求模
- struts2类型转换器日期转换小例详解
- JS闭包、作用域链、垃圾回收、内存泄露相关知识小结
- 今日头条2017后端工程师笔试题
- Butterknife下的BaseAdapter封装。
- Unity学习日常问题记录八-反弹和静止条件值是可以设的,ParticleSystem的方向
- maven工程里面install时jdk报错
- For Me ...
- Ubuntu日记——adb无法启动的解决
- 几何画板中作函数图像的几种方法
- PL/SQL查询oracle数据库对象
- 推荐算法:基于领域的协同滤波:数据稀疏和冷启动
- 将其他Android项目打成aar包集成到自己的项目中
- 如何在30分钟之内编辑排版好文章并发布在30个媒体平台?
- 自定义圆形图片控件
- 《machine learning》week 2,class 3
- BDD(behaviour driven development), TDD(test driven development)
- Delphi 字符指针分配内存