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#版本中存在的问题,其表现形式主要是:"文件名中的汉字个数是偶数,完全没有影响,读取和创建都正常,如果文件名中的汉字个数是奇数,读取和创建都会报错." ...
随机推荐
- ASP.NET快速开发框架、这才是高大上档次后台管理UI界面
另外献上在<线体验Demo地址>希望大家也能从中得到一些启发.地址:http://121.40.148.178:8080/ . 用户名:guest,密码:123456QQ技术交流群:239 ...
- Windows Server 2012 R2 服务器管理器介绍和配置使用
1. 服务管理器是用于管理系统服务的管理工具.一般常用于windows系统,使用这个工具你可以启动.停止服务:设置服务是自动.手动启动或禁用:查看某个服务的相关信息:设置服务以什么用户启动等等(一般包 ...
- connot find one or more components. please reinstall the application
正在用 Visual Studio 2013 写程序,程序一直执行正常. 此时,手动把注册表"HKEY_USERS"的当前用户的权限删除.再运行程序会提示:“是否继续并运行上次的成 ...
- ExtJS002Window创建
Ext.onReady(function () { Ext.create('Ext.window.Window', { title: 'window', width: 400, height: 300 ...
- 二分查找(Java)
二分查找的前提的要查找的数组必须有序. 代码如下: 程序1 public class source { public int binary_sort(int[] array, int item) { ...
- PHP mysqli类
<?php header("content-type:text/html;charset=utf-8"); $conn = new mysqli("localhos ...
- python函数callable
callable(object) 中文说明:检查对象object是否可调用.如果返回True,object仍然可能调用失败:但如果返回False,调用对象ojbect绝对不会成功. 注意:类或函数是可 ...
- C指针(转)
第一章 指针的概念 指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址. 要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的 类型,指针的值或者叫指针所指向的内存区,还有 ...
- sping+maven+mybatis+ehcache续之实现mapper
配置接着上一篇文章 新建UserMapper.java和UserMapper.xml 其中UserMapper.xml的namespace以及文件名要和UserMapper.java一致 <ma ...
- 禁用Java DNS缓存-Disable DNS caching
Once an application has performed network access (i.e. urlconnection, parsing of xml document with e ...