设为首页 加入收藏

TOP

CBitmap位图操作
2012-03-11 08:14:05 来源: 作者: 【 】 浏览:932
Tags:CBitmap 位图 操作
在Visual C++(www.cppentry.com)6.0中,显示位图的方法及过程如下: # S% i* H% y& H* H$ v+ m2 Q
  1. 显示程序资源中的位图(位图的所有数据均存在于可执行文件中) ) j' t, M6 Q6 z0 V4 I+ z7 q
  (1)从资源中装入位图
  ● 定义位图对象数据成员CBitmap m_Bitmap; 
  ● 调用CBitmap成员函数LoadBitmap(),如m_Bitmap.LoadBitmap(IDB_BITMAP1); 0 ], . j" \8 r
  ● 传入LoadBitmap的参数是位图在图形编辑器中生成或从位图文件中引入时赋予的识别符。  w6 A3 e3 p' T1 D8 @0 z
  (2)生成与位图相联系的内存设备情境对象2 B2 }% M' & ~3 U1 L" Q
0 c0 S0 M5 B0 f; n: t+ E
CDC MemDC; 
MemDC.CreateCompatibleDC(NULL); 
MemDC.SelectObject(&m_Bitmap); + l& x' S5 k7 R! z  L* W
  (3)显示位图
; t; t  X$ D6 t; B( u
CClientDC ClientDC(this); 
BITMAP BM; 7 ]2 U: [0 A; _& N2 m2 l
m_Bitmap.GetObject(sizeof(BM),&BM); $ T. A' t) I4 F  q2 X; \  V( N' ]
ClientDC.BitBlt 
( X,Y, //目标设备逻辑横、纵坐标 , @    V! w4 M) Z. p6 l
BM.bmWidth, BM.bmHeight, //显示位图的像素宽、高度 
&MemDC, 
//待显示位图数据的设备情境对象 " X5 }, s) V1 F# d4 l! I/ V7 `
0,0, //源数据中的横、纵坐标$ G  X3 s. f% x4 ^+ j+ p. \
SRCCOPY); //位操作方式
  这种方法显示位图速度快,但不是很灵活,而且会使可执行文件增大。
  2. 显示独立文件方式的位图(位图的所有数据独立于可执行文件) 5 U' r/ l  [* C! B: Y) }
( j% k6 A( @; @- C
HBITMAP *hBitmap; //定义位图对象句柄 . P6 G$ z* ^, M3 X# v3 j, D
BITMAP BM; 
CDC MemDC; 
CClientDC ClientDC(this); 
MemDC.CreateCompatibleDC(&ClientDC); 
hBitmap=(HBITMAP*):: LoadImage ' X1 O# o( x7 C" e; f
( AfxGetInstanceHandle(), / y- T$ n( p1 B* g+ K
//取得应用程序句柄 
“demo1.bmp”, ">位图文件名 
IMAGE_BITMAP, 9 d3 `7 I8 A1 d* d9 _9 U4 H
//类型为Windows位图 
0,0, 
LR_LOADFROMFILE); 
//从文件中取位图数据 
MemDC.SelectObject(hBitmap); $ s% [( k  D: S, l' s+ e. Z& k6 h
:: GetObject(hBitmap,sizeof(BM),&BM); ) ~. P, \; t  E- ]8 t' P
ClientDC.BitBlt(……) * w( F, L8 h- j$ W
//使用格式与方法一同1 [$ `7 a" v3 a+ v# e
  这种方法显示位图速度较之前一种慢了一点,但其灵活性较大,可以任意变换位图文件,而无需重新编译源程序, 也减小了可执行文件的大小。 

实现方法. M7 r, J, w3 t6 E9 y
  下面介绍各种图形显示技巧的具体实现原理及方法。以下所有程序算法的实现均可放在视类(CView,也可视自己的需要放在其他类)中处理,且有必要进行如下的相关操作:5 i/ r/ G1 B8 a
  增加如下类成员变量: 

BITMAP m_Bm; ! i/ ]' Y8 @# ^3 z
//保存位图的宽、高度等数据 
HBITMAP *m_hBitmap; 
//保存位图数据句柄 
CDC m_MemDC; //内存设备情境对象 ( {: A) f. n, r! f1 b, y5 f1 x2 b
  在类构造函数中加入如下代码:

m_MemDC.CreateCompatibleDC(NULL); //产生内存设备情境对象 
m_hBitmap=(HBITMAP *):oadImage( 
//从文件中装入位图数据 
AfxGetInstanceHandle(), ( m1 T9 @8 q4 z2 a, P4 }
“demo1.bmp”, 5 Z5 `5 \  F& q- D
IMAGE_BITMAP, 
0,0, 
LR_LOADFROMFILE ); , H) Z. y* R- [.
m_MemDC.SelectObject(m_hBitmap); //将位图选入内存设备情境对象
::GetObject(m_hBitmap,sizeof(m_Bm),&m_Bm); 

-page-

保存位图, b!  w5 B' z9 v' W

# c2 ~+ c" h7 M2 f: b
       CString m_Path("C://");
1 E! u9 L8 v& Y
       int       nX, nY, nX2, nY2;      % e5 {. o# d. y; w
       // 选定区域坐标
       int       Width, Height;0 d6 p5 F/ L, v3 ! j6 o
       
       // 确保选定区域不为空矩形
       if (IsRectEmpty(lpRect))
              return NULL;
4 Q. c/ g* a# v* R
6 i5 m7 K5 Q( y& ]9 _* L0 O
       // 获得选定区域坐标
       nX = lpRect->left;. z7 H8 G: T% l$ g; {( q# i
       nY = lpRect->top;5 C# b* j) Q* U6 |2 u$ {
       nX2 = lpRect->right;( x' h* \. Z! Y. H6 C6 m, d
       nY2 = lpRect->bottom;/ l# X* S) O/ K! x5 P+ E$ V

       //确保选定区域是可见的6 }% C& % s3 W9 e
       if (nX < 0). S( r2 J" M; W
              nX = 0;
       if (nY < 0)
              nY = 0;
       if (nX2 > m_xScreen)# p0 ^0 I$ v3 # A5 U
              nX2 = m_xScreen;7 |- j7 l8 ~+ g
       if (nY2 > m_yScreen)
              nY2 = m_yScreen;</SPA< span>n>4 R5 V, K' f# i' i/ I; H
       Width = nX2 - nX;
       Height = nY2 - nY;6 ' i" m, }3 B1 {. v+ N
    CDC dc;
       dc.CreateDC("DISPLAY",NULL,NULL,NULL);: }2 Y" u& O" k( 1 `
       CBitmap bm;2 B  u. G! m, N; }$ J! W) w
       bm.CreateCompatibleBitmap(&dc,Width,Height);
       CDC tdc;. C# g+ G6 {1 g$ y. J. L& ], N' i
       tdc.CreateCompatibleDC(&dc);; u0 t. {& r) o; D% X. H9 n' j0 T
       CBitmap*pOld=tdc.SelectObject(&bm);$ M' M$ w/ }/ K8 j
       tdc.BitBlt(0,0,Width,Height,&dc,nX,nY,SRCCOPY);5 l& O5 v- c' z. L0 @

       tdc.SelectObject(pOld);5 i- V7 f2 p3 a# s
       BITMAP btm;" q# P- v6 [$ O# I) z, @
       bm.GetBitmap(&btm);* A0 O% L( Z& a  z2 A8 g
       ( N, T3 F- c. u" V3 j: d6 S' j
       DWORD size=btm.bmWidthBytes*btm.bmHeight;
       LPSTR lpData=(LPSTR)GlobalAllocPtr(GPTR,size);9 H1 W% F! _. M( e% m, D
/////////////////////////////////////////////
       BITMAPINFOHEADER bih;8 U' R$ Y* i3 ~* [1 N7 U9 @
       bih.biBitCount=btm.bmBitsPixel;
       bih.biClrImportant=0;
       bih.biClrUsed=0;0 E; n/ Y/ m/ T' K
       bih.biCompression=0;
       bih.biHeight=btm.bmHeight;. O* O( f1 w) D( f9 y" b
       bih.biPlanes=1;$ _% k( X) U+ V& ~( I
       bih.biSize=sizeof(BITMAPINFOHEADER);
       bih.biSizeImage=size;
       bih.biWidth=btm.bmWidth;
       bih.biXPelsPerMeter=0;7 C8 P. n2 O* e% e9 y
       bih.biYPelsPerMeter=0;* e, y  E7 X, H7 d
///////////////////////////////////
       GetDIBits(dc,bm,0,bih.biHeight,lpData,(BITMAPINFO*)&bih,DIB_RGB_COLORS);
//     bm.GetBitmapBits(size,lpData);     //此函数在处理5-5-5模式的16位色下会出现颜色混乱8 L- Q; P, N8 [. @
/////////////////////////////// g. Y  O' U( v3 \( f6 a8 r
       static int filecount=0;8 W4 t% f  S5 N, c$ P% O
       CString name;
       name.Format("pict%04d.bmp",filecount++);
       name=m_Path+name;
              MessageBox(name);; Y; y1 ^& c: C  }( c9 Z1 D3 T
       BITMAPFILEHEADER bfh;
       bfh.bfReserved1=bfh.bfReserved2=0;
       bfh.bfType=((WORD)(''M''<< 8)|''B'');
       bfh.bfSize=54+size;
       bfh.bfOffBits=54;1 M0 a6 k" F/ O- Y" u! 3 {
       CFile bf;
       if(bf.Open(name,CFile::modeCreate|CFile::modeWrite)){: d" X# l$ [' \
              bf.WriteHuge(&bfh,sizeof(BITMAPFILEHEADER));
              bf.WriteHuge(&bih,sizeof(BITMAPINFOHEADER));; P" L' _$ D; b
              bf.WriteHuge(lpData,size);7 k3 {' W* w2 J1 O
              bf.Close();
       
       }, E8 j1 U6 y. L1 [( D
       GlobalFreePtr(lpData);8 @8 c- h* G: Y( U! g6 O% T  ^
) s7 N/ _! M6 T8 v
- d( p5 B. a. [2 k6 n: J4 N' u4 w
32位位图到24位位图的转换

(一)功能9 n( x$ s4 m9 p6 |
在图像处理的很多实际应用中,我们需要对图像的颜色表示进行转换(如,将32位颜色转换到24位颜色等等)。本文通过一个简单的例子,说明了32位颜色到24位颜色的转换过程。程序假设当前windows桌面颜色为32位颜色值。

(一)功能
在图像处理的很多实际应用中,我们需要对图像的颜色表示进行转换(如,将32位颜色转换到24位颜色等等)。本文通过一个简单的例子,说明了32位颜色到24位颜色的转换过程。程序假设当前windows桌面颜色为32位颜色值。 + v; m+ w" T+ j9 \  }3 n
(二)准备工作
建立VC CONSOLE APPLICATION,选择MFC SUPPORT+ O& o" N2 n2 Y

(三)主函数
函数Bmp32ToBmp24将32位位图转换到24位位图格式。
注意:该函数假设当前windows桌面颜色为32位颜色值。

// transform 32-bit bitmap format to 24-bit bitmap format 
void Bmp32ToBmp24(char Filename[])7 t5 j" u( y% C- x6 |
{
char Filename2[] = "output.bmp";4 T% {" f2 G5 f4 C; b; r; r* h$ a
& h2 J. ], ~& y9 {- F" x$ z
//注意:如果没有LR_CREATEDIBSECTION,位图颜色将被映射到屏幕DC颜色7 J5 U4 I* c1 t. F9 \
//也就是说,如果屏幕是16位颜色,则所有的图像都将映射到16位颜色5 I# {5 |( Z) J+ e: s& X0 m0 h
HBITMAP hbmp32 = (HBITMAP) LoadImage(NULL, Filename, + P* I: E; g) n+ k, l( c, c: o& n
IMAGE_BITMAP, 0, 0, 
LR_LOADFROMFILE | ( v/ g/ k( u$ X, `: @
LR_CREATEDIBSECTION);

BITMAP bmp;//获取位图信息
GetObject(hbmp32, sizeof(BITMAP), &bmp);5 u6 v1 b- X+ g4 H' q
3 l4 Y  Z+ S0 E7 C5 `0 p
printf("Image Bit Depth : %d/nWidth : %d , Height : %d /n", 
bmp.bmBitsPixel, bmp.bmWidth, bmp.bmHeight);//显示位图颜色模式和图像宽高" l/ q: X! G8 h1 @4 ^$ X, O
7 [5 z' j: Z9 Y) ~/ $ U7 [# `+ e  m
//计算24位图像每行的字节数
int BytesPerLine = 3 * bmp.bmWidth;
while(BytesPerLine % 4 != 0)
BytesPerLine ++;
% T, o' b6 B6 T& h) E
BITMAPINFOHEADER bih = {0};//位图信息头; v& H3 N9 M  |2 j: , y2 v
bih.biBitCount = 24;//每个像素字节大小0 X5 H, W% n2 S4 }
bih.biCompression = BI_RGB;
bih.biHeight = bmp.bmHeight;//高度4 \  V4 |/ C  O. B
bih.biPlanes = 1;: l! S3 M9 Q0 C1 ]0 O! B
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biSizeImage = BytesPerLine * bmp.bmHeight;//图像数据大小: f3 Q- D# u* m
bih.biWidth = bmp.bmWidth;//宽度
, H; L- a" ~3 f1 K
BITMAPFILEHEADER bfh = {0};//位图文件头
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);//到位图数据的偏移量3 _# z- ]* {6 C- v; v
bfh.bfSize = bfh.bfOffBits + bih.biSizeImage;//文件总的大小
bfh.bfType = (WORD)0x4d42;6 r4 O  q' G1 F* O
/ i8 @$ N' A! c! f+ V
FILE *fp = fopen(Filename2, "w+b");# [' M) c' u* g0 `6 t

fwrite(&bfh, 1, sizeof(BITMAPFILEHEADER), fp);//写入位图文件头+ Q4 m. [! V' m  `# }

fwrite(&bih, 1, sizeof(BITMAPINFOHEADER), fp);//写入位图信息头

byte * p = new byte[bih.biSizeImage];
9 S& [  E& G6 l' L
//获取当前32位图像数据
GetDIBits(GetDC(NULL), hbmp32, 0, bmp.bmHeight, p, (LPBITMAPINFO)&bih, DIB_RGB_COLORS);
& q4 V: E  [: }. q0 Q: \
//只取rgb值,存入文件3 U7 F4 W2 l2 6 e
byte b = 0;//用于填充7 X* t$ v! a/ I' [
for(int i = 0 ; i < bmp.bmWidth * bmp.bmHeight ; i ++)$ W8 I4 V& w/ X/ @, M* k- c
{" v9 t; {9 Y: H9 |
//32位位图图像的格式为:Blue, Green, Red, Alpha
fwrite(&(p[i * 3]), 1, 3, fp);3 v  p6 l( B5 l: X% m% Z
if(i % bmp.bmWidth == bmp.bmWidth - 1)//填充字节9 }2 H. }2 ) f, `* \
{$ y& S( ) S2 q. v, d  ]4 N6 |
   for(int k = 0 ; k < (BytesPerLine - bmp.bmWidth * 3) ; k ++)
    fwrite(&b, sizeof(byte), 1, fp);
}0 r% O) W. n: G/ h9 Y' l8 s4 S
}
1 ]: q6 ]0 z/ o% H2 U
delete [] p;0 i5 S- r# q% d  k( r

fclose(fp);# ]0 w% a" ~3 O
- {& O$ j! y2 ~/ v' y( D
DeleteObject(hbmp32);  k, ~- e3 C: T! }+ n) X
}
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇vc显示bmp位图 下一篇C/C++中动态链接库的创建和调用

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: