📄 dib.cpp
字号:
// Dib.cpp: implementation of the CDib class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ImageTest.h"
#include "Dib.h"
#include <io.h>
#include <errno.h>
#include <math.h>
#include <direct.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDib::CDib()
{
m_hDib = NULL;
m_bIsImageMap = FALSE;
m_x1 = m_y1 = 0.0;
m_x2 = m_y2 = 0.0;
m_dScale = 0.0;
}
CDib::~CDib()
{
if(m_hDib != NULL)
{
// 释放内存
::GlobalFree((HGLOBAL) m_hDib);
m_hDib = NULL;
}
//删除调色板对象
if(m_Pal.GetSafeHandle())
{
m_Pal.DeleteObject();
}
}
/*
* Dib文件头标志(字符串"BM",写DIB时用到该常数)
*/
#define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
/*************************************************************************
*
* 函数名称:
* PaintDIB()
*
* 参数:
* HDC hDC - 输出设备DC
* LPRECT lpDCRect - 绘制矩形区域
* LPRECT lpDIBRect - 要输出的DIB区域
*
* 返回值:
* BOOL - 绘制成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数主要用来绘制DIB对象。其中调用了StretchDIBits()或者
* SetDIBitsToDevice()来绘制DIB对象。输出的设备由由参数hDC指
* 定;绘制的矩形区域由参数lpDCRect指定;输出DIB的区域由参数
* lpDIBRect指定。
*
************************************************************************/
BOOL CDib::PaintDIB(HDC hDC,
LPRECT lpDCRect,
LPRECT lpDIBRect)
{
LPTSTR lpDIBHdr; // BITMAPINFOHEADER指针
LPTSTR lpDIBBits; // DIB象素指针
BOOL bSuccess=FALSE; // 成功标志
HPALETTE hPal=NULL; // DIB调色板
HPALETTE hOldPal=NULL; // 以前的调色板
// 判断DIB对象是否为空
if (m_hDib == NULL)
{
// 返回
return FALSE;
}
// 锁定DIB
lpDIBHdr = (LPTSTR) ::GlobalLock((HGLOBAL) m_hDib);
// 找到DIB图像象素起始位置
lpDIBBits = FindDIBBits(lpDIBHdr);
// 获取DIB调色板,并选中它
if (m_Pal.m_hObject != NULL)
{
hPal = (HPALETTE) m_Pal.m_hObject;
// 选中调色板
hOldPal = ::SelectPalette(hDC, hPal, TRUE);
}
// 设置显示模式
::SetStretchBltMode(hDC, COLORONCOLOR);
// 判断是调用StretchDIBits()还是SetDIBitsToDevice()来绘制DIB对象
if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) &&
(RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
{
// 原始大小,不用拉伸。
bSuccess = ::SetDIBitsToDevice(hDC, // hDC
lpDCRect->left, // DestX
lpDCRect->top, // DestY
RECTWIDTH(lpDCRect), // nDestWidth
RECTHEIGHT(lpDCRect), // nDestHeight
lpDIBRect->left, // SrcX
(int)DIBHeight(lpDIBHdr) -
lpDIBRect->top -
RECTHEIGHT(lpDIBRect), // SrcY
0, // nStartScan
(WORD)DIBHeight(lpDIBHdr), // nNumScans
lpDIBBits, // lpBits
(LPBITMAPINFO)lpDIBHdr, // lpBitsInfo
DIB_RGB_COLORS); // wUsage
}
else
{
// 非原始大小,拉伸。
bSuccess = ::StretchDIBits(hDC, // hDC
lpDCRect->left, // DestX
lpDCRect->top, // DestY
RECTWIDTH(lpDCRect), // nDestWidth
RECTHEIGHT(lpDCRect), // nDestHeight
lpDIBRect->left, // SrcX
lpDIBRect->top, // SrcY
RECTWIDTH(lpDIBRect), // wSrcWidth
RECTHEIGHT(lpDIBRect), // wSrcHeight
lpDIBBits, // lpBits
(LPBITMAPINFO)lpDIBHdr, // lpBitsInfo
DIB_RGB_COLORS, // wUsage
SRCCOPY); // dwROP
}
// 解除锁定
::GlobalUnlock((HGLOBAL) m_hDib);
// 恢复以前的调色板
if (hOldPal != NULL)
{
::SelectPalette(hDC, hOldPal, TRUE);
}
// 返回
return bSuccess;
}
/*************************************************************************
*
* 函数名称:
* CreateDIBPalette()
*
* 返回值:
* BOOL - 创建成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数按照DIB创建一个逻辑调色板,从DIB中读取颜色表并存到调色板中,
* 最后按照该逻辑调色板创建一个新的调色板。这样
* 可以用最好的颜色来显示DIB图像。
*
************************************************************************/
BOOL CDib::CreateDIBPalette(HDIB hDIB)
{
// 指向逻辑调色板的指针
LPLOGPALETTE lpPal;
// 逻辑调色板的句柄
HANDLE hLogPal;
// 调色板的句柄
HPALETTE hPal = NULL;
// 循环变量
int i;
// 颜色表中的颜色数目
WORD wNumColors;
// 指向DIB的指针
LPTSTR lpbi;
// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPINFO lpbmi;
// 指向BITMAPCOREINFO结构的指针
LPBITMAPCOREINFO lpbmc;
// 表明是否是Win3.0 DIB的标记
BOOL bWinStyleDIB;
// 创建结果
BOOL bResult = TRUE;
// 判断DIB是否为空
if (hDIB == NULL)
{
// 返回FALSE
return FALSE;
}
// 锁定DIB
lpbi = (LPTSTR) ::GlobalLock((HGLOBAL) hDIB);
// 获取指向BITMAPINFO结构的指针(Win3.0)
lpbmi = (LPBITMAPINFO)lpbi;
// 获取指向BITMAPCOREINFO结构的指针
lpbmc = (LPBITMAPCOREINFO)lpbi;
// 获取DIB中颜色表中的颜色数目
wNumColors = DIBNumColors(lpbi);
if (wNumColors != 0)
{
// 分配为逻辑调色板内存
hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)
+ sizeof(PALETTEENTRY)
* wNumColors);
// 如果内存不足,退出
if (hLogPal == 0)
{
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回FALSE
return FALSE;
}
lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
// 设置版本号
lpPal->palVersion = PALVERSION;
// 设置颜色数目
lpPal->palNumEntries = (WORD)wNumColors;
// 判断是否是WIN3.0的DIB
bWinStyleDIB = IS_WIN30_DIB(lpbi);
// 读取调色板
for (i = 0; i < (int)wNumColors; i++)
{
if (bWinStyleDIB)
{
// 读取红色分量
lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
// 读取绿色分量
lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
// 读取蓝色分量
lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
// 保留位
lpPal->palPalEntry[i].peFlags = 0;
}
else
{
// 读取红色分量
lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
// 读取绿色分量
lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
// 读取红色分量
lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
// 保留位
lpPal->palPalEntry[i].peFlags = 0;
}
}
// 按照逻辑调色板创建调色板,并返回指针
bResult = m_Pal.CreatePalette(lpPal);
// 解除锁定
::GlobalUnlock((HGLOBAL) hLogPal);
// 释放逻辑调色板
::GlobalFree((HGLOBAL) hLogPal);
}
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回结果
return bResult;
}
/*************************************************************************
*
* 函数名称:
* FindDIBBits()
*
* 参数:
* LPTSTR lpbi - 指向DIB对象的指针
*
* 返回值:
* LPTSTR - 指向DIB图像象素起始位置
*
* 说明:
* 该函数计算DIB中图像象素的起始位置,并返回指向它的指针。
*
************************************************************************/
LPTSTR CDib::FindDIBBits(LPSTR lpbi)
{
return (lpbi + *(LPDWORD)lpbi + PaletteSize(lpbi));
}
/*************************************************************************
*
* 函数名称:
* DIBWidth()
*
* 参数:
* LPTSTR lpbi - 指向DIB对象的指针
*
* 返回值:
* DWORD - DIB中图像的宽度
*
* 说明:
* 该函数返回DIB中图像的宽度。对于Windows 3.0 DIB,返回BITMAPINFOHEADER
* 中的biWidth值;对于其它返回BITMAPCOREHEADER中的bcWidth值。
*
************************************************************************/
LONG CDib::DIBWidth(LPTSTR lpDIB)
{
// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPINFOHEADER lpbmi;
// 指向BITMAPCOREINFO结构的指针
LPBITMAPCOREHEADER lpbmc;
// 获取指针
lpbmi = (LPBITMAPINFOHEADER)lpDIB;
lpbmc = (LPBITMAPCOREHEADER)lpDIB;
// 返回DIB中图像的宽度
if (IS_WIN30_DIB(lpDIB))
{
// 对于Windows 3.0 DIB,返回lpbmi->biWidth
return lpbmi->biWidth;
}
else
{
// 对于其它格式的DIB,返回lpbmc->bcWidth
return (LONG)lpbmc->bcWidth;
}
}
/*************************************************************************
*
* 函数名称:
* DIBHeight()
*
* 参数:
* LPTSTR lpDIB - 指向DIB对象的指针
*
* 返回值:
* DWORD - DIB中图像的高度
*
* 说明:
* 该函数返回DIB中图像的高度。对于Windows 3.0 DIB,返回BITMAPINFOHEADER
* 中的biHeight值;对于其它返回BITMAPCOREHEADER中的bcHeight值。
*
************************************************************************/
LONG CDib::DIBHeight(LPTSTR lpDIB)
{
// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPINFOHEADER lpbmi;
// 指向BITMAPCOREINFO结构的指针
LPBITMAPCOREHEADER lpbmc;
// 获取指针
lpbmi = (LPBITMAPINFOHEADER)lpDIB;
lpbmc = (LPBITMAPCOREHEADER)lpDIB;
// 返回DIB中图像的宽度
if (IS_WIN30_DIB(lpDIB))
{
// 对于Windows 3.0 DIB,返回lpbmi->biHeight
return lpbmi->biHeight;
}
else
{
// 对于其它格式的DIB,返回lpbmc->bcHeight
return (LONG)lpbmc->bcHeight;
}
}
long CDib::GetWidth()
{
if(m_hDib == NULL)
return 0;
// 锁定DIB
LPTSTR lpDIB = (LPTSTR)::GlobalLock((HGLOBAL)m_hDib);
//得到DIB宽度
long dwWidth = DIBWidth(lpDIB);
// 解除锁定
::GlobalUnlock((HGLOBAL)m_hDib);
return dwWidth;
}
long CDib::GetHeight()
{
if(m_hDib == NULL)
return 0;
// 锁定DIB
LPTSTR lpDIB = (LPTSTR)::GlobalLock((HGLOBAL)m_hDib);
//得到DIB高度
long dwHeight = DIBHeight(lpDIB);
// 解除锁定
::GlobalUnlock((HGLOBAL)m_hDib);
return dwHeight;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -