操作一個圖像的時候,必須讀取其中的數據。
一 WIN API
1 文件的創建與打開
2 文件的寫入
3 文件的讀取
二 MFC
1 寫入
2 讀取
三,位圖的讀取
我們要把DIB數據讀入到內存中,那麼就要分配相應的內存,把讀入的數據寫到對應的內存區中,這裏SDK 提供的數據結構是各種結構體,結構體的各個字段對應磁盤文件中各個信息值。我們這裏爲了邏輯清楚,使用最常使用的DIB結構體。
如圖,文件中的數據讀到對應的內存結構中完成文件的讀入,內存結構中的數據寫到對應的文件中完成文件的保存。其中,
文件信息頭數據讀到BITMAPFILEHEADER結構體中
位圖信息頭讀到BITMAPINFOHEADER結構體中
位圖調色板讀到RGBQUAD結構體數組中
位圖數據讀到根據位圖信息頭提供的信息而分配的相應大小的數據區中
把BITMAPINFOHEADER和RGBQUAD[0]作爲BITMAPINFO結構體成員,這樣一方面是爲了和磁盤文件對應,另一方面也是爲了訪問調色板數據方便。
這裏的磁盤文件中各個段在磁盤上保存位置必須是連續的,但是對應的內存中文件信息頭、位圖信息和位圖數據三大塊不一定要是連續的。ps:位圖信息中的信息頭和調色板應該得是連續的。因此,在讀入文件中你既可以一次性讀入磁盤文件到連續的內存中,也可以分開讀入到三個分別連續的內存中。下面貼一段很有參考價值的讀取。
public:
BITMAPFILEHEADER bf; //文件頭
BITMAPINFOHEADER bi; //信息頭
RGBQUAD* quad; //調色板
BYTE* lpBuf; //圖像數據
BITMAPINFO* pbi;
int flag; //標誌表示是否打開了bmp文件
int numQuad; //調色板數目
void CMyseeDoc::OnFileOpen()
{
LPCTSTR lpszFilter="BMP Files(*.bmp)|*.bmp|任何文件|*.*||"; //打開文件類型設置
CFileDialog dlg1(TRUE,lpszFilter,NULL,OFN_HIDEREADONLY|
OFN_OVERWRITEPROMPT,lpszFilter,NULL);
CString filename;
CFile file;
//打開文件對話框
if(dlg1.DoModal()==IDOK)
{
filename=dlg1.GetPathName();
if(file.Open(filename,CFile::modeRead|CFile::shareDenyNone,NULL)==0)
{
//讀取文件失敗
AfxMessageBox("無法打開文件!",MB_OK,0);
return;
}
//讀取文件頭
file.Read(&bf,sizeof(bf));
//判斷是否是BMP文件
if(bf.bfType!=0x4d42)//'BM'
{
AfxMessageBox("非BMP文件!",MB_OK,0);
return;
}
//判斷文件是否損壞
if(file.GetLength()!=bf.bfSize)
{
AfxMessageBox("文件已算壞,請檢查!",MB_OK,0);
return;
}
//讀文件信息頭
file.Read(&bi,sizeof(bi));
//計算調色板數目
numQuad=0;
if(bi.biBitCount<24)
{
numQuad=1<<bi.biBitCount;
}
//爲圖像信息pbi申請空間
pbi=(BITMAPINFO*)HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)
+numQuad*sizeof(RGBQUAD));
memcpy(pbi,&bi,sizeof(bi));
quad=(RGBQUAD*)((BYTE*)pbi+sizeof(BITMAPINFOHEADER));
//讀取調色板
if(numQuad!=0)
{
file.Read(quad,sizeof(RGBQUAD)*numQuad);
}
//爲圖像數據申請空間
bi.biSizeImage=bf.bfSize-bf.bfOffBits;
lpBuf=(BYTE*)HeapAlloc(GetProcessHeap(),0,bi.biSizeImage);
//讀取圖像數據
file.Read(lpBuf,bi.biSizeImage);
//圖像讀取完畢,關閉文件,設置標誌
file.Close();
flag=1;
}
}