CPalette,CBitmap与DIB

本文介绍MFC框架下CPalette类的调色板创建与使用方法,包括从位图创建调色板的过程;同时讲解CBitmap类的基本操作,如位图的读取、显示及DIB文件的结构解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CPalette是MFC封装的调色板类。CPalette的操作如下:
1. 创建调色板。要创建一个调色板,需要首先知道要创建的调色板对象所包含的颜色数nColors,然后创建一个逻辑调色板

LOGPALETTE结构,并利用该逻辑调色板结构初始化调色板对象。
UINT nSize=sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY)*(nColors-1));//计算逻辑调色板所需空间
LOGPALETTE *pLP=(LOGPALETTE*) new BYTE[nSize];
//初始化逻辑调色板,假设R,G,B 保存的是调色板各颜色红,绿,蓝三个分量的数组
pLP->palVersion=0x300;//固定值
pLP->palNumEntries=nColors;
for(int i=0;i<nColors;i++)
{
pLP->palPalEntry[i].peRed=R[i];
pLP->palPalEntry[i].peGreen=G[i];
pLP->palPalEntry[i].peBlue=B[i];
pLP->palPalEntry[i].peFlags=0;
}
//创建调色板
CPalette m_palette;
m_palette.CreatePalette(pLP);
2.从位图创建调试版。假设m_bitmap是一个CBitmap对象。
DIBSECTION ds;
m_bitmap.GetObject(sizeof(DIBSECTION),&ds);

//计算颜色数
int nColors;
if(ds.dsBmih.biClrUsed!=0)
{
nColors=ds.dsBmih.biClrUsed;
}
else
{
nColors=1<<ds.dsBmih.biBitCount;
}

//创建调色板
if(nColors>256)
m_palette.CreateHalftonePalette(&dc);
else
{
RGBQUAD *pRGB=new RGBQUAD[nColors];

//得到位图颜色列表
CDC memDC;
memDC.CreateCompatibleDC(&dc);
CBitmap *pOldBitmap=memDC.SelectObject(&m_bitmap);
::GetDIBColorTable((HDC)memDC,0,nColors,pRGB);//得到颜色列表
memDC.SelectObject(pOldBitmap);

//初始化逻辑调色板
UINT nSize=sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY)*(nColors-1));
LOGPALETTE *pLP=(LOGPALETTE*) new BYTE[nSize];
pLP->palVersion=0x300;
pLP->palNumEntries=nColors;
for(int i=0;i<nColors;i++)
{
pLP->palPalEntry[i].peRed=pRGB[i].rgbRed;
pLP->palPalEntry[i].peGreen=pRGB[i].rgbGreen;
pLP->palPalEntry[i].peBlue=pRGB[i].rgbBlue;
pLP->palPalEntry[i].peFlags=0;
}

//创建调色板
m_palette.CreatePalette(pLP);
}

3.使用调色板:
要使用以创建好的调试版m_palette,需要在画图前选如调色板,并实现之。
CPalette *pOldPalette=pDC->SelectPalette(&m_palette,FALSE);
pDC->RealizePalette();
...//图像显示或画图操作
pDC->SelectPalette(pOldPalette,FALSE);

CBitmap是MFC封装的一个位图类,这个位图可以使DDB或DIB,即设备相关位图或设备无关位图。

关于CBitmap的操作如下:

1. 位图读取。如果从文件读取一幅位图并保持在m_bitmap对象中,操作如下:

HBITMAP hBitmap;
hBitmap=(HBITMAP)::LoadImag (NULL, lpszPathName, IMAGE_BITMAP,
0,0,

LR_LOADFROMFILE | LR_CREATEDIBSECTION);
if(!hBitmap)
m_bitmap.Attach(hBitmap);
如果从资源载入一幅位图直接用m_bitmap.LoadBitmap( nIDResource );
2.位图显示。首先如果位图有调色板,把位图调色板选人DC并实现之
CPalette *pOldPalette=pDC->SelectPalette(pPalette,FALSE);
pDC->RealizePalette();
然后再用BitBlt或StretchBlt显示
CDC* memDC;
memDC->CreateCompatibleDC(pDC);
CBitmap *pOldBitmap=memDC->SelectObject(&m_bitmap);
pDC->BitBlt(0,0,bitmapWidth,bitmapHeight, &memDC,0,0,SRCCOPY);//显示图像

DIB又叫设备无关位图,顾名思义,像素的颜色独立于系统调色板,因此可以用来在不同的系统之间或不同的应用程序之间交流,或永久性地保存图象。
DIB文件是以BITMAPFILEHEADER结构开头的,紧随该结构的是一个BITMAPINFOHEADER结构,然后是RGBQUAD结构组成的颜色表(对于2、8、16、256色位图而言,24位真彩色位图没有),文件最后存储的是DIB的像素阵列。BITMAPFILEHEADER结构的定义为:
   typedef struct tagBITMAPFILEHEADER
{
   WORD bfType;
//文件类型,必须为"BM"
   DWORD bfSize;//文件的大小
   WORD bfReserved1;//为0
   WORD bfReserved2;//为0
   DWORD bfOffBits;//存储的像素阵列相对于文件头的偏移量
   } BITMAPFILEHEADER;
在内存中,一个完整的DIB由两部分组成:一个BITMAPINFO结构和一个存储像素阵列的数组。BITMAPINFO 描述了位图的大小,颜色模式和调色板等各种属性,其定义为:
  typedef struct tagBITMAPINFO
{
   BITMAPINFOHEADER bmiHeader;
   RGBQUAD bmiColors[1];
//颜色列表,在此只是占位,如果位图没有颜色列表,该数组为空。
  } BITMAPINFO;
其中BITMAPINFOHEADER结构包含了DIB的各种信息,其定义为:
  typedef struct tagBITMAPINFOHEADER
{
   DWORD biSize;
//该结构的大小
   LONG biWidth;//位图的宽度(以像素为单位)
   LONG biHeight;//位图的高度(以像素为单位)
   WORD biPlanes;//必须为1
   WORD biBitCount//每个像素的位数(1、4、8、16、24或32)
   DWORD biCompression;//压缩方式,一般为0或BI_RGB (未压缩)
   DWORD biSizeImage;//以字节为单位的图象大小(仅用于压缩位图)
   LONG biXPelsPerMeter;//以目标设备每米的像素数来说明位图的水平分辨率
   LONG biYPelsPerMeter;//以目标设备每米的像素数来说明位图的垂直分辨率
   DWORD biClrUsed;//颜色表的颜色数,若为0则位图使用由biBitCount指定的最大颜色数
   DWORD biClrImportant;//重要颜色的数目,若该值为0则所有颜色都重要
  } BITMAPINFOHEADER;
RGBQUAD结构用来描述颜色,其定义为:
  typedef struct tagRGBQUAD
{
   BYTE rgbBlue;
//蓝色分量
   BYTE rgbGreen;//绿色分量
   BYTE rgbRed;//红色分量
   BYTE rgbReserved;//保留字节,为0
  } RGBQUAD;
DIB的字节数组是从图象的最下面一行开始的逐行向上存储的,也即等于把图象倒过来然后在逐行扫描。另外,字节数组中每个扫描行的字节数必需是4的倍数,如果不足要用0补齐。

http://hi.baidu.com/tuenmei/blog/item/5a34bce6178b4e27b8382059.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值