数学建模社区-数学中国

标题: BMP位图文件结构及平滑缩放 [打印本页]

作者: 韩冰    时间: 2005-1-26 12:42
标题: BMP位图文件结构及平滑缩放

8 R& A/ W7 z- U# J

西安交通大学流体机械研究所

0 _" W' Z! l% y) x+ l5 O- P

张义云

: B" [% Y! [1 J+ L: }( F

5 k, V- L7 n. v

---- 用普通方法显示BMP位图,占内存大,速度慢,在图形缩小时,失真严重,

) W: ~+ `" Q, ]+ F0 I; r" t; ^

在低颜色位数的设备上显示高颜色位数的图形图形时失真大。本文采用视频函数

6 i$ r+ g; P% V! A7 `, ? F

显示BMP位图,可以消除以上的缺点。

7 u# G0 y; g* s$ Z' C

- B5 I* ^: X4 U) M

---- 一、BMP文件结构

g$ }4 u1 ^- E

; a4 P9 s) i& J' e, `7 m7 s

---- 1. BMP文件组成

* ?1 c$ C: g/ l4 |# j+ ^" o

, d2 X4 l5 J( f5 ?+ N& T

---- BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。

. A, x. I) }, N, M* j

9 A- E- X) V ^; R5 c |

---- 2. BMP文件头

1 k0 }/ m6 F( n! _

- S" a: q9 D+ i7 p+ d% k

---- BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息

9 W0 x9 D# q# [, c0 e

7 X3 J% z! e( U( E" ]

$ A, K3 h/ b% [) H1 c4 J

---- 其结构定义如下:

0 W! I- h- f4 L* d: i- I5 n

" y) z+ r+ q; ~7 @

typedef struct tagBITMAPFILEHEADER

8 P8 ]3 h* i- O& ^! S" b

{

% J* y* Y% f% j5 T

WORDbfType; // 位图文件的类型,必须为BM

) K8 k1 j' |8 K9 b6 k \, p8 r

DWORD bfSize; // 位图文件的大小,以字节为单位

: T8 W. F, \/ p8 ~- p

WORDbfReserved1; // 位图文件保留字,必须为0

+ J# f. l& i4 w8 V5 ?/ F4 `

WORDbfReserved2; // 位图文件保留字,必须为0

8 b2 k `* X$ ^. t- V

DWORD bfOffBits; // 位图数据的起始位置,以相对于位图

. ~( a7 b& o$ u! t

// 文件头的偏移量表示,以字节为单位

# O l; X1 t$ {

} BITMAPFILEHEADER;

, I1 R: `, H( q$ b. Z) E

' Z* B$ s6 N( b5 Q! y

?# ~7 ~- y( }. z( t1 E1 {- y& t

---- 3. 位图信息头

' M! C/ m" q8 m5 p# `& K

----

! U5 m$ W$ n# A: X

6 i( Y* t4 ?& z; w

BMP位图信息头数据用于说明位图的尺寸等信息。

; X9 J+ @8 N& ?) H

typedef struct tagBITMAPINFOHEADER{

& l4 c7 y+ {! n3 R3 M5 e

DWORD biSize; // 本结构所占用字节数

X7 Y% E) n# k( v% @

LONGbiWidth; // 位图的宽度,以像素为单位

, x" y8 p# H* o3 M5 a4 s

LONGbiHeight; // 位图的高度,以像素为单位

+ x& U* c3 o3 u9 c7 O, \2 Y X7 u

WORD biPlanes; // 目标设备的级别,必须为1

, t' r o9 V F7 n

WORD biBitCount// 每个像素所需的位数,必须是1(双色),

: e! d, e3 Q1 y; H! M

// 4(16色),8(256色)或24(真彩色)之一

! \) B/ v5 N! u7 V A \

DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),

- n: {8 e9 ^2 P7 K7 u

// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一

; J; ~) J* a. ]1 z, L P8 d$ R: E

DWORD biSizeImage; // 位图的大小,以字节为单位

# j' U* c4 d$ t) I6 y( {

LONGbiXPelsPerMeter; // 位图水平分辨率,每米像素数

- A9 J' B; s1 S8 f8 W) o1 ^

LONGbiYPelsPerMeter; // 位图垂直分辨率,每米像素数

% H2 ^9 z. s2 a

DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数

" X5 |$ y9 t) C( X a G

DWORD biClrImportant;// 位图显示过程中重要的颜色数

% Q2 S+ Z5 k* V( k. Y

} BITMAPINFOHEADER;

/ ]% g; I+ ~+ \/ g

* c8 @- o4 h/ @2 a: |5 C9 b) c P5 M9 b

( `* g5 i% j# _* B6 f& N

---- 4. 颜色表

1 G' w! ?) X& S% I. V4 Z% _

---- 颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个

/ N" G% @; r. X) y( J0 I4 ?$ h7 T

RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:

, I3 u: R& `+ s) t* J

0 `+ l* Z1 r' H+ E& r

typedef struct tagRGBQUAD {

1 F: k5 R" d1 g9 f, W& r1 j; Z

BYTErgbBlue;// 蓝色的亮度(值范围为0-255)

c" ~9 k" x. [3 `3 l, o S

BYTErgbGreen; // 绿色的亮度(值范围为0-255)

* l& Y9 n4 [3 f. q7 _# m, |) m

BYTErgbRed; // 红色的亮度(值范围为0-255)

1 K9 ]+ `( A n% H

BYTErgbReserved;// 保留,必须为0

$ F. f5 O9 ?" ~' f0 L1 T

} RGBQUAD;

. ?6 }0 G5 l0 y ?% l Y3 K3 @* }4 h

颜色表中RGBQUAD结构数据的个数有biBitCount来确定:

$ ~/ x. S$ X) L0 K( q3 [1 m z8 Y

当biBitCount=1,4,8时,分别有2,16,256个表项;

" n& u4 ]6 ^/ h1 N

当biBitCount=24时,没有颜色表项。

( Q) e0 D4 J3 E2 L9 t/ g

位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:

/ c8 ^" g) c" g. Q" }5 F

typedef struct tagBITMAPINFO {

! Y5 j& L* K% J* E2 x' ` e" \* |6 R

BITMAPINFOHEADER bmiHeader; // 位图信息头

6 ^$ `4 ]4 u2 G& X# n: |

RGBQUAD bmiColors[1]; // 颜色表

/ J# m1 e' P2 R5 X7 F+ T

} BITMAPINFO;

4 ~* [. F: B, ?3 N' O# z8 n

! t# E2 d- `: _ \! Z

/ V, L1 Q) V( Q6 U! H/ p5 b0 w* `

$ z% d' a& t6 ?6 B8 K4 x7 f, d

---- 5. 位图数据

4 ?# T# [8 G4 [

---- 位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右

4 t. l( u$ P5 ?4 {# L& [2 l! N( C

,扫描行之间是从下到上。位图的一个像素值所占的字节数:

/ l; S0 [9 c( i. y3 ~1 [

/ F* B7 |% x. G! X2 T$ @- S7 @7 v

当biBitCount=1时,8个像素占1个字节;

8 ~. E# k$ ~9 V" ^( R

当biBitCount=4时,2个像素占1个字节;

, _6 `& x" v0 G' i$ ~: s4 ^" |

当biBitCount=8时,1个像素占1个字节;

, `6 `& D# R4 X9 c; P5 M' N) h* X; n8 r

当biBitCount=24时,1个像素占3个字节;

2 g. _* U9 U: v+ o# X! V

Windows规定一个扫描行所占的字节数必须是

8 l: `$ d: k- U& y9 d$ ^) A3 V5 f- U

4的倍数(即以long为单位),不足的以0填充,

+ G4 G4 {0 f2 Q0 ^) k4 i0 }, I

一个扫描行所占的字节数计算方法:

- B% ]$ v0 w7 a- C8 f9 h0 x: B: y

DataSizePerLine= (biWidth* biBitCount+31)/8;

; B) q3 \7 Y) l& o+ Q/ ?2 P

// 一个扫描行所占的字节数

8 k5 l! E, D' m# O' @# ]

DataSizePerLine= DataSizePerLine/4*4; // 字节数必须是4的倍数

9 t1 d) T! _" U# Z2 M; U' F0 I

位图数据的大小(不压缩情况下):

) M. `( C8 s4 B+ Z9 s- s% u/ u

DataSize= DataSizePerLine* biHeight;

$ u. {& R$ l7 F4 r! [' ?) q

8 ^, g+ p4 _, B3 N1 C

( y; [# A5 W5 C$ D. B/ b& ?: V( @ o

---- 二、BMP位图一般显示方法

A6 v+ n( Z' Z3 J! F

---- 1. 申请内存空间用于存放位图文件

* ?% `* G! @" H

% ^& i& g" p' \6 c' A

---- GlobalAlloc(GHND,FileLength);

3 i8 q& L. Z; Z9 X2 ]. n! ]( T

+ r3 ~9 j8 ]/ \! h2 o

---- 2. 位图文件读入所申请内存空间中

& q& p8 S/ ]- [4 Q+ q

: o }: E f% F0 x# k

---- LoadFileToMemory( mpBitsSrc,mFileName);

$ R3 W" w" q5 F, R H" b

; o8 M# e$ w* h6 _* h$ N$ }

---- 3. 在OnPaint等函数中用创建显示用位图

( }# C2 D9 V$ S- M5 n# t

- I% x" ^) z; U$ X8 ?

---- 用CreateDIBitmap()创建显示用位图,用CreateCompatibleDC()创建兼容

! ~5 S- [( O( Q" |; l

DC,

2 O5 ^$ ~2 |1 {" m

) _% w% e6 b7 L2 N0 F3 T" H

---- 用SelectBitmap()选择显示位图。

4 y/ i3 s: i$ g+ \

2 N7 ?% \/ e4 i# `. g/ n& W

---- 4. 用BitBlt或StretchBlt等函数显示位图

/ e8 I6 j- f$ H, C

' [! [% H4 m. B( W6 y4 M

---- 5. 用DeleteObject()删除所创建的位图

; |5 {) i. g1 l) J3 M, V2 B2 C

! t& D. K, Y! ^# J( |8 s

---- 以上方法的缺点是: 1)显示速度慢; 2) 内存占用大; 3) 位图在缩小显示

/ L+ O. l3 n7 W; W% O; {

时图形失真大,(可通过安装字体平滑软件来解决); 4) 在低颜色位数的设备上(

+ K3 G) ^* Z9 C

如256显示模式)显示高颜色位数的图形(如真彩色)图形失真严重。

J( Z4 ]/ J3 T+ l

Q% J+ R+ x" b) U& `4 R

---- 三、BMP位图缩放显示

7 G3 S# G( T: A6 }5 h2 X: O4 F8 _& j

1 n. y, f; k8 W' `1 J, i

---- 用DrawDib视频函数来显示位图,内存占用少,速度快,而且还可以对图形

6 o: t9 L w: X+ ^

进行淡化(Dithering)处理。淡化处理是一种图形算法,可以用来在一个支持比

8 c* \" Z+ ^; W8 Z& m' W+ A

图像所用颜色要少的设备上显示彩色图像。BMP位图显示方法如下:

_% G# h# F: Y ]: ?/ d( ?& S6 [0 g9 P

2 U0 k A5 L# b' R

---- 1. 打开视频函数DrawDibOpen(),一般放在在构造函数中

! _. Q: P! F' c8 r) f. U

. I! y5 B- I% V& p

---- 2. 申请内存空间用于存放位图文件

6 Y) Z1 ]$ p; G" Q' X2 J$ {; l* k+ x

5 `7 {- V( c, J M

---- GlobalAlloc(GHND,FileLength);

! h( K4 g2 y g* q

0 y1 O8 U7 W% S w+ S! z/ k" {

---- 3. 位图文件读入所申请内存空间中

# v+ |# y/ B9 r+ {

. c3 n- |6 }2 \$ h& J% b; t

---- LoadFileToMemory( mpBitsSrc,mFileName);

2 B8 C) Q6 G& v% p9 K/ n' }6 x# w# W

: N2 ~" [. Q6 k; C

---- 4. 在OnPaint等函数中用DrawDibRealize(),DrawDibDraw()显示位图

* a# ]- V1 E/ A' ?+ o/ ~

5 U0 {/ g0 h1 p

---- 5. 关闭视频函数DrawDibClose(),一般放在在析构函数中

9 _, W# W8 ?- t) \# y2 \

: Y% X1 x# @) Z: |9 S! V7 Y9 X( V

---- 以上方法的优点是: 1)显示速度快; 2) 内存占用少; 3) 缩放显示时图形

" D! t7 S9 m! W

失真小,4) 在低颜色位数的设备上显示高颜色位数的图形图形时失真小; 5) 通

6 f) r3 ~* P$ [9 G/ T

过直接处理位图数据,可以制作简单动画。

" s# f( U$ E) I5 [7 ?

3 a2 L5 \' |2 B' O) p

---- 四、CViewBimap类编程要点

7 l7 X# a$ L; U- s+ M9 ]$ ^

0 u9 C! D' z3 V" C% j1 s- ^9 Y, S y

---- 1. 在CViewBimap类中添加视频函数等成员

" o7 e5 [- b. b: \3 |

7 y: Q) `2 Z6 v* ?

HDRAWDIB m_hDrawDib; // 视频函数

) Z$ r! {- k/ Q7 [. s) }2 r- U C s

HANDLEmhBitsSrc; // 位图文件句柄(内存)

+ }& [, w# v) f/ s1 a

LPSTR mpBitsSrc; // 位图文件地址(内存)

. u1 E, ?0 b. I

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

, I, e9 _1 W, q( H

2 k6 V0 d" t+ W- {

' q# U( ]; k: [- I

---- 2. 在CViewBimap类构造函数中添加打开视频函数

/ q) r; \, j! J) x" q* o$ z6 Z$ J

---- m_hDrawDib= DrawDibOpen();

2 |1 P+ U" A3 N) n% k3 T9 Q5 x

. W8 l7 ^. B7 e, ^1 O# j, J

---- 3. 在CViewBimap类析构函数中添加关闭视频函数

Z3 `! A8 g8 g/ g. t# {

# R4 [+ j% G+ E, H" f

if( m_hDrawDib != NULL)

. d! B% L0 Z$ p

{

$ ~$ h5 o8 S1 d7 ]

DrawDibClose( m_hDrawDib);

( P' i, O- `5 n& l4 m0 ?7 Z

m_hDrawDib = NULL;

' [1 ~- }/ O5 z& @: s

}

; J' B9 |/ J# U3 z# u1 O

