?? cdib.cpp
字號:
// 如果文件類型部位"BM",則返回并進行相應錯誤處理
if(bmfh.bfType != 0x4d42) {
// throw new CException;
}
// 計算信息頭加上調色板的大小,并分配相應的內存
nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSize];
m_nBmihAlloc = crtAlloc;
m_nImageAlloc = noAlloc;
// 讀取信息頭和調色板
nCount = pFile->Read(m_lpBMIH, nSize);
// 如果圖象為壓縮格式,則不進行后續處理
if(m_lpBMIH->biCompression != BI_RGB) {
// throw new CException;
}
// 計算圖象數據大小并設置調色板指針
ComputeMetrics();
// 計算調色板的表項數
ComputePaletteSize(m_lpBMIH->biBitCount);
// 如果DIB中存在調色板,則創建一個Windows調色板
MakePalette();
// 將CDib對象的邏輯調色板選入設備上下文
UsePalette(pDC);
// 創建一個DIB段,并分配圖象內存
m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(), (LPBITMAPINFO) m_lpBMIH,
DIB_RGB_COLORS, (LPVOID*) &m_lpImage, NULL, 0);
ASSERT(m_lpImage != NULL);
// 從文件中讀取圖象數據
nCount = pFile->Read(m_lpImage, m_dwSizeImage);
}
// 錯誤處理
catch(CException* pe) {
AfxMessageBox("ReadSection error");
pe->Delete();
return FALSE;
}
return TRUE;
}
/*************************************************************************
*
* \函數名稱:
* Write()
*
* \輸入參數:
* CFile* pFile - 指向CFile對象的指針
*
* \返回值:
* BOOL - 如果成功,則返回TRUE
*
* \說明:
* 該函數把DIB從CDib對象寫進文件中。該文件必須成功打開或者創建
*
************************************************************************
*/
BOOL CDib::Write(CFile* pFile)
{
BITMAPFILEHEADER bmfh;
// 設置文件頭中文件類型為"BM"
bmfh.bfType = 0x4d42;
// 計算信息頭和調色板的大小尺寸
int nSizeHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;
// 設置文件頭信息
bmfh.bfSize = sizeof(BITMAPFILEHEADER) + nSizeHdr + m_dwSizeImage;
bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * m_nColorTableEntries;
// 進行寫操作
try {
pFile->Write((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
pFile->Write((LPVOID) m_lpBMIH, nSizeHdr);
pFile->Write((LPVOID) m_lpImage, m_dwSizeImage);
}
// 錯誤處理
catch(CException* pe) {
pe->Delete();
AfxMessageBox("write error");
return FALSE;
}
// 返回
return TRUE;
}
/*************************************************************************
*
* \函數名稱:
* Serialize()
*
* \輸入參數:
* CArchive& ar - 指向應用程序歸檔對象
*
* \返回值:
* 無
*
* \說明:
* 該函數進行串行化過程,將CDib數據進行讀入或者寫出
*
************************************************************************
*/
void CDib::Serialize(CArchive& ar)
{
DWORD dwPos;
// 獲得此歸檔文件的CFile對象指針
dwPos = ar.GetFile()->GetPosition();
TRACE("CDib::Serialize -- pos = %d\n", dwPos);
// 從歸檔文件緩沖區中沖掉未寫入數據
ar.Flush();
// 重新獲得此歸檔文件的CFile對象指針
dwPos = ar.GetFile()->GetPosition();
TRACE("CDib::Serialize -- pos = %d\n", dwPos);
// 確定歸檔文件是否被存儲,是則進行存儲
if(ar.IsStoring()) {
Write(ar.GetFile());
}
// 否則進行加載
else {
Read(ar.GetFile());
}
}
/*************************************************************************
*
* \函數名稱:
* ComputePaletteSize()
*
* \輸入參數:
* int nBitCount - 指向CFile對象的指針
*
* \返回值:
* 無
*
* \說明:
* 該函數根據位圖象素位數計算調色板的尺寸
*
************************************************************************
*/
void CDib::ComputePaletteSize(int nBitCount)
{
// 如果biClrUsed為零,則用到的顏色數為2的biBitCount次方
if((m_lpBMIH == NULL) || (m_lpBMIH->biClrUsed == 0)) {
switch(nBitCount) {
case 1:
m_nColorTableEntries = 2;
break;
case 4:
m_nColorTableEntries = 16;
break;
case 8:
m_nColorTableEntries = 256;
break;
case 16:
case 24:
case 32:
m_nColorTableEntries = 0;
break;
default:
ASSERT(FALSE);
}
}
// 否則調色板的表項數就是用到的顏色數目
else {
m_nColorTableEntries = m_lpBMIH->biClrUsed;
}
ASSERT((m_nColorTableEntries >= 0) && (m_nColorTableEntries <= 256));
}
/*************************************************************************
*
* \函數名稱:
* ComputeMetrics()
*
* \輸入參數:
* 無
*
* \返回值:
* 無
*
* \說明:
* 該函數計算圖象位圖的尺寸,并對DIB中的調色板的指針進行賦值
*
************************************************************************
*/
void CDib::ComputeMetrics()
{
// 如果結構的長度不對,則進行錯誤處理
if(m_lpBMIH->biSize != sizeof(BITMAPINFOHEADER)) {
TRACE("Not a valid Windows bitmap -- probably an OS/2 bitmap\n");
// throw new CException;
}
// 保存圖象數據內存大小到CDib對象的數據成員中
m_dwSizeImage = m_lpBMIH->biSizeImage;
// 如果圖象數據內存大小為0,則重新計算
if(m_dwSizeImage == 0) {
DWORD dwBytes = ((DWORD) m_lpBMIH->biWidth * m_lpBMIH->biBitCount) / 32;
if(((DWORD) m_lpBMIH->biWidth * m_lpBMIH->biBitCount) % 32) {
dwBytes++;
}
dwBytes *= 4;
m_dwSizeImage = dwBytes * m_lpBMIH->biHeight;
}
// 設置DIB中的調色板指針
m_lpvColorTable = (LPBYTE) m_lpBMIH + sizeof(BITMAPINFOHEADER);
}
/*************************************************************************
*
* \函數名稱:
* Empty()
*
* \輸入參數:
* 無
*
* \返回值:
* 無
*
* \說明:
* 該函數清空DIB,釋放已分配的內存,并且必要的時候關閉映射文件
*
************************************************************************
*/
void CDib::Empty()
{
// 關閉內存映射文件的連接
DetachMapFile();
// 根據內存分配的狀態,調用相應的函數釋放信息頭
if(m_nBmihAlloc == crtAlloc) {
delete [] m_lpBMIH;
}
else if(m_nBmihAlloc == heapAlloc) {
::GlobalUnlock(m_hGlobal);
::GlobalFree(m_hGlobal);
}
// 釋放圖象數據內存
if(m_nImageAlloc == crtAlloc) delete [] m_lpImage;
// 釋放調色板句柄
if(m_hPalette != NULL) ::DeleteObject(m_hPalette);
// 如果創建了BITMAP,則進行釋放
if(m_hBitmap != NULL) ::DeleteObject(m_hBitmap);
// 重新設置內存分配狀態
m_nBmihAlloc = m_nImageAlloc = noAlloc;
// 釋放內存后,還需要將指針設置為NULL并將相應的數據設置為0
m_hGlobal = NULL;
m_lpBMIH = NULL;
m_lpImage = NULL;
m_lpvColorTable = NULL;
m_nColorTableEntries = 0;
m_dwSizeImage = 0;
m_lpvFile = NULL;
m_hMap = NULL;
m_hFile = NULL;
m_hBitmap = NULL;
m_hPalette = NULL;
}
/*************************************************************************
*
* \函數名稱:
* DetachMapFile()
*
* \輸入參數:
* 無
*
* \返回值:
* 無
*
* \說明:
* 函數可以釋放現有的已分配的內存,并關閉以前關聯的任何內存映射文件。
*
************************************************************************
*/
void CDib::DetachMapFile()
{
// 如果沒有進行內存映射,則不進行處理
if(m_hFile == NULL) return;
// 關閉內存映射
::UnmapViewOfFile(m_lpvFile);
// 關閉內存映射對象和文件
::CloseHandle(m_hMap);
::CloseHandle(m_hFile);
m_hFile = NULL;
}
/*************************************************************************
*
* \函數名稱:
* PaletteSize()
*
* \輸入參數:
* 無
*
* \返回值:
* DWORD - 返回調色板的尺寸
*
* \說明:
* 該函數計算機調色板所需的尺寸
*
************************************************************************
*/
WORD CDib::PaletteSize()
{
// 臨時變量
WORD NumColors;
LPBITMAPINFOHEADER lpbi=m_lpBMIH;
// 如果biClrUsed為零,且圖象象素位數小于8,則計算調色板用到的表項數
NumColors = ((lpbi)->biClrUsed == 0 && (lpbi)->biBitCount <= 8 \
? (int)(1 << (int)(lpbi)->biBitCount) \
: (int)(lpbi)->biClrUsed);
// 根據顏色表示的字節數計算調色板的尺寸
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
return NumColors * sizeof(RGBTRIPLE);
else
return NumColors * sizeof(RGBQUAD);
}
/*************************************************************************
*
* \函數名稱:
* IsEmpty()
*
* \輸入參數:
* 無
*
* \返回值:
* BOOL - 如果信息頭和圖象數據為空,則返回TRUE
*
* \說明:
* 判斷信息頭和圖象數據是否為空
*
************************************************************************
*/
BOOL CDib::IsEmpty()
{
if( m_lpBMIH == NULL&&m_lpImage == NULL)
return TRUE;
else
return FALSE;
}
/*************************************************************************
*
* \函數名稱:
* GetDibSaveDim()
*
* \輸入參數:
* 無
*
* \返回值:
* CSize - DIB實際存儲的高度和寬度
*
* \說明:
* 該函數函數用來得到dib的實際存儲寬度(DWORD對齊)
*
************************************************************************
*/
CSize CDib::GetDibSaveDim()
{
CSize sizeSaveDim;
sizeSaveDim.cx = ( m_lpBMIH->biWidth * m_lpBMIH->biBitCount + 31)/32 * 4;
sizeSaveDim.cy = m_lpBMIH->biHeight;
return sizeSaveDim;
}
/*************************************************************************
*
* \函數名稱:
* GetPixelOffset()
*
* \輸入參數:
* int x - 象素在X軸的坐標
* int y - 象素在Y軸的坐標
*
* \返回值:
* int - 返回象素在圖象數據塊中的真實地址
*
* \說明:
* 該函數得到坐標為(x,y)的象素點的真實地址。由于DIB結構中對圖象數據排列的
* 方式為從下到上,從左到右的,所以需要進行轉換。
*
************************************************************************
*/
LONG CDib::GetPixelOffset(int x, int y)
{
CSize sizeSaveDim;
sizeSaveDim = GetDibSaveDim();
LONG lOffset = (LONG) (sizeSaveDim.cy - y - 1) * sizeSaveDim.cx +
x / (8 / m_lpBMIH->biBitCount);
return lOffset;
}
/*************************************************************************
*
* \函數名稱:
* GetPixel()
*
* \輸入參數:
* int x - 象素在X軸的坐標
* int y - 象素在Y軸的坐標
*
* \返回值:
* RGBQUAD - 返回DIB在該點真實的顏色
*
* \說明:
* 該函數得到DIB圖象在該點真是的顏色。
*
************************************************************************
*/
RGBQUAD CDib::GetPixel(int x, int y)
{
// 顏色結構
RGBQUAD cColor;
// 根據每象素比特數得到此點的象素值
switch (m_lpBMIH->biBitCount)
{
case 1 :
if (1<<(7-x%8) & *(LPBYTE)(m_lpImage+GetPixelOffset(x, y)))
{
cColor.rgbBlue = 255;
cColor.rgbGreen = 255;
cColor.rgbRed = 255;
cColor.rgbReserved =0;
}
else
{
cColor.rgbBlue = 0;
cColor.rgbGreen = 0;
cColor.rgbRed = 0;
cColor.rgbReserved =0;
}
break;
case 4 :
{
int nIndex = (*(LPBYTE)(m_lpImage+GetPixelOffset(x, y)) &
(x%2 ? 0x0f : 0xf0)) >> (x%2 ? 0 : 4);
LPRGBQUAD pDibQuad = (LPRGBQUAD) (m_lpvColorTable) + nIndex;
cColor.rgbBlue = pDibQuad->rgbBlue;
cColor.rgbGreen = pDibQuad->rgbGreen;
cColor.rgbRed = pDibQuad->rgbRed;
cColor.rgbReserved =0;
}
break;
case 8 :
{
int nIndex = *(BYTE*)(m_lpImage+GetPixelOffset(x, y));
LPRGBQUAD pDibQuad = (LPRGBQUAD) (m_lpvColorTable) + nIndex;
cColor.rgbBlue = pDibQuad->rgbBlue;
cColor.rgbGreen = pDibQuad->rgbGreen;
cColor.rgbRed = pDibQuad->rgbRed;
cColor.rgbReserved =0;
}
break;
default:
int nIndex = *(BYTE*)(m_lpImage+GetPixelOffset(x, y));
cColor.rgbRed = m_lpImage[nIndex];
cColor.rgbGreen = m_lpImage[nIndex + 1];
cColor.rgbBlue = m_lpImage[nIndex + 2];
cColor.rgbReserved =0;
break;
}
// 返回顏色結構
return cColor;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -