// Dib.cpp: implementation of the CDib class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CDib.h"
#include <math.h>
#include <windowsx.h>
#include <afxadv.h>
#include <io.h>
#include <errno.h>
//CDib
IMPLEMENT_DYNAMIC(CDib,CObject)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDib::CDib()
{
m_pBMI = NULL;
m_pBits = NULL;
m_pPalette = NULL;
}
CDib::~CDib()
{
Free();
}
void CDib::Free()
{
//确保所有将被分配内存的成员变量被释放
if (m_pBMI)
{
GlobalFreePtr(m_pBMI);
m_pBMI = NULL;
}
if (m_pBits)
{
GlobalFreePtr(m_pBits);
m_pBits = NULL;
}
if (m_pPalette)
{
m_pPalette -> DeleteObject();
delete m_pPalette;
m_pPalette = NULL;
}
}
/*************************************************************************
* 函数名称:Width()
* 函数类型:DWORD
* 函数功能:该函数返回DIB中图象的宽度
************************************************************************/
DWORD CDib::Width() const
{
if(!m_pBMI)
return 0;
return m_pBMI->bmiHeader.biWidth;//返回DIB宽度
}
/*************************************************************************
* 函数名称:Height()
* 函数类型:DWORD
* 函数功能:该函数返回DIB中图象的高度
************************************************************************/
DWORD CDib::Height() const
{
if(!m_pBMI)
return 0;
return m_pBMI->bmiHeader.biHeight;//返回DIB高度
}
/*************************************************************************
* 函数名称:PaletteSize(LPSTR lpdib)
* 函数类型:WORD
* 函数功能:该函数返回DIB中调色板的大小
************************************************************************/
WORD CDib::PaletteSize() const
{
if(!m_pBMI)
return 0;
return NumColors() * sizeof(RGBQUAD);
}
/*************************************************************************
* 函数名称:NumColors()
* 函数类型:WORD
* 函数功能:该函数返回DIB中调色板的颜色的种数
************************************************************************/
WORD CDib::NumColors() const
{
if(!m_pBMI)
return 0;
WORD wBitCount; //DIB的bit数
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;
}
}
/*************************************************************************
* 函数名称:Read(CFile& file)
* 函数参数:
* CFile& file,要读取得文件文件CFile
* 函数类型:DWORD
*返回值:读入的byte数
* 函数功能:将指定的文件中的DIB对象读到指定的内存区域中
*************************************************************************/
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; //文件大小
CreatPalette();
return dwReadBytes;
}
#ifdef _DEBUG
void CDib::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
}
#endif
/*************************************************************************
* 函数名称:SaveFile(HGLOBAL hDib, CFile& file)
* 函数参数:
* HGLOBAL hDib,要保存的DIB
* CFile& file,保存文件CFile
* 函数类型:BOOL
* 函数功能:将指定的DIB对象保存到指定的CFile中
*************************************************************************/
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))
{
//如果是RLE位图,不能计算图像尺寸,直接采用biSizeImage
dwDIBSize += m_pBMI->bmiHeader.biSizeImage;
}
else
{
DWORD dwBmBitSize; //位图数据块大小
//不是RLE位图,大小为Width(DWORD aligned)*Height
dwBmBitSize = WIDTHBYTES((m_pBMI->bmiHeader.biWidth) * ((DWORD) m_pBMI->bmiHeader.biBitCount))*m_pBMI->bmiHeader.biHeight;
dwDIBSize += dwBmBitSize;
m_pBMI->bmiHeader.biSizeImage=dwBmBitSize;
}
//计算整个文件大小,并书写图像文件头
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 dwByteSaved = sizeof(BITMAPFILEHEADER);
//信息头
UINT nCount = sizeof(BITMAPINFO)+(NumColors()-1)*sizeof(RGBQUAD);
dwByteSaved += 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();
dwByteSaved += nCount;
file.WriteHuge(m_pBits,nCount);
return dwByteSaved;// 返回存储的字节数
}
/*****************************************************************
*paint()
参数:
*HDC hDC -设备环境句柄
*LPRECT lpDCRect -设备环境矩形区域
*LPRECT lpDIBRect -位图矩形区域
*CPalette * Pal -位图调色板指针
*返回值
*BOOL
*说明:该函数主要功能是将位图从矩形区域lpDIBRect拷贝到设备环境hDC上的矩形区域LpDCRect。
********************************************************************/
BOOL CDib::Paint(HDC hDC,LPCRECT lpDCRect,LPCRECT 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,