📄 dib.cpp
字号:
//Dib.cpp
#include "stdafx.h"
#include "dib.h"
#include <windowsx.h>
#include <afxadv.h>
#include <io.h>
#include <errno.h>
IMPLEMENT_DYNAMIC(CDib,CObject)
//构造函数,初始化
CDib::CDib()
{
m_pBMI=NULL;
m_pBits=NULL;
m_pPalette=NULL;
}
//析构函数,释放内存
CDib::~CDib()
{
Free();
}
//确保所有将被分配的内存的成员变量被释放
void CDib::Free()
{
if(m_pBits)
{
GlobalFreePtr(m_pBits);
m_pBits=NULL;
}
if(m_pBMI)
{
GlobalFreePtr(m_pBMI);
m_pBMI=NULL;
}
if(m_pPalette)
{
m_pPalette->DeleteObject();
delete m_pPalette;
m_pPalette=NULL;
}
}
//Paint()
//参数
//HDC hDC 设备环境句柄
//LPRECT lpDCRect 设备环境矩形区域
//LPRECT lpDIBRect 位图矩形区域
//CPalette* pPal 位图调色板指针
//返回值
//BOOL 绘制成功返回TRUE,否则返回FALSE
//说明:该函数主要功能是将位图从矩形区域lpDIBRect,拷贝到设备环境hDC上的矩形区域lpDCRect
BOOL CDib::Paint(HDC hDC,LPRECT lpDCRect,LPRECT lpDIBRect) const
{
if(!m_pBMI)
return FALSE;
HPALETTE hPal=NULL;
HPALETTE hOldPal=NULL;
if(m_pPalette!=NULL)
{
hPal=(HPALETTE) m_pPalette->m_hObject;
hOldPal=::SelectPalette(hDC,hPal,TRUE);
}
::SetStretchBltMode(hDC,COLORONCOLOR);
BOOL bSuccess;
if((RECTWIDTH(lpDCRect)==RECTWIDTH(lpDIBRect))&&
(RECTHEIGHT(lpDCRect)==RECTHEIGHT(lpDIBRect)))
bSuccess=::SetDIBitsToDevice(hDC,lpDCRect->left,lpDCRect->top,
RECTWIDTH(lpDCRect),RECTHEIGHT(lpDCRect),lpDIBRect->left,
(int)Height()-lpDIBRect->top-RECTHEIGHT(lpDIBRect),0,(WORD)Height(),
m_pBits,m_pBMI,DIB_RGB_COLORS);
else
bSuccess=::StretchDIBits(hDC,lpDCRect->left,lpDCRect->top,
RECTWIDTH(lpDCRect),RECTHEIGHT(lpDCRect),lpDIBRect->left,lpDIBRect->top,
RECTWIDTH(lpDCRect),RECTHEIGHT(lpDCRect),m_pBits,m_pBMI,DIB_RGB_COLORS,SRCCOPY);
if(hOldPal!=NULL)
{
::SelectPalette(hDC,hOldPal,TRUE);
}
return bSuccess;
}
//CreatePalette()
//返回值
//BOOL 绘制成功返回TRUE,否则返回FALSE
//说明:这个函数用来生成位图调色板
BOOL CDib::CreatePalette()
{
if(!m_pBMI)
return FALSE;
WORD wNumColors=NumColors();
if(wNumColors!=0)
{
HANDLE hLogPal=::GlobalAlloc(GHND,sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*wNumColors);
if(hLogPal==0)
return FALSE;
LPLOGPALETTE lpPal=(LPLOGPALETTE)::GlobalLock((HGLOBAL)hLogPal);
lpPal->palVersion=PALVERSION;
lpPal->palNumEntries=(WORD)wNumColors;
for(int i=0;i<(int)wNumColors;i++)
{
lpPal->palPalEntry[i].peRed=m_pBMI->bmiColors[i].rgbRed;
lpPal->palPalEntry[i].peGreen=m_pBMI->bmiColors[i].rgbGreen;
lpPal->palPalEntry[i].peBlue=m_pBMI->bmiColors[i].rgbBlue;
lpPal->palPalEntry[i].peFlags=0;
}
if(m_pPalette)
{
m_pPalette->DeleteObject();
delete m_pPalette;
}
m_pPalette=new CPalette;
BOOL bResult=m_pPalette->CreatePalette(lpPal);
::GlobalUnlock((HGLOBAL)hLogPal);
::GlobalFree((HGLOBAL)hLogPal);
return bResult;
}
return TRUE;
}
//Width()
//返回值
//DWORD 位图的宽度
//说明:该函数获得位图的宽度
DWORD CDib::Width() const
{
if(!m_pBMI)
return 0;
return m_pBMI->bmiHeader.biWidth;
}
//Height()
//返回值
//DWORD 位图的高度
//说明:该函数获得位图的高度
DWORD CDib::Height() const
{
if(!m_pBMI)
return 0;
return m_pBMI->bmiHeader.biHeight;
}
//PaletteSize()
//返回值
//WORD 位图调色板大小
//说明:该函数获得位图调色板尺寸
WORD CDib::PaletteSize() const
{
if(!m_pBMI)
return 0;
return NumColors()* sizeof(RGBQUAD);
}
//NumColors()
//返回值
//WORD 颜色数
//说明:这个函数获得颜色数
// 如果位数为1:colors=2
// 如果位数为4:colors=16
// 如果位数为8:colors=256
// 如果位数为24,颜色表中没有颜色
WORD CDib::NumColors() const
{
if(!m_pBMI)
return 0;
WORD wBitCount;
DWORD dwClrUsed;
dwClrUsed=m_pBMI->bmiHeader.biClrUsed;
if(dwClrUsed!=0)
return (WORD)dwClrUsed;
wBitCount=m_pBMI->bmiHeader.biBitCount;
switch(wBitCount)
{
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
return 0;
}
}
//Save()
//参数
//CFile& file 保存位图的文件
//返回值
//DWORD 存储字节数
//说明:将图像保存到指定文件
DWORD CDib::Save(CFile& file) const
{
BITMAPFILEHEADER bmfHdr;
DWORD dwDIBSize;
if(m_pBMI==NULL)
return 0;
bmfHdr.bfType=DIB_HEADER_MARKER;
dwDIBSize=*(LPDWORD)&m_pBMI->bmiHeader+PaletteSize();
if((m_pBMI->bmiHeader.biCompression==BI_RLE8)||(m_pBMI->bmiHeader.biCompression==BI_RLE4))
{
dwDIBSize+=m_pBMI->bmiHeader.biSizeImage;
}
else
{
DWORD dwBmBitsSize;
dwBmBitsSize=WIDTHBYTES((m_pBMI->bmiHeader.biWidth)*((DWORD)m_pBMI->bmiHeader.biBitCount))*m_pBMI->bmiHeader.biHeight;
dwDIBSize+=dwBmBitsSize;
m_pBMI->bmiHeader.biSizeImage=dwBmBitsSize;
}
bmfHdr.bfSize=dwDIBSize+sizeof(BITMAPFILEHEADER);
bmfHdr.bfReserved1=0;
bmfHdr.bfReserved2=0;
bmfHdr.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+m_pBMI->bmiHeader.biSize+PaletteSize();
file.Write((LPSTR)&bmfHdr,sizeof(BITMAPFILEHEADER));
DWORD dwBytesSaved=sizeof(BITMAPFILEHEADER);
UINT nCount=sizeof(BITMAPINFO)+(NumColors()-1)*sizeof(RGBQUAD);
dwBytesSaved+=nCount;
file.Write(m_pBMI,nCount);
DWORD dwBytes=m_pBMI->bmiHeader.biBitCount*Width();
if(dwBytes%32==0)
dwBytes/=8;
else
dwBytes=dwBytes/8+(32-dwBytes%32)/8+(((32-dwBytes%32)%8>0)?1:0);
nCount=dwBytes*Height();
dwBytesSaved+=nCount;
file.WriteHuge(m_pBits,nCount);
return dwBytesSaved;
}
//Read()
//返回值
//DWORD 读入的byte数
//说明:将指定的位图文件读入内存
DWORD CDib::Read(CFile& file)
{
Free();
BITMAPFILEHEADER bmfHeader;
if(file.Read((LPSTR)&bmfHeader,sizeof(bmfHeader))!=sizeof(bmfHeader))
return 0;
if(bmfHeader.bfType!=DIB_HEADER_MARKER)
return 0;
DWORD dwReadBytes=sizeof(bmfHeader);
m_pBMI=(LPBITMAPINFO)GlobalAllocPtr(GHND,bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER)
+256*sizeof(RGBQUAD));
if(m_pBMI==0)
return 0;
if(file.Read(m_pBMI,bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER))!=(UINT)(bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER)))
{
GlobalFreePtr(m_pBMI);
m_pBMI=NULL;
return 0;
}
dwReadBytes+=bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER);
DWORD dwLength=file.GetLength();
m_pBits=(LPBYTE)GlobalAllocPtr(GHND,dwLength-bmfHeader.bfOffBits);
if(m_pBits==0)
{
GlobalFreePtr(m_pBMI);
m_pBMI=NULL;
return 0;
}
if(file.ReadHuge(m_pBits,dwLength-bmfHeader.bfOffBits)!=(dwLength-bmfHeader.bfOffBits))
{
GlobalFreePtr(m_pBMI);
m_pBMI=NULL;
GlobalFreePtr(m_pBits);
m_pBits=NULL;
return 0;
}
dwReadBytes+=dwLength-bmfHeader.bfOffBits;
CreatePalette();
return dwReadBytes;
}
#ifdef _DEBUG
void CDib::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
}
#endif
//CopyToHandle()
//返回值
//HGLOBAL 指向新的全局存储空间
//说明:拷贝位图到一个全局存储空间
HGLOBAL CDib::CopyToHandle() const
{
CSharedFile file;
try
{
if(Save(file)==0)
return 0;
}
catch(CFileException* e)
{
e->Delete();
return 0;
}
return file.Detach();
}
//ReadFromHandle()
//返回值
//DWORD 读入的Byte数
//说明:初始化给定的内存空间
DWORD CDib::ReadFromHandle(HGLOBAL hGlobal)
{
CSharedFile file;
file.SetHandle(hGlobal,FALSE);
DWORD dwResult=Read(file);
file.Detach();
return dwResult;
}
void CDib::Serialize(CArchive& ar)
{
CFile* pFile=ar.GetFile();
ASSERT(pFile!=NULL);
if(ar.IsStoring())
{
Save(*pFile);
}
else
{
Read(*pFile);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -