位图文件读写综述
2008-02-26 20:26:55 来源:WEB开发网二、位图文件读写操作
认识了位图文件的结构以后,对特定位图文件进行读写操作就显得简单了。本文附带的源代码中包含了一个能够方便进行位图读写操作的C++类。以下给出该类的使用参考,对于实现代码中的关键部分做出了讲解。
1、类的声明
class CFG_DIB : public CObject
{
public:
//默认构造函数
CFG_DIB();
//构造函数,根据图象宽和高,以及记录每个象素所需字节数来初始化
CFG_DIB(int width, int height, int nBitCounts);
virtual ~CFG_DIB();
public:
HBITMAP m_hBitmap;
LPBYTE m_lpDIBits; //DIB位的起始位置
LPBITMAPINFOHEADER m_lpBMPHdr; //BITMAPINFOHEADER信息
LPVOID m_lpvColorTable; //颜色表信息
HPALETTE m_hPalette; //条调色板
private:
DWORD m_dwImageSize; //非BITMAPINFOHEADER或BITMAPFILEHEADER的位
int m_nColorEntries; //颜色表项的个数
//显示参数
public:
CPoint m_Dest; //目的矩形域的左上角坐标
CSize m_DestSize; //显示矩形的宽度和高度
CPoint m_Src; //原矩形左下角坐标
CSize m_SrcSize; //原矩形宽度和高度
public:
void InitDestroy(); //初始化变量
void ComputePaletteSize(int nBitCounts); //计算调色板大小
void ComputeImage(); //计算图象大小
//从BMP文件中读入DIB信息
BOOL ReadFile(CFile* pFile);
//从BMP文件中读入DIB信息,与ReadFile不同的是使用CreateSection创建位图位
BOOL ReadSection(CFile* pFile, CDC* pDC = NULL);
//将DIB写入文件,保存成BMP图片格式
BOOL WriteFile(CFile* pFile);
//创建新的位图文件,根据参数width,height,nBitCounts分配内存空间
BOOL NewFile(int width, int height, int nBitCounts);
//关闭位图文件
BOOL CloseFile();
//显示位图
BOOL Display(CDC* pDC);
HBITMAP CreateBitmap(CDC* pDC); //用DIB创建DDB
HBITMAP CreateSection(CDC* pDC = NULL); //创建位图位数据,即象素数据
//如果DIB没有颜色表,可以用逻辑调色板
BOOL SetLogPalette(CDC* pDC);
//如果DIB有颜色表,可以创建系统调色板
BOOL SetWinPalette();
//把DIB对象的逻辑调色板选进设备环境里,然后实现调色板
UINT UseLogPalette(CDC* pDC);
//得到BitmapInfoHeader的大小,包含颜色表数据
int GetHeaderSize()
{
return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorEntries;
}
//得到图像的高度
int GetHeight()
{
if(m_lpBMPHdr == NULL) return 0;
return m_lpBMPHdr->biHeight;
}
//得到图像的宽度
int GetWidth()
{
if(m_lpBMPHdr == NULL) return 0;
return m_lpBMPHdr->biWidth;
}
//得到图像的大小
int GetImageSize()
{
return m_dwImageSize;
}
long GetLineBit(); //得到一行的象素数
};
2、位图的读取。
CFG_DIB提供了两个从位图文件读取位图数据的方法:ReadFile和ReadSection,二者不同之处,前者使用动态分配内存的方法初始化存储位位图数据的指针,后者则使用API函数,根据位图信息初始化存储位图数据的指针。
方法1 m_lpDIBits = (LPBYTE) new char[m_dwImageSize];
方法2 m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(),
3、位图读取过程中的调色板的创建和调用。
(LPBITMAPINFO) m_lpBMPHdr, DIB_RGB_COLORS,
(LPVOID*) &m_lpDIBits, NULL, 0);
关于调色板的详细情况,本文不作详细介绍,只是对读取位图的过程中需要调用的对调色板进行操作的相关函数进行说明。
读取文件的过程中,计算出调色板大小,然后调用创建调色板函数:
ComputePaletteSize(m_lpBMPHdr->biBitCount);
SetWinPalette();
在显示位图之前,设置调色板:if(m_hPalette != NULL) {
::SelectPalette(pDC->GetSafeHdc(), m_hPalette, TRUE);
}
4、位图的显示。
位图的显示还是调用Windows的API函数来进行,需要传递的参数包括当前位图信息头,位图数据等: ::StretchDIBits(pDC->GetSafeHdc(), m_Dest.x, m_Dest.y,
其中的m_Dest,m_DestSize,m_Src,m_SrcSize分别代表了图像在当前设备上显示的左上角坐标和范围以及需要显示的源图像的左下角坐标和范围。此处需要说明的是,位图数据的字节数组是从图像的最下面一行开始逐行想上存储的,所以用户在选取源位图的现实范围的时候需要特别注意!
m_DestSize.cx, m_DestSize.cy,
m_Src.x, m_Src.y,
m_SrcSize.cx, m_SrcSize.cy,
m_lpDIBits, (LPBITMAPINFO) m_lpBMPHdr,
DIB_RGB_COLORS, SRCCOPY);
m_Dest,m_DestSize,m_Src,m_SrcSize需要在现实之前设置好。
5、位图的存储。位图的存储用WriteFile实现。
6、新位图的创建。新位图的创建由NewFile实现。需要的参数是位图的宽度、高度、以及位图像素占用的位数。
7、其它问题。存取位图数据的字节数组有个问题需要引起开发人员的注意:字节数组中每个扫描行的字节数必需是4的倍数,如果不足要用0补齐。
以下是处理的办法:DWORD dwBytes = ((DWORD) m_lpBMPHdr->biWidth * m_lpBMPHdr->biBitCount) / 32;
这段代码按照要求算出了用于记录图像数据的字节数组的大小。
if(((DWORD) m_lpBMPHdr->biWidth * m_lpBMPHdr->biBitCount) % 32) {
dwBytes++;
}
dwBytes *= 4;
m_dwImageSize = dwBytes * m_lpBMPHdr->biHeight;
更多精彩
赞助商链接