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#版本中存在的问题,其表现形式主要是:"文件名中的汉字个数是偶数,完全没有影响,读取和创建都正常,如果文件名中的汉字个数是奇数,读取和创建都会报错." ...
随机推荐
- 委托与Lambda表达式
~,先不急说委托和Lambda表达式,先看两个例子再说: 1. 通过委托,为一个数字加10,如下代码: class Program { private delegate int JiSuan(int ...
- jsp中的两种跳转方式分别是?有什么区别?
在JSP中跳转有两种方式 forward跳转:<jsp:forward page ="跳转页面地址"> response跳转:response.sendRedirect ...
- 关于playframework2.5
加入了很多新东西: 1.用akka streams 替换了大部分 iteratee-based async io,当然还有一些模块在用iteratees 2.java 的一些API 做了调整升级,以及 ...
- 0520 python
配置python环境变量我的电脑->右键->属性->高级系统设置->环境变量->(1)用户变量->新建 Path=C:\Python27(2)系统变量->编辑 ...
- kinect for windows - SkeletonBasics-D2D详解之二
首先看骨骼追踪例子代码的结构:
- swjtu 2213 A Game About Cards(模拟题)
题目链接:http://acm.swjtu.edu.cn/JudgeOnline/showproblem?problem_id=2213 思路分析:该问题与约瑟夫问题相似:每次将前n张牌放到队列的最后 ...
- Three Swaps DFS
E. Three Swaps time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- android中使用jni对字符串加解密实现分析
android中使用jni对字符串加解密实现分析 近期项目有个需求.就是要对用户的敏感信息进行加密处理,比方用户的账户password,手机号等私密信息.在java中,就对字符串的加解密我们能够使用A ...
- 将一个数转化为二进制后,求其中1的个数 C++
#include <iostream>using namespace std;int func(int x){ int count=0; while(x) { x=x&(x-1); ...
- resolve "Undefined attribute name" warning for Angular "ng-" attributes in HTML files
由于这些attributes引起的warning数量较多, 影响直观查找其他warning. 因此选择将这类warning忽视掉: Project Property -> Validation ...