對於通常的遙感影像文件,金字塔文件默認都是與影像文件放在同一個目錄下,金字塔文件名通常與源影像文件名相同,但後綴名不一樣。或者金字塔內建於影像內部,但這不是這裏所涉及的。
在使用ArcGIS桌面版或者Erdas遙感影像處理軟件打開遙感影像文件的時候,若是影像不含(帶有)金字塔,則會提示是否建立金字塔。git
咱們碰到這麼一種狀況,就是原始影像是不帶金字塔的,而且所在的目錄不容許修改,也就是不能將金字塔建立在其中,原始影像文件更是不容許修改,因此也不能更新內建金字塔。github
對於這個問題,爲了加速影像的瀏覽,只能將金字塔創建在外部的目錄,而讀取的時候根據讀取輸出的分辨率,來確認是使用源影像讀取仍是使用金字塔文件讀取,這都須要本身控制。
由於本身控制會將一些控制流程變複雜,因此我想讓GDAL直接支持索引到這個外部的金字塔文件。函數
在GDAL中,金字塔稱之爲Overviews(概覽視圖),因此與之相關的接口都帶有Overview單詞。ui
我看了GDAL的RasterIO流程相關的代碼,簡單的製做了以下的流程圖:指針
與金字塔路徑查找的關鍵代碼在函數GDALDefaultOverviews::OverviewScan()
中。code
經過查看其實現代碼,和被調用時候的參數(參數在GDALDefaultOverviews::Initialize
函數被調用的時候肯定,能夠搜索poDS->oOvManager.Initialize
查看,都是在對應格式的XXXDataset::Open()函數中被調用,不一樣格式影像調用時候傳的參數可能不一樣),能夠知道GDAL搜尋金字塔的方式與順序。orm
這裏不詳細說這裏面的流程結構了,一些判斷條件也略過,只大概說一下搜索順序(若是有內建金字塔則不會讀取外部金字塔):blog
.ovr
後綴金字塔文件.aux
後綴金字塔文件.rrd
後綴金字塔文件(若是配置有USE_RRD=YES)OVERVIEW_FILE
指定的金字塔路徑若是須要使用到自定義的金字塔文件,能夠在此處修改,添加一段搜索代碼,示例以下:索引
if( poODS == nullptr ) { osOvrFilename = MyOverviewFileSearch(pszInitName); poODS = GDALDataset::Open(osOvrFilename, GDAL_OF_RASTER | (poDS->GetAccess() == GA_Update ? GDAL_OF_UPDATE: 0)); }
MyOverviewFileSearch是用於搜索自定義路徑下金字塔的函數。接口
上面說若是有內建金字塔則不會讀取外部金字塔,這個其實是各個影像文件格式的相關代碼裏面本身定義的。
由於virtual GDALRasterBand* GDALRasterBand::GetOverview(int);
原本就是一個虛函數,而GDAL中又基本都是依賴指針進行操做,因此實際上會調用各自的實現。
以GeoTiff格式爲例,在它的Overview相關函數中就是先搜索Tiff目錄內的金字塔,若是找不到才調用GDALRasterBand
中對應的接口,進而訪問外部金字塔文件。
例如如下代碼:
/************************************************************************/ /* GetOverviewCount() */ /************************************************************************/ int GTiffRasterBand::GetOverviewCount() { poGDS->ScanDirectories(); if( poGDS->nOverviewCount > 0 ) { return poGDS->nOverviewCount; } const int nOverviewCount = GDALRasterBand::GetOverviewCount(); if( nOverviewCount > 0 ) return nOverviewCount; // Implicit JPEG overviews are normally hidden, except when doing // IRasterIO() operations. if( poGDS->nJPEGOverviewVisibilityCounter ) return poGDS->GetJPEGOverviewCount(); return 0; } /************************************************************************/ /* GetOverview() */ /************************************************************************/ GDALRasterBand *GTiffRasterBand::GetOverview( int i ) { poGDS->ScanDirectories(); if( poGDS->nOverviewCount > 0 ) { // Do we have internal overviews? if( i < 0 || i >= poGDS->nOverviewCount ) return nullptr; return poGDS->papoOverviewDS[i]->GetRasterBand(nBand); } GDALRasterBand* const poOvrBand = GDALRasterBand::GetOverview( i ); if( poOvrBand != nullptr ) return poOvrBand; // For consistency with GetOverviewCount(), we should also test // nJPEGOverviewVisibilityCounter, but it is also convenient to be able // to query them for testing purposes. if( i >= 0 && i < poGDS->GetJPEGOverviewCount() ) return poGDS->papoJPEGOverviewDS[i]->GetRasterBand(nBand); return nullptr; }
上面代碼中的poGDS->ScanDirectories();
語句,內部調用去遍歷Tiff目錄,找到TIFFTAG_SUBFILETYPE
(子文件類型)字段爲FILETYPE_REDUCEDIMAGE
(縮小圖像)的目錄,而後解析出須要的金字塔信息(僅第一次調用時作,後面調用會判斷bScanDeferred直接跳過)。
若是沒有找到才調用基類GDALRasterBand
對應的函數去訪問外部金字塔。
構建也是差很少的過程,這裏就簡單的寫一下調用過程:GDALDataset::BuildOverviews ---> GDALDataset::IBuildOverviews ---> GDALDefaultOverviews::BuildOverviews
因此設置構建外部金字塔的路徑,也能夠修改GDALDefaultOverviews::BuildOverviews
。
一樣,對於不一樣的影像格式,能夠有本身的GDALDataset::IBuildOverviews
實現,例如GeoTiff的就是GTiffDataset::IBuildOverviews
,若是須要建立內建的金字塔,則作另外的實現。