数学建模社区-数学中国

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

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

7 H9 N i' R0 z7 Z# w3 |/ P

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

" p5 `9 c/ X1 v; X1 W7 K/ s

张义云

7 E# p2 J* j! p- @

2 f3 [: u: H- r

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

) w) @/ n- j3 N' m* l9 H( c/ q% s

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

+ K" l2 y8 R! w0 T# r3 x& i

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

) _7 o8 T5 l. A2 {& C Z6 s' D

* w0 f8 ?8 \* N `; U1 {! M

---- 一、BMP文件结构

' { \" V/ |) M9 c! t5 i

7 H: v/ o' M8 I9 T/ x% o

---- 1. BMP文件组成

) @: A/ j) J) d& n! S1 i9 x

2 F, {, H. h8 O

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

9 j( u! X$ {5 m/ W+ ]3 H+ @9 v. \

& L5 }6 f `0 ^1 a" J* ^

---- 2. BMP文件头

6 }5 e. F' c. n# ~! k0 s+ @

9 ^1 U* w6 m0 J( `8 u: J

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

' S. G. x, R; [; V# O

$ i3 y" Y* ?# Z' f: _' M

' Y" g! M! ]2 e V+ x; D# k! c

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

$ _- E* K- F" Z

) E0 ?5 H& g0 n) J! `7 n- f

typedef struct tagBITMAPFILEHEADER

# [( u- S! j3 t8 f% v

{

0 M8 k. c: s. W2 d1 }6 ]( ]

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

/ m6 ~) \4 O. s; b. ?

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

" F( f8 D- z s8 p8 k g9 t

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

2 @4 c* F4 g: }+ I: L8 o* W6 Y, i* R. j* S

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

& ]( f+ r4 O" Q- _( S

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

0 {" T2 |/ v" D7 `9 w6 K4 `# Y! T

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

1 f5 g- F: v7 l: ?& |" M5 i/ s

} BITMAPFILEHEADER;

$ E' q6 d9 S- d5 Q. q

$ ~& m) q' s2 h9 T9 ]/ V0 |, t

$ t/ c h: X6 S! T/ e3 d

---- 3. 位图信息头

% `- i- i" Z0 z6 u. C- F. P

----

4 F( w+ J) P9 B9 C, e- a8 s

k; i( s: p) E8 W4 Q

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

: d# A4 c& B/ U. W" u8 b

typedef struct tagBITMAPINFOHEADER{

6 Q4 Y- i a7 w( h+ X

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

3 }+ W+ l" p6 N1 C7 M3 ~% X

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

( \! J3 r8 [# u* F

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

$ ?* W2 B3 A5 y, m, T, t

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

T* W# `7 f: ~: ~" C# C3 \

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

& c6 Z9 `+ p- u( B' f' g! P* @

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

7 h8 H- \9 D. o; R; ^( |: L

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

0 @! f1 g2 `7 ]5 g) q

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

3 C. |, X; {* ~$ h1 _7 \( O% J

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

6 R9 D4 Y: B. K, b7 A5 s

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

8 E1 L1 V$ q0 O

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

& h$ q+ j% o; c

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

) `7 Z( J! n* ~+ S- r9 a

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

, N+ c" G2 N2 n) J# g5 S) n

} BITMAPINFOHEADER;

4 v" j; G5 q! p8 W" \

% c, v' I+ ^9 f+ ]

4 f+ L0 f; F, N- V0 h" M# Q; P# y

---- 4. 颜色表

4 M# S# r! L. t

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

5 ~" H) u- }5 e1 o* Q! `* f4 {

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

* N- L7 n( A' \" o

$ }6 D$ U0 i% l7 |; `

typedef struct tagRGBQUAD {

& [; ?" e& s" J$ \

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

8 f3 I4 Y) Q. F: t

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

b }5 b+ _% ^, s5 D: T7 S) y

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

* t* V6 z% j3 w8 f+ O# ]8 t

BYTErgbReserved;// 保留,必须为0

8 ?% Z3 n8 C7 U$ H- }% F

} RGBQUAD;

2 x7 f: z7 } C1 [: s1 o7 S' U

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

: [# @' `( X1 I

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

5 g& |3 ~9 ^2 X

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

1 i" \; ]6 Z- T) u3 T

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

/ _- I- I/ j$ w& {/ ^

typedef struct tagBITMAPINFO {

" {9 c4 X& ^& f: ?/ k! c4 M( |1 N

BITMAPINFOHEADER bmiHeader; // 位图信息头

0 F3 y/ ~3 B! z) Y% w

RGBQUAD bmiColors[1]; // 颜色表

. F' i% J; ]( J- q- \

} BITMAPINFO;

% J v$ a W1 u7 o

6 C2 f9 r2 l2 Q: i+ R2 m

$ i- s" d$ b6 V5 \" H' c( K: ?

1 b' l# }( \" h0 J* \

---- 5. 位图数据

) J" n. h6 o6 A: S* `* H

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

* } e! b* X7 _! F% m- m6 R

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

5 i& e* c; C. S. n7 W6 A

3 {. Y/ [+ o6 C8 k' n% S

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

?# ]& N! K% q; O

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

4 P5 G. H& I$ E c3 r

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

( u7 m8 ~; R9 Z9 s3 g' e2 U) w2 \

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

% m i k2 V) N

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

# N7 P$ @' ~ E) T$ Y

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

3 v5 M& B& Q! W' i: o( U- C1 j

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

& E( X$ ?2 y: B5 f' ^8 b( e

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

; C1 m. R) l8 y8 y7 e1 @" B' _

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

/ A/ {1 P1 V, G. W0 |) w; E

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

( o; ^3 _/ z6 X" [" e* M

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

8 @4 O1 a9 \" x

DataSize= DataSizePerLine* biHeight;

7 x" T( m+ o9 W& k+ @$ F, a

4 U7 T9 n; C! |: v1 [1 y6 ~7 k! a

; A$ U2 l; I! w

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

4 d+ n- b4 L, d$ G: b$ {+ k" U) w- C

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

7 p) U0 C" x1 |( ?7 }1 q& V

0 Q% K$ g, Z' D0 f- ]

---- GlobalAlloc(GHND,FileLength);

+ q( ]+ B% V, w6 d. _

3 ?7 Y K* u2 H' H+ }

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

6 \8 P& X9 q K3 N) Z0 x6 j7 W1 _

" }* w/ W5 }3 O+ M+ c3 V0 ?

---- LoadFileToMemory( mpBitsSrc,mFileName);

& Y( o$ p. [! s" Z

- m* s( }* M% q1 G: ?

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

; B2 E( ]: d g

1 q8 G% Z; S2 P4 `& @, B& q* v

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

& [: a J q; j* j

DC,

( Z3 b5 T5 L+ G) y9 \+ ]* U: R

" \0 X5 ^# ?, \8 q

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

/ u- D. @, E! B6 t7 G

& d1 g' `) k" l. c5 l% q( j- t

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

- k, M q0 y" N) R0 r

/ S0 a8 y. P6 ? I: C! l( C

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

& E% p9 W: o# R" C

* C z* a) }8 C

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

/ b- L9 d" k3 O) O! R) J) Q

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

0 R$ V* B! C: n" y

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

; [9 v6 u7 y! F# ?! t( F. \$ s

+ C" M6 A; q" {9 S% w; i

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

" B2 g x. e+ c( r

8 w) z" h/ G0 I% E9 M) H

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

+ X& B Q3 i( v

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

+ r a0 q/ [" C, P. u" Q" n. Z) j

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

' [+ z% [$ N- b" C8 g" H! U

/ z/ R0 }8 H# o4 Y- G5 u

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

1 O9 W0 W j) m$ I N) M7 s2 p. q0 O

# Q5 k7 t. V4 v0 g" K# c

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

$ o+ m. z/ `) S6 n* m! [9 a

$ G# [( L Q; T( D+ D

---- GlobalAlloc(GHND,FileLength);

( p" A! |* b8 w) ^

% v* R, H5 w% Q( T' c A

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

: x5 I; b5 X4 Q: b# |

6 G: P9 B& R# s" z3 Q r3 x$ r

---- LoadFileToMemory( mpBitsSrc,mFileName);

# S5 O( e2 w* H: V: ~

% d! g+ m" c; P6 `7 j/ F

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

' W. \1 X: S! Y4 |

1 [& k1 N0 h! l1 f' u' ~) I; z1 {

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

4 ? D9 p- m6 _. I3 U, m* y" Q

. Q/ Z ~; @2 X3 p! D' f6 \" P

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

7 O6 w1 F( @( [2 L+ L K* Z" @, l

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

: g1 e: ~) {4 {, M9 a

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

" M. w y! m5 @) S6 p8 H

1 Y! f* E/ U# Z) L. V7 W2 f/ u

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

" c, m0 z, _/ C- m; y1 }1 k

, q+ W: w; ]* y6 b( J: p

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

! M2 V( H! L/ w; _) n

& D- ] _) g; I0 O& m

HDRAWDIB m_hDrawDib; // 视频函数

. m1 [# \6 ]6 F4 h9 F5 Y

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

1 ^* b1 Z# r2 E$ @, B- C

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

7 m& x: h" m% ^1 ?; `$ m- B& @, }4 ]

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

3 T% w9 U# m3 W

+ o- _& M) B0 v2 ~3 l. }+ J

% t6 {( {6 B0 j# v. U. {

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

3 D6 v- P# A& x p6 T9 q1 p4 U

---- m_hDrawDib= DrawDibOpen();

: {0 H$ {6 X8 k$ I

# V$ o/ [: a/ I5 m: O

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

9 R0 Y) a9 u! |6 f5 ~; t- c

) h8 ~2 L1 h) Y+ b

if( m_hDrawDib != NULL)

8 E4 q T' Z) v4 e9 {! D( ]

{

) s% q' f4 E! S/ D, ^

DrawDibClose( m_hDrawDib);

8 k8 ^! c! _7 i1 H/ H+ j/ ]

m_hDrawDib = NULL;

9 Y9 B7 c/ @2 b" X: [

}

3 H0 a" V" c0 y+ ^

1 R; b+ e8 |, s: P* j# W

5 C+ Q# v/ z* N! [3 [ a; p

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

" F, }9 n7 M1 r8 d% \. K

voidCViewBitmap::OnPaint()

# {& F- [6 r" L) c' \

{

0 ]7 \: P; l1 P& M

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

' f+ c# X: i0 o/ y: y

GraphicDraw( );

, l" V) @! a3 Z; f- c

}

6 c. A7 Y" U4 ?( v% e* x- _

+ F( V( r/ O C% u

voidCViewBitmap::GraphicDraw( void )

, ?/ _' ^) l$ {8 ^: [

{

. Y6 Z- Q `9 v; f6 d, R- S0 h

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

# w, Z2 j' I; Y# t& a

BITMAPFILEHEADER *pBitmapFileHeader;

- _* \* M: v0 X: J: Z' G- Y* }

ULONG bfoffBits= 0;

7 b( X: u- h- F, N

CPoint Wid;

9 A6 E; P! B! G- x* l

2 m; L# f( w& U) E

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

7 I, U% P' F c+ J

if( mBitmapFileType < ID_BITMAP_BMP ) return;

4 Y$ X9 {/ Z2 Q" ]

9 L9 ?* a3 S; W! D

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

$ [7 C8 e9 k w3 J" f; d

// 准备显示真彩位图

, V; B% X4 x" t3 C

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

) E5 L( B' t# P! |. E1 t% p

bfoffBits= pBitmapFileHeader->bfOffBits;

& c$ x- l4 p% a* R

5 `5 A% l! `# V* q" ^/ }/ o

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

% M/ D* `2 ]3 \' W: c. a

8 I; f1 }' N+ @$ \) g( I

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

$ T P$ M' @# S( q: v, a

{

4 I( t+ v ?$ [3 t/ b" [4 Y

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

' W$ d3 D) h* [4 ^ w3 n

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

9 F5 ~2 p W- }/ n: v/ q

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

) K, Y& W9 W+ b- N4 {1 U

// 建立位图

% J* c% O* v& V2 J: z

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

, l" M5 D8 D1 r( D: \5 A

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

; L; A0 T; Y# R8 u; N" B" a9 A& {

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

" x: O3 k2 W* N3 u( N

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

+ d) v' F" Y/ \. V" [0 n+ d& B

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

% G6 X% J+ L& ]4 _8 S

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

. ?! W* @" i0 K7 u7 F

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

! j+ I+ w2 [' j) x# {. S

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

8 l! c* G) T- i. m! W/ n7 q

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

7 D u1 a1 P; t

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

! A& o# G% q. G* E; k

9 u* K9 z! ~+ X) B

if( mFullViewTog == 0)

, N9 f! g. p$ i0 k% b C& e, N

{

$ ]+ D- [! m. I

// 显示真彩位图

& _6 ^4 I* [+ `9 m

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

: ]- T/ v' n& C# O% |- k! q9 }9 l/ `

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

/ O0 @: G# w, W) S( F

} else {

5 g6 n- D e- j; ^" R" C! Z

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

' |) y2 ~/ [3 I1 S z' N' @

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

0 w' X' D7 t- M5 H$ a+ {

>biHeight, SRCCOPY);

) s6 O* R; Y. ]

}

8 ^) P, }; W) x5 a, v( v

// 结束显示真彩位图

6 u" x9 C- e. X3 g0 N( Y

:eleteObject(SelectObject(hMemDC,hBitmapOld));

& J) u. _) B/ t* @$ O6 y1 g* ?

// 删 除 位 图

: Q# x6 H0 C& R1 J" p

} else {

4 I" R0 i# `7 H* y0 T& ] b

; Y1 u `3 i8 }

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

( s' o$ s" Y( z' h4 H

9 H4 M4 k9 A9 P" D e5 i

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

$ Z n9 E+ s4 }9 z$ B- n

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

! ]4 M+ M9 W4 ^; N! u) A

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

2 l" ?3 s/ J* x

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

7 ^, w7 \; g" w4 u, z, k( [, I

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

7 t- D; C& P- A5 n

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

, B( x, Y" J' H. q

+ J3 @: {/ @% @9 I! L/ |

// 显示真彩位图

# a, O0 O. T. g5 k9 Q( u% d6 x: m

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

; Z) F% v# A) p7 N7 \( t

3 e T7 t1 Q9 t

if( mFullViewTog == 0)

/ H# X8 e, L4 P3 w5 U

{

% I8 P( _3 F9 N. L" Q& _

Wid.x= mDispR.Width();

" S) T. V) J! o! R) p; V" K1 ?

Wid.y= mDispR.Height();

$ u% _3 o6 J+ Y3 Y3 O- ~% P

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

2 v" t5 O) ^# d/ S1 c

if( Wid.x > mpBitmapInfo- >biWidth )

* n1 _+ m8 L7 h

Wid.x = mpBitmapInfo- >biWidth;

: q; Q6 n8 c: d4 T5 n% D

if( Wid.y > mpBitmapInfo- >biHeight)

- W6 A# q+ I; c$ B1 c2 ]2 K

Wid.y = mpBitmapInfo- >biHeight;

9 Z7 `% s/ A f* q. {3 B

! C# w0 ]) A8 M5 G" k

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

& \$ {2 ~6 c9 [5 x3 h& O, B0 A

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

' z Y0 _7 \, @6 B( y. I

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

* l; w- r2 g! z( A( \/ f7 j. ?. Q

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

2 y& w8 j: g/ ]0 ^+ ~$ \

} else {

! Z8 a' e- F! ^. e" M) k# x- o

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

% Z: J- e! _1 u* F

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

2 e: s+ y$ L( h# k) N, Q

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

1 S0 d1 \. s w t( u! O' a: J

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

) s: C( H' S: |. i' Z) o3 N

DDF_BACKGROUNDPAL);

) i: y, {8 Y) b

}

( Y' A! [4 \- b- n5 j+ P

}

* X" S [# X" L$ W1 C' u/ q

return;

8 E1 B V' n% G2 S- ^; m4 I4 e2 V! ]

}

a+ f9 L3 b W, _5 } Y: |

7 M: ^; a! e& B$ w! h

/ }" y3 c& A3 }* N8 s1 C

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

6 x2 o. `5 E4 `+ {5 N9 i: j3 c& N

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

R: k) h) y! ]/ J* ]4 b. Z

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

. ?5 K7 y/ s1 a' Q; ` J1 g

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

7 v* J6 q2 ^1 H6 q

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

5 I* g# |. J" J! ~" ^

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

4 R0 P* Z X9 t8 ?3 L

" E4 W; ^# B( {; K

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

: Y* ]8 `- \8 Q+ j+ C* c# `' r/ e

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

# a- @, k9 L$ b2 G7 w- X! f( D

9 A7 W" ]# M& \# p

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

4 L$ ~1 Q) z9 C: W* d2 N* w

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

- \) C- \/ l) k7 Z' Q# \$ K

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

5 [* P2 i5 B5 ?$ k

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

2 b, `: [( I) ]- @2 j& J

。代码如下:

# N: D' r/ K0 U* _# l

; t; O( A8 z% O- h. P

void CMainFrame::OnViewBitmap()

7 M1 E3 n2 O* N, Y2 ]0 z% {

{

& N( \8 O. z" m/ Y7 O3 R

// TOD Add your command handler code here

! o4 u# c3 o ?9 |1 T

CViewBitmap *pViewBitmap= NULL;

! C; i3 t! \5 x" s$ |

7 N2 O9 k$ K+ ]$ H3 e& {

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

+ O7 y, E) t( p: i m! h0 q

pViewBitmap- >ShowWindow( TRUE);

; @' k" G; e$ }) f% _

}

4 m' C) ~' C9 N; S+ y, p

! ?4 ?4 s. c, k% b6 _

5 U0 o/ J7 K1 o0 J3 v* G

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

' ~; B0 n" o, H0 Z

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

r5 L; a1 T% n- P) H- c1 e1 }3 U

2 U" D P0 S; ~# H

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

1 F7 V0 U5 V, K0 F0 P. u4 {

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

. m0 U% R' q8 b" e0 i

; d& e* \. ~4 z, C' E! M7 `

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

$ T6 Y: _' A- M9 D1 w8 m

9 l3 z) F8 p4 i$ d% \$ }, _- n& u

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

