天天看點

VC GDAl 讀取并顯示圖像

GDAL是一個操作各種栅格和矢量地理資料格式的開源庫。包括讀取、寫入、轉換、處理各種栅格和矢量資料格式。它支援各種圖像格式,其詳細清單見: http://www.gdal.org/formats_list.htm  。

 完成了圖像的讀取和顯示,但不知這種方法是否為最佳,請各位指正,謝謝!

本文就以VC為開發平台介紹GDAL對圖像資料的操作方法。

1.首先進行GDAl的配置工作,這在上文中已經提到,不再做陳述。

2.然後,我是在Doc類裡面添加OnOpenDocument(LPCTSTR lpszPathName)函數,其具體的操作在其中進行。建立檔案對話框:,傳回lpszPathName.

CFile file;

CFileException fe;

if (!file.Open(lpszPathName,CFile::modeRead | CFile::shareDenyWrite,&fe))

{

ReportSaveLoadException(lpszPathName,&fe,FALSE,AFX_IDP_FAILED_TO_CREATE_DOC);

return FALSE;

}

3.函數中,首先的進行驅動的注冊。所使用的函數是GDALAllRegister()函數,然後進行打開檔案操作,這裡介紹一個DataSet概念,在GDAL中可以說資料的核心就是Dataset,簡單來說可以将Dataset就了解為圖像檔案。在資料集下最重要組成部分就是所謂的波段band,檔案的打開使用的是:GDALOpen函數。

GDALDataset * DataSet; // 在這裡資料集即為了解為圖像檔案

GDALAllRegister(); //注冊驅動,這項萬不可少,必要步驟。

DataSet = (GDALDataset *)GDALOpen(lpszPathName,GA_ReadOnly);//檔案的打開使用的是GDALOpen函數

4.在确認DataSet不是NULL的情況下就可以對圖像資料集進行操作了。

if (DataSet == NULL)

{

AfxMessageBox("無法打開遙感圖像");

return 0;

}

 5.接下來,我們就開始進入到波段處理。波段的擷取使用GetRasterBand函數,

GDALRasterBand **pBand; //資料集下最重要的成分波段。

int m_Bands = DataSet->GetRasterCount();

pBand = new GDALRasterBand * [m_Bands]; //建立波段

if (pBand == NULL)

{

AfxMessageBox("建立資料集波段失敗");

return 0;

}

for (int i =0;i<m_Bands;i++)

{

pBand[i] = DataSet->GetRasterBand(i+1);//預讀取遙感的第一個波段,因該是這個作用吧!

if (pBand[i] == NULL)

{

AfxMessageBox("建立i波段資料集失敗!");

return 0;

}

}

6,建立一個對話框,其布局如圖所示:

VC GDAl 讀取并顯示圖像

對話框的設計此處就不作詳述啦,它的作用是傳回顯示模式以及波段選擇。

CDlgBands dlg;

dlg.m_mBands = m_Bands;

if (dlg.m_mBands == 1)

{

dlg.mBandsType = 0;

}

else

{

dlg.mBandsType = 1;

}

dlg.DoModal();

7,進入我認為最重要的步驟:波段資料的讀寫核心函數就是RasterIO。這個函數可以将圖像的某一個子塊讀入或寫入。當然此處要判斷一下要打開的的是灰階圖像還是彩色圖像。

if (dlg.mBandsType == 0)//打開灰色圖像

{

BandsType = dlg.mBandsType;

BdCGray = dlg.BdChoiceGray;

if (pBand[BdCGray] == NULL)

{

return 0;

}

nXsize = pBand[BdCGray]->GetXSize();

nYsize = pBand[BdCGray]->GetYSize(); //資料塊的xy方向像素尺寸

poBandBlock_Gray = (BYTE*)CPLMalloc(sizeof(BYTE)*(nXsize*nYsize));//配置設定緩沖區空間

//RasterIO函數可以将圖像的某一個子塊讀入或寫入

pBand[BdCGray]->RasterIO(GF_Read, 0, 0, nXsize,

nYsize, poBandBlock_Gray, nXsize, nYsize, pBand[BdCGray]->GetRasterDataType(), 0, 0);

}

if (dlg.mBandsType == 1)

{

BandsType = dlg.mBandsType;

BdCR = dlg.BdChoiceR;

BdCG = dlg.BdChoiceG;

BdCB = dlg.BdChoiceB;

int nXsizeR,nXsizeG,nXsizeB;

int nYsizeR,nYsizeG,nYsizeB;

nXsizeR = pBand[BdCR]->GetXSize();

nYsizeR = pBand[BdCR]->GetYSize();

nXsizeG = pBand[BdCG]->GetXSize();

nYsizeG = pBand[BdCG]->GetYSize();

nXsizeB = pBand[BdCB]->GetXSize();

nYsizeB = pBand[BdCB]->GetYSize();

nXsize = nXsizeR;

nYsize = nYsizeR;

poBandBlock_R = (BYTE*)CPLMalloc(sizeof(BYTE)*(nXsizeR*nYsizeR));

poBandBlock_G = (BYTE*)CPLMalloc(sizeof(BYTE)*(nXsizeG*nYsizeG));

poBandBlock_B = (BYTE*)CPLMalloc(sizeof(BYTE)*(nXsizeB*nYsizeB));

pBand[BdCR]->RasterIO(GF_Read,0,0,nXsizeR,nYsizeR,poBandBlock_R,nXsizeR,nYsizeR,pBand[BdCR]->GetRasterDataType(),0,0);

pBand[BdCG]->RasterIO(GF_Read,0,0,nXsizeG,nYsizeG,poBandBlock_G,nXsizeG,nYsizeG,pBand[BdCG]->GetRasterDataType(),0,0);

pBand[BdCB]->RasterIO(GF_Read,0,0,nXsizeB,nYsizeB,poBandBlock_B,nXsizeB,nYsizeB,pBand[BdCB]->GetRasterDataType(),0,0);

}

 8.更新和釋放指針

UpdateAllViews(NULL);

delete DataSet; //釋放資源

return TRUE;

要顯示圖像,當然得在View類的OnDraw()函數中添加必要的代碼:

1.假如要打開的是灰階圖像,先對資料頭檔案操作,包括資料頭和顔色表的指派。然後建立資料區,為各像素指派,即完成圖像的顯示:

if (pDoc->BandsType == 0)//GDI繪圖法

{

//資料頭檔案

//1.圖像資料塊頭

int i,j;

int nWidth = pDoc->nXsize;

int nHeight = pDoc->nYsize;

BITMAPINFO * pBmpInfo = (BITMAPINFO*) new char[sizeof(BITMAPINFO) + sizeof(RGBQUAD)*(256)];

pBmpInfo->bmiHeader.biBitCount = 8;

pBmpInfo->bmiHeader.biClrImportant = 0;

pBmpInfo->bmiHeader.biClrUsed = 0;

pBmpInfo->bmiHeader.biCompression = BI_RGB;

pBmpInfo->bmiHeader.biWidth = nWidth;

pBmpInfo->bmiHeader.biHeight = nHeight;

pBmpInfo->bmiHeader.biPlanes = 1;

pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

pBmpInfo->bmiHeader.biSizeImage = (nWidth*8+31)/32*4*nHeight;

pBmpInfo->bmiHeader.biXPelsPerMeter = 0;

pBmpInfo->bmiHeader.biYPelsPerMeter = 0;

//2.顔色表

for (i = 0;i < 256;i++)

{

pBmpInfo->bmiColors[i].rgbRed = i;

pBmpInfo->bmiColors[i].rgbGreen = i;

pBmpInfo->bmiColors[i].rgbBlue = i;

pBmpInfo->bmiColors[i].rgbReserved = 0;

}

//建立資料區

LONG LineBytes = (nWidth*8+31)/32*4;

LPBYTE pData = (LPBYTE)new char[LineBytes*nHeight];

//為各像素指派!!!!!!

for (i=0;i<nHeight;i++)

{

for (j=0;j<nWidth;j++)

{

pData[(nHeight-i-1)*LineBytes + j] = pDoc->poBandBlock_Gray[i*nWidth+j];//此表達式有待研究

}

}

SetStretchBltMode(pDC->m_hDC,BLACKONWHITE|WHITEONBLACK);

StretchDIBits(pDC->m_hDC, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,

pData, pBmpInfo, DIB_RGB_COLORS, SRCCOPY);

UpdateWindow();

delete pBmpInfo;

delete pData;

}

2,當然打開彩色圖像也要如此操作

  if (pDoc->BandsType == 1)//GDI繪圖法

{

//資料頭檔案

//1.圖像資料塊頭

int i,j,k;

int nWidth = pDoc->nXsize;

int nHeight = pDoc->nYsize;

BITMAPINFO * pBmpInfo = (BITMAPINFO*) new char[sizeof(BITMAPINFO) + sizeof(RGBQUAD)*(256)];

pBmpInfo->bmiHeader.biBitCount = 24;

pBmpInfo->bmiHeader.biClrImportant = 0;

pBmpInfo->bmiHeader.biClrUsed = 0;

pBmpInfo->bmiHeader.biCompression = BI_RGB;

pBmpInfo->bmiHeader.biWidth = nWidth;

pBmpInfo->bmiHeader.biHeight = nHeight;

pBmpInfo->bmiHeader.biPlanes = 1;

pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

pBmpInfo->bmiHeader.biSizeImage = (nWidth*24+31)/32*4*nHeight;

pBmpInfo->bmiHeader.biXPelsPerMeter = 0;

pBmpInfo->bmiHeader.biYPelsPerMeter = 0;

//2.顔色表

for (i = 0;i < 256;i++)

{

pBmpInfo->bmiColors[i].rgbRed = i;

pBmpInfo->bmiColors[i].rgbGreen = i;

pBmpInfo->bmiColors[i].rgbBlue = i;

pBmpInfo->bmiColors[i].rgbReserved = 0;

}

//建立資料區

LONG LineBytes = (nWidth*24+31)/32*4;

LPBYTE pData = (LPBYTE)new char[LineBytes*nHeight*3];

//為各像素指派!!!!!!

for (i=0;i<nHeight;i++)

{

for (j=0,k=0;j<nWidth,k<3*nWidth;j++,k+=3)

{

// pData[(nHeight-i-1)*LineBytes + j] = pDoc->poBandBlock_Gray[i*nWidth+j];//此表達式有待研究

pData[(nHeight-i-1)*LineBytes + k] = pDoc->poBandBlock_B[i*nWidth + j];

pData[(nHeight-i-1)*LineBytes + k+1] = pDoc->poBandBlock_G[i*nWidth + j];

pData[(nHeight-i-1)*LineBytes + k+2] = pDoc->poBandBlock_R[i*nWidth + j];

}

}

SetStretchBltMode(pDC->m_hDC,BLACKONWHITE|WHITEONBLACK);

StretchDIBits(pDC->m_hDC, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,

pData, pBmpInfo, DIB_RGB_COLORS, SRCCOPY);

UpdateWindow();

delete pBmpInfo;

delete pData;

}