问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

CDIB什么意思

发布网友 发布时间:2022-04-23 10:31

我来回答

1个回答

热心网友 时间:2023-10-11 13:05

VC里的类

Visual C++ MFC中没有提供一个专门的类来处理DIB位图,因此,为了方便地使用位图文件,我们有必要派生一个CDib类。类的源代码如下:

(1) CDib类的声明

// DIB.h:类CDib声明头文件
#ifndef __DIB_H__
#define __DIB_H__
#include <wingdi.h>
class CDib
{
public:
CDib();
~CDib();

BOOL Load( const char * );
BOOL Save( const char * );
BOOL Draw( CDC *, int nX = 0, int nY = 0, int nWidth = -1, int nHeight = -1, int mode = SRCCOPY);
BOOL SetPalette( CDC * );

private:
CPalette m_Palette;
unsigned char *m_pDib, *m_pDibBits;
DWORD m_dwDibSize;
BITMAPINFOHEADER *m_pBIH;
RGBQUAD *m_pPalette;
int m_nPaletteEntries;
};
#endif

(2) CDib类的实现

// DIB.cpp:类CDib实现文件
#include "stdafx.h"
#include "DIB.h"

CDib::CDib()
{
m_pDib = NULL;
}

CDib::~CDib()
{
// 如果位图已经被加载,释放内存
if (m_pDib != NULL)
delete []m_pDib;
}

下面这个函数非常重要,其功能为加载位图,类似于CBitmap类的LoadBitmap函数:

BOOL CDib::Load(const char *pszFilename)
{
CFile cf;

// 打开位图文件
if (!cf.Open(pszFilename, CFile::modeRead))
return (FALSE);

// 获得位图文件大小,并减去BITMAPFILEHEADER的长度
DWORD dwDibSize;
dwDibSize = cf.GetLength() - sizeof(BITMAPFILEHEADER);

// 为DIB位图分配内存
unsigned char *pDib;
pDib = new unsigned char[dwDibSize];
if (pDib == NULL)
return (FALSE);

BITMAPFILEHEADER BFH;

// 读取位图文件数据
try
{
// 文件格式是否正确有效
if ( cf.Read(&BFH, sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER) ||
BFH.bfType != ’MB’ || cf.Read(pDib, dwDibSize) != dwDibSize)
{
delete []pDib;
return (FALSE);
}
}
catch (CFileException *e)
{
e->Delete();
delete []pDib;
return (FALSE);
}

// delete先前加载的位图
if (m_pDib != NULL)
delete m_pDib;

// 将临时Dib数据指针和Dib大小变量赋给类成员变量
m_pDib = pDib;
m_dwDibSize = dwDibSize;

// 为相应类成员变量赋BITMAPINFOHEADER和调色板指针
m_pBIH = (BITMAPINFOHEADER*)m_pDib;
m_pPalette = (RGBQUAD*) &m_pDib[sizeof(BITMAPINFOHEADER)];

// 计算调色板中实际颜色数量
m_nPaletteEntries = 1 << m_pBIH->biBitCount;
if (m_pBIH->biBitCount > 8)
m_nPaletteEntries = 0;
else if (m_pBIH->biClrUsed != 0)
m_nPaletteEntries = m_pBIH->biClrUsed;

// 为相应类成员变量赋image data指针
m_pDibBits = &m_pDib[sizeof(BITMAPINFOHEADER) + m_nPaletteEntries * sizeof (RGBQUAD)];

// delete先前的调色板
if (m_Palette.GetSafeHandle() != NULL)
m_Palette.DeleteObject();

// 如果位图中存在调色板,创建LOGPALETTE 及CPalette
if (m_nPaletteEntries != 0)
{
LOGPALETTE *pLogPal = (LOGPALETTE*)new char[sizeof(LOGPALETTE) + m_nPaletteEntries *sizeof(PALETTEENTRY)];

if (pLogPal != NULL)
{
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = m_nPaletteEntries;

for (int i = 0; i < m_nPaletteEntries; i++)
{
pLogPal->palPalEntry[i].peRed = m_pPalette[i].rgbRed;
pLogPal->palPalEntry[i].peGreen = m_pPalette[i].rgbGreen;
pLogPal->palPalEntry[i].peBlue = m_pPalette[i].rgbBlue;
}

//创建CPalette并释放LOGPALETTE的内存
m_Palette.CreatePalette(pLogPal);
delete []pLogPal;
}
}

return (TRUE);
}

//函数功能:保存位图入BMP文件
BOOL CDib::Save(const char *pszFilename)
{
if (m_pDib == NULL)
return (FALSE);

CFile cf;
if (!cf.Open(pszFilename, CFile::modeCreate | CFile::modeWrite))
return (FALSE);

try
{
BITMAPFILEHEADER BFH;
memset(&BFH, 0, sizeof(BITMAPFILEHEADER));
BFH.bfType = ’MB’;
BFH.bfSize = sizeof(BITMAPFILEHEADER) + m_dwDibSize;
BFH.bfOffBits = sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER) + m_nPaletteEntries *sizeof(RGBQUAD);

cf.Write(&BFH, sizeof(BITMAPFILEHEADER));
cf.Write(m_pDib, m_dwDibSize);
}
catch (CFileException *e)
{
e->Delete();
return (FALSE);
}
return (TRUE);
}

下面这个函数也非常重要,其功能为在pDC指向的CDC中绘制位图,起点坐标为(nX,nY),绘制宽度和高度为nWidth、nHeight,最后一个参数是光栅模式:

BOOL CDib::Draw(CDC *pDC, int nX, int nY, int nWidth, int nHeight, int mode)
{
if (m_pDib == NULL)
return (FALSE);

// 获取位图宽度和高度赋值
if (nWidth == - 1)
nWidth = m_pBIH->biWidth;
if (nHeight == - 1)
nHeight = m_pBIH->biHeight;

// 绘制位图
StretchDIBits(pDC->m_hDC, nX, nY, nWidth, nHeight, 0, 0, m_pBIH->biWidth, m_pBIH->biHeight, m_pDibBits, (BITMAPINFO*)m_pBIH, BI_RGB, mode);

return (TRUE);
}

//函数功能:设置调色板
BOOL CDib::SetPalette(CDC *pDC)
{
if (m_pDib == NULL)
return (FALSE);

// 检查当前是否有一个调色板句柄,对于大于256色的位图,为NULL
if (m_Palette.GetSafeHandle() == NULL)
return (TRUE);

// 选择调色板,接着实施之,最后恢复老的调色板
CPalette *pOldPalette;
pOldPalette = pDC->SelectPalette(&m_Palette, FALSE);
pDC->RealizePalette();
pDC->SelectPalette(pOldPalette, FALSE);

return (TRUE);
}

从整个CDib类的代码中我们可以看出,DIB位图的显示需遵循如下步骤:

(1)读取位图,本类中使用pDib = new unsigned char[dwDibSize]为位图中的信息分配内存,另一种方法是调用API函数CreateDIBSection,譬如:

m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(),
(LPBITMAPINFO) m_lpBMPHdr, DIB_RGB_COLORS,
(LPVOID*) &m_lpDIBits, NULL, 0);

m_hBitmap定义为:

HBITMAP m_hBitmap;

(2)根据读取的位图信息,计算出调色板大小,然后创建调色板;

(3)调用CDib::SetPalette( CDC *pDC )设置调色板,需要用到CDC::SelectPalette及CDC::RealizePalette两个函数;

(4)调用CDib::Draw(CDC *pDC, int nX, int nY, int nWidth, int nHeight, int mode)函数绘制位图。在此函数中,真正发挥显示位图作用的是对StretchDIBits API函数的调用。StretchDIBits函数具有缩放功能,其最后一个参数也是光栅操作的模式。

下面给出DIB位图的打开及显示并在其中加入天极网logo的函数源代码。"DIB位图"父菜单下"打开"子菜单的单击事件消息处理函数为(其功能为打开位图并显示之):

