前面寫了用GDAL讀取數據集和波段信息,使用GDAL最重要的就是讀取圖像的波段數據,因為對圖像的處理就是對數據(也可以說是像素點)的處理。這里討論下gdal讀取波段數據。
參考文章:http://www.gdal.org/gdal_tutorial.html
這里有個中文翻譯版,翻譯的還是可以的:http://opencv-extension-library.googlecode.com/svn/doc/gdal-doc/gdal_tutorial.html
讀取波段數據
gdal讀取波段數據的接口為RasterIO,這是一個及其重要的函數,GDALDataset和GDALRasterBand類都有這個函數,利用GDALDataset類中的RasterIO時可以按指定波段數並按一定的波段序讀取數據,GDALRasterBand類中的RasterIO可以讀取該波段的數據,讀數據時可以全部讀取、讀取某一塊或抽樣讀取。用的多的是GDALRasterBand類的RaterIO函數,下面就說下這個函數,函數原型如下:
CPLErr GDALRasterBand::RasterIO (
GDALRWFlag eRWFlag, //讀寫標志。GF_Read:讀取數據到緩存 GF_Write:將緩存中數據寫入數據集的波段
int nXOff, //起始X方向像素位置
int nYOff, //起始Y方向像素位置
int nXSize, //數據的X方向像素大小
int nYSize, //數據的Y方向像素大小 注:以上四個參數制定了要讀取數據的位置和大小
void * pData, //緩存
int nBufXSize, //緩存的X方向像素大小
int nBufYSize, //緩存的Y方向像素大小
GDALDataType eBufType, //數據類型,指定緩存中的數據類型
int nPixelSpace, //讀取每個像素的字節偏移量,即下一個讀取的的像素與此時讀取的像素的字節距離,默認為0
int nLineSpace //讀取每一行像素的字節偏移量,默認為0
)
參數意義見注釋,
nPixelSpace為0時,表示偏移的字節量為eBufType大小的字節數
nLineSpace為0時,表示偏移的字節量為eBufType * nBufXSize字節數
采樣實現:設置最后兩個參數,設置nPixelSpace指定每行隔幾個像素點進行讀取,設置nLineSpace指定每隔幾行讀取,注意緩存的大小。
對數據全部讀取示例:
//數據集注冊及對象獲取這里不贅述,見上篇
int sizeX = poDataset->GetRasterXSize();
int sizeY = poDataset->GetRasterYSize();
unsigned char *pMemData1;
pMemData = (unsigned char*)CPLMalloc(sizeX * sizeY);
poBand = poDataset->GetRasterBand(1);
poBand->RasterIO(GF_Read,
0,0,
sizeX,sizeY,
pMemData,
sizeX,sizeY,
GDT_Byte,
0,0);
CPLFree(pMemData);
有時,需要每行進行字節對齊,即每行的字節數為8的倍數,即位數為32的倍數(32位系統一個內存單元是32位),對於上面的情況,如下:
bytePerLine=(sizeX*8=31)/32*4 即pMemData每行的位數就是32的倍數了(為什么這樣計算,自個體會吧)
每行的字節對齊后,pMemData每行就不是sizeX了,應該是bytePerLine,對應上面的代碼也要改變。
分塊讀取:
這里,如果圖像很大,一般遙感圖像,特別是高分辨率圖像數據量都很大,直接全部讀取對於內存開銷會很大,這時可以采取分塊讀取的方法,比如每100為一個數據塊進行讀取,這樣可以減小內現存開銷。分塊的例子(以每100行為一塊為例):
int sizeX = poDataset->GetRasterXSize();
int sizeY = poDataset->GetRasterYSize();
unsigned char *pMemData1;
//100行一塊
pMemData = (unsigned char*)CPLMalloc(sizeX * 100);
poBand = poDataset->GetRasterBand(1);
for(int i=0;i<sizeY/100;i++)
{
poBand->RasterIO(GF_Read,
0,i*100,
sizeX,100,
pMemData,
sizeX,100,
GDT_Byte,
0,0);
}
CPLFree(pMemData);
注意:上面的代碼中還有最后剩下的不到100行的數據沒有讀,這里只為了說明怎么分塊,剩下的數據就不管了。實際中千萬要加上。
讀取完后申請的內存要記得釋放掉。
GDALRasterBand類的RasterIO函數可以滿足大部分要求,也比較容易理解,波段多時大不了多用幾次。GDALDataset類的RasterIO目前沒怎么用,只是多了幾個參數,功能更強大,需要時再去用吧。