数学建模社区-数学中国

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

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

) i! A) w0 K4 s9 L( F

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

5 ~- f; ^( _+ r' n5 b

张义云

* {) m6 [1 T9 a* r) _* _

! O0 Y* O' l+ S, f# X6 j

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

/ _7 i$ C" q$ N3 t

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

% W" Q4 X3 ^) {+ m

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

, Y2 t$ G: y$ z: c* ?( M( `

* \6 c& i) `0 I

---- 一、BMP文件结构

, p$ j% b+ U% h ]# E

. X2 `# _" G/ z/ S6 E

---- 1. BMP文件组成

4 N% O8 }5 F5 d8 M

. e9 b- I' P4 y, p8 c! C

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

1 X0 q7 t% I! E! j( W5 v \ f

8 O' |! V3 q* D$ C1 ?! N, h) h

---- 2. BMP文件头

( h! t- e4 I' ]/ [; C: Q

. y& O2 n2 }1 M4 N' e8 w

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

# ] s; ~+ U8 ~1 J

q" ^$ K9 e# Q. u% S6 V0 e9 D

2 w% k. O. y: W( W) `- K

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

4 N( ?8 v9 v: r5 k4 G7 A

2 b+ J3 P9 l% z+ Y! F& m

typedef struct tagBITMAPFILEHEADER

: C% x+ s% g) S1 D. K$ T

{

0 H8 o8 D0 Y$ H4 z( }( r

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

, e9 q$ c; c5 n, W

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

6 t$ S! T: ?$ e, P% }

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

4 B" R% N; `0 S$ }1 Y

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

$ {6 h0 c6 w8 [: o' ^

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

& F/ [3 d. O) ?2 }" N% K. I

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

! K5 L3 d) @: I' V4 b+ A

} BITMAPFILEHEADER;

# P$ ~. i! r% }4 q" l1 w" G- T

4 @& F* F2 w$ [

6 `) G1 v* L- R4 }* K% Z# M

---- 3. 位图信息头

0 i( |, a% {( Q8 r

----

5 K B+ g0 D8 B' o

, E! C$ i1 h+ @3 o% X% `

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

# j: q6 x+ f5 r6 B* X( u0 H( h

typedef struct tagBITMAPINFOHEADER{

7 g+ \( `3 B R# C

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

# V/ U r$ }+ E u4 x

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

: r: ?: ]: [5 ?7 N1 {# X9 Y- z

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

( K# J/ y4 |0 B( c

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

" V7 V5 l6 s% R2 I5 m

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

$ m0 Y4 S9 m& a% \# R! L/ L0 H9 F- @

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

; {4 F) j- ]% d1 ?; @/ }

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

- l, |2 I6 p5 `

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

' {: P, ]- d9 i- o$ ^$ \+ L

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

# v' ~/ A/ }8 P. C. F/ b- n

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

) ?7 L0 n N5 _9 e0 t

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

2 w+ l/ f8 Y9 c4 A. ~

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

0 f0 U6 |/ W2 z, D) u+ X

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

4 g: u( r1 p9 w# S, h6 `

} BITMAPINFOHEADER;

. {: \" ~- b5 u1 G- `

6 A/ I' r+ n$ t* p7 x1 G- C) Y$ t

# g- M; Z0 R/ Q& X. ~$ ?

---- 4. 颜色表

4 a7 _' F- P$ v! D' t

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

+ L6 U( k0 @; I3 s* {

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

3 ?/ ]- p* i5 H# h! l

# E4 j! w, b4 O8 A

typedef struct tagRGBQUAD {

. p5 ^- ~1 s. R

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

& Z: b3 U$ J, q$ Y( {

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

6 l8 ]5 e3 F' y ^

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

$ S, K$ U; {$ C+ d7 c a" x( A

BYTErgbReserved;// 保留,必须为0

% C" Z- K" ]$ W* a0 G* A8 s) @; ?

} RGBQUAD;

2 w/ u% f7 p7 [7 K4 P! e

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

4 ~7 U0 \, x# _+ K$ r- M1 K& p

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

, @* Y: b* P- g4 ~; L# W

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

" Y+ x, S% i q9 a: `6 d" \; J5 Y

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

$ V0 A' S1 y/ O- u2 p- J, d

typedef struct tagBITMAPINFO {

4 ~$ T( _" D& ~; l+ |$ c

BITMAPINFOHEADER bmiHeader; // 位图信息头

2 x& A* ?: }9 e5 k

RGBQUAD bmiColors[1]; // 颜色表

4 J# v- `+ U6 Y3 ~- C5 p* A

} BITMAPINFO;

1 A) _5 k q# M" _

* a# B' _5 k0 t; M/ N

1 S2 V7 P9 T! p

! _- B( }, P3 @! z; b7 C. W r

---- 5. 位图数据

& y' a# f# I0 T5 l8 g# }- {

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

) A3 l8 ?7 u0 @9 y1 o

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

" `) G; ?; O: n& L. F; i% o$ G1 }, j3 ]

( r& u) t- U6 \8 l0 G7 Q

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

6 _1 f2 g Y3 [- h

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

d5 ~' Y7 W* W% I5 P1 ^

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

& d; `- m7 ? s- J/ f3 G3 w

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

# k" |9 H7 l* F% S

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

) t" A. I' ?( e' H" ?4 \5 R% }2 w c+ o

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

& c" C# c5 _. e) C

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

+ k5 y( ~3 e3 K

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

& V' d) t5 R' v

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

. u* _, T" B( _/ m- F6 J

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

( |% {) R5 f! P9 _

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

3 {4 L3 p2 z% I9 S& ^

DataSize= DataSizePerLine* biHeight;

9 F0 x/ E# x2 S# ]( |: x2 _; F% A

0 I+ S6 Q1 R7 u/ o* [ Y2 O8 ?

) K, g0 K$ L0 O2 F

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

9 p, N- r% M( V4 w7 T) b

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

1 U# ~8 g* J2 q9 `" N- ]

) k' n8 S8 x( Q2 ]8 |

---- GlobalAlloc(GHND,FileLength);

: Y s% `2 `% T. v

7 E' x. M' J/ J: Q

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

' Q* i/ p) r! q( l* l8 r

7 y* S- Z; s& p# x

---- LoadFileToMemory( mpBitsSrc,mFileName);

, g; Q9 J# e* j- l/ u, y

& @( r# G' K1 w; m d6 M4 T

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

* G- Z& Y6 I9 E3 h" C

( x: A) F3 L" F( ?2 q0 c( F

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

" J. a- B2 Z! X/ M

DC,

8 k2 ~/ F4 b. y9 Z

7 O- d3 e% i3 \6 |

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

% S: w m( ^' R: J# J/ M- s. p

# J# g2 M# a, P! R$ \ T! L! K

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

* q0 y5 h7 w# Q3 C2 |

9 H+ o/ X; J* f5 [3 F/ }5 W

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

" H {/ O/ x: I

- l8 s+ S. b0 M, M+ S

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

. w4 J2 n& U, }8 p

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

! Y. |. n7 R1 M! ?& c

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

& K/ i7 t3 C, t5 s. e1 M

2 b- V7 t3 i, c9 h1 @

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

; \- k; E( U$ H$ M* x: r) z( U

1 Q! r& w. l* m2 A1 L3 B+ a

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

6 r, e2 c* u% i8 h- ^: x4 |

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

! i7 Q1 B0 g$ P( X- C& O+ e* E

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

+ U" I% w' e2 f6 ]$ w6 A& n+ u0 K

1 o5 ?6 D0 Y) ^; {, Q

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

. T/ e- x! k3 R v* k+ S6 D2 D& o% n8 S- ?

% L. u. g# K: `1 _7 S$ w, p1 K% ^1 z

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

4 j; }8 o0 x8 g( c

3 m7 r/ c' @1 {! V: [3 L/ u

---- GlobalAlloc(GHND,FileLength);

( d2 g+ \$ F) S5 d, M b, ~% {/ H

+ D' j1 o1 x- [: [1 R# Q

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

: _; C/ [/ q& a4 X

( y5 R" [9 P+ |3 _0 n$ d8 S

---- LoadFileToMemory( mpBitsSrc,mFileName);

, u' P; {, m( l6 Z

4 J+ T& _* O) v& X; t4 M0 l

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

; N# L) J! O- _( A: @

: b% Z, A. `/ Q# w4 o' Y# A$ g, e

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

7 }+ S7 b% n7 k) V# N' E

" m! b5 [' e; ?* l( r

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

/ C1 N9 J! o% D n1 f& u

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

7 y6 n4 ?9 d0 S

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

! N# _0 E) E; X) n

" s% [+ d8 n$ t+ i

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

* q, r) n& u. ]

+ Y1 n+ J7 L) _

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

( j5 |; L& d- o% E" y J+ N: c- P

# y' U/ Z# e0 Y8 t7 ]" v, c/ {

HDRAWDIB m_hDrawDib; // 视频函数

' z; o D9 i# h; d) x' L

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

* r# x% r7 \- n( q- x7 h- p

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

. V* R; l) U! y9 D; Q

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

% a- T3 c% ?/ }' R& e, T8 n

- x8 n! Z4 b- e3 ?

/ ^) [* w% H. e0 p; Q3 t

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

h! v# r6 c N

---- m_hDrawDib= DrawDibOpen();

+ t3 L; p9 n- E) o& }/ c; M2 X3 j8 Q

, E0 G& s2 Z9 T ]: |* Q a

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

6 p y" F! q$ p

* p. @" `1 J. j5 b6 i7 \

if( m_hDrawDib != NULL)

$ b) D* K3 I) G7 `) a5 B, y

{

# d$ @" y; A& n) R4 A3 g. I

DrawDibClose( m_hDrawDib);

# {" H5 }0 d8 M, A+ Z5 ?

m_hDrawDib = NULL;

/ _/ t4 f* ?( |) i% o9 H

}

+ P- m9 a0 j0 x6 c; v) q( W6 t+ G

& S7 R( z: o( r/ T

. n; a" D+ V& I% u. N( G5 {

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

, b1 Z& @7 `: q0 u) w

voidCViewBitmap::OnPaint()

2 |1 \; N: n8 Y8 S1 H) O; u

{

+ N' e( w4 i2 M' A' E

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

0 P0 }% B( L+ R$ ?. d

GraphicDraw( );

. D& w& L8 ?, S# v# ]9 I

}

) a# k# {! ` J) W0 K' r3 \( ?

# m- [4 F3 E- S0 X! ?6 B

voidCViewBitmap::GraphicDraw( void )

! c: h9 x9 V! v% q

{

: \. R0 |* M' f. S. \3 N# `1 O% V

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

. R: N& `9 K* j0 a* M7 C; Z0 r

BITMAPFILEHEADER *pBitmapFileHeader;

* o) p, r# y& O

ULONG bfoffBits= 0;

- Z) Q( K, ]% r! ^# M+ a

CPoint Wid;

& N. n" p2 r8 y7 K& y* z

7 A0 ]/ h" Y: d- u8 N" V

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

) {1 X/ K/ e2 D. g! i9 H

if( mBitmapFileType < ID_BITMAP_BMP ) return;

! |% W$ e& \- g- `1 T

' C6 z$ Z9 d6 N( Z" j

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

2 G1 z; }6 e+ t: n

// 准备显示真彩位图

- D4 l- ~1 W5 B! i; H0 ^

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

1 |/ y: J7 S* R/ u8 C) y

bfoffBits= pBitmapFileHeader->bfOffBits;

! f2 N& c% o6 I7 ? c7 }+ h

L: {$ `- |: L" [+ l

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

3 K" d) P1 ^' { Q, ~( [

: T/ w# a3 z( X# J6 n s

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

7 B" o3 \! r" y p$ ?

{

4 M, i e' f* c! Q* U6 ~

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

' e: V6 y/ @+ d1 C

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

; P+ U, v5 ]% s- D

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

3 V& s: p4 ~% O( V5 P4 J

// 建立位图

! ^. c" d' i6 |2 A

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

; I% X1 [% w) n0 \) k

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

3 \' F/ x( t+ E3 ?5 J9 k8 D. r% J' g m

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

! ^. ?3 v1 o6 E1 Q, t

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

- n1 ~, M! }3 t$ T7 c

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

$ ~% ?% _* E4 d; k+ {5 `1 z7 g( r* \

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

% d4 t% ~( ]5 g7 \- T- x" c

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

, Y. O/ Q6 ]( T% X, N% D

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

7 l* w+ q+ u/ v( a- \0 N

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

2 c0 M+ V- _, a$ D0 O: I( l

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

- j" ?7 I7 O7 ]: r$ q3 ^

- v, ~$ K3 M! G! g; a% ~! s

if( mFullViewTog == 0)

0 j- ?% o. ?. A/ D _

{

+ N' I0 K# L- M% Q) Q4 ^

// 显示真彩位图

4 ~. c" v6 M' s ^4 R1 P% K& x

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

$ w8 P8 f, e& |8 V0 g

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

, E8 z' ]$ G4 I: j' O" d" L. x

} else {

6 b% M' G- J. b# X% e

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

5 z' @ i1 g/ Z) o/ n5 ]% t

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

+ y' P5 w" Z4 O9 m% X1 K

>biHeight, SRCCOPY);

( v& V1 {" n; h/ e p& v2 N4 s) l

}

% u' o# h6 j- A# W

// 结束显示真彩位图

7 x! y; E5 b0 b3 E. Q! f; Z. i

:eleteObject(SelectObject(hMemDC,hBitmapOld));

9 u2 `' y6 Y6 ?! m3 ]/ y/ B) `. N8 o

// 删 除 位 图

6 D6 L1 `" N! |: c* w: J

} else {

& v! n5 y% z8 G: q! U) x; J; u

# q1 t3 Z8 j$ s" u

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

# e; |& w0 V9 I, {& ~

- B8 z) ?7 t+ h' I* T7 [9 o; M6 I- Z

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

l( o' ^( Q! E% c9 o2 x, `6 S

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

- W. r* h4 K7 u

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

* X0 @3 f, l: m0 x

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

* m' B. ~2 M1 r6 |

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

- C6 t' }2 `. c. Y

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

; g9 Q9 y1 u* m

! t: ?- H0 M6 d( ^- X+ w

// 显示真彩位图

0 M( ~! a! h5 X. R9 d/ z' I) L: g' P

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

' ~7 z. _9 K/ o5 F h. P9 `

& H# |- F0 N9 P( F& R

if( mFullViewTog == 0)

8 n' @# T7 L: F

{

7 G. c% g& H q, }

Wid.x= mDispR.Width();

9 S, J1 R+ c+ O4 \- N) i! `. B

Wid.y= mDispR.Height();

1 x. Z ~5 f/ j( E, y: t' y

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

) g4 C2 [0 Z8 B( m/ N- ?# @% Z/ G

if( Wid.x > mpBitmapInfo- >biWidth )

, v% i6 M% A! ~- Q9 h! L

Wid.x = mpBitmapInfo- >biWidth;

3 {0 ?9 k3 B+ C0 |) N

if( Wid.y > mpBitmapInfo- >biHeight)

; J) I6 }$ L: m0 t+ T* {: a9 c

Wid.y = mpBitmapInfo- >biHeight;

* d$ R$ w) N; P2 g! t: T1 k( Q6 z% L

4 C) S$ c# `9 O9 S

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

4 \+ L. Q: n3 p9 @% [/ D2 F

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

. T+ o/ e; t2 H, C

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

: B y, @9 T* A9 P* O u% v7 G

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

" @1 I3 X) H- Z+ U6 V

} else {

: e; Y/ Z1 m: w3 x% i, w2 Q: N6 M* f

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

$ e; _% i2 m8 i6 H) \

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

: F5 Q9 ^8 H9 |7 Y

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

) Y, W3 x; s# Z6 _

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

, D- @$ G4 b9 H: n9 K! Y

DDF_BACKGROUNDPAL);

+ A7 a9 L" H% w, C7 d, W

}

, k0 Z' O5 {4 K3 G7 g1 {

}

0 d& d* ]. N& C6 m& E

return;

3 r/ M6 X' _5 V2 q( j+ B

}

5 j5 G2 b* y% `4 S# D# O

- D/ { k: `# X3 Q

/ b) z* q! b! I9 ?, p% e, q

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

9 L) _7 [/ C! X! [9 @* T; u9 l* E

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

* J* ?$ a5 M1 c& H% x: k3 C; y

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

, ]3 d% \. o8 @( _

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

2 H4 X) a' n& `5 G9 t) S1 g

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

2 T, j' m6 D7 A

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

3 C) h! ^$ d4 X/ B: O

$ u/ N) l4 V+ ]0 q

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

, d4 }8 m* ]' i* {) o

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

, U+ ]; N1 l8 I% w/ x

9 S3 ~$ |" D8 r' c( r

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

" y$ |3 @1 P! o3 f

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

% A: l6 f9 v8 ^

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

: L* [1 C' B' ~, q

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

0 _" W. Q; B+ X5 {+ p I1 I

。代码如下:

# Q/ y) y) Y* } s6 a- D' f* s1 S

L- R& I, o5 K% J% W

void CMainFrame::OnViewBitmap()

- K+ P9 E+ n6 `: y6 K

{

+ b' X M, A& n: A t+ E3 p

// TOD Add your command handler code here

- }% u/ K2 o% i

CViewBitmap *pViewBitmap= NULL;

4 R/ q$ x& z5 v) i; b4 |: y8 t/ w

9 g+ Q, u x; ~3 ]2 O

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

- y x, _% x2 W6 H5 N; ?

pViewBitmap- >ShowWindow( TRUE);

, G* I& M) ~, Y, Y# c' ^

}

" \# ^# v4 p9 L) t* J

/ r! g& I; b, N+ m1 u' S3 S

4 X# s# o8 q8 b

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

- {! k- v7 j* [1 D. I( [) n- }" F7 s! p

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

$ z, |- e, N# L8 U! S

. ~, F8 W% [# o# L% l

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

5 E. h u7 C1 P- ~# L8 A5 T

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

+ X3 n# m& [% S* V+ p

- r+ C! n! t) _& W5 Z/ u4 {

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

" n; K3 U( }2 i& S

' H5 j+ w" n- _1 _

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

7 n" [/ e2 V- N4 N, m% j8 [

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

7 j' y: L4 Q# ^, T* A

9 `( |* V9 W, D1 @

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

5 z& p& L2 y0 v* L# J

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

0 f/ m5 _( j- z* s

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

/ b/ J- S; O @ X) v/ @! n: i

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

- X7 A4 H1 e4 _. K; n% |

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

7 C. q2 B- N/ a/ \

8 t. _% {8 S) h

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

$ m( U$ y. B( W; h; @0 i

就可以显示该位图。

! I3 e% G. \8 c* I( R

9 l4 F8 Q8 f$ ]& o1 _8 F1 i

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

4 J" }1 ~$ A" @# E1 v+ Y( C5 I9 V) i6 {

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

- ~9 g3 [' {9 s5 F( x+ w9 c7 l

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

. s3 |& h7 R2 ?2 ]

真小,显示速度快。

; c5 T7 g) a `

" j2 ~1 M2 z" F! R' I

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

; [, n$ y8 r6 F# n. O1 f& Q

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

! O1 j* _5 Y7 ]6 X

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

& P; }0 h4 b8 ]; Q, B( W( |

5 h% W2 u5 g) j, h5 s* X

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

0 O) e4 c: V& R: j

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






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