///////////////////////////////////////////////////////////////////////
/*
目的:BMP位图处理类。(源代码文件)
创建:张伟(SXZ)
日期:2000.01
版本:2.4
SXZ software workgroup. No.200001
*/
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
/*
注释:
# 类中的位图都是兼容于当前显示器颜色格式的DDB位图
# 如果读入的位图格式与当前显示器的颜色格式不同,则读入函数会先将其转换
为兼容于当前显示器颜色格式的位图之后才放入类中
# 对于所有BOOL型返回的函数,TRUE表示成功,FALSE表示失败
*/
///////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <math.h>
#include <io.h>
#include <errno.h>
#include <direct.h>
#include "BmpProc.h"
////////////////////////////// defines ///////////////////////////////////
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// 用于调试目的计数变量,它表示程序中构造的CBmpProc类实例个数
// 可以用类中static DWORD GetObjectCount()成员函数访问该变量
// 注意:该变量和访问它的函数都只是在调试模式下才会有效,如果
// 转换为发布模式,它们都会失效。所以在使用GetObjectCount()
// 这个成员函数时,应加入#ifdef _DEBUG .... #endif语句块
#ifdef _DEBUG
DWORD CBmpProc::m_ObjectCount = 0;
#endif
/*************************************************************************
* 构造函数。初始化类为空。
*************************************************************************/
CBmpProc::CBmpProc()
{
// 初始化核心数据为空
m_mark = FALSE; // 有效标志。(TRUE-有有效位图,否则为FALSE)
m_type = IT_NULL; // 图像类型。
m_addInfo = 0; // 附加信息。
m_cFileName.Empty(); // 文件路径。
m_pInfo = NULL; // DIB信息结构
m_hObject = NULL; // 清除核心DDB位图句柄。(基类成员)
#ifdef _DEBUG
CBmpProc::m_ObjectCount++;
#endif
}
/*************************************************************************
* 调试用函数,获取进程中CBmpProc类目标的个数。
*************************************************************************
#ifdef _DEBUG
DWORD CBmpProc::GetObjectCount()
{
return m_ObjectCount;
}
#endif
*************************************************************************/
/*************************************************************************
* 析构函数。如果类不为空则清空它。
*************************************************************************/
CBmpProc::~CBmpProc()
{
Clear();
#ifdef _DEBUG
CBmpProc::m_ObjectCount--;
#endif
}
/*************************************************************************
*
* operator=()
*
* 参数说明:
*
* const CBmpProc& ds - 源位图类
*
* 返回值:
*
* CBmpProc& - 类自身引用
*
* 描述:
*
* 复制取指定的位图类
*
* 如果函数成功,则类中原来的位图(如果有的话)将被删除,如果不成功,它保留
* 原位图。执行本函数之后,可调用该类的IsValid()函数判断是否成功复制(这种
* 情况只使用于没有图像的类,如果复制前类中就存在图像,可用==操作符判断该类
* 与源位图类是否相同,如果相同则表示复制成功,不同就说明失败)
*
************************************************************************/
CBmpProc& CBmpProc::operator=(const CBmpProc& ds)
{
// 如果类中没有图像,直接返回
if (!ds.IsValid())
return *this;
ASSERT(ds.m_pInfo);
ASSERT(ds.m_pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));
// 复制源图信息块
LPBITMAPINFO pInfo = (LPBITMAPINFO)CreateMemoryBlockFromAddress(
(LPVOID)ds.m_pInfo);
if (!pInfo)
return *this;
// 复制源图
CBitmap tempBmp;
HBITMAP hBmp;
HWND hWnd = ::GetDesktopWindow();
ASSERT(hWnd);
HDC hDC = ::GetDC(hWnd);
CDC dc;
dc.Attach(hDC);
if (tempBmp.CreateCompatibleBitmap(&dc, ds.Width(), ds.Height()))
{
CDC compDC, compDC2;
CBitmap *pOldBmp, *pOldBmp2;
// 创建与当前显示设备兼容的内存设备描述表
compDC.CreateCompatibleDC(NULL);
compDC2.CreateCompatibleDC(NULL);
pOldBmp = compDC.SelectObject((CBitmap*)&tempBmp);
pOldBmp2= compDC2.SelectObject((CBitmap*)&ds);
// 复制指定尺寸的源位图到目标位图
compDC.BitBlt(0, 0, ds.Width(), ds.Height(),
&compDC2, 0, 0, SRCCOPY);
compDC2.SelectObject(pOldBmp2);
compDC.SelectObject(pOldBmp);
hBmp = (HBITMAP)tempBmp.Detach();
// 如果分离操作失败,返回FALSE
ASSERT(hBmp);
if (!hBmp)
{
::ReleaseDC(hWnd, dc.Detach());
::free((void*)pInfo);
return *this;;
}
::ReleaseDC(hWnd, dc.Detach());
// 删除原来的图像,并且设置新的位图
if (!ClearAndSetData(IT_MEMORY,0,(LPCTSTR)"",pInfo,hBmp))
{
::free((void*)pInfo);
::DeleteObject(hBmp);
return *this;
}
return *this;
}
else
{
::ReleaseDC(hWnd, dc.Detach());
::free((void*)pInfo);
return *this;;
}
}
/*************************************************************************
*
* operator=()
*
* 参数说明:
*
* const HBITMAP sou - 源位图句柄
*
* 返回值:
*
* CBmpProc& - 类自身引用
*
* 描述:
*
* 复制取指定的位图
*
* 如果函数成功,则类中原来的位图(如果有的话)将被删除,如果不成功,它保留
* 原位图。执行本函数之后,可调用该类的IsValid()函数判断是否成功复制(这种
* 情况只使用于没有图像的类,如果复制前类中就存在图像,可用==操作符判断该类
* 与源位图类是否相同,如果相同则表示复制成功,不同就说明失败)
* 如果入口参数指定的位图句柄无效,则函数失败。
*
************************************************************************/
CBmpProc& CBmpProc::operator=(const HBITMAP sou)
{
// 入口检测
if (!sou)
return *this;
CBmpProc tmp;
if (!tmp.Attach(sou))
return *this;
ASSERT(sou == (HBITMAP)tmp);
// 调用类赋值操作符函数
*this = tmp;
// 分离源位图,防止析构函数将其删除
tmp.Detach();
return *this;
}
/*************************************************************************
*
* operator==()
*
* 参数说明:
*
* const CBmpProc& ds - 源位图类
*
* 返回值:
*
* BOOL - 如果相同返回TRUE,不同返回FALSE
*
* 描述:
*
* 判断源位图类与本身类是否相同
*
* 该函数通过比较两个类的位图来判定它们是否具有相同的图像。
*
* 注:# 如果两个类都是空的(即都没有图像),则该函数将视它们是不相同的
*
************************************************************************/
BOOL CBmpProc::operator==(const CBmpProc& ds)
{
// 如果两个类中有一个或都是空的(即都没有图像),则该函数将视它们
// 是不相同的
if ((ds.IsValid()==FALSE)||(IsValid()==FALSE))
return FALSE;
// 如果是与自身比较,则直接返回TRUE
if (this == &ds)
return TRUE;
ASSERT(m_pInfo);
ASSERT(ds.m_pInfo);
ASSERT(m_pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));
ASSERT(ds.m_pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));
// 信息块长度比较
if (::_msize(m_pInfo) != ::_msize(ds.m_pInfo))
return FALSE;
// 信息块内容比较
if (::memcmp((const void*)m_pInfo, \
(const void*)ds.m_pInfo,::_msize(m_pInfo)))
return FALSE;
// 创建存放DIB位数据的缓冲区
LPSTR pBits1 = (LPSTR)CreateMemoryBlockFromAddress((LPVOID)NULL,
CalculateDIBitsSize((LPBITMAPINFOHEADER)m_pInfo));
if (!pBits1)
return FALSE;
LPSTR pBits2 = (LPSTR)CreateMemoryBlockFromAddress((LPVOID)NULL,
CalculateDIBitsSize((LPBITMAPINFOHEADER)m_pInfo));
if (!pBits2)
{
::free((void*)pBits1);
return FALSE;
}
// 复制位图信息块,因为GetDIBits()函数有可能会改变颜色表数据
LPBITMAPINFO pInfo = (LPBITMAPINFO)CreateMemoryBlockFromAddress(
(LPVOID)m_pInfo);
if (!pInfo)
{
::free((void*)pBits1);
::free((void*)pBits2);
return FALSE;
}
ASSERT(pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));
HWND hWnd = ::GetDesktopWindow();
ASSERT(hWnd);
HDC hDC;
// 获取位图的DIB位数据
hDC = ::GetDC(hWnd);
ASSERT(m_hObject);
ASSERT(ds.m_hObject);
if (!::GetDIBits(hDC,(HBITMAP)m_hObject,0,pInfo->bm