数学建模社区-数学中国

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

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

* b$ a, d* k- Z# f3 W1 }- I

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

* ?" q1 h+ J9 H: h2 Y7 t

张义云

; t$ i+ M" T ~& P& T6 K5 n9 w

. P4 f K) b f

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

- ~2 v/ V& P6 [) g

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

) V& ?7 s; n2 I3 p4 ~

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

2 Y; n$ {6 C0 p% c3 k. Y1 @; m

6 R. O3 W* g9 ^( r

---- 一、BMP文件结构

; w. \! u1 A/ j5 W

1 p8 g4 _& `& x+ t* J0 j

---- 1. BMP文件组成

* [% l7 O0 ~' o8 @$ z

* a3 W; f! z: [9 |) K$ d. V, X

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

; @* q! t6 T( e$ U' p3 w' t3 V6 K

" T' A% u) a: k2 _* j1 K7 {7 }1 G

---- 2. BMP文件头

8 h- g" I# K" E

6 J8 r/ e' s* |# r5 q3 K8 K" e

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

% p3 ^$ k8 {7 I& N

' u- j2 X, a2 K3 J. P& d7 c+ i8 K

" W( U) V3 [' X n# r9 t

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

) y- p' v" ~1 s9 T

m) Y6 V! y/ Y3 u8 z2 O2 h

typedef struct tagBITMAPFILEHEADER

2 u; |1 X1 I1 P: y. A. V) B1 \

{

0 L% s( R+ g: t! q9 ?3 G# l) c2 V

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

# i r- g# }( u% L {5 X. U

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

9 ]" M4 _/ r2 @2 o9 T* C

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

2 U$ M& P- ?, N

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

5 \9 _% \# _" n% Z. H+ J

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

5 |3 _1 Y5 `2 q2 d+ V9 g+ k% U$ \

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

0 S: V* o& i1 J, @

} BITMAPFILEHEADER;

3 x- d3 \& [! C* Q1 ~

. z8 h3 r. q* \

; k2 Q+ o% B9 Z9 |& ]( y3 V, E% N

---- 3. 位图信息头

( v; n0 h' _9 K& b# C% @

----

+ S# o' }; G6 J& G) `

/ z2 L& l* r* C. b

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

+ C6 E( W; J% ~

typedef struct tagBITMAPINFOHEADER{

, j1 p. Y* o3 S2 o G/ M3 [

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

z3 i8 S( ~, F6 U: q$ a9 F

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

9 B, x: R% l0 R

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

( D- a* l, k+ U$ k

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

) X: k3 [2 Z6 W! V

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

) H, |3 I( p% y

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

5 M0 U+ ^$ J& K6 B6 g

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

0 o9 ]$ w. D& c5 _8 i

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

& v1 b% @4 B2 a! e3 E4 V$ M# Y

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

- }$ ~, o; x) c- i+ i, h8 e

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

) r6 Q/ A/ `! Q( c d2 N' S; Y

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

$ y+ Z& I8 Z/ ~ }" t

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

) ~( L, k% P% M% ]& z

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

, W# I4 b- } n) j5 J0 Y

} BITMAPINFOHEADER;

6 ?. G1 E/ N0 r9 K+ X0 {

( P+ l! M$ X) u

0 m" n& \* @" S5 u' J p

---- 4. 颜色表

! h' | m3 \: H' @ A3 e. u' C

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

@& {, a: U Z' G8 a; v9 z

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

# T: _7 d7 w6 O+ K

% ?/ ~: X1 ?, R& u; {" ~ R

typedef struct tagRGBQUAD {

% _3 K4 g4 ^' Q4 v9 B9 H# X

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

# i/ e9 \2 H( w) _3 @ _+ g. x

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

- j* r+ ~( N% x- c' H' z8 ?; R% Y6 i

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

6 [# G6 X2 y: T: G+ ]5 x

BYTErgbReserved;// 保留,必须为0

( b' ]: B. ^0 m* L: `

} RGBQUAD;

7 i1 n* X U+ g

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

: \3 K2 l+ {2 \6 }& v2 F

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

5 z& x) T8 F7 G( @

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

N- I4 q9 D) r8 R# ?

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

3 l' [; X/ G6 ^& E& v

typedef struct tagBITMAPINFO {

. C X5 A/ {+ q3 w+ g0 ?

BITMAPINFOHEADER bmiHeader; // 位图信息头

0 N$ n& P) u2 T- l5 e7 @- \) _

RGBQUAD bmiColors[1]; // 颜色表

0 _8 H: N% O7 b: ^' R8 ?. a

} BITMAPINFO;

( ~: u6 u* C' `7 P/ f- G1 K6 ]

( I U) S! }4 n' U) {( f

; D a% z1 {3 B4 W6 n+ {( S

7 x5 `( N( c8 d! |( S# @2 u' A, u

---- 5. 位图数据

- A% }* p6 ?# a1 f

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

! V* Q# v( {8 o/ q9 H

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

" h0 d$ ]* ^; u6 Z! s3 ]' Q9 N5 L

* G& o; U# C8 q/ G: G

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

" X. \. w7 J T9 B) V& U% e

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

; w. I/ Z) Y& I$ `# }* M

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

0 q* q& T: K" |* g( D& }) Y, o

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

$ B; ?* ?8 b8 D+ _! X* z

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

1 b: A" z% B/ r7 j2 r' ?/ s! O

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

+ s1 a* m l( m) g/ H( c

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

$ z* C' I7 X1 u5 q( v( ~0 J2 X D

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

$ d# P; a# F3 u' D: I3 B

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

( K) I0 X$ Y) J' I! y+ I$ O' U

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

0 B* y% m' x! x' X4 [6 m# o

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

0 Q- ?9 o# s9 d' b/ ]0 D9 L$ P

DataSize= DataSizePerLine* biHeight;

4 W4 n1 O4 k# ^% ?' v, F& A. p

# x5 ?1 `+ C( ? U. `3 H$ W7 A

- J1 H2 N, a8 b! K8 s+ H

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

# r! w6 X4 C0 ?, I+ N: s4 G, Q

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

! A% s9 M* b a7 J

& `2 j+ g3 P9 E! @

---- GlobalAlloc(GHND,FileLength);

, q+ l$ J, d' |1 c# \

/ H. Y2 q& |2 c9 W) B% r* O

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

4 ?; d; o/ D, ~

5 P1 \2 ^$ d Z( }- i% @

---- LoadFileToMemory( mpBitsSrc,mFileName);

0 c+ f) A' M5 Z2 q$ D

) Z" Y4 ]+ c9 ?, _

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

; Y5 i7 B( J: r: k) b2 G- ?2 k

/ d5 L& E: R' b

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

. K! L% r% c' e0 ^6 M5 O4 j

DC,

. G" l+ ]( e/ }" ^" n9 P. ]

& g! w1 }, S6 I2 c4 V0 P, G9 @/ I

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

- J" L8 `6 t* a! r

- x; ^" R, a) S9 K1 L3 e

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

$ _' z' ^: q0 Q9 h r' S, y6 i

% L8 F: q8 I! ]' ~: _0 k; g! }/ a

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

5 Q0 n0 F! L) w6 J% e

! t. A7 H. |* B$ ^; Q8 \% F p

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

# H1 A$ P# w% u& C+ x* z

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

) j1 u( f# w4 u0 l6 r3 I1 R7 R5 d

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

* j: n) s% n. e* w2 w5 }! D

/ t4 ^1 S6 s4 w

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

% R0 A: S* {8 V2 R, g. |$ ^/ L5 t

/ D2 u& x, p. ]; r9 U

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

6 o; Q: i K3 x: ^5 Z; i0 Y

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

% r* q% Z$ ]% {" i+ T3 t

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

* B1 Q4 m, N( |3 L+ u* m0 l7 z2 h; N

$ x7 Y* U) M( f% r& E2 z) h- _

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

4 R% C* _6 C; Z, c) f e L

