永发信息网

CDIB什么意思

答案:1  悬赏:20  手机版
解决时间 2021-01-16 04:41
CDIB什么意思
最佳答案
VC里的类

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

(1) CDib类的声明

// DIB.h:类CDib声明头文件
#ifndef __DIB_H__
#define __DIB_H__
#include
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);
}
}
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
我们安全生产的基本防护要求包括
石茶盘应该如何保养?
城堡的入口处有3个分别编号为1,2,3的按钮.
欧盟总部、北约总部、国际奥委会总部、联合国
仿佛造句
古剑人物星蕴怎么设置的好
小学生必背古诗90首中的20,21首
圣经以西结书11章5至12节的意思
以路为主题写一首现代诗,励志的。一定要是自
52度泸州浓香型价格
领导把我加班报错了,少发50元,有必要找吗?
给一万玩三批你干吗
厨房改造,拆除旧橱柜自己可以拆吗,雇人一般
郑州补一张移动卡多少钱
涤纶弹力复合面料用英语怎么说
推荐资讯
梦见自己很勤奋的写化学作业是什么意思
速8快捷酒店怎么算钱的,我晚上一点开的单间
72年的属鼠男和81年属鸡女相配吗
best boy什么意思
晴字意思是什么
如何给电冰箱加氟?冰箱加氟的小方法
鸽子从含草做窝到下蛋一般要多长时间
windows将在一分钟内关闭是怎么回事?
中国移动栖霞臧家庄镇营业厅电话是多少
美国森乐净水(保利水城旗舰店)地址好找么,我
谁有风云小说-十二惊惶后面的部分??
人有不怕挨打的吗
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?