一個小測試程序開發全過程實錄,完全新手入門級的實例,如果你還在爲處理大影像而發愁,來試試這個稱手的工具吧。
Imagec 開發日記
2013-6-25
需求:
影像數據切割,重採樣
數據切割的要求是簡單的給予矩形的等分切割,並以2的冪次爲分割單元,無需使用AOI裁切,
重採樣需要實現多種採樣模式,用戶可以切換採樣模式(下文中所提供的代碼只是利用了RasterIO的一個特性使用了默認的最近鄰重採樣方法)
基本思路
考慮是否存在使實用的gdal接口,
自行設計,利用GDAL的讀寫接口完成數據輸入輸出工作
初步瞭解,GDAL並不提供現成的切割和重採樣的接口。
/////////////////////////////////////////////////////////////////////
2013-6-26
確定使用自己的方法實現:
裁切
1、讀入數據
2、設置剪切範圍
3、完成裁切,將數據寫入目標文件
2013-6-27
重採樣
1.讀入數據
2.借鑑Warp工具代碼重寫重採樣代碼
將數據寫入目標文件
2013-6-28
重採樣2
1.讀入數據
2.使用RasterIO自帶的重採樣功能
3.數據寫入目標文件
////////////////////////////////////////////////////////////////////////////
2013-6-27
實現算法
裁切:
讀入文件
GDALDataset *poDataset;
GDALAllRegister();
//open a dataset
poDataset =(GDALDataset *)GDALOpen(fn,GA_ReadOnly);
if(poDataset == NULL)
設置相關參數爲實現裁切做準備
char **papsOptions = NULL;
const int iXSize = poSrcDS->GetRasterXSize()/2;
const int iYSize = poSrcDS->GetRasterYSize()/2;
int iSize = GDALGetBandTypeSize(GDT_Byte)/8;
//生成一個用於存放數據的緩存空間
poDstDS = poDriver->Create(fnDst,iXSize,iYSize,3,GDT_Byte,papsOptions);
GByte *abyByte = new GByte[iXSize*iYSize*bandCount];
int bandMap[3] = {1,2,3};
const char *pszSRS_WKT = poSrcDS->GetProjectionRef();
poDstDS->SetProjection(pszSRS_WKT);
poDstDS->SetGeoTransform(adfGeoTransform);
//進行裁切工作,讀取原始的數據,寫入目標文件
poSrcDS->RasterIO(GF_Read,0,0,iXSize,iYSize,abyRater,
iXSize,iYSize,GDT_Byte,bandCount,bandMap,iSize*bandCount,iSize*iXSize*3,iSize);
poDstDS->RasterIO(GF_Write,0,0,iXSize,iYSize,abyRater,
iXSize,iYSize,GDT_Byte,bandCount,bandMap,iSize*bandCount,iSize*iXSize*3,iSize);
////////////////////////////////////////////////////////////////
//數據重採樣實現:
打開數據
GDALDataset *SrcDS = (GDALDataset *)GDALOpen(fn,GA_ReadOnly);
爲RasterIO設置一些必要參數:
const char *strWkt =pSrcDS->GetProjectionRef();
int bandCount = pSrcDS->GetRasterCount();
int iSize = GDALGetDataTypeSize(GDT_Byte)/8;
int bandMap = {1,2,3};
double adfGeoTransform[6];
pSrcDS->GetGeoTransformation(adfGeoTransform);
double dProj[4] ={0};
ImageRowCol2Projection(adfGeoTransform,0,0,dProj[0],dProj[2]);//具體參考李明錄重採樣博文
ImageRowCol2Projection(adfGeoTransform,pSrcDS->GetRasterXSize(),pSrcDS->GetRasterYSize(),dProj[1],dProj[3]);
double maxX = dProj[0] >dProj[1]?dProj[0]:dProj[1];
double minX = dProj[0]<dProj[1]?dProj[1]:dProj[0];
double maxY = dProj[2]>dProj[3]?dProj[2]:dProj[3];
double minY = dProj[2]<dProj[3]?dProj[2]:dProj[3];
double fResX = 2;
double fResY = 2;
adfGeoTransform[0] = maxX;
adfGeoTransform[3] = maxY;
adfGeoTransform[1] = adfGeoTransform[1]/fResX;
adfGeoTransform[4] = adfGeoTransform[5]/fResY;
//得到輸出圖像長寬
int iNewWidth = static_cast<int>((maxX-minX)/ABS(adfGeoTransform[1]) + 0.5);
int iNewHeight = static_cast<int>((maxY-minY)/ABS(adfGeoTransform[5]) + 0.5);
GByte *abyraster2= new GByte[iNewWidth*iNewHeight*bandCount];
創建輸出文件:
GDALDataset *pDstDS2 = poDriver->Create("good.img",
iNewWidth,iNewHeight,3,GDT_Byte,NULL);
設置輸出數據的投影:
pDstDS2->SetGeoTransform(adfGeoTransform);
pDstDS2->SetProjection(strWkt);
使用RasterIO實現數據讀寫:(重採樣全在這讀寫之間,參考第一篇文獻的 第四種方式 一節)
pSrcDS->RasterIO(GF_Read,0,0,pSrcDS->GetRasterXSize(),pSrcDS->GetRasterYSize(),abyraster2,
iNewWidth,iNewHeight,GDT_Byte,bandCount,bandMap,iSize*bandCount,
iSize*iNewWidth*3,iSize);
pDstDS->RasterIO(GF_Write,0,0,iNewWidth,iNewHeight,GDT_Byte,bandCount,bandMap,iSize*bandCount,
iSize*iNewWidth*3,iSize);
完成讀寫後關閉打開的數據集,釋放佔用的內存
if(pDstDS != NULL)
{
GDALClose((GDALDatasetH)pDstDS2);
}
GDALClose((GDALDatasetH)pSrcDS);
報錯實例
沒有註冊驅動導致數據讀取失敗
GDALAllRegister();
ERROR 4'../image/result.img' not recognized as a supported format.
投影問題
setGeoTransform 無法爲輸出圖像計算一個投影
參考文獻