?
作者:朱金燦
來源: http://blog.csdn.net/clever101
?
???????? 最近使用gdal庫比較多,就談?wù)刧dal庫的一些使用心得。
???????? 第一個是GDALOpen的訪問權(quán)限參數(shù)會影響圖像的創(chuàng)建金字塔方式。比如你是這樣打開圖像和創(chuàng)建金字塔:
?
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);
?
?
??? ??? 運行完這段代碼之后你會奇怪地發(fā)現(xiàn)在圖像文件所在的文件夾并沒有ovr文件或rrd文件出現(xiàn),那么究竟有沒有金字塔生成呢?實際上是有的。那么圖像金字塔數(shù)據(jù)究竟存儲在哪里,我猜測是存儲在圖像文件本身去了。為何這么說呢?因為我試著把第一行代碼的 GA_Update 改為GA_ReadOnly ,結(jié)果出現(xiàn)了ovr文件,也就是說當(dāng)設(shè)置為GA_Update,金字塔數(shù)據(jù)是有可能放在圖像文件的,當(dāng)然我沒有確認(rèn)。這里還有一些疑問:如果金字塔數(shù)據(jù)是存儲在文件里,那么對于tif文件具體是存儲在哪里?對于其它圖像文件又是存儲在哪里呢?
?????
??????? 第二個在調(diào)用完RasterIO 函數(shù)對圖像進行寫入操作之后只是保留在緩存,需要再調(diào)用FlushCache函數(shù)才能真正把數(shù)據(jù)寫到磁盤去。
?
?????? 第三個是網(wǎng)上有一篇關(guān)于坐標(biāo)轉(zhuǎn)換的教程: GDAL庫學(xué)習(xí)筆記( 五):坐標(biāo)系之間的轉(zhuǎn)化。其中有一段代碼是這樣的:
?
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總是執(zhí)行失敗。后來看了gdal的源碼,發(fā)現(xiàn)ogr集成prj4庫進行投影坐標(biāo)轉(zhuǎn)換頗有些坑爹的地方。我們看一些OGRCreateCoordinateTransformation函數(shù)大致是怎么做的:
?
OGRCreateCoordinateTransformation函數(shù)大致是怎么做的: 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 函數(shù) :
?
?
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庫有兩種方式:靜態(tài)庫集成和動態(tài)庫集成,使用預(yù)處理器 PROJ_STATIC 。首先看看靜態(tài)庫集成:
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;
?
?????????? 這里只是函數(shù)指針的賦值,那么函數(shù)調(diào)用的地方在哪里呢?我并沒有找到。動態(tài)庫集成就更扯淡了,首先通過 GetProjLibraryName 函數(shù)獲取prj4 庫的動態(tài)庫名字,這里名字規(guī)定為:
#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究竟放在哪個路徑下呢?據(jù)我經(jīng)驗,LoadLibrary沒有指定路徑的話,在Windows平臺只能在當(dāng)前目錄和在系統(tǒng)環(huán)境變量路徑中找到,具體見: 關(guān)于DLL搜索路徑的順序問題 。動態(tài)庫集成和靜態(tài)庫集成存在一樣的問題,只找到函數(shù)地址,并不見調(diào)用的地方。
?
?
?
?
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
