gdal使用经验(二)影像投影

http://blog.csdn.net/clever101/article/details/11716041

 最近使用gdal库比较多,就谈谈gdal库的一些使用心得。

         第一个是GDALOpen的访问权限参数会影响图像的创建金字塔方式。比如你是这样打开图像和创建金字塔:

[cpp]  view plain copy
  1. std::string strImgPath = _T(“C:\\1.tif”);  
  2. GDALDataset* mGdalDataset=(GDALDataset*)(GDALOpen(strImgPath.c_str(),GA_Update));  
  3. mGdalDataset ->BuildOverviews(_T("NEAREST"),nLevel,pBandList,0,NULL,GdalBuildPyramidProgress,NULL);  

        运行完这段代码之后你会奇怪地发现在图像文件所在的文件夹并没有ovr文件或rrd文件出现,那么究竟有没有金字塔生成呢?实际上是有的。那么图像金字塔数据究竟存储在哪里,我猜测是存储在图像文件本身去了。为何这么说呢?因为我试着把第一行代码的GA_Update改为GA_ReadOnly,结果出现了ovr文件,也就是说当设置为GA_Update,金字塔数据是有可能放在图像文件的,当然我没有确认。这里还有一些疑问:如果金字塔数据是存储在文件里,那么对于tif文件具体是存储在哪里?对于其它图像文件又是存储在哪里呢?

     

        第二个在调用完RasterIO函数对图像进行写入操作之后只是保留在缓存,需要再调用FlushCache函数才能真正把数据写到磁盘去。

 

       第三个是网上有一篇关于坐标转换的教程:GDAL库学习笔记(五):坐标系之间的转化。其中有一段代码是这样的:

[cpp]  view plain copy
  1. OGRSpatialReference    oUTM, *poLatLong;  
  2. OGRCoordinateTransformation *poTransform;  
  3. oUTM.SetProjCS("UTM 17 / WGS84");  
  4. oUTM.SetWellKnownGeogCS( "WGS84" );  
  5.  oUTM.SetUTM( 17 );  
  6.  poLatLong = oUTM.CloneGeogCS();  
  7.  poTransform = OGRCreateCoordinateTransformation( &oUTM, poLatLong );  
  8.  if( poTransform == NULL )  
  9.  {  
  10.      ...  
  11.  }  
  12.   ...  
  13. if( !poTransform->Transform( nPoints, x, y, z ) )  
  14.   ...  

        我试过多次,OGRCreateCoordinateTransformation总是执行失败。后来看了gdal的源码,发现ogr集成prj4库进行投影坐标转换颇有些坑爹的地方。我们看一些OGRCreateCoordinateTransformation函数大致是怎么做的:

[cpp]  view plain copy
  1. OGRCreateCoordinateTransformation函数大致是怎么做的:  
  2. OGRCoordinateTransformation*    
  3. OGRCreateCoordinateTransformation( OGRSpatialReference *poSource,   
  4.                                    OGRSpatialReference *poTarget )  
  5.   
  6. {  
  7.     OGRProj4CT  *poCT;  
  8.   
  9.     if( !LoadProjLibrary() )  
  10.     {  
  11.         CPLError( CE_Failure, CPLE_NotSupported,   
  12.                   "Unable to load PROJ.4 library (%s), creation of\n"  
  13.                   "OGRCoordinateTransformation failed.",  
  14.                   GetProjLibraryName() );  
  15.         return NULL;  
  16.     }  
  17.   
  18.     poCT = new OGRProj4CT();  
  19.       
  20.     if( !poCT->Initialize( poSource, poTarget ) )  
  21.     {  
  22.         delete poCT;  
  23.         return NULL;  
  24.     }  
  25.     else  
  26.     {  
  27.         return poCT;  
  28.     }  
  29. }  
         其中 LoadProjLibrary 的含义很明显,就是加载prj4 库。我们再看看 LoadProjLibrary 函数

