GDAL的RASTERIO功能


 
        為了能快速的顯示大影像,最近一直在學習GDAL,GDAL確實是一個功能強大的開源庫,其核心部分數據集和波段,下面這個圖很詳細的描述了它們之間的關系,還有其中的細節:

     GDAL的RASTERIO功能非常強大,簡短的一句話就能實現圖像的顯示,但也是這個簡單函數,把我折騰的半死。在學習使用GDAL的過程中,非常感謝李林大哥和貟建明大哥,他們不厭其煩地解答我的疑問,提示關鍵性要點,使我在解決問題的過程中事半功倍。
      我現在要把最近學習過程中的心得寫下來,留給自己以后看看,也希望可以給新手們一點幫助!
     
GDALAllRegister();    
const char*    str ;
    
m_pDataset = (GDALDataset*) GDALOpen( str, GA_ReadOnly );
    這一部分應該很好理解,首先打開一個影像,我們必須注冊其驅動,因為每種不同的柵格數據都有不同的驅動,也就是driver。之后我們就可以用GDALOpen()函數來打開一個數據集dataset,如果打開的格式並不是GDAL支持的,我們就需要通過 new GDALDriver()創建一個新的driver並設置,這樣才能打開。如果GDALOpen()函數返回NULL,表示打開文件失敗。
    打開了一個dataset之后,我們就可以對dataset的內部信息進行操作,dtaset的詳細信息以及內部的關系在上圖表述的非常詳細。
m_pDataset->GetGeoTransform( m_AdfGeoTransform );
上面這行代碼是用來獲取仿射信息用的,m_AdfGeoTransform是一個含6個元素的數組,執行了這行代碼后,我們就可以獲取m_AdfGeoTransform數組的信息,m_AdfGeoTransform[0],m_AdfGeoTransform[3]是整個影像的坐下角坐標,m_AdfGeoTransform[1]是影像寬度上的分辨率,m_AdfGeoTransform[5]是影像高度上的分辨率,而對於m_AdfGeoTransform[2]和m_AdfGeoTransform[4]來說,如果影像是指北的,這兩個參數的值為0。有了這幾個參數,我們就能通過以下兩行代碼求出影像左下角和右上角的信息:
XMin = m_AdfGeoTransform[0];
YMin = m_AdfGeoTransform[3];

XMax = m_AdfGeoTransform[0] + nX * m_AdfGeoTransform[1] + m_AdfGeoTransform[2]; 
YMax = m_AdfGeoTransform[3] + m_AdfGeoTransform[4] + nY * m_AdfGeoTransform[5]; 

    有了影像的信息之后,我們要做的就是將影像顯示出來,這里就有一個分辨率的問題,一個是圖像分辨率,一個是顯示分辨率。圖像分辨率就是單位長度內的像素數,而顯示分辨率就是把數字圖像在輸出設備(比如顯示屏或打印機等)上能夠顯示的像素數目和所顯示像素之間的點距。這兩個分辨率在顯示影像的時候非常有作用。弄清楚原理的東西確實是成功的基石!
    然后就到了GDAL的核心部分了:
pBuffer = (BYTE*) CPLMalloc(sizeof(BYTE)*(xBuf)*(yBuf)*nBand);

m_pDataset->RasterIO( GF_Read, xSrc, ySrc, xWidth, yHight, pBuffer, xBuf, yBuf,GDT_Byte, nBand, NULL, nBand, 0, 1 );    
對於三個波段以上的影像,我們可以直接通過以上兩行代碼講影像讀入pBuffer這個內存,然后根據我們的需要,比如說OPENGL,我們就可以利用glDrawPixels( )這個函數直接顯示出影像了。現在關鍵的地方就是RasterIO里面的幾個參數了,對照GDAL官方的函數說明:
GDALDataset::RasterIO  (  GDALRWFlag  eRWFlag,  
        int  nXOff,  
        int  nYOff,  
        int  nXSize,  
        int  nYSize,  
        void *  pData,  
        int  nBufXSize,  
        int  nBufYSize,  
        GDALDataType  eBufType,  
        int  nBandCount,  
        int *  panBandMap,  
        int  nPixelSpace,  
        int  nLineSpace,  
        int  nBandSpace 
 )  

如果為GF_Read,則是將影像內容寫入內存,如果為GF_Write,則是將內存中內容寫入文件。
nXOff,nYOff,nXSize,nYSize這四個參數是用於影像的,nXOff,nYOff就是說我們要從影像的這個像素坐標開始取數據,nXSize,nYSize就是從影像上取數據的寬度和高度,也就是說要從影像上取出來的數據范圍是(nXOff,nYOff)到(nXOff+nXSize,nYOff+nYSize)。如果我們要顯示這個取出來的范圍,我們就要把這個數據域寫入緩存pData中,nBufXSize,nBufYSize即是這個緩存區的大小范圍。
       RasterIO這個函數只有這些說明,那我們在應用的時候就需要根據我們的實際需要計算,如果有一幅100M的影像,你想快速顯示,那么這六個參數的設置就是關鍵,不過有一個前提條件就是這個影像是金字塔影像,這樣你設置好了buffer的size,那么GDAL就會根據GDAL內部函數的實現過程,自動幫你完成縮放操作(把nXSize,nYSizen的數據縮放到BufXSize,nBufYSize的buffer里顯示),而並不需要你去控制獲取哪個overview,由於開始我並沒有理解透這個函數的真正含義,在大影像的顯示上走了很多彎路,自己去判斷要讀金字塔的第幾層,以至於自己都把自己快搞崩潰了,這里要非常感謝李林大哥,呵呵,每個細節都給我講的很詳細,並且對於一些抽象的東西他也耐心的給我舉些例子,加上自己的時間,最后終於明白了這個函數的原理所在。呵呵,在這里要真摯的感謝李大哥。 
       nBufXSize,nBufYSize這個緩存區的大小范圍,決定了我們要在多大的屏幕范圍顯示你想顯示的圖像內容,因此我們要根據屏幕范圍和縮放比例來計算這個buffer的size。
      nPixelSpace表示一個像素所占byte大小,假如是24位的,那么一個像素就占3個字節,那么nPixelSpace =  3。nLineSpace表示一行所占大小,如果設為0的話,就默認為nBufXSize*nBufYSize。
nBandSpace為一個波段數據所占大小,如果設為0的話,就是以RRRGGGBBB這種形式存儲,如果設為1的話,就是以RGBRGBRGB這種形式存儲。
    不過這個函數還是要自己試了才知道真正的意義,呵呵,希望新手少走我的彎路!!以后還會陸續添加自己的學習心得的,^_^Fighting!!!o(∩_∩)o...
 
分類:  編程相關


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM