📄 mbmpclass.cpp
字号:
// MBmpClass.cpp: implementation of the MBmpClass class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "FPSystem.h"
#include "MBmpClass.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
MBmpClass::MBmpClass()
{
hImgData=NULL;
hBitmap=NULL;
hPalette=NULL;
}
MBmpClass::~MBmpClass()
{
if(hBitmap)
DeleteObject(hBitmap);
if(hPalette)
DeleteObject(hPalette);
if(hImgData!=NULL)
{
GlobalUnlock(hImgData);
GlobalFree(hImgData);
hImgData=NULL;
}
}
/****************************************************************
*
* 函数名称:
* LoadBMPFile();
*
* 参数:
* char *inFileName 加载图像的文件名
* CDC *pDC 设备上下文
* 返回值:
* TRUE 成功读取;
* FALSE 失败;
*
* 说明:
* 该函数读入图像文件文件数据到全局内存句柄hImgData中;
*
****************************************************************/
BOOL MBmpClass::LoadBmpFile(CString &inFileName,CDC *pDC) //070426加上了CDC *pDC
{
if(hImgData!=NULL)
{
GlobalUnlock(hImgData);
GlobalFree(hImgData);
hImgData=NULL;
}
CFile file; //文件对象
if(NULL==file.Open(inFileName,CFile::modeRead))
{
AfxMessageBox("文件打开有误!",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
//读入文件头,并判断是否为Bmp格式
file.Read((LPSTR)&bf,sizeof(BITMAPFILEHEADER));
if(bf.bfType!=0x4D42)
{
AfxMessageBox("File isn't a bmp file!");
file.Close();
return FALSE;
}
//读入信息头
file.Read((LPSTR)&bi,sizeof(BITMAPINFOHEADER));
//计算一行所需的字节数
DWORD LineBytes; //BMP图像中一行所需的数据长度
LineBytes=(DWORD)WIDTHBYTES(bi.biWidth*bi.biBitCount);
//计算整幅图像数据所需的内存空间
DWORD ImgSize; //整幅图像数据所需的内存空间
ImgSize=(DWORD)LineBytes*bi.biHeight;
//颜色数
DWORD NumColors; //用到的颜色数,if=0 then True color 24 bits
if(bi.biClrUsed!=0)//直接指定颜色数
{
NumColors=(DWORD)bi.biClrUsed;
}
else //根据图像深度计算颜色数
{
switch(bi.biBitCount)
{
case 1:
NumColors=2; //二值图像
bi.biClrUsed=2;
break;
case 4:
NumColors=16; //16色图像
bi.biClrUsed=16;
break;
case 8:
NumColors=256; //256色图像
bi.biClrUsed=256;
break;
case 24:
NumColors=0; //无调色板
break;
default:
AfxMessageBox("Invalid color numbers!",MB_OK|MB_ICONEXCLAMATION);
file.Close();
return FALSE;
}
}
//判断图像的偏移地址是否正确
if(bf.bfOffBits!=(DWORD)(sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD)))
{
AfxMessageBox("Invalid color numbers!",MB_OK|MB_ICONEXCLAMATION);
file.Close();
return FALSE;
}
//计算整个文件的大小
bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD)+ImgSize;
//内存数据区hImgData=包括位图信息头+颜色表+图象数据
if(hImgData!=NULL)
{
GlobalUnlock(hImgData);
GlobalFree(hImgData);
hImgData=NULL;
}
if((hImgData=GlobalAlloc(GHND,(DWORD)(sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD)+ImgSize)))==NULL)
{
AfxMessageBox("Error alloc memory!",MB_OK|MB_ICONEXCLAMATION);
file.Close();
return FALSE;
}
////锁定内存数据区,将图像数据区内容读入内存
LPBITMAPINFOHEADER lpImgData; //原始逻辑位图信息头
lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
file.Seek(sizeof(BITMAPFILEHEADER),CFile::begin);
file.Read((void *)lpImgData,(DWORD)(bf.bfSize-sizeof(BITMAPFILEHEADER)));
file.Close();
/////////////////////设置调色板/////////////////
LOGPALETTE *pPal; //逻辑调色板指针
LPRGBQUAD lpRGB;
HPALETTE hPrevPalette; //前一个调色板句柄
HLOCAL hPal;
if(hBitmap)
{
DeleteObject(hBitmap);
hBitmap=NULL;
}
if(hPalette)
{
hPalette=NULL;
DeleteObject(hPalette);
}
if(NumColors) //NumColors不为零,说明用到了调色板
{
//为逻辑调色板分配局部内存,大小为逻辑调色板结构长度加NumColors个PALETTENTRY
hPal=LocalAlloc(LHND,sizeof(LOGPALETTE)+NumColors*sizeof(PALETTEENTRY));
pPal=(LOGPALETTE *)LocalLock(hPal); //指针pPal指向该内存区
//填写逻辑调色板结构的头
pPal->palNumEntries=(WORD)NumColors;
pPal->palVersion=0x300; //为什么是0x300?
//lpRGB指向的是调色板开始的位置
lpRGB=(LPRGBQUAD)((LPSTR)lpImgData+(DWORD)sizeof(BITMAPINFOHEADER));
//填写每一项
for(DWORD i=0;i<NumColors;i++)
{
pPal->palPalEntry[i].peRed=lpRGB->rgbRed;
pPal->palPalEntry[i].peGreen=lpRGB->rgbGreen;
pPal->palPalEntry[i].peBlue=lpRGB->rgbBlue;
pPal->palPalEntry[i].peFlags=(BYTE) 0;
lpRGB++;
}
hPalette=CreatePalette(pPal); //调色板产生
LocalUnlock(hPal);
LocalFree(hPal); //释放逻辑调色板空间
}
if(hPalette)
{
hPrevPalette=SelectPalette(pDC->m_hDC,hPalette,FALSE);
RealizePalette(pDC->m_hDC); //将现有逻辑调色板影射到系统调色板
}
hBitmap=CreateDIBitmap(pDC->m_hDC,(LPBITMAPINFOHEADER)lpImgData,(DWORD)CBM_INIT,
(LPSTR)lpImgData+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD),
(LPBITMAPINFO)lpImgData,DIB_RGB_COLORS);
if(hPalette && hPrevPalette)
{
SelectPalette(pDC->m_hDC,hPrevPalette,FALSE);
RealizePalette(pDC->m_hDC); //将现有逻辑调色板影射到系统调色板
}
GlobalUnlock(hImgData); //解锁内存数据区
return TRUE;
}
/****************************************************************
*
* 函数名称:
* SaveBmpFile();
*
* 参数:
* char *inFileName 加载图像的文件名
* 返回值:
* TRUE 成功读取;
* FALSE 失败;
*
* 说明:
* 该函数读入图像文件文件数据到全局内存句柄hImgData中;
*
****************************************************************/
BOOL MBmpClass::SaveBmpFile(CString fileName)
{
CFile file;
if(!(file.Open(fileName,CFile::modeCreate|CFile::modeWrite)))
{
AfxMessageBox("文件打开失败!",MB_OK|MB_ICONINFORMATION);
return FALSE;
}
LPBITMAPINFOHEADER lpImgDatan; //逻辑位图信息头
lpImgDatan=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
//写文件头
file.Write((char*)&bf,sizeof(bf));
//写信息头 调色板 数据区
file.Write( (char*)lpImgDatan,bf.bfSize-sizeof(BITMAPFILEHEADER));
file.Flush(); //将输出缓冲区的数据送出,并清出。
file.Close();
GlobalUnlock(hImgData); //解锁hImgData
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -