gdal库的三个使用心得

系统 2522 0

 

作者:朱金灿

来源: 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库的三个使用心得


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论