Z8 u; R0 z1 B3 m9 p

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

q8 K- b$ F; ?& ~; u( `& M K* D) a- [

% B: K* e/ Q- _# X6 M, C& ]

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

2 I) P- y! l; ^2 M

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

# D( _% p% ^% A3 }

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

9 q% L x; p* D

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

5 a. ?# s$ v) N, h

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

0 C c5 `/ }2 N) [5 R1 B W

# ` S) f. y4 S1 Q

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

0 s' H7 v/ _1 i1 a V _- v8 L

就可以显示该位图。

5 ?2 d1 q$ v) p% q& C: I

2 Q' |% T2 A4 b7 r

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

6 V3 ?, a8 s3 g6 k+ D6 t: N2 i. B ! k+ C( S4 i, s7 P( [

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

5 f/ j, S& W' C; V1 p

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

& b0 b8 I; ]/ ?/ i* ~: {6 S |

真小,显示速度快。

4 b* `. W. F! l, j& j; H5 x6 l

: _7 ^; \" b6 V' q _' L

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

- Z) t* f' ^. \* }/ r8 i1 J

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

4 @( v e6 M) u1 e7 N

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

# k, w& `. D2 H" q

5 j* M/ H- H+ {. x2 W$ M% v! b6 |. X. A

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

! w: ?5 a1 {' n. ]

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






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