[cpp]  view plain copy
  1. static int LoadProjLibrary()  
  2.   
  3. {  
  4.     CPLMutexHolderD( &hPROJMutex );  
  5.     static int  bTriedToLoad = FALSE;  
  6.     const char *pszLibName;  
  7.       
  8.     if( bTriedToLoad )  
  9.         return( pfn_pj_transform != NULL );  
  10.   
  11.     bTriedToLoad = TRUE;  
  12.   
  13.     pszLibName = GetProjLibraryName();  
  14.   
  15. #ifdef PROJ_STATIC  
  16.     pfn_pj_init = pj_init;  
  17.     pfn_pj_init_plus = pj_init_plus;  
  18.     pfn_pj_fwd = pj_fwd;  
  19.     pfn_pj_inv = pj_inv;  
  20.     pfn_pj_free = pj_free;  
  21.     pfn_pj_transform = pj_transform;  
  22.     pfn_pj_get_errno_ref = (int *(*)(void)) pj_get_errno_ref;  
  23.     pfn_pj_strerrno = pj_strerrno;  
  24.     pfn_pj_dalloc = pj_dalloc;  
  25. #if PJ_VERSION >= 446  
  26.     pfn_pj_get_def = pj_get_def;  
  27. #endif      
  28. #else  
  29.     CPLPushErrorHandler( CPLQuietErrorHandler );  
  30.   
  31.     pfn_pj_init = (projPJ (*)(intchar**)) CPLGetSymbol( pszLibName,  
  32.                                                        "pj_init" );  
  33.     CPLPopErrorHandler();  
  34.       
  35.     if( pfn_pj_init == NULL )  
  36.        return( FALSE );  
  37.   
  38.     pfn_pj_init_plus = (projPJ (*)(const char *))   
  39.         CPLGetSymbol( pszLibName, "pj_init_plus" );  
  40.     pfn_pj_fwd = (projUV (*)(projUV,projPJ))   
  41.         CPLGetSymbol( pszLibName, "pj_fwd" );  
  42.     pfn_pj_inv = (projUV (*)(projUV,projPJ))   
  43.         CPLGetSymbol( pszLibName, "pj_inv" );  
  44.     pfn_pj_free = (void (*)(projPJ))   
  45.         CPLGetSymbol( pszLibName, "pj_free" );  
  46.     pfn_pj_transform = (int (*)(projPJ,projPJ,long,int,double*,  
  47.                                 double*,double*))  
  48.                         CPLGetSymbol( pszLibName, "pj_transform" );  
  49.     pfn_pj_get_errno_ref = (int *(*)(void))  
  50.         CPLGetSymbol( pszLibName, "pj_get_errno_ref" );  
  51.     pfn_pj_strerrno = (char *(*)(int))  
  52.         CPLGetSymbol( pszLibName, "pj_strerrno" );  
  53.   
  54.     CPLPushErrorHandler( CPLQuietErrorHandler );  
  55.     pfn_pj_get_def = (char *(*)(projPJ,int))  
  56.         CPLGetSymbol( pszLibName, "pj_get_def" );  
  57.     pfn_pj_dalloc = (void (*)(void*))  
  58.         CPLGetSymbol( pszLibName, "pj_dalloc" );  
  59.     CPLPopErrorHandler();  
  60.   
  61. #endif  
  62.   
  63.     if( pfn_pj_transform == NULL )  
  64.     {  
  65.         CPLError( CE_Failure, CPLE_AppDefined,   
  66.                   "Attempt to load %s, but couldn't find pj_transform.\n"  
  67.                   "Please upgrade to PROJ 4.1.2 or later.",   
  68.                   pszLibName );  
  69.   
  70.         return FALSE;  
  71.     }  
  72.   
  73.     return( TRUE );  
  74. }  

         gdal库集成prj4库有两种方式:静态库集成和动态库集成,使用预处理器PROJ_STATIC。首先看看静态库集成:

[cpp]  view plain copy
  1. pfn_pj_init = pj_init;  
  2. pfn_pj_init_plus = pj_init_plus;  
  3. pfn_pj_fwd = pj_fwd;  
  4. pfn_pj_inv = pj_inv;  
  5. pfn_pj_free = pj_free;  
  6. pfn_pj_transform = pj_transform;  
  7. pfn_pj_get_errno_ref = (int *(*)(void)) pj_get_errno_ref;  
  8. pfn_pj_strerrno = pj_strerrno;  
  9. pfn_pj_dalloc = pj_dalloc;  

           这里只是函数指针的赋值,那么函数调用的地方在哪里呢?我并没有找到。动态库集成就更扯淡了,首先通过GetProjLibraryName函数获取prj4库的动态库名字,这里名字规定为:

[cpp]  view plain copy
  1. #if (defined(WIN32) || defined(WIN32CE)) && !defined(__MINGW32__)  
  2. #  define LIBNAME      "proj.dll"  
  3. #elif defined(__CYGWIN__) || defined(__MINGW32__)  
  4. // XXX: If PROJ.4 library was properly built using libtool in Cygwin or MinGW  
  5. // environments it has the interface version number embedded in the file name  
  6. // (it is CURRENT-AGE number). If DLL came somewhere else (e.g. from MSVC  
  7. // build) it can be named either way, so use PROJSO environment variable to  
  8. // specify the right library name. By default assume that in Cygwin/MinGW all  
  9. // components were buit in the same way.  
  10. #  define LIBNAME      "libproj-0.dll"  
  11. #elif defined(__APPLE__)  
  12. #  define LIBNAME      "libproj.dylib"  
  13. #else  
  14. #  define LIBNAME      "libproj.so"  
  15. #endif  
  

          也就是说假如在windows平台下不叫proj.dll,压根加载不了prj4库,还有致命一条:proj.dll究竟放在哪个路径下呢?据我经验,LoadLibrary没有指定路径的话,在Windows平台只能在当前目录和在系统环境变量路径中找到,具体见:关于DLL搜索路径的顺序问题。动态库集成和静态库集成存在一样的问题,只找到函数地址,并不见调用的地方。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值