. Y+ g0 V1 g7 W- @! M

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

) E; }+ z! B( l8 W, ]1 H# V" n

) ^" k7 o9 V0 P

---- GlobalAlloc(GHND,FileLength);

; B) x/ B1 t8 P2 y5 K4 @) {

7 i: W7 X- N6 w2 S0 v* W6 I

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

7 k& J+ a% M/ b* ]* m3 V

, v/ x" f! H' j4 `; J; }

---- LoadFileToMemory( mpBitsSrc,mFileName);

) m4 B$ w$ V6 F; C- w

4 f* n d+ W q9 M) Y3 Y# W

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

5 p* r) _# I D/ x! ?7 R2 ?8 q9 r9 p. B

4 A2 [5 b) B3 ^) f: c

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

0 Y; N$ \" @- z. v9 L8 \& t

- I* {' b9 U Z2 }. ~: D3 |4 A. y# I

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

3 B4 }0 {0 R1 R8 @

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

5 w6 U: p9 T1 ]' S

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

6 Y0 ?3 a8 X2 q8 t8 ~4 A

0 s1 w# d: B1 M8 B* B7 r5 v: G

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

- e3 w% T( Z5 o! `$ V7 z+ d, `

7 L+ `" G2 p% {6 V

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

# a8 A8 t! R* L2 f' e( Z6 w- ?1 C5 M- P

% J- l8 A/ y3 l! d

HDRAWDIB m_hDrawDib; // 视频函数

, ?: t) y& |& {# T9 z% A! u, U; K

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

" D5 k$ ?0 Y7 \; b5 l

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

+ P. z1 P/ a8 O6 a

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

9 p; X9 s7 b! r6 E$ H8 ?/ _$ o6 H

i3 Z7 D2 X; K$ j. \" T9 V

% t6 z, Q0 d2 |, r7 }, ^* c; w

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

" v+ y/ T9 y4 l' \9 i6 N

---- m_hDrawDib= DrawDibOpen();

7 W- ^8 L* O' c9 j H! s

$ h7 a* p' ~( k

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

# b% x( }6 W& L7 F. h/ }

: r( _1 x2 B! V! @- R

if( m_hDrawDib != NULL)

. K3 }6 q# f+ f

{

+ z3 T% y; [ e6 }2 g

DrawDibClose( m_hDrawDib);

" F6 @, d, h# b$ L* K- I4 ^

m_hDrawDib = NULL;

8 I0 b3 t. u9 G4 n5 g

}

! T; |: G' Q3 G3 s' v# j0 Z3 _

0 o. F" F }* F0 w: f0 T" w4 w9 N- Y, y

$ K( x- d- {% c; M; j% N

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

7 Z4 y$ h% N; a/ i b

voidCViewBitmap::OnPaint()

9 m6 `& h' X5 X! I, H

{

# T. `4 O2 {1 r6 C

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

# i3 h5 n$ ]6 G: M) F8 a

GraphicDraw( );

- ^) y0 I. x' c7 g1 _& g

}

