gdal库的三个使用心得
作者:朱金灿
来源:http://blog.csdn.net/clever101
最近使用gdal库比较多,就谈谈gdal库的一些使用心得。
第一个是GDALOpen的访问权限参数会影响图像的创建金字塔方式。比如你是这样打开图像和创建金字塔:
std::string strImgPath = _T(“C:\\1.tif”);
GDALDataset* mGdalDataset=(GDALDataset*)(GDALOpen(strImgPath.c_str(),GA_Update));
mGdalDataset ->BuildOverviews(_T("NEAREST"),nLevel,pBandList,0,NULL,GdalBuildPyramidProgress,NULL);
运行完这段代码之后你会奇怪地发现在图像文件所在的文件夹并没有ovr文件或rrd文件出现,那么究竟有没有金字塔生成呢?实际上是有的。那么图像金字塔数据究竟存储在哪里,我猜测是存储在图像文件本身去了。为何这么说呢?因为我试着把第一行代码的GA_Update改为GA_ReadOnly,结果出现了ovr文件,也就是说当设置为GA_Update,金字塔数据是有可能放在图像文件的,当然我没有确认。这里还有一些疑问:如果金字塔数据是存储在文件里,那么对于tif文件具体是存储在哪里?对于其它图像文件又是存储在哪里呢?
第二个在调用完RasterIO函数对图像进行写入操作之后只是保留在缓存,需要再调用FlushCache函数才能真正把数据写到磁盘去。
第三个是网上有一篇关于坐标转换的教程:GDAL库学习笔记(五):坐标系之间的转化。其中有一段代码是这样的:
OGRSpatialReference oUTM, *poLatLong;
OGRCoordinateTransformation *poTransform;
oUTM.SetProjCS("UTM 17 / WGS84");
oUTM.SetWellKnownGeogCS( "WGS84" );
oUTM.SetUTM( 17 );
poLatLong = oUTM.CloneGeogCS();
poTransform = OGRCreateCoordinateTransformation( &oUTM, poLatLong );
if( poTransform == NULL )
{
...
}
...
if( !poTransform->Transform( nPoints, x, y, z ) )
...
我试过多次,OGRCreateCoordinateTransformation总是执行失败。后来看了gdal的源码,发现ogr集成prj4库进行投影坐标转换颇有些坑爹的地方。我们看一些OGRCreateCoordinateTransformation函数大致是怎么做的:
OGRCreateCoordinateTransformation函数大致是怎么做的:
OGRCoordinateTransformation*
OGRCreateCoordinateTransformation( OGRSpatialReference *poSource,
OGRSpatialReference *poTarget ) {
OGRProj4CT *poCT; if( !LoadProjLibrary() )
{
CPLError( CE_Failure, CPLE_NotSupported,
"Unable to load PROJ.4 library (%s), creation of\n"
"OGRCoordinateTransformation failed.",
GetProjLibraryName() );
return NULL;
} poCT = new OGRProj4CT(); if( !poCT->Initialize( poSource, poTarget ) )
{
delete poCT;
return NULL;
}
else
{
return poCT;
}
}
其中 LoadProjLibrary 的含义很明显,就是加载prj4库。我们再看看 LoadProjLibrary 函数:
static int LoadProjLibrary() {
CPLMutexHolderD( &hPROJMutex );
static int bTriedToLoad = FALSE;
const char *pszLibName; if( bTriedToLoad )
return( pfn_pj_transform != NULL ); bTriedToLoad = TRUE; pszLibName = GetProjLibraryName(); #ifdef PROJ_STATIC
pfn_pj_init = pj_init;
pfn_pj_init_plus = pj_init_plus;
pfn_pj_fwd = pj_fwd;
pfn_pj_inv = pj_inv;
pfn_pj_free = pj_free;
pfn_pj_transform = pj_transform;
pfn_pj_get_errno_ref = (int *(*)(void)) pj_get_errno_ref;
pfn_pj_strerrno = pj_strerrno;
pfn_pj_dalloc = pj_dalloc;
#if PJ_VERSION >= 446
pfn_pj_get_def = pj_get_def;
#endif
#else
CPLPushErrorHandler( CPLQuietErrorHandler ); pfn_pj_init = (projPJ (*)(int, char**)) CPLGetSymbol( pszLibName,
"pj_init" );
CPLPopErrorHandler(); if( pfn_pj_init == NULL )
return( FALSE ); pfn_pj_init_plus = (projPJ (*)(const char *))
CPLGetSymbol( pszLibName, "pj_init_plus" );
pfn_pj_fwd = (projUV (*)(projUV,projPJ))
CPLGetSymbol( pszLibName, "pj_fwd" );
pfn_pj_inv = (projUV (*)(projUV,projPJ))
CPLGetSymbol( pszLibName, "pj_inv" );
pfn_pj_free = (void (*)(projPJ))
CPLGetSymbol( pszLibName, "pj_free" );
pfn_pj_transform = (int (*)(projPJ,projPJ,long,int,double*,
double*,double*))
CPLGetSymbol( pszLibName, "pj_transform" );
pfn_pj_get_errno_ref = (int *(*)(void))
CPLGetSymbol( pszLibName, "pj_get_errno_ref" );
pfn_pj_strerrno = (char *(*)(int))
CPLGetSymbol( pszLibName, "pj_strerrno" ); CPLPushErrorHandler( CPLQuietErrorHandler );
pfn_pj_get_def = (char *(*)(projPJ,int))
CPLGetSymbol( pszLibName, "pj_get_def" );
pfn_pj_dalloc = (void (*)(void*))
CPLGetSymbol( pszLibName, "pj_dalloc" );
CPLPopErrorHandler(); #endif if( pfn_pj_transform == NULL )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Attempt to load %s, but couldn't find pj_transform.\n"
"Please upgrade to PROJ 4.1.2 or later.",
pszLibName ); return FALSE;
} return( TRUE );
}
gdal库集成prj4库有两种方式:静态库集成和动态库集成,使用预处理器PROJ_STATIC。首先看看静态库集成:
pfn_pj_init = pj_init;
pfn_pj_init_plus = pj_init_plus;
pfn_pj_fwd = pj_fwd;
pfn_pj_inv = pj_inv;
pfn_pj_free = pj_free;
pfn_pj_transform = pj_transform;
pfn_pj_get_errno_ref = (int *(*)(void)) pj_get_errno_ref;
pfn_pj_strerrno = pj_strerrno;
pfn_pj_dalloc = pj_dalloc;
这里只是函数指针的赋值,那么函数调用的地方在哪里呢?我并没有找到。动态库集成就更扯淡了,首先通过GetProjLibraryName函数获取prj4库的动态库名字,这里名字规定为:
#if (defined(WIN32) || defined(WIN32CE)) && !defined(__MINGW32__)
# define LIBNAME "proj.dll"
#elif defined(__CYGWIN__) || defined(__MINGW32__)
// XXX: If PROJ.4 library was properly built using libtool in Cygwin or MinGW
// environments it has the interface version number embedded in the file name
// (it is CURRENT-AGE number). If DLL came somewhere else (e.g. from MSVC
// build) it can be named either way, so use PROJSO environment variable to
// specify the right library name. By default assume that in Cygwin/MinGW all
// components were buit in the same way.
# define LIBNAME "libproj-0.dll"
#elif defined(__APPLE__)
# define LIBNAME "libproj.dylib"
#else
# define LIBNAME "libproj.so"
#endif
也就是说假如在windows平台下不叫proj.dll,压根加载不了prj4库,还有致命一条:proj.dll究竟放在哪个路径下呢?据我经验,LoadLibrary没有指定路径的话,在Windows平台只能在当前目录和在系统环境变量路径中找到,具体见:关于DLL搜索路径的顺序问题。动态库集成和静态库集成存在一样的问题,只找到函数地址,并不见调用的地方。
gdal库的三个使用心得的更多相关文章
- gdal库中设置prj4库全路径的用法
作者:朱金灿 来源:http://blog.csdn.net/clever101 gdal库实现投影转换之类的功能实际上底层都是调用prj4库的功能.如果gdal使用非静态的方式集成prj4库,实际上 ...
- GDAL库三个读取Jpeg2000格式驱动测试
0.目的 GDAL库中提供了四五种读取Jpeg2000的驱动,但是各个驱动读取数据的效率各不相同,下面就针对三种读取jpeg2000的效率进行测试. GDAL库中提供的读取Jpeg2000的驱动有下面 ...
- C++调用GDAL库读取并输出tif文件,并计算斑块面积输出景观指数:CSD
部分源码选自GDAL库的官方网址:www.gdal.org,其余的代码为笔者自己编写. // readfile.cpp : 定义控制台应用程序的入口点. // /* part of the codes ...
- GDAL库进度信息编写示例
GDAL进度信息编写 GDAL库中的算法以及读写数据的时候一般都会提供两个与进度信息相关的参数,下面分别进行描述: GDALProgressFunc pfnProgress void * pProgr ...
- GDAL库扩展Landsat系列MTL文件格式支持
Landsat系列卫星提供的数据,一般都是每个波段一个tif文件,然后外加一个MTL.txt的元数据文件,使用gdal可以直接打开每个波段的tif文件,但是有时候想在打开tif数据的同时能够自动读取M ...
- 使用GDAL库中的RPC校正问题
最近将GDAL库更新至1.11版本之后,发现之前写的RPC像方改正模型校正的结果偏差特别大(更新版本之前结果和PCI处理的结果一致).所以初步判断是GDAL库的bug,经过各个参数修改发现原来是指定的 ...
- 修改GDAL库支持RPC像方改正模型
最近在做基于RPC的像方改正模型,方便对数据进行测试,修改了GDAL库中的RPC纠正模型,使之可以支持RPC像方改正参数. 下面是RPC模型的公式,rn,cn为归一化之后的图像行列号坐标,PLH为归一 ...
- GDAL库中WFS服务中含有中文不能获取数据的问题
GDAL库中目前提供了对WFS服务发布的数据进行获取,目前发现对于中文的服务名称或者图层名为中文,GDAL不能正确识别.通过调试发现,其原因有下面两点: 1.输入的URL路径没有使用UTF8编码而从网 ...
- 浅析GDAL库C#版本支持中文路径问题(续)
上篇博客中主要说了GDAL库C#版本中存在的问题,其表现形式主要是:"文件名中的汉字个数是偶数,完全没有影响,读取和创建都正常,如果文件名中的汉字个数是奇数,读取和创建都会报错." ...
随机推荐
- entity framework 中一些常用的函数 转自http://www.cnblogs.com/williamzhu/
一般查询 var Courses = db.Courses.Where(c => c.Title == "Physics").OrderBy(c => c.Title) ...
- java线程的使用(Runnable)
在实际项目开发过程中,线程是经常要用到的,特别是为了不影响项目的运行效果. 以下就以实际项目中的简单例子来介绍: public class SystemRedisInfoController exte ...
- JavaSE_ 反射 目录(27)
JavaSE学习总结第27天_反射 & 设计模式 & JDK5.7.8新特性27.01 反射_类的加载概述和加载时机27.02 反射_类加载器的概述和分类27.03 反射_反射概述27 ...
- CSS复习第一天(简单规范)
1.有意义的html 优点:与表现性的页面相比,有意义的页面更容易后期的处理与维护. 便于浏览器与屏幕阅读器识别. 更加便于调试样式 ...
- 利用fitnesse实现api接口自动化测试
上午在园子里乱逛,看了不少小伙伴们分享的接口测试方面的知识,仔细想想,我做接口测试也有几个年头了,大家所叙述到的一些经验或多或少,我也曾遇到过,突然意识到知识的点滴积累是多么的重要,我记得我最早接触接 ...
- linxu添加定时任务
1. 在需要定时执行的php文件的第一行加 也就是文件开头加 #! /bin/local/php -q 其中 /bin/local/php 是自己的php.exe 所在的位置 2. 上传要定时执行的 ...
- pyhton10min系列之程序员的浪漫-足迹生成器,有视频教程
记录去过的足迹 本文为原创文章 项目主页 跪求star 程序员的浪漫,我女朋友蘑菇喜欢旅游,于是我做了这个,记录2015一起去过的地方,祝她圣诞快乐 如果觉得对你有帮助,github求个star 视频 ...
- chrome dev tools
chrome dev tools介绍一下Chrome dev tools 的基本使用和一些意想不到的小技巧.\\Chrome Developer Tools 是Chrome内嵌的一系列编辑和调试的工具 ...
- 试用阿里云RDS的MySQL压缩存储引擎TokuDB
以前就用过自己搭建MySQL服务器的两种存储引擎MyISAM和InnoDB(也用过一点Memory方式),在今年初转向阿里云关系型数据库服务RDS的时候,看到可调参数中有一个TokuDB,不过不太了解 ...
- 统计难题(trie树)
统计难题 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others)Total Submi ...