?
作者:朱金燦
來源: 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搜索路徑的順序問題 。動態庫集成和靜態庫集成存在一樣的問題,只找到函數地址,并不見調用的地方。
?
?
?
?
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