; o* s$ m1 {$ A1 U. r

g. H6 k) Y l+ s* d( |

voidCViewBitmap::GraphicDraw( void )

. N% ~1 h, n# N8 j

{

% d; m6 V( p9 c8 Y. G0 c4 `' k

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

9 M8 C1 A/ h3 G! b7 M* l1 `

BITMAPFILEHEADER *pBitmapFileHeader;

7 U1 C! u3 u5 B' g3 m

ULONG bfoffBits= 0;

8 t7 j4 P6 p/ q: X. L

CPoint Wid;

# L* _. R5 l* @

4 Y6 Z2 w* s! s

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

" Q: I8 x% c- P

if( mBitmapFileType < ID_BITMAP_BMP ) return;

+ K- q' v/ [8 [; A

( l0 P! s' ?: B, o, _

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

# X+ V) w6 u. C5 g7 B5 W

// 准备显示真彩位图

6 Q2 \; G, y. }) V6 ~ F4 @' W

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

7 H: b' ]5 {. w" M+ n

bfoffBits= pBitmapFileHeader->bfOffBits;

8 V" G# I3 p7 Q0 \

/ B) _- P) C4 C+ ]3 S6 `& k! l

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

% M* M1 ~- \# [: ^. R, n, F7 {

& J6 V0 e- G( M4 Y

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

$ W) t2 j- @& D2 f# K9 `% j

