1. 程式人生 > >GDAL分塊處理簡單的流程

GDAL分塊處理簡單的流程

GDAL分塊處理簡單的流程

 

GDAL分塊處理流程

使用GDAL庫在編寫影象處理演算法時,為了提高處理的效率,經常會進行分塊處理,下面的程式碼是使用GDAL分塊處理的一個簡單示例:

影象分塊程式碼

影像分塊程式碼,只有輸入輸出影象路徑,對原始影象經過一定的處理,將結果寫入輸出影象。此處原始影象和結果影象的大小完全一致。具體流程參考下面的程式碼以及裡面的註釋部分。

#include "gdal_priv.h"

bool ImageProcess(const char* pszSrcFile, const char* pszDstFile, const char* pszFormat)
{
    //註冊GDAL驅動
    GDALAllRegister();

    //獲取輸出影象驅動
    GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
    if (poDriver == NULL)   //輸出檔案格式錯誤
        return false;

    //開啟輸入影象
    GDALDataset *poSrcDS = (GDALDataset*)GDALOpen(pszSrcFile, GA_ReadOnly);
    if (poSrcDS == NULL)    //輸入檔案開啟失敗
        return false;

    //獲取輸入影象的寬高波段書
    int nXSize = poSrcDS->GetRasterXSize();
    int nYSize = poSrcDS->GetRasterYSize();
    int nBands = poSrcDS->GetRasterCount();

    //獲取輸入影象仿射變換引數
    double adfGeotransform[6] = { 0 };
    poSrcDS->GetGeoTransform(adfGeotransform);
    //獲取輸入影象空間參考
    const char* pszProj = poSrcDS->GetProjectionRef();

    GDALRasterBand *poBand = poSrcDS->GetRasterBand(1);
    if (poBand == NULL)    //獲取輸入檔案中的波段失敗
    {
        GDALClose((GDALDatasetH)poSrcDS);
        return false;
    }

    //建立輸出影象,輸出影象是1個波段
    GDALDataset *poDstDS = poDriver->Create(pszDstFile, nXSize, nYSize, 1, GDT_Byte, NULL);
    if (poDstDS == NULL)    //建立輸出檔案失敗
    {
        GDALClose((GDALDatasetH)poSrcDS);
        return false;
    }

    //設定輸出影象仿射變換引數,與原圖一致
    poDstDS->SetGeoTransform(adfGeotransform);
    //設定輸出影象空間參考,與原圖一致
    poDstDS->SetProjection(pszProj);

    int nBlockSize = 256;     //分塊大小

    //分配輸入分塊快取
    unsigned char *pSrcData = new unsigned char[nBlockSize*nBlockSize*nBands];
    //分配輸出分塊快取
    unsigned char *pDstData = new unsigned char[nBlockSize*nBlockSize];

    //定義讀取輸入影象波段順序
    int *pBandMaps = new int[nBands];
    for (int b = 0; b < nBands; b++)
        pBandMaps[b] = b + 1;

    //迴圈分塊並進行處理
    for (int i = 0; i < nYSize; i += nBlockSize)
    {
        for (int j = 0; j < nXSize; j += nBlockSize)
        {
            //定義兩個變數來儲存分塊大小
            int nXBK = nBlockSize;
            int nYBK = nBlockSize;

            //如果最下面和最右邊的塊不夠256,剩下多少讀取多少
            if (i + nBlockSize > nYSize)     //最下面的剩餘塊
                nYBK = nYSize - i;
            if (j + nBlockSize > nXSize)     //最右側的剩餘塊
                nXBK = nXSize - j;

            //讀取原始影象塊
            poSrcDS->RasterIO(GF_Read, j, i, nXBK, nYBK, pSrcData, nXBK, nYBK, GDT_Byte, nBands, pBandMaps, 0, 0, 0, NULL);

            //再這裡填寫你自己的處理演算法
            //pSrcData 就是讀取到的分塊資料,儲存順序為,先行後列,最後波段
            //pDstData 就是處理後的二值圖資料,儲存順序為先行後列

            memcpy(pDstData, pSrcData, sizeof(unsigned char)*nXBK*nYBK);
            //上面這句是一個測試,將原始影象的第一個波段資料複製到輸出的影象裡面

            //寫到結果影象
            poDstDS->RasterIO(GF_Write, j, i, nXBK, nYBK, pDstData, nXBK, nYBK, GDT_Byte, 1, pBandMaps, 0, 0, 0, NULL);
        }
    }

    //釋放申請的記憶體
    delete[]pSrcData;
    delete[]pDstData;
    delete[]pBandMaps;

    //關閉原始影象和結果影象
    GDALClose((GDALDatasetH)poSrcDS);
    GDALClose((GDALDatasetH)poDstDS);

    return true;
}