VC+ + 視圖內容導出成位圖的方法
張 弦, 鮑徵宇
(中國地質大學地球化學研究所, 武漢 430074)
摘 要: 爲了獲得程序視圖的內容, 我們多采用屏幕硬拷貝的方法, 在視圖內容較多, 需要滾屏顯示的時候, 這種方法尤其費時費力, 且在圖形拼合時易產生偏差。作者在本文中介紹了在VC+ + 編程中直接把視圖內容導出成位圖文件的方法, 闡述了基本原理, 並提供了源代碼。
關鍵詞: 位圖; 導出; VC+ + ; 圖形圖像; 文檔/視圖
Microsoft Visual C+ + 6. 0 是Windows 操作系統中程序設計的利器, 並有強大的圖形圖像編程能力。在進行數值圖像處理(如遙感圖像處理、巖礦顯微組構的數值圖像分析等) 時, 常用VC+ + 作爲編程工具,程序運行結果多以圖形(如: 直方圖、等值線圖、曲線圖、以符號描述的目標物體分佈圖)、圖像(如岩石顯微圖像的礦物邊界的圈定及目標物體的分割) 的形式呈現。爲了保存程序視圖的內容, 我們平時多用的是屏幕拷貝再粘貼至其它圖像處理軟件(如: Photoshop) 中。編輯保存成圖像文件的方法, 不能實現程序本身把視圖內容導出成圖像的功能, 在保存視圖內容時不方便, 尤其是在視圖內容較多, 需要滾屏顯示時, 要分次
對屏幕進行硬拷貝, 再採用圖像處理軟件進行裁剪、拼合的方法, 費時費力, 而且多個小圖像拼合成一個大圖像時也存在偏差。作者在文中介紹了把視圖內容(全部或局部) 直接導出成位圖文件的方法, 易於編程實現。
1 基本原理
Windows系統中有兩種類型的位圖: 設備相關位圖(Device Dependent Bitmap, 簡稱DDB) 和設備無關位圖(Device Independent Bitmap, 簡稱DIB)。DDB 是一種內部位圖格式, 它們在內存中的結構和位置依賴於管理它們的設備驅動程序, 顯示的圖像依計算機顯示系統的不同而不同, 因此, 一般不存儲爲文件。與DDB 相比, D IB 是一種外部的位圖格式, 文件的結構與計算機系統硬件無關, 因此, 在不同的顯示系統中具有相同的顯示結果, 常存儲爲以. bmp 爲後綴的文件。
Ms VC+ + 6.0 基於Document/View 結構的程序中, 由視圖類的OnDraw(CDC* pDC) 函數在窗口客戶區中顯示文字、圖形、圖像等視圖內容。位圖的顯示就是把位圖顯示在屏幕上, 其反過程就是在截取屏幕的指定區域內放入位圖。顯示一幅D IB 位圖圖像的方法之一是先把D IB 位圖轉換成DDB 位圖bmp, 再把bmp 位圖選入設備繪圖環境(Device Context) 中pDC2>SelectObject (&bmp) , 調用BitBlt () 函數畫至顯示屏, 即可完成位圖的顯示。DDB 位圖選入設備繪圖環境後, 在設備環境沒有選入新的繪圖對象之前, 其視圖內容就與DDB 位圖的內容一致。我們可以通過更改視圖內容來更改被選入設備繪圖環境的DDB 位圖。
這樣就可以獲得視圖的DDB 位圖, 再把DDB 轉換成D IB, 完成D IB 位圖的保存即可。
2 實現代碼詳解
211 DDB 位圖的生成與視圖內容的獲取
以下的代碼要加入到視圖類的成員函數中。
CBitmap bmp; //用於保存視圖的內容的DDB 位圖
CDC memDC; //與當前顯示設備相兼容的內存設備環境
CSize sizeTotal= GetTotalSize () ; //獲取全部視圖的大小, 在這裏可以通過
//指定sizeTotal 來獲取視圖中特定的區域
int nMemDC; //保存顯示設備環境, 用於恢復初始設備環境
nMapMode= MM-LOENGLISH; //顯示模式, MM-LOENGLISH
int bits= GetDC()->GetDeviceCaps(BITSPIXEL )*GetDC()->GetDeviceCaps(PLANES);
//獲取顯示設備的顏色表位數
bmp.CreateBitmap( sizeTotal.cx, sizeTotal.cy, 1, bits, NULL ) ; //創建DDB 視圖, 大小由sizeTotal 來指定
memDC.CreateCompatibleDC(GetDC() ) ; //創建兼容的內存設備環境
nMemDC= memDC.SaveDC() ; //保存設備環境的初始狀態
memDC.SelectObject(&bmp) ; //把DDB 位圖選入繪圖設備
memDC.FillSolidRect(0, 0, sizeTotal. cx, sizeTotal. cy, GetDC()->GetBkColor () ) ;
//以當前視圖的背景色來填充位圖(初始化位圖)
memDC.SetMapMode(nMapMode) ;
OnDraw(&memDC) ; //完成視圖內容的獲取
memDC.RestoreDC(nMemDC) ; //恢復至設備環境的初始狀態
212 DDB 位圖轉換成D IB 位圖
由於D IB 圖像的每行都被填充到一個四字節邊界, 因此需要經常計算其每行所實際佔用的倍數。宏WIDTHBYTE 將一個數對齊於四字節邊界, 可方便地用於計算D IB 行的長度, 定義如下:
#define WIDTHBYTES(bits) ( ( ( (bits) + 31)/ 32) 3 4)
// pBmp 是傳遞過來的要轉換的DDB 位圖的指針, pDC 爲顯示設備環境的指針
//函數返回DIB 位圖的句柄
//全局函數
HGLOBAL ConvertDDB2D IB (CBitmap* pBmp, CDC3 pDC)
{
BITMAPINFOHEADER bi; //DIB 位圖信息頭
LPBITMAPINFO lpBi; //DIB 位圖信息指針
BITMAP bm;
DWORD dwSizeCT;
DWORD dwDibL en;
HGLOBAL hData;
pBmp2> GetBitmap(&bm) ; //獲得B ITMA P 結構
bi.biSize= sizeof (BITMAPINFOHEADER);
bi.biW idth= bm.bmW idth;
bi.biHeight= bm.bmHeigh t;
bi.biP lanes= bm.bmPlanes;
bi.biBitCount= bm. bmPlanes* bm.bmBitsPixel;
bi.biSize Image= 0;
bi.biXPelsPerM eter= 0;
bi.biYPelsPerM eter= 0;
bi.biComp ression= B I- RGB;
bi.biClrUsed= 0;
bi.biClrImportant= 0;
switch (bi. biB itCoun)
{
case 1: {dwSizeCT= 2; break; }
case 4: {dwSizeCT= 16; break; }
case 8: {dwSizeCT= 256; break; }
case 24: {dwSizeCT= 0; break; }
default: {dwSizeCT= 0; }
}
dwDibL en= bi.biSize+ dwSizeCT* sizeof(RGBQUAD) ;
hData= ::GlobalAlloc(GHND, dwDibLen) ;
lpBi= (LPBITMAPINFO) ::GlobalLock(hData);
lpBi2>bmiHeader= bi;
//獲得DIB 位圖文件信息, 即爲lpBi賦值
VERIFY
(
::GetDIBits
(
pDC2>GetSafeHdc() ,
(HBITMAP)pBmp2>GetSafeHandle() ,
0,(WORD)bi.biHeight,
NULL ,
lpBi,
DIB- RGB- COLORS
)
) ;
DWORD dwErr;
dwErr= GetLastError () ;
bi= lpBi2>bmiHeader; //獲得D IB 位圖信息頭
::GlobalUnlock(hData) ;
//計算位圖大小( inbytes)
if (! bi.biSizeImage)
{
bi.biSizeImage= WIDTHBYTES (bi.biBitCount* bi. biWidth) *bi.biHeight;
}
dwDibLen+ = bi.biSizeImage;
hData= ::GlobalReAlloc(hData, dwDibLen, CHND) ;
ASSERT (hData) ;
lpBi= (LPBITMAPIN FO) ::GlobalLock(hData) ;
ASSERT ( lpBi) ;
//複製DDB 位圖內容到DIB 位圖
V ER IFY
(
::GetDIBits
(
pDC->GetSafeHdc(),
(HBITMAP)pBmp->GetSafeHandle() ,
0,
(WORD) bi. biHeigh t,
(L PSTR) lpB i+ sizeof (B ITMA P IN FOHEADER) + dw SizeCT3 sizeof (RGBQUAD) ,
lpB i,
D IB- RGB- COLORS
)
) ;
: : GlobalU nlock (hData) ;
return hData;
}
213 保存D IB 位圖
öö hD ib 爲D IB 位圖的句柄
ööstrN ame 爲保存文件的全路徑名
öö全局函數
·88· 物探化探計算技術24 卷
void SaveD ibBmp (HGLOBAL hD ib, CString strN ame)
{
B ITMA PF IL EHEADER bmf; ööD IB 位圖文件頭
B ITMA P IN FOHEADER bi; ööD IB 位圖信息頭
L PB ITMA P IN FOHEADER lpB i; ööD IB 位圖信息頭指針
CF ile file;
CF ileExcep tion fxError;
DWORD dw SizeCT;
lpB i= (L PB ITMA P IN FOHEADER) : : GlobalLock (hD ib) ; öö獲得D IB 信息頭指針
bi= 3 lpB i;
if (! bi. biSize Image) bi. biSize Image= W IDTHBYTES (bi. biB itCount3 bi. biW idth) 3 bi. biHeigh t;
sw itch (bi. biB itCoun) öö獲取每個像素所需要的位數
{
case 1: { dw SizeCT= 2; break; }
case 4: { dw SizeCT= 16; break; }
case 8: { dw SizeCT= 256; break; }
case 24: { dw SizeCT= 0; break; }
default: { dw SizeCT= 0; }
}
öö獲得位圖文件頭的詳細信息
bmf. bfType= ′MB′;
bmf. bfSize= sizeof (bmf) + : : GlobalSize (hD ib) ;
bmf. bfOffB its= sizeof (bmf) + bi. biSize+ dw SizeCT3 sizeof (RGBQUAD) ;
bmf. bfReserved1= 0;
bmf. bfReserved2= 0;
öö用CF ile 創建一個二進制文件
if (! file. Open (strN ame, CF ile: :modeCreateûCF ile: :modeW rite, &fxError) )
{
TCHAR buf [255 ];
fxError. GetErrorM essage (buf, 255) ; öö獲得出錯信息
A fxM essageBox (buf) ; öö顯示出錯信息
return;
}
öö寫入D IB 文件頭及文件內容
file. W rite (&bmf, sizeof (B ITMA PF IL EHEADER) ) ;
file. W rite ( (L PSTR) lpB i, bi. biSize+ dw SizeCT3 sizeof (RGBQUAD) + bi. biSize Image) ;
file. Close () ;
öö進行清除
: : GlobalU nlock (hD ib) ;
: : GlobalF ree (hD ib) ;}
3 結束語
作者在本文中解決了VC+ + 程序視圖內容導出的問題, 可方便的把視圖內容導出成位圖。作者在文中
給出了關鍵代碼, 直接把相關代碼複製到程序中便可實現位圖導出功能。訪問鏈接h ttp: ööw altzforever.
edu. ch inaren. com , 下載Output. zip 文件可得到演示程序與完整演示程序源代碼。本文中所使用的方法在
M icrosoft VC+ + 6. 0 平臺上運行通過(由VC+ + 6. 0 的AppW izard 生成M FC AppW izard (exe) 工程, 選用
DocumentöV iew 支持, 視圖基類選用CScrollV iew 類)。
參考文獻:
[ 1 ] David J. Kruglinski. Programm ing V isual C+ + 6. 0 技術內幕(第五版) [M ] . 北京: 北京希望電子出版社, 19991
[ 2 ] 周長發1 精通V isual C+ + 圖像編程[M ] . 北京: 電子工業出版社, 20001
[ 3 ] John E. Swanke. VC+ + M FC Extensitons by Examp le[M ] . 北京: 機械工業出版社, 20001
[ 4 ] 劉厲, 周家紀1 位圖拼移技術在批量圖形處理中的應用[J ] . 物探化探計算技術, 2001, 23 (2) : 1761
[ 5 ] 李火亙, 周家紀1 設備場境化在W indow s GD I 中的應用[J ] . 物探化探計算技術, 1998, 20 (1) : 761
作者簡介: 張 弦(1976—) , 男, 中國地質大學(武漢) 地球化學碩士研究生, 研究方向: 計算地球化學, 地
球物質組構的數值圖像處理。
1 期朱 劍等: 統一建模語言UML 及應用實例·95·__