{

# n( K. v+ l3 n' t7 U. `

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

* _5 d3 B1 k8 h' v: p5 a6 z/ p: a/ Z

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

: m2 B; | w3 Q

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

% O( J2 k/ U0 Z: j

// 建立位图

$ B8 b8 C$ Q7 e0 e

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

" h5 Z- J) _" @; g( z7 n/ D

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

; r, v, ]- c+ j2 }9 h8 M! y) y) p8 \

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

5 n* I, C" U; g$ t# M" C8 ? ?

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

, W4 `: A( T1 h. x0 l, c

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

N! `8 G/ G# j7 b

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

8 k* F) B5 h0 i! {0 `

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

+ D5 Y; d: H( X7 I6 o& p) v2 F

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

. E+ G' D. |+ x) }+ u" O5 {

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

7 K' i% g& C' ~( W

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

1 |- w) }+ ^9 @3 M3 d* ?* s! g3 l

- w& ?* e x" n+ r

if( mFullViewTog == 0)

2 N) r: C# e' Q; k2 y& }

{

1 k# j) x. | l) v4 T

// 显示真彩位图

7 [7 y" j+ F' F& z+ g5 z

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

7 I' I0 J0 B( F& t r/ u. b

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

5 U4 X2 w- r( k. s$ c

} else {

2 I: C! u# @" ?+ p

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

7 Y G, I0 g" m* n

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

1 s' E9 z) c. d1 U" P! ~+ F

>biHeight, SRCCOPY);

' u/ v- S' I( B& v( F3 \

}

1 \8 P1 ~0 d) r |$ S" n

// 结束显示真彩位图

2 o; o' o' W+ w% s! T

:eleteObject(SelectObject(hMemDC,hBitmapOld));

4 N, h& u/ e+ F2 r+ z/ _/ Y

// 删 除 位 图

7 B8 i9 M( `0 A9 C7 L

} else {

& J) e$ ]2 Q7 |' S: X' |

/ z# p5 l3 K1 V2 s8 ^, U

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

& v5 w* _. p. F* t% T5 h8 `

0 [! d/ v* t6 L4 N5 i) J

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

0 H1 @" r& {* U" g5 b, n

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

6 C4 r6 a) u" K

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

+ e: i( Z! ~* g* ~; I7 E; e# w4 P

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

, ^1 a& }: c4 F8 F

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

' |# C0 U5 F V6 X

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

/ I3 b) Y( N9 U- D; Q# A

! u3 D8 b- |) O" A% b

// 显示真彩位图

! R0 p* A6 E# _3 A

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

3 k7 [3 V* [, c2 D& F& }. Q1 j2 X& k

+ [1 m$ S6 x7 C. u3 S( h8 t

if( mFullViewTog == 0)

6 t0 K3 g+ O* o, e

{

- S( F; j( n5 p6 j1 z8 u- e7 g

Wid.x= mDispR.Width();

2 S* d& A* x. S: \- A' p

Wid.y= mDispR.Height();

+ L$ o! A% M( m8 y9 P0 y8 l0 d

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

0 e) e1 {; H; |* h! K+ b1 @6 f

if( Wid.x > mpBitmapInfo- >biWidth )

) r, v q9 @% Z: k, N9 K

Wid.x = mpBitmapInfo- >biWidth;

. q h# J- b. q# ], X: ], b

if( Wid.y > mpBitmapInfo- >biHeight)

# Z5 X! ?) a" Y) X9 {1 ?

Wid.y = mpBitmapInfo- >biHeight;

% b! s, [- L4 g! |$ V7 S3 ?: H

3 q& m s* n7 L P; |; G$ P$ a

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

( m$ h$ F. v) P4 @

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

/ }/ f/ ]# ~8 L$ P1 t* G0 y

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

p" ?5 y% Y* h

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

, z4 |9 _) w) T* C- m! C

} else {

6 l8 P. ?+ A4 Y0 \+ F/ \2 f

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

7 l( w4 z' n5 a- S( X! R* y& q2 `' R

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

: x8 y7 u( G0 S! x( l: f1 ~

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

& v* g, ^6 w- L$ f7 [

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

$ M4 j& d {3 c

DDF_BACKGROUNDPAL);

2 r1 p& X) ] R& x' z

}

: U" F9 a* B5 k

}

5 }& w6 N+ c& _% s: d/ q4 f- }. t

return;

5 j0 h6 I/ M/ K( u8 T9 R- M3 o

}

* b. x1 i- x9 ^# T- D$ `3 x

, L. V( W5 h0 L" B: `! l

e8 e; K# O& v4 \# P

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

; h0 K; X! M% y! V9 f, ?% b7 D

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

' V% z( M: Y* l9 ?4 g+ O( i

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

9 w# `! z9 \# [1 w7 }

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

/ b, b7 \+ b# T; z7 h( D9 V0 h2 d# b

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

# o6 E& l0 J1 b4 d

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

, M3 `7 S7 \. i6 v% z2 A

! s5 _4 B$ i7 V

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

( q2 E& q" \2 Z5 T. i

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

+ [% l, w3 G2 U8 z6 X

2 b$ A- x, L/ c5 r5 E9 \

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

* [/ t! Y$ C5 G

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

# G$ a2 a* Y0 u* r% S

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

+ J& [& F$ r, `$ B4 e

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

5 ]- u8 {, }* _, A

。代码如下:

3 [; `5 g4 l! C& J( P6 B

; P! `5 z) ]# L7 y( A) S( ^

void CMainFrame::OnViewBitmap()

# Z3 S$ K) f# ]& Q7 D9 C

{

0 P1 a# [7 G9 z) E6 T) Z5 z P3 j

// TOD Add your command handler code here

2 F3 }+ K [4 Y2 Y

CViewBitmap *pViewBitmap= NULL;

) M# W0 E) B# T, O: F

& F8 v) _' ^/ q

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

4 ]( }( Z2 s' C2 m' v% s/ ]( ]) ~% a/ \

pViewBitmap- >ShowWindow( TRUE);

# u' B% O& w; A6 [* Z+ v

}

3 C% E0 F4 T* m

( }1 l# N% D B' k3 h

" c$ j: g A# G

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

: R( b; G7 ]4 I5 G0 x8 F# ~ i9 P4 `

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

' z O* m' u+ ~. D! U

' ~# g' n. i3 q: P. t. G5 U

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

! n" Y4 n% Q8 L+ j) w

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

9 u) |+ _8 X" l/ \5 H

& e% p* B* }( C/ S$ u

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

8 o+ C- B+ {2 n% [7 w5 U

/ M! t0 k3 J5 I5 D$ x

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

( w9 V/ J+ V7 ^ [8 _

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

& y: U: B! q6 s) w8 G2 c

) S8 _, H& ]. P5 W3 J" S, j

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

' V' h+ F. q, R9 f, U

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

: S3 k2 {4 }. Q" M, ]& t. r

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

: a6 @. k1 S) {* l2 Q; u3 }6 K

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

$ o) D& J$ K q. P* ?; h4 ]+ s! N

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

$ G8 p: p3 ~' \! J# b" @- R- z

5 F8 t, p* |6 }

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

* H! ~- s* C% p- g0 h9 d' ~

就可以显示该位图。

, { I) Y" p( N: M# O

$ \9 y- f# ]8 ^7 D9 D! Q. q% x, u

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

: p8 w& a+ L* {! I. @ # R1 H' h- x3 F v! q

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

, y. |, u; R: U

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

$ l. C/ c8 h; [' y8 `% e

真小,显示速度快。

) `8 w0 E( Y9 t. Z! H9 w1 z

+ @0 i8 `. W+ Y: q9 D

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

. G4 A! N) \, o

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

/ G0 s8 U1 j" @2 H/ _. ]

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

/ c2 y/ b" y- x

& c; ^: [) P0 b! Y

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

4 f$ P$ A+ H) S# _+ x8 a% I9 k) h

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






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