void CBitMapExampleDlg::OnOpendibpic()
{
// 弹出文件对话框,让用户选择位图文件
CFileDialog fileDialog(TRUE, "*.BMP", NULL, NULL,"位图文件(*.BMP)|*.bmp;*.BMP|");
if (IDOK == fileDialog.DoModal())
{
// 加载位图并显示之
CDib dib;
if (dib.Load(fileDialog.GetPathName()))
{
CClientDC dc(this);
dib.SetPalette(&dc);
dib.Draw(&dc);
}
}
}

"DIB位图"父菜单下"标记"子菜单的单击事件消息处理函数为(其功能为给位图加上天极网logo):

void CBitMapExampleDlg::OnMarkDibpic()
{
// 弹出文件对话框,让用户选择标记logo
CFileDialog fileDialog(TRUE, "*.BMP", NULL, NULL, "标记位图文件(*.BMP)|*.bmp;*.BMP|");
if (IDOK == fileDialog.DoModal())
{
// 加载标记logo位图并与目标位图相与
CDib dib;
if (dib.Load(fileDialog.GetPathName()))
{
CClientDC dc(this);
dib.SetPalette(&dc);
dib.Draw(&dc, 0, 0, - 1, - 1, SRCAND);
}
}
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
2024年四川570分能考上什么大学? 2024年四川文科560分能考上什么大学? 2024年广东561分能考上什么大学? 2024年江苏历史类561分能考上什么大学? 在形ABC中,角A.B.C所对的边分别为a.b.c,且acosB+bcosA=2c cos 求... ...B、C的对边分别为a、b、c,已知acosB+bcosA=2(bcosC+ccosB).(1... ...b、c的对边分别为a、b、c,且acosb+bcosa=2cosc 在△ ABC中,角A、B、C所对的边分别为a、b、c,已知b=cosA,c=2cosB,试... 在△ABC中,角A,B,C所对的边分别为a,b,c,且满足bcosA+acosB=2ccosC,△... ...对应的边分别为a、b、c,且满足aCOSB+bcosA=2cCOSC... java 如何让以下代码画图流畅,而不是断断续续,因双缓冲没学,尽量在以下代码基础上该把,求大师指点 怎样用mfc在窗口指定区域显示位图 C# WindowsForm pictureBox实现后台图片切换功能 vb 画多边形 怎样画冲压件以及轴类图纸?需要哪些数据? 非均齐超网络演化模型用python实现 怎样基于python networkx实现社区发现 python的networkx怎么给边加注释 结婚孝敬父母的句子 结婚现场新郎对新娘父亲说的话 结婚时向岳父岳母说的感恩的话 结婚时,女儿对父母该说些什么感恩词? 婚礼新郎对父母感谢话 婚礼上新人对父母说的话 婚礼上对父母说的话简短 结婚祝福父母的话语 在婚礼上对父母说的话 结婚感恩父母的句子好段 结婚时男方对女方父母说的话 有道词典怎么离线下载单词? 递归算法 汉诺塔 演示 镂空图算法的基本思想是什么 请将下述公式改为选股公式,选出当天同时出现钱袋子和B的股票 vb屏幕保护代码 金山词霸的屏幕取词是什么原理 关于GDI的Bitblt VFP 表单circle画圆的问题 家具拆单用什么软件 如何把通达信的条件选股公式修改成主图指标呀?谢谢 qq里的看点,看完一篇文章,发表评论,下面有个打钩:biu到看点·关注,啥子... 为什么QQ看点发表了评论直接biu到主页去了 并且没有那个勾勾取消biu? 别人在我QQ看点biu的下面骂人怎么办? 在qq看点biu能匿名@别人吗 QQ看点为什么我评论的,有的好友会收到BIU,感觉好尴尬,不过有的好友没有收到 江苏交通违章罚款可以网上缴费吗 我是外地罚款,现罚款单丢失。如何交罚款呢 为什么江苏交通违章用12123处理要用融支付而付不了款? 盐城有没有处理交通违章的APP啊,可以在手机 江苏银行能不能交电动车违章罚款? 上海的汽车在江苏违章了,如何缴纳罚款?