📄 dib.cpp
字号:
// ************************************************************************
// 文件名:dib.cpp
//
// DIB(Independent Bitmap) 函数库:
//
// PaintDIB() - 绘制DIB对象
// CreateDIBPalette() - 创建DIB对象调色板
// FindDIBBits() - 返回DIB图像象素起始位置
// DIBWidth() - 返回DIB宽度
// DIBHeight() - 返回DIB高度
// PaletteSize() - 返回DIB调色板大小
// DIBNumColors() - 计算DIB调色板颜色数目
// CopyHandle() - 拷贝内存块
// DIBBitCount() - 该函数返回DIBBitCount
// SaveDIB() - 将DIB保存到指定文件中
// ReadDIBFile() - 重指定文件中读取DIB对象
// SetRgnColor() - 用指定的颜色填充指定的区域
// SetCircleColor() - 用指定的颜色填充指定的圆形区域
//
// ************************************************************************
#include "stdafx.h"
#include "dib.h"
#include <io.h>
#include <errno.h>
#include <math.h>
#include <direct.h>
// Dib文件头标志(字符串"BM",写DIB时用到该常数)
#define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
CDIB::CDIB()
{
}
CDIB::~CDIB()
{
}
////////////////////////////////////////////////////////////////////////////
// 功能模块开始 //
////////////////////////////////////////////////////////////////////////////
/*************************************************************************
*
* 函数名称:
* PaintDIB()
*
* 参数:
* HDC hDC - 设备环境句柄
* LPRECT lpDCRect - 矩形区域
* HDIB hDIB - 指向DIB对象的指针
* LPRECT lpDIBRect - 待输出DIB区域
* CPalette* pPal - 调色板指针
*
* 返回值:
* BOOL - 绘制成功返回TRUE,否则返回FALSE。
*
* 说明:
* 绘制DIB对象
*
************************************************************************/
BOOL CDIB::PaintDIB(HDC hDC,
LPRECT lpDCRect,
HDIB hDIB,
LPRECT lpDIBRect,
CPalette* pPal)
{
LPBYTE lpDIBINFOHEADER; // BITMAPINFOHEADER指针
LPBYTE lpDIBBits; // DIB象素指针
BOOL bRet = FALSE; // 返回成功标志
HPALETTE hNewPal = NULL; // 当前的调色板
HPALETTE hOldPal = NULL; // 以前的调色板
// 判断DIB对象是否为空
if (hDIB == NULL)
{
// 返回
return FALSE;
}
// 锁定DIB
lpDIBINFOHEADER = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 找到DIB图像象素起始位置
lpDIBBits = FindDIBBits(lpDIBINFOHEADER);
// 获取DIB调色板,并选中
if (pPal != NULL)
{
hNewPal = (HPALETTE) pPal->m_hObject;
// 选中调色板
hOldPal = ::SelectPalette(hDC, hNewPal, TRUE);
}
// 设置显示模式
::SetStretchBltMode(hDC, COLORONCOLOR);
// 判断是调用StretchDIBits()还是SetDIBitsToDevice()来绘制DIB对象
if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) &&
(RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
{
//AfxMessageBox("原始大小,不用拉伸。 ");
// 原始大小,不用拉伸。
bRet = ::SetDIBitsToDevice(hDC, // hDC
lpDCRect->left, // DestX
lpDCRect->top, // DestY
RECTWIDTH(lpDCRect), // nDestWidth
RECTHEIGHT(lpDCRect), // nDestHeight
lpDIBRect->left, // SrcX
(int)DIBHeight(lpDIBINFOHEADER) -
lpDIBRect->top -
RECTHEIGHT(lpDIBRect), // SrcY
0, // nStartScan
(WORD)DIBHeight(lpDIBINFOHEADER), // nNumScans
lpDIBBits, // lpBits
(LPBITMAPINFO)lpDIBINFOHEADER, // lpBitsInfo
DIB_RGB_COLORS); // wUsage
}
else
{
//AfxMessageBox("非原始大小,拉伸。 ");
// 非原始大小,拉伸。
bRet = ::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)lpDIBINFOHEADER, // lpBitsInfo
DIB_RGB_COLORS, // wUsage
SRCCOPY); // dwROP
}
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 恢复以前的调色板
if (hOldPal != NULL)
{
::SelectPalette(hDC, hOldPal, TRUE);
}
// 返回
return bRet;
}
/*************************************************************************
*
* 函数名称:
* CreateDIBPalette()
*
* 参数:
* HDIB hDIB - 指向DIB对象的指针
* CPalette* pPal - 调色板指针
*
* 返回值:
* BOOL - 创建成功返回TRUE,否则返回FALSE。
*
* 说明:
* 创建DIB对象调色板
*
************************************************************************/
BOOL CDIB::CreateDIBPalette(HDIB hDIB, CPalette* pPal)
{
// 指向逻辑调色板的指针
LPLOGPALETTE lpPal;
// 逻辑调色板的句柄
HANDLE hLogPal;
// 调色板的句柄
HPALETTE hPal = NULL;
// 循环变量
int i;
// 颜色表中的颜色数目
int nNumColors;
// 指向DIB的指针
LPBYTE lpbi;
// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPINFO lpbmi;
// 指向BITMAPCOREINFO结构的指针
LPBITMAPCOREINFO lpbmc;
// 表明是否是Win3.0 DIB的标记
BOOL bWinStyleDIB;
// 创建结果
BOOL bRet = FALSE;
// 判断DIB是否为空
if (hDIB == NULL)
{
// 返回FALSE
return FALSE;
}
// 锁定DIB
lpbi = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 获取指向BITMAPINFO结构的指针(Win3.0)
lpbmi = (LPBITMAPINFO)lpbi;
// 获取指向BITMAPCOREINFO结构的指针
lpbmc = (LPBITMAPCOREINFO)lpbi;
// 获取DIB中颜色表中的颜色数目
nNumColors = DIBNumColors(lpbi);
if (nNumColors != 0)
{
// 分配为逻辑调色板内存
hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)
+ sizeof(PALETTEENTRY)
* nNumColors);
// 如果内存不足,退出
if (hLogPal == 0)
{
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回FALSE
return FALSE;
}
lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
// 设置版本号
lpPal->palVersion = PALVERSION;
// 设置颜色数目
lpPal->palNumEntries = (WORD)nNumColors;
// 判断是否是WIN3.0的DIB
bWinStyleDIB = IS_WIN30_DIB(lpbi);
// 读取调色板
for (i = 0; i < nNumColors; 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;
}
}
// 按照逻辑调色板创建调色板,并返回指针
bRet = pPal->CreatePalette(lpPal);
// 解除锁定
::GlobalUnlock((HGLOBAL) hLogPal);
// 释放逻辑调色板
::GlobalFree((HGLOBAL) hLogPal);
}
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回结果
return bRet;
}
/*************************************************************************
*
* 函数名称:
* FindDIBBits()
*
* 参数:
* LPBYTE lpbi - 指向DIB对象的指针
*
* 返回值:
* LPBYTE - 指向DIB图像象素起始位置
*
* 说明:
* 返回DIB图像象素起始位置
*
************************************************************************/
LPBYTE CDIB::FindDIBBits(LPBYTE lpbi)
{
return (lpbi + *(LPDWORD)lpbi + PaletteSize(lpbi));
}
/*************************************************************************
*
* 函数名称:
* DIBWidth()
*
* 参数:
* LPBYTE lpbi - 指向DIB对象的指针
*
* 返回值:
* DWORD - DIB位像宽度
*
* 说明:
* 获取DIB位图的宽度
*
************************************************************************/
DWORD CDIB::DIBWidth(LPBYTE 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 (DWORD)lpbmc->bcWidth;
}
}
/*************************************************************************
*
* 函数名称:
* DIBHeight()
*
* 参数:
* LPBYTE lpDIB - 指向DIB对象的指针
*
* 返回值:
* DWORD - DIB位图高度
*
* 说明:
* 获取DIB位图高度
*
************************************************************************/
DWORD CDIB::DIBHeight(LPBYTE 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 (DWORD)lpbmc->bcHeight;
}
}
/*************************************************************************
*
* 函数名称:
* PaletteSize()
*
* 参数:
* LPBYTE lpbi - 指向DIB对象的指针
*
* 返回值:
* WORD - DIB中调色板的大小
*
* 说明:
* 返回DIB调色板大小
*
************************************************************************/
WORD CDIB::PaletteSize(LPBYTE lpbi)
{
// 计算DIB中调色板的大小
if (IS_WIN30_DIB (lpbi))
{
//返回颜色数目×RGBQUAD的大小
return (WORD)(DIBNumColors(lpbi) * sizeof(RGBQUAD));
}
else
{
//返回颜色数目×RGBTRIPLE的大小
return (WORD)(DIBNumColors(lpbi) * sizeof(RGBTRIPLE));
}
}
/*************************************************************************
*
* 函数名称:
* DIBNumColors()
*
* 参数:
* LPBYTE lpbi - 指向DIB对象的指针
*
* 返回值:
* WORD - 返回调色板中颜色的种数
*
* 说明:
* 计算DIB调色板颜色数目
*
************************************************************************/
WORD CDIB::DIBNumColors(LPBYTE lpbi)
{
int nBitCount;
// 对于Windows的DIB, 实际颜色的数目可以比象素的位数要少。
// 对于这种情况,则返回一个近似的数值。
// 判断是否是WIN3.0 DIB
if (IS_WIN30_DIB(lpbi))
{
// 读取dwClrUsed值
DWORD dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
if (dwClrUsed != 0)
{
// 如果dwClrUsed(实际用到的颜色数)不为0,直接返回该值
return (WORD)dwClrUsed;
}
}
// 读取象素的位数
if (IS_WIN30_DIB(lpbi))
{
// 读取biBitCount值
nBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
}
else
{
// 读取biBitCount值
nBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
}
// 按照象素的位数计算颜色数目
switch (nBitCount)
{
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
return 0;
}
}
/*************************************************************************
*
* 函数名称:
* DIBBitCount()
*
* 参数:
* LPBYTE lpbi - 指向DIB对象的指针
*
* 返回值:
* WORD - 返回调色板中颜色的种数
*
* 说明:
* 该函数返回DIBBitCount。
*
************************************************************************/
WORD CDIB::DIBBitCount(LPBYTE lpbi)
{
int nBitCount;
// 读取象素的位数
if (IS_WIN30_DIB(lpbi))
{
// 读取biBitCount值
nBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
}
else
{
// 读取biBitCount值
nBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
}
// 返回nBitCount
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -