//#ifndef __CDIB_H
#define __CDIB_H
class CDib:public CObject
{
public:
RGBQUAD* m_pRGB;//调色板指针
BYTE* m_pData;//指向实际图像数据指针
UINT m_numberOfColors;//颜色数
BOOL m_valid;
BITMAPFILEHEADER bitmapFileHeader;//保存文件头的内容
BITMAPINFOHEADER* m_pBitmapInfoHeader;//信息头指
LPBITMAPINFO m_pBitmapInfo;//BITMAPINFO结构体指针指
BYTE* pDib;//分配一段size大小的内存段,返回该内存区域头指针
DWORD size; //文件大小-文件头结构体的大小
public:
CDib();
~CDib();
CString m_fileName;//记录文件名
CString GetFileName();//返回位图文件名
BOOL IsValid();
DWORD GetSize();//返回位图文件大小
UINT GetWidth();//返回位图的宽度
UINT GetHeight();//返回位图的高度
UINT GetNumberOfColors();//返回位图颜色数目
RGBQUAD* GetRGB();//返回颜色表首地址
BYTE* GetData();//返回图像数据首地址
BITMAPINFO* GetInfo();//获得BITMAPINFO结构体
WORD PaletteSize(LPBYTE lpDIB);//
WORD DIBNumColors(LPBYTE lpDIB);//返回位图颜色数目
void SaveFile(const CString Filename);//存储位图文件
void LoadFile(CString dibFileName);//装载位图文件
};
#endif
DIB类的实现DIB.CPP
#include "stdafx.h"
#include "Dib.h"
#include "windowsx.h"
CDib::CDib()
{
size=0;
}
CDib::~CDib()
{
GlobalFreePtr(m_pBitmapInfo);
}
void CDib::LoadFile(CString
dibFileName)
{
m_fileName.Format(_T("%s"),
dibFileName); //将路径名拷贝到参数m_fileName
CFile
dibFile(m_fileName,
CFile::modeRead);//创建CFile类对象,只读方式
dibFile.Read((void*)&bitmapFileHeader,sizeof(BITMAPFILEHEADER));
//读取文件头的内容
if
(bitmapFileHeader.bfType == 0x4d42)
{
DWORD fileLength = dibFile.GetLength();//读取文件的大小
size = fileLength -sizeof(BITMAPFILEHEADER);
//文件大小-文件头结构体的大小
//先分配size大小的内存,接着锁定内存块,然后返回指针,可以用该指针来操作该内存
pDib =(BYTE*)GlobalAllocPtr(GMEM_MOVEABLE,
size);//分配一段size大小的内存段,返回该内存区域头指针
dibFile.Read((void*)pDib,
size);//通过读取,把读出的数据存入刚才分配的内存之中
dibFile.Close();
m_pBitmapInfo = (BITMAPINFO*)
pDib;//BITMAPINFO结构体指针指向该内存
m_pBitmapInfoHeader = (BITMAPINFOHEADER*)
pDib;//信息头指向该内存
m_pRGB = (RGBQUAD*)(pDib +
m_pBitmapInfoHeader->biSize);
//调色板指针指向该内存的调色板部分。因为pDib原本指向信息头,偏移40字节(信息头结构体的大小)之后便到了调色板部分,因此用加法来实现指针的偏移
int m_numberOfColors =
GetNumberOfColors();//调用GetNumberOfColors函数来得到颜色数
if (m_pBitmapInfoHeader->biClrUsed ==
0)
m_pBitmapInfoHeader->biClrUsed = m_numberOfColors;
//把颜色数赋予biClrUsed之中
DWORD colorTableSize = m_numberOfColors
*sizeof(RGBQUAD);//用每个调色板结构体大小乘以颜色数量,得到调色板的大小
m_pData = pDib + m_pBitmapInfoHeader->biSize+
colorTableSize;//这时候代表把m_pData指针指向实际图像数据了
if (m_pRGB == (RGBQUAD*)m_pData)
//如果调色板指针位置和实际图像位置指针指向位置相同,那就代表没有调色板
m_pRGB = NULL;//指针赋予空
m_pBitmapInfoHeader->biSizeImage =
GetSize();//赋予实际位图的大小
m_valid = TRUE;
}
else
{
m_valid = FALSE;
AfxMessageBox("This isn't a bitmap file!");
}
}
BOOL CDib::IsValid()
{
return
m_valid;
}
CString CDib::GetFileName()
{
return
m_fileName;
}
UINT CDib::GetWidth()
{
return
(UINT)
m_pBitmapInfoHeader->biWidth;
}
UINT CDib::GetHeight()
{
return
(UINT)
m_pBitmapInfoHeader->biHeight;
}
DWORD CDib::GetSize()
{
if
(m_pBitmapInfoHeader->biSizeImage !=
0)
return
m_pBitmapInfoHeader->biSizeImage;
else
{
DWORD height = (DWORD) GetHeight();
DWORD width = (DWORD) GetWidth();
return height * width;
}
}
UINT
CDib::GetNumberOfColors()
{
int numberOfColors;
if
((m_pBitmapInfoHeader->biClrUsed == 0)
&&
(m_pBitmapInfoHeader->biBitCount <
9))
//biClrUsed表示实际用到的颜色数,若0为2的biBitCount次中颜色
//biBitCount为用到的颜色的位数,小于9则表示最大为8位,那么之多为256色
{
switch
(m_pBitmapInfoHeader->biBitCount)
{
case 1: numberOfColors = 2; break;
case 4: numberOfColors = 16; break;
case 8: numberOfColors = 256;
}
}
else
numberOfColors = (int)
m_pBitmapInfoHeader->biClrUsed;
return
numberOfColors;
}
BYTE* CDib::GetData()
{
return m_pData;
}
RGBQUAD* CDib::GetRGB()
{
return m_pRGB;
}
BITMAPINFO* CDib::GetInfo()
{
return m_pBitmapInfo;
}
WORD CDib::PaletteSize(LPBYTE
lpDIB)
{
return (DIBNumColors(lpDIB)*sizeof(RGBTRIPLE));
}
WORD CDib::DIBNumColors(LPBYTE
lpDIB)
{
WORD
wBitCount; // DIB bit count
wBitCount =
((LPBITMAPCOREHEADER)lpDIB)->bcBitCount;
switch
(wBitCount)
{
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
return 0;
}
}
void CDib::SaveFile(const CString
filename)
{
char m_filename[256];;
strcpy(m_filename,filename);
CFile
dibFile(m_filename,CFile::modeCreate|CFile::modeWrite);
dibFile.Write((void*)&bitmapFileHeader,sizeof(BITMAPFILEHEADER));
dibFile.Write((void*)pDib,size);
dibFile.Close();
}