Chinaunix首页 | 论坛 | 博客
  • 博客访问: 103119307
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类: C/C++

2008-05-19 21:15:40

 来源:

1. 基本概念

先来用通俗的语句讲解位图和调色板的概念。
我们知道,界中的所有颜色都可以由红、绿、蓝(R,G,B)三基色组合而成。针对含有红、绿、蓝色成分的多少,可以对其分别分成0~255个等级,而红、绿、蓝的不同组合共有256×256×256种,因此约能表示1600万种颜色。对于人眼而言,这已经是"真彩色"了。

对每个像素进行了(R,G,B)量化的图像就是位图,其在计算机中对应文件的扩展名一般为.bmp。既然用R,G,B的量化值就可以直接记录一张位图的所有像素,那我们需要调色板干什么呢?

首先,我们可以计算完全利用(R,G,B)组合来存储一个800×600的位图所需要的空间为:

800×600×3 = 1440000(字节)= 1.37M(字节)

惊人的大!因此,调色板横空出世了,它的功能在于缓解位图文件存储空间过大的问题。

假设一个位图为16色,其像素总数为800×600。我们只需要用4个bit就可以存储这个位图的每个像素在16种颜色中所处的等级,然后调色板提供了这16种等级对应的(R,G,B)值,这样,存储这个16色位图只需要:

800×600×4/8 = 240000(字节)= 0.22 M(字节)

额外的存储R,G,B表的开销(即调色板Palette,也称为颜色查找表LUT)仅仅为16×3=48字节。

存储空间被大为减少!

常见的位图有单色、16色、256色、16位及24位真彩色5种,对于前三者(即不大于256色)都可以调色板方式进行存储,而对16位及24位真彩色以调色板进行存储是不划算的,它们直接按照R,G,B分量进行存储。

在此基础上我们来DDB位图(Device-dependent bitmap,与设备相关的位图)与DIB位图(Device-independent bitmap,与设备无关的位图)的概念以及二者的区别。

DDB依赖于具体设备,它只能存在于内存中(内存或系统内存),其颜色模式必须与特定的输出设备相一致,使用系统调色板。一般只能载入色彩较简单的DDB位图,对于颜色较丰富的位图,需使用DIB才能长期保存。

DIB不依赖于具体设备,可以用来永久性地保存图象。DIB一般是以*.BMP文件的形式保存在磁盘中的,有时也会保存在*.DIB文件中。 DIB位图的是将颜色信息储存在位图文件自身的颜色表中,应用程序要根据此颜色表为DIB创建逻辑调色板。因此,在输出一幅DIB位图之前,程序应该将其逻辑调色板选入到相关的设备上下文并实现到系统调色板中。

2. 例程简述

本文后续的讲解都基于这样的一个例子工程,它是一个基于对话框的MFC应用程序,包括2个父菜单:

(1) DDB位图

DDB位图父菜单又包括两个子菜单:

a. ID:IDM_LOADDDBPIC caption:加载

单击事件:加载资源中的DDB位图并显示之

b. ID:IDM_MARK_DDBPIC caption:标记

单击事件:在DIB位图中透明地添加天极网logo

(2) DIB位图

DIB位图父菜单又包括两个子菜单:

a. ID:IDM_OPENDIBPIC caption:打开

单击事件:弹出文件对话框,打开.bmp位图文件,并显示

b. ID:IDM_MARK_DIBPIC caption:标记

单击事件:在DIB位图中透明地添加天极网logo

工程中还包含下列位图资源:

(1)IDB_LOADED_BITMAP:要加载的位图资源

(2)IDB_YESKY_BITMAP:天极网logo

后续篇章将集中在对4个子菜单单击事件消息处理函数的讲解,下面的代码是整个对话框类CBitMapExampleDlg的消息映射:

BEGIN_MESSAGE_MAP(CBitMapExampleDlg, CDialog)
//{{AFX_MSG_MAP(CBitMapExampleDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_COMMAND(IDM_LOADDDBPIC, OnLoadddbpic)
ON_COMMAND(IDM_MARK_DDBPIC, OnMarkDdbpic)
ON_COMMAND(IDM_OPENDIBPIC, OnOpendibpic)
ON_COMMAND(IDM_MARK_DIBPIC,OnMarkDibpic) //}}AFX_MSG_MAP
END_MESSAGE_MAP()

3. DDB位图编程

先看DDB加载按钮的单击事件代码:

void CBitMapExampleDlg::OnLoadddbpic()
{
1: CBitmap bmpDraw;
2: bmpDraw.LoadBitmap( IDB_LOADED_BITMAP );//装入要加载的DDB位图
3: BITMAP bmpInfo;
4: bmpDraw.GetBitmap( &bmpInfo ); //获取要加载DDB位图的尺寸
5: CDC memDC;//定义一个兼容DC
6: CClientDC dc( this );
7: memDC.CreateCompatibleDC( &dc );//创建兼容DC
8: CBitmap* pbmpOld = memDC.SelectObject( &bmpDraw );//保存原有DDB,并选入新DDB入DC

9: dc.BitBlt( 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC, 0, 0, SRCCOPY );

10: memDC.SelectObject( pbmpOld );//选入原DDB
}

上述代码将产生如图1所示的,位图被安置在对话框(0,0)坐标开始的位置上。

阅读(569) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~