+ b }9 P2 c% {( {- V6 |

" |& P6 K( L: U+ [

---- 4. 在CViewBimap类图形显示函数OnPaint中添加GraphicDraw()

7 E1 [( ?3 {3 R# Y; s9 d/ t. e" L' ~

voidCViewBitmap::OnPaint()

2 B/ S4 Y( @ ~/ L; C

{

+ _' g" E3 D: b. `

CPaintDC dc(this); // device context for painting

& B5 b$ @# t+ @ W

GraphicDraw( );

. E/ N4 [. j/ x* ?4 x6 ]

}

. [' ^. J* A# c0 L; z- C

/ Y3 D# ]$ E3 N1 d; o

voidCViewBitmap::GraphicDraw( void )

0 t6 M2 r; l$ r, B% [" ~. O

{

H$ g* y! R" ~ B* ^) @7 q ?

CClientDC dc(this); // device context for painting

% Q3 k& e4 q; L, k' _6 N% U- K

BITMAPFILEHEADER *pBitmapFileHeader;

" ^$ T1 Y: r1 v4 l

ULONG bfoffBits= 0;

& j: U4 Y! a- t+ O: z N8 w

CPoint Wid;

& [: v: y! {6 ~2 f. A1 T8 V+ M' j

% T& I4 V7 u$ I

// 图形文件名有效 (=0 BMP)

% S& V1 m( |# n7 `+ q

if( mBitmapFileType < ID_BITMAP_BMP ) return;

6 i2 D) y& y4 C3 C; P6 J& k7 m8 S% U

. t, W) j1 r/ z1 f! K, x

// 图形文件名有效 (=0 BMP)

2 i- G4 |% p% J

// 准备显示真彩位图

9 Z& v. _, w' ?4 y0 `) V, h

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

* i: z2 E0 h. g" k$ t; n# E

bfoffBits= pBitmapFileHeader->bfOffBits;

6 L! d* h; d. z8 p6 _% Q

# _) k' @: I: m6 I6 G- W/ U

// 使用普通函数显示位图

% t1 ~5 o u! G* ^6 z9 e) c% E" d

3 N' v5 q/ G3 u- f5 W2 k2 n

if( m_hDrawDib == NULL || mDispMethod == 0)

$ C, I, m' @. y! z1 J( i4 v5 l

{

% r$ x3 L- E i9 F% y3 X

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

0 B; u! c7 o' d# b& D2 r* X

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

2 `) S+ S% ^/ q. m! y7 A" o

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

" r' |% N8 W3 W* L6 f: |

// 建立位图

4 n* V9 |, f. ]+ a. o& C! S

HDC hMemDC=::CreateCompatibleDC(dc.m_hDC);// 建立内存

% @3 M# T% F7 I0 T& E

HBITMAP hBitmapOld= SelectBitmap(hMemDC, hBitmap); // 选择对象

- F6 X! R, {3 A' R1 x; J/ m

// 成员CRect mDispR用于指示图形显示区域的大小.

9 g& M( Y3 W+ I2 K9 S9 P

// 成员CPoint mPos用于指示图形显示起始位置坐标.

7 @1 v/ I9 j1 q8 n1 P! r

if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() ))

$ u9 X# v, l1 I$ l+ O: B' c

mPos.x= mpBitmapInfo->biWidth - mDispR.Width() ;

! t* ]4 B1 A- R$ ^

if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height()))

V! X4 G {- ~$ m' F( E% d

mPos.y= mpBitmapInfo- >biHeight- mDispR.Height();

& F) Q0 m- G; i3 T

if( mPos.x < 0 ) mPos.x= 0;

) z+ X/ F- u9 P4 W! V

if( mPos.y < 0 ) mPos.y= 0;

, g6 N/ u9 O' y: l) H+ ]& [

1 d5 h T2 q% \% q& z/ F6 [

if( mFullViewTog == 0)

6 ^+ n! q; W/ N# t d5 K

{

) Y1 \! |/ R+ p c

// 显示真彩位图

- }- |, ~: Q3 _. H) h9 H

::BitBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),

$ D& L( L/ V) v% R/ N

hMemDC,mPos.x,mPos.y, SRCCOPY);

- k/ L& C- Y. H+ x% E. F( S

} else {

3 _3 Z# @8 V( `( I; c( q; n" ?- b

::StretchBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),

2 f1 X/ B% p8 r+ S% j

hMemDC,0,0, mpBitmapInfo- >biWidth, mpBitmapInfo-

. {7 M/ L/ e) w" R0 j

>biHeight, SRCCOPY);

$ j ]6 X4 R* x2 e2 n: R

}

$ J7 @- r& X4 R5 @

// 结束显示真彩位图

' @2 Y: z$ P6 _, }) s- P9 Q

:eleteObject(SelectObject(hMemDC,hBitmapOld));

1 P( z r, g1 y* Z! \& l

// 删 除 位 图

" E' m2 X8 Y" W

} else {

5 t: J; n7 h" y( r% x% c0 L9 P% k

7 e$ E( R3 {2 ?& s' C

// 使用视频函数显示位图

" A) J$ T2 M0 `$ j4 I4 @1 U

* d$ K6 ^# r3 O( a+ \

if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() ))

0 G) n S9 h% k) J

mPos.x= mpBitmapInfo- >biWidth - mDispR.Width() ;

5 _7 S9 ?4 q8 `$ h3 F

if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height()))

x* z/ j, I: K& d7 R7 Q8 q9 O

mPos.y= mpBitmapInfo- >biHeight- mDispR.Height();

7 f. J$ d. N6 R# R

if( mPos.x < 0 ) mPos.x= 0;

" }' q1 o) r) V2 u" A

if( mPos.y < 0 ) mPos.y= 0;

; ^* H( d) n% G

4 r E7 j% @* j5 K

// 显示真彩位图

& K5 @7 d2 a" N( i3 W; Q

DrawDibRealize( m_hDrawDib, dc.GetSafeHdc(), TRUE);

7 N1 A. @3 n# j7 j3 B3 K

. Z+ }8 O D( V: s e

if( mFullViewTog == 0)

6 z1 T- F O; b1 y; m

{

1 ]% z R& T) X' Y6 Z9 c

Wid.x= mDispR.Width();

7 l" U6 J/ t9 J/ A3 {6 S" \

Wid.y= mDispR.Height();

2 v$ `+ x! _/ S$ \

// 1:1 显示时, 不能大于图形大小

6 K0 T8 K- r5 ^ k6 J1 q

if( Wid.x > mpBitmapInfo- >biWidth )

2 g8 J/ ^# z& [ a* _

Wid.x = mpBitmapInfo- >biWidth;

- X, C# C0 U) J3 P

if( Wid.y > mpBitmapInfo- >biHeight)

% p) I4 b4 x9 l/ k

Wid.y = mpBitmapInfo- >biHeight;

9 K1 g: n9 d: Y, y p& f5 w" M

8 L# M& o l6 t9 k! i! k( e

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

5 V4 r1 d7 z" m2 H4 H

, 0, 0, Wid.x, Wid.y,

7 X( _4 @# L7 t h

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

7 {, @) |8 X, Q

mPos.x, mPos.y, Wid.x, Wid.y, DDF_BACKGROUNDPAL);

8 t Y/ X- K8 [

} else {

- N3 m( a$ x, p4 M% ?; H, j) o, A

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

' e7 f9 d6 q6 _0 z; \4 j x; O

0, 0, mDispR.Width(), mDispR.Height(),

1 x! B6 M- ]. N" i5 ]5 ^

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

' d3 n. M$ i, H; c' X( D% k+ D$ q

0, 0, mpBitmapInfo- >biWidth, mpBitmapInfo- >biHeight,

8 M5 |4 X( A5 u8 f/ n

DDF_BACKGROUNDPAL);

0 f0 I$ e8 u% m: R. f

}

- q. s0 o/ h% _* B2 u! ]( H

}

( R7 `$ e1 k& z ?# e* e2 W

return;

9 ~- b5 h( K6 G4 ?/ n$ v3 H

}

$ V0 {9 \* }" u0 E0 }

' h/ }1 p2 O% d" O3 D

" k1 @2 Y( I6 g& M% A

---- 五、使用CViewBimap类显示BMP位图

' T: e. X. C! v7 O! ^$ t

---- 1. 在Visual C++5.0中新建一个名称为mymap工程文件,类型为MFC

4 {) }& J4 b8 e' S* r7 ~

AppWizard[exe]。在编译运行通过后,在WorkSpace(如被关闭,用Alt_0打开)点

# q+ ` s, t5 _* o; B

击ResourceView,点击Menu左侧的+符号展开Menu条目,双击IDR_MAINFRAME条目

; O. {$ _3 A8 r- v

,进入菜单资源编辑,在'“查看(V)”下拉式菜单(英文版为View下拉式菜单)的

( V: Z+ Q, u' G1 S2 I

尾部添加“ViewBitmap”条目,其ID为ID_VIEW_BITMAP。

, o' ? W C* R8 y/ e$ m

+ }3 Z: I/ A: i7 m2 Y# W

---- 2. 在Visual C++5.0中点击下拉式菜单Project- >Add To project-

' F3 T" v' Y3 r& B- s# N

>Files...,将Bitmap0.h和Bitmap0.cpp添加到工程文件中。

' ^# G6 I/ s. [5 S

, @8 A& |, O7 D7 B N

---- 3. 在Visual C++5.0中按Ctrl_W进入MFC ClassWizard,选择类名称为

; t6 P4 @' ^1 q2 b7 J

CMainFrame,ObjectIDs: ID_VIEW_BITMAP,Messages选择Command,然后点击Add

# a& a$ J9 s. L: I2 L$ W

Fucction按钮,然后输入函数名为OnViewBimap。在添加OnViewBimap后,在

- ?! Z9 q0 h1 c5 H" t" g" R

Member functions: 中点击OnViewBimap条目,点击Edit Code按钮编辑程序代码

; ^% b, f9 S) W1 n: T! t$ r

。代码如下:

`, u2 @: U$ `6 j' H

' J# g7 V, [$ B% t. f2 h

void CMainFrame::OnViewBitmap()

/ ^. H* [+ J% K% R* ~) Z

{

/ F) z( \% Q7 Q! R; V

// TOD Add your command handler code here

& J) K+ z7 I0 i" g: x1 b2 v

CViewBitmap *pViewBitmap= NULL;

3 Y% T2 z. h; x! X# F% M) V+ R5 x

+ n9 p" _' S$ Y9 B x, R+ Z9 U

pViewBitmap= new CViewBitmap( "BITMAP.BMP", this);

8 [6 u, T H2 v# e/ q% n5 G$ ]

pViewBitmap- >ShowWindow( TRUE);

4 w% @! _5 B E) y/ X

}

5 W; ^! X, U3 ?( i, Q% s, J' a3 o, L R

8 o' L. u+ C- Z% v

7 P! R( J5 @5 ^- p

---- 并在该程序的头部添加#include "bitmap0.h",然后编译运行。

0 A4 l% Z# G0 T) G3 R1 E% p$ [- o

---- 4. 找一个大一点的真彩色的BMP位图,将它拷贝到BITMAP.BMP中。

6 _1 I( o4 Z; h

" N* j8 r6 ^% o% S2 w$ i. f1 `0 P

---- 5. 运行时,点击下拉式菜单“查看(V)- >ViewBitmap”(英文版为View- >

$ z" l! f4 y" W* u5 h

ViewBitmap)即可显示BITMAP.BMP位图。

_4 Q4 J3 \# Z1 Q; k! U

4 B( L a/ a0 f

---- 六、CViewBimap类功能说明

v3 }% F7 C) w

9 o. H7 j6 R5 S: U! i

---- 1. 在客户区中带有水平和垂直滚动条。在位图大小大于显示客户区时,可

* C6 A4 A0 `4 M t/ x5 _1 Y1 `

以使用滚动条;在位图大小小于显示客户区或全屏显示时,滚动条无效。

& R7 Z' a) K" ?1 \8 b% [7 I, M

: L3 L% Q5 X+ |- [$ R" l" T9 Y

---- 2. 在客户区中底部带有状态条。状态条中的第一格为位图信息,第二格为

% ^% y+ V0 j$ V6 z9 E' U

位图显示方法,可以是使用普通函数或使用视频函数。在第二格区域内点击鼠标

; |; x& w7 d; v6 n6 \

,可在两者之间接换。第三格为位图显示比例,可以是1;1显示或全屏显示。在

- ^4 p9 D5 s" J; P' _3 B' B3 v

第三格区域内点击鼠标,可在两者之间接换。在全屏显示时,如果位图比客户区

) K) M5 s/ W, R/ I6 p/ o

小,则对位图放大; 如果位图比客户区大,则对位图缩小。

' Q* H* _9 f5 Q

9 p' b$ B; x4 O- b9 M0 s

---- 3. 支持文件拖放功能。可以从资源管理器中拖动一个位图文件到客户区,

! O6 V( K5 o0 z7 M

就可以显示该位图。

% Z' n7 T5 W, A* [

* z; q C0 y# R; K& w* A' d2 N; h

---- 程序调试通过后,可以找一个较大的真彩色位图或调整客户区比位图小,

; A* v) f( z) e5 { , ?: O' U1 w; l/ H- _$ g4 b

在全屏显示方式下,比较使用普通函数与使用视频函数的差别。可以看出,位图

6 e2 B, }8 y/ }( g" ]8 F

放大时两者差别不大,但在位图缩小时,两者差别明显; 使用视频函数时位图失

; B' e% P1 Q& c" n& W9 M

真小,显示速度快。

/ M/ o4 n$ z' d' m( u9 [

8 q& y) ~" l, o+ W2 G

---- 还可以从控制面板中将屏幕显示方式从真彩色显示模式切换到256色显示模

# |( b. Q6 ^0 t8 W& c, i

式,再比较使用普通函数与使用视频函数显示同一个真彩色位图的差别。现在可

F6 }0 S/ g, p! _2 X/ Q9 G; G

以体会到使用视频函数的优越性了吧。

1 M: A, z# k/ {5 D

+ h3 k+ I7 g7 D; M Q% e

---- 在全屏显示时,位图的xy方向比例不相同,如要保持相同比例,可在显示

( Y. l5 o5 Z! ^8 l, M1 U

程序中加以适当调整即可,读者可自行完成。






欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5