// Dib.h: interface for the CDib class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_DIB_H__AC952C3A_9B6B_4319_8D6E_E7F509348A88__INCLUDED_)
#define AFX_DIB_H__AC952C3A_9B6B_4319_8D6E_E7F509348A88__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CDib : public CObject
{
public:
CDib();
virtual ~CDib();
//operations
public:
// 用于操作DIB的函數聲明
BOOL ConstructPalette(HGLOBAL,CPalette* ); //構造邏輯調色板
LPSTR GetBits(LPSTR); //取得位圖數據的入口地址
DWORD GetWidth(LPSTR); //取得位圖的寬度
DWORD GetHeight(LPSTR); //取得位圖的高度
WORD GetPalSize(LPSTR); //取得調色板的大小
WORD GetColorNum(LPSTR); //取得位圖包含的顏色數目
WORD GetBitCount(LPSTR); //取得位圖的顏色深度
HGLOBAL LoadFile(CFile&); //從文件中加載位圖
BOOL SaveFile(HGLOBAL hDib, CFile& file);
// 在對圖象進行處理時,針對位圖的字節寬度必須是4的倍數的這一要求,
// 我們設計了函數GetRequireWidth,來處理這種比較特殊的情況
int GetReqByteWidth(int ); //轉換后的字節數GetRequireByteWidth
long GetRectWidth(LPCRECT ); //取得區域的寬度
long GetRectHeight(LPCRECT); //取得區域的高度
public:
void ClearMemory();
void InitMembers();
public:
LPBITMAPINFO lpbminfo; // 指向BITMAPINFO結構的指針
LPBITMAPINFOHEADER lpbmihrd; //指向BITMAPINFOHEADER結構的指針
BITMAPFILEHEADER bmfHeader; //BITMAPFILEHEADER結構
LPSTR lpdib; //指向DIB的指針
LPSTR lpDIBBits; // DIB像素指針
DWORD dwDIBSize; //DIB大小
HGLOBAL m_hDib;//DIB對象的句柄
CPalette* m_palDIB;//調色板指針
};
#endif // !defined(AFX_DIB_H__AC952C3A_9B6B_4319_8D6E_E7F509348A88__INCLUDED_)
/////////////////////////////////////////////////////////////////////實現文件//////////////////////////////////////////////////////////////////////////////
// Dib.cpp: implementation of the CDib class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Dib.h"
#include <math.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDib::CDib()
{
InitMembers();
}
CDib::~CDib()
{
ClearMemory();
}
/*************************************************************************
* 函數名稱:ConstructPalette(HGLOBAL hDIB, CPalette* pPal)
* 函數參數:
* HGLOBAL hDIB,DIB對象的句柄
* CPalette* pPal,調色板的指針
* 函數類型:BOOL
* 函數說明:該函數按照DIB創建一個邏輯調色板
************************************************************************/
BOOL CDib::ConstructPalette(HGLOBAL hDIB, CPalette* pPal)
{
HANDLE hLogPal;// 邏輯調色板的句柄
int iLoop;// 循環變量
BOOL bSuccess = FALSE;// 創建結果
if (hDIB == NULL)//判斷是否是有效的DIB對象
{
return FALSE;// 返回FALSE
}
lpdib = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);// 鎖定DIB
lpbminfo= (LPBITMAPINFO)lpdib;
long wNumColors =GetColorNum(lpdib);// 獲取DIB中顏色表中的顏色數目
if (wNumColors != 0)
{
hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)// 分配為邏輯調色板內存
+ sizeof(PALETTEENTRY)
* wNumColors);
if (hLogPal == 0)// 如果失敗則退出
{
::GlobalUnlock((HGLOBAL) hDIB);// 解除鎖定
return FALSE;
}
LPLOGPALETTE lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
lpPal->palVersion = 0x300;// 設置調色板版本號
lpPal->palNumEntries = (WORD)wNumColors;// 設置顏色數目
for (iLoop=0; iLoop<(int)wNumColors;iLoop++)// 讀取調色板
{
lpPal->palPalEntry[iLoop].peRed =lpbminfo->bmiColors[iLoop].rgbRed;// 讀取三原色分量
lpPal->palPalEntry[iLoop].peGreen =lpbminfo->bmiColors[iLoop].rgbGreen;
lpPal->palPalEntry[iLoop].peBlue =lpbminfo->bmiColors[iLoop].rgbBlue;
lpPal->palPalEntry[iLoop].peFlags =0;// 保留位
}
bSuccess=pPal->CreatePalette(lpPal);// 按照邏輯調色板創建調色板,并返回指針
::GlobalUnlock((HGLOBAL) hLogPal);// 解除鎖定
::GlobalFree((HGLOBAL) hLogPal);// 釋放邏輯調色板
}
::GlobalUnlock((HGLOBAL) hDIB);// 解除鎖定
return bSuccess;// 返回結果
}
/*************************************************************************
* 函數名稱:GetBits(LPSTR lpdib)
* 函數參數:
* LPSTR lpdib,指向DIB對象的指針
* 函數類型:LPSTR
* 函數功能:計算DIB像素的起始位置,并返回指向它的指針
************************************************************************/
LPSTR CDib::GetBits(LPSTR lpdib)
{
return (lpdib + ((LPBITMAPINFOHEADER)lpdib)->biSize+GetPalSize(lpdib));
// return (lpdib + *(LPDWORD)lpdib+GetPalSize(lpdib));
}
/*************************************************************************
* 函數名稱:GetWidth(LPSTR lpdib)
* 函數參數:
* LPSTR lpdib,指向DIB對象的指針
* 函數類型:DWORD
* 函數功能:該函數返回DIB中圖象的寬度
************************************************************************/
DWORD CDib::GetWidth(LPSTR lpdib)
{
return ((LPBITMAPINFOHEADER)lpdib)->biWidth;//返回DIB寬度
}
/*************************************************************************
* 函數名稱:GetHeight(LPSTR lpdib)
* 函數參數:
* LPSTR lpdib ,指向DIB對象的指針
* 函數類型:DWORD
* 函數功能:該函數返回DIB中圖象的高度
************************************************************************/
DWORD CDib::GetHeight(LPSTR lpdib)
{
return ((LPBITMAPINFOHEADER)lpdib)->biHeight;//返回DIB高度
}
/*************************************************************************
* 函數名稱:GetPalSize(LPSTR lpdib)
* 函數參數:
* LPSTR lpdib,指向DIB對象的指針
* 函數類型:WORD
* 函數功能:該函數返回DIB中調色板的大小
************************************************************************/
WORD CDib::GetPalSize(LPSTR lpdib)
{
return (WORD)(GetColorNum(lpdib) * sizeof(RGBQUAD));// 計算DIB中調色板的大小
}
/*************************************************************************
* 函數名稱:GetColorNum(LPSTR lpdib)
* 函數參數:
* LPSTR lpdib,指向DIB對象的指針
* 函數類型:WORD
* 函數功能:該函數返回DIB中調色板的顏色的種數
************************************************************************/
WORD CDib::GetColorNum(LPSTR lpdib)
{
long dwClrUsed = ((LPBITMAPINFOHEADER)lpdib)->biClrUsed; // 讀取dwClrUsed值
if (dwClrUsed != 0)
{
return (WORD)dwClrUsed;// 如果dwClrUsed不為0,直接返回該值
}
else
{
dwClrUsed=(long)pow(2,24);
return (WORD)dwClrUsed;
}
}
/*************************************************************************
* 函數名稱:GetBitCount(LPSTR lpdib)
* 函數參數:
* LPSTR lpdib,指向DIB對象的指針
* 函數類型:WORD
* 函數功能:該函數返回DIBBitCount
************************************************************************/
WORD CDib::GetBitCount(LPSTR lpdib)
{
return ((LPBITMAPINFOHEADER)lpdib)->biBitCount;// 返回位寬
}
/*************************************************************************
* 函數名稱:LoadFile(CFile& file)
* 函數參數:
* CFile& file,要讀取得文件文件CFile
* 函數類型:HGLOBAL
* 函數功能:將指定的文件中的DIB對象讀到指定的內存區域中
*************************************************************************/
HGLOBAL CDib::LoadFile(CFile& file)
{
DWORD dwFileSize;
dwFileSize= file.GetLength();//獲取文件大小
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))// 讀取DIB文件頭
{
return NULL;// 大小不一致,返回NULL
}
// 如果文件類型不是"BM",其16進制值為0x4d42,則返回并進行相應錯誤處理
if (bmfHeader.bfType !=0x4d42)
{
return NULL;// 如果不是則返回NULL
}
m_hDib= (HGLOBAL) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwFileSize-sizeof(BITMAPFILEHEADER));// 分配DIB內存
if (m_hDib==NULL)
{
return NULL;// 分配失敗,返回NULL
}
/////////////////////////////////////////////////////////////////////////
//給CDib類的成員變量賦值
lpdib = (LPSTR) ::GlobalLock((HGLOBAL) m_hDib);// 鎖定
if (file.ReadHuge(lpdib, dwFileSize - sizeof(BITMAPFILEHEADER)) !=// 讀像素
dwFileSize - sizeof(BITMAPFILEHEADER) )//大小不一致
{
::GlobalUnlock((HGLOBAL) m_hDib); // 解除鎖定
::GlobalFree((HGLOBAL) m_hDib); // 釋放內存
return NULL;
}
::GlobalUnlock((HGLOBAL) m_hDib);// 解除鎖定
return m_hDib;// 返回DIB句柄
}
/*************************************************************************
* 函數名稱:GetReqByteWidth(int bits)
* 函數參數:
* int bits,位數
* 函數類型:int
* 函數功能:獲取需要的行字節數,應為4的倍數
*************************************************************************/
int CDib::GetReqByteWidth(int bits)
{
int getBytes=(bits + 31) / 32 * 4;
return getBytes;
}
/*************************************************************************
* 函數名稱:GetRectWidth(LPCRECT lpRect)
* 函數參數:
* LPCRECT lpRect,指向矩形區域的指針
* 函數類型:long
* 函數功能:獲取矩形區域的寬度
*************************************************************************/
long CDib::GetRectWidth(LPCRECT lpRect)
{
long nWidth=lpRect->right - lpRect->left;
return nWidth;
}
/*************************************************************************
* 函數名稱:GetRectHeight(LPCRECT lpRect)
* 函數參數:
* LPCRECT lpRect,指向矩形區域的指針
* 函數類型:long
* 函數功能:獲取矩形區域的高度
*************************************************************************/
long CDib::GetRectHeight(LPCRECT lpRect)
{
long nHeight=lpRect->bottom - lpRect->top;
return nHeight;
}
/*************************************************************************
* 函數名稱:InitMembers()
* 函數類型: void
* 函數功能:初始化類的成員變量
*************************************************************************/
void CDib::InitMembers()
{
m_hDib=NULL;
lpdib=NULL;
lpDIBBits=NULL;
}
/*************************************************************************
* 函數名稱:ClearMemory()
* 函數類型: void
* 函數功能:復位類的成員變量
*************************************************************************/
void CDib::ClearMemory()
{
if(m_hDib!=NULL)
::GlobalFree(m_hDib);
lpdib=NULL;
}
/*************************************************************************
* 函數名稱:SaveFile(HGLOBAL hDib, CFile& file)
* 函數參數:
* HGLOBAL hDib,要保存的DIB
* CFile& file,保存文件CFile
* 函數類型:BOOL
* 函數功能:將指定的DIB對象保存到指定的CFile中
*************************************************************************/
BOOL CDib::SaveFile(HGLOBAL hDib, CFile& file)
{
if (hDib == NULL)
{
return FALSE;// 如果DIB為空,返回FALSE
}
lpbmihrd = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);// 讀取BITMAPINFO結構,并鎖定
if (lpbmihrd == NULL)
{
return FALSE;// 為空,返回FALSE
}
bmfHeader.bfType ='BM'; // 填充文件頭
dwDIBSize = *(LPDWORD)lpbmihrd + GetPalSize((LPSTR)lpbmihrd);// 文件頭大小+顏色表大小
DWORD dwBmBitsSize;// 像素的大小
dwBmBitsSize =GetReqByteWidth((lpbmihrd->biWidth)*((DWORD)lpbmihrd->biBitCount)) * lpbmihrd->biHeight;// 大小為Width * Height
dwDIBSize += dwBmBitsSize;// 計算后DIB每行字節數為4的倍數時的大小
lpbmihrd->biSizeImage = dwBmBitsSize;// 更新biSizeImage
bmfHeader.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);// 文件大小
bmfHeader.bfReserved1 = 0;// 兩個保留字
bmfHeader.bfReserved2 = 0;
bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpbmihrd->biSize// 計算偏移量bfOffBits
+ GetPalSize((LPSTR)lpbmihrd);
file.Write(&bmfHeader, sizeof(BITMAPFILEHEADER));// 寫文件頭
file.WriteHuge(lpbmihrd, dwDIBSize);// 寫DIB頭和像素
::GlobalUnlock((HGLOBAL) hDib);// 解除鎖定
return TRUE;// 返回TRUE
}
posted on 2008-02-03 18:26
cpsprogramer 閱讀(13617)
評論(8) 編輯 收藏 引用