📄 dib.cpp
字号:
// Dib.cpp: implementation of the CDib class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Dib.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
// 计算图像每行像素所占的字节数
inline int BytePerLine(int w, int c)
{
return 4 * (w * c + 31) / 32;
}
// 根据表示的颜色位数来确定能表示的颜色数
inline int PaletteSize(int b)
{
switch(b)
{
case 4:return 16;
case 8:return 256;
case 24:return 0;
default:return 0;
}
}
CDib::CDib()
{
m_lpBits = NULL;
m_lpPatte = NULL;
m_nWidth = m_nHeight = 0;
m_nBitCount = 0;
m_IsGrayed = FALSE;
m_IsPixeled = FALSE;
}
CDib::~CDib()
{
Clear();
}
void CDib::Clear()
{
if (m_lpBits)
delete[] m_lpBits;
m_lpBits = NULL;
if (m_lpPatte)
delete[] m_lpPatte;
m_lpPatte = NULL;
m_nWidth = m_nHeight = 0;
m_nBitCount = 0;
}
BOOL CDib::LoadFromFile(LPCTSTR filename)
{
CFile f;
// 打开指定文件名的文件失败,返回
if (!f.Open(filename, CFile::modeRead))
{
return FALSE;
}
BOOL ret = LoadFromFile(&f);
f.Close();
return ret;
}
BOOL CDib::LoadFromFile(CFile *pf)
{
// 获取位图文件的大小
UINT nLen = (UINT)pf->GetLength();
// 为位图文件申请内存空间
BYTE *lpBitmap, *lpDib;
lpBitmap = new BYTE[nLen];
// 从文件内读出内容
pf->Read(lpBitmap, nLen);
// 检查文件类型,若不是位图文件提示错误,然后释放内存
if (lpBitmap[0] != 'B' && lpBitmap[1] != 'M')
{
AfxMessageBox(_T("非位图文件!"));
delete[] lpBitmap;
return FALSE;
}
lpDib = lpBitmap + sizeof(BITMAPFILEHEADER);
m_IsGrayed = FALSE;
m_IsPixeled = FALSE;
// 将DIB位图数据填充到CDib类的数据结构中
BOOL ret = LoadDib(lpDib);
// 释放内存
delete[] lpBitmap;
return ret;
}
BOOL CDib::SaveToFile(LPCTSTR filename)
{
CFile f;
// 打开指定文件名的文件失败,返回
if (!f.Open(filename, CFile::modeCreate | CFile::modeWrite))
{
return FALSE;
}
BOOL ret = SaveToFile(&f);
f.Close();
return ret;
}
BOOL CDib::SaveToFile(CFile *pf)
{
if (m_lpBits == NULL)
return FALSE;
// 获得图像文件每行图像所占字节数
int nByteWidth = BytePerLine(m_nWidth, m_nBitCount);
// 填充位图信息头结构—指定文件的相关信息
BITMAPFILEHEADER bfh;
// 指定文件类型为位图文件
bfh.bfType = 'M' * 256 + 'B';
// 指定位图文件大小
bfh.bfSize = nByteWidth * m_nHeight;
// 保留的结构元素,必须为0
bfh.bfReserved1 = bfh.bfReserved2 = 0;
// 计算从文件头开始到实际的图像数据之间的偏移量
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
// 如果不是24位真彩色位图,加上调色板信息长度
if (m_nBitCount != 24)
{
bfh.bfOffBits += PaletteSize(m_nBitCount) * sizeof(RGBQUAD);
}
// 向文件中写入文件头信息
pf->Write(&bfh, sizeof(BITMAPFILEHEADER));
// 填充位图信息头结构—指定位图的大小和颜色信息
BITMAPINFOHEADER bih;
// 指定位图信息头结构的大小
bih.biSize = sizeof(BITMAPINFOHEADER);
// 指定位图的宽度
bih.biWidth = m_nWidth;
// 指定位图的高度
bih.biHeight = m_nHeight;
// 目标设备的位面数,总为1
bih.biPlanes = 1;
// 指定表示颜色时用到的位数
bih.biBitCount = m_nBitCount;
// 指定为没有压缩的图像数据
bih.biCompression = BI_RGB;
// 指定实际的位图数据占用的字节数
// 使用BI_RGB格式时,设置为0
bih.biSizeImage = 0;
// 指定目标设备的分辨率
bih.biXPelsPerMeter = bih.biYPelsPerMeter = 0;
// 指定位图实际使用的颜色索引数,设置为0表明使用所有调色板项
bih.biClrUsed = 0;
// 指定对图像显示有重要影响的颜色索引数,设置为0表明所有的都重要
bih.biClrImportant = 0;
// 将信息头写入文件
pf->Write(&bih, sizeof(BITMAPINFOHEADER));
// 如果不是24位真彩色位图将调色板信息写入文件
if (m_nBitCount != 24)
pf->Write(m_lpPatte, PaletteSize(m_nBitCount) * sizeof(RGBQUAD));
// 将位图数据写入文件
pf->Write(m_lpBits, nByteWidth * m_nHeight);
return TRUE;
}
BOOL CDib::LoadDib(BYTE *lpDib)
{
// 清楚以前的图像数据,并释放相关内存
Clear();
BYTE *lpBits;
BITMAPINFOHEADER *lpInfo;
int nWidth,nHeight,nBitCount,nByteWidth;
RGBQUAD *lpPalette;
unsigned int nPaletteSize;
lpInfo = (BITMAPINFOHEADER*)lpDib;
lpBits = lpDib + sizeof(BITMAPINFOHEADER);
nWidth = lpInfo->biWidth;
nHeight = lpInfo->biHeight;
nBitCount = lpInfo->biBitCount;
nByteWidth = BytePerLine(nWidth, nBitCount);
// 释放以前的位图数据和调色板数据占有的内存
if (m_lpBits)
delete[] m_lpBits;
m_lpBits = NULL;
if (m_lpPatte)
delete[] m_lpPatte;
m_lpPatte = NULL;
// 检查位图的颜色数
switch(nBitCount)
{
case 24:// 如果是24真彩色,没有调色板信息
break;
case 8:// 如果是8位或4位颜色的位图,有调色板信息
case 4:
// 计算调色板中实际颜色数量
nPaletteSize = 1 << lpInfo->biBitCount;
if (lpInfo->biClrUsed != 0 && lpInfo->biClrUsed < nPaletteSize)
{
nPaletteSize = lpInfo->biClrUsed;
}
// 获取调色板信息数据
lpPalette = (RGBQUAD*)lpBits;
// 移动文件指针到图像像素数据开始的地方
lpBits += sizeof(RGBQUAD) * nPaletteSize;
// 为保存调色板信息数据的m_lpPalette分配空间
m_lpPatte = new BYTE[sizeof(RGBQUAD) * nPaletteSize];
// 将调色板信息复制到m_lpPalette指向的内存空间中
memcpy(m_lpPatte, lpPalette, sizeof(RGBQUAD) * nPaletteSize);
break;
default:
return FALSE;
}
// 为保存像素数据的m_lpBits分配内存空间
m_lpBits = new BYTE[nByteWidth * nHeight];
// 将位图数据复制到m_lpBIts
memcpy(m_lpBits, lpBits, nByteWidth * nHeight);
// 记录位图的宽度
m_nWidth = nWidth;
// 记录位图的高度
m_nHeight = nHeight;
// 记录位图表示颜色所用的位数
m_nBitCount = nBitCount;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -