VC++和VC++.NET中與圖像處理有關的幾個概念、結(jié)構(gòu)和類最近一直在看VC++有關圖像處理方面的書,,終于把以前一直混淆的幾個概念,、結(jié)構(gòu)和類弄清楚了,特整理如下,。如有錯誤,,請大家批評指正,不勝感激,。下一步想好好學習學習OpenCV,,希望也能總結(jié)點東西。 一,、DDB與DIB位圖 一個Windows的位圖實際上是一些和顯示像素相對應的位陣列,,它有兩種類型:一種稱之為GDI(Graphic Device Interface)位圖,另一種是DIB位圖(Device-Independent Bitmap),。 GDI位圖包含了一種和Windows的GDI模塊有關的Windows數(shù)據(jù)結(jié)構(gòu),該數(shù)據(jù)結(jié)構(gòu)是與設備有關的,故此位圖又稱為DDB位圖(Device-Dependent Bitmap),。當用戶的程序取得位圖數(shù)據(jù)信息時,,其位圖顯示方式視顯示卡而定。由于GDI位圖的這種設備依賴性,,當位圖通過網(wǎng)絡傳送到另一臺PC,,很可能就會出現(xiàn)問題。 DIB比GDI位圖有很多編程優(yōu)勢,,例如它自帶顏色信息,,從而使調(diào)色板管理更加容易。且任何運行Windows的機器都可以處理DIB,,并通常以后綴為.BMP的文件形式被保存在磁盤中或作為資源存在于程序的EXE或DLL文件中,。 二、CBitmap類,、BITMAP結(jié)構(gòu) CBitmap類繼承自CGdiObject,,是封裝了圖形設備接口(GDI)的位圖,提供成員函數(shù)來操縱位圖,。要使用一個CBitmap對象,,構(gòu)造該對象,用初始化成員函數(shù)之一把一個位圖句柄連接到該對象,,然后調(diào)用該對象的成員函數(shù),。 CBitmap類主要用于處理DDB位圖,封裝了與DDB位圖操作函數(shù)相關的數(shù)據(jù)結(jié)構(gòu)和操作函數(shù),。結(jié)構(gòu)體BITMAP定義了DDB位圖的類型,、寬度、高度,、顏色和像素值,,其定義如下:
而CBitmap的LoadBitmap、CreateCompatibleBitmap,、SetBitmapBits,、GetBitmap等成員函數(shù)則定義了對DDB位圖的裝載、創(chuàng)建,、設定位值和屬性查詢等操作,。 創(chuàng)建或裝入內(nèi)存的位圖必須用CDC::SelectObject函數(shù)來將其選入設備上下文中,然后用CDC的BitBlt或StretchBlt函數(shù)顯示出來,,這兩個函數(shù)的原型如下:
該函數(shù)把源設備上下文中的位圖復制到本身的設備上下文中,,兩個設備下下文可以是內(nèi)存設備下下文,也可以是同一個設備上下文,。 三,、Image類和Bitmap類 在VC++.NET中,,GDI+的Image類封裝了對BMP、GIF,、JPEG,、PNG、TIFF,、WMF(Windows元文件)和EMF(增強WMF)圖像文件的調(diào)入,、顯示、格式轉(zhuǎn)換以及簡單處理(如縮放,、旋轉(zhuǎn),、拉伸等)的功能。而Bitmap類(注意不是結(jié)構(gòu)BITMAP)是從Image類繼承的一個圖像(另一個從Image繼承的類是Metafile類),,它封裝了Windows位圖操作的常用功能,。例如,Bitmap::SetPixel和Bitmap::GetPixel分別用來對位圖進行讀寫像素操作,,從而可以為圖像的柔化和銳化處理提供一種可能,。這些功能和MFC的新類CImage功能基本一樣,如果僅用于圖像的讀取與顯示,,用Bitmap類或Image類是不錯的選擇,,如果是做圖像處理,則CImage可能更符合MFC程序員的編程習慣,。 四,、CImage類 CImage類是VC++.NET中MFC和ATL共享的新類,它能從外部磁盤中調(diào)入一個JPEG,、GIF,、BMP和PNG格式的圖像文件加以顯示,而且這些文件格式可以相互轉(zhuǎn)換,。 CImage既能處理DIB位圖也能處理非DIB位圖,,但你可以僅用DIB位圖來Create或CImage::Load。你也可以使用Attach把一個非DIB位圖連接給CImage對象,,但你不能使用下列方法,,這些方法僅支持DIB位圖:GetBits、GetColorTable,、GetMaxColorTable,、Entries、GetPitch,、GetPixelAddress,、IsIndexed、SetColorTable,。要確定一個連接的位圖是否是一個DIB位圖,,調(diào)用IsDibSection,。 由于CImage在不同的Windows操作系統(tǒng)中其某些性能是不一樣的,因此在使用時要特別注意,。例如,,CImage::PlgBlt和CImage::MaskBlt只能在 Windows NT 4.0 或更高版本中使用,但不能運行在Windows 95/98 應用程序中,。CImage::AlphaBlend和CImage::TransparentBlt也只能在 Windows 2000/98或其更高版本中使用。即使在Windows 2000運行程序還必須將stdafx.h文件中的WINVER和_WIN32_WINNT的預定義修改成0x0500才能正常使用,。 CImage可以在MFC或ATL中使用,。當使用CImage創(chuàng)建一個項目時,必須包含atlimage.h文件,。 CImage封裝了DIB(設備無關位圖)的功能,,因而可以讓我們能夠處理每個位圖像素。 CImage提供了HBITMAP操作符,,因此HBITMAP為參數(shù)的地方,,都可以用CImage來替代。 五,、傳統(tǒng)的VC++中的圖像處理方法與VC++.NET中的圖像處理方法 由于DIB圖不依賴于具體設備,,因此可以用來永久性地保存圖象。DIB一般是以*.BMP文件的形式保存在磁盤中的,,有時也會保存在*.DIB文件中,。運行在不同輸出設備下的應用程序可以通過DIB來交換圖象。因而在數(shù)字圖象處理中會經(jīng)常用到DIB位圖,。DIB還可以用一種RLE算法來壓縮圖像數(shù)據(jù),,但一般來說DIB是不壓縮的。 在VC++.net之前MFC未提供現(xiàn)成的類來封裝DIB,,這給MFC用戶帶來很多不便,。因為用戶要想使用DIB,首先應該了解DIB的結(jié)構(gòu),。
注意,,RGBQUAD結(jié)構(gòu)中的顏色順序是BGR,而不是平常的RGB,。
與DDB不同,DIB的字節(jié)數(shù)組是從圖象的最下面一行開始的逐行向上存儲的,,也即等于把圖象倒過來然后在逐行掃描,。另外,字節(jié)數(shù)組中每個掃描行的字節(jié)數(shù)必需是4的倍數(shù),,如果不足要用0補齊,。
緊隨該結(jié)構(gòu)的是一個BITMAPINFOHEADER結(jié)構(gòu),然后是RGBQUAD結(jié)構(gòu)組成的顏色表(如果有的話),,文件最后存儲的是DIB的像素陣列,。 DIB的顏色信息儲存在自己的顏色表中,程序一般要根據(jù)顏色表為DIB創(chuàng)建邏輯調(diào)色板,。在輸出一幅DIB之前,,程序應該將其邏輯調(diào)色板選入到相關的設備上下文中并實現(xiàn)到系統(tǒng)調(diào)色板中,然后再調(diào)用相關的GDI函數(shù)(如::SetDIBitsToDevice或::StretchDIBits)輸出DIB,。在輸出過程中,,GDI函數(shù)會把DIB轉(zhuǎn)換成DDB,這項工作主要包括以下兩步:將DIB的顏色格式轉(zhuǎn)換成與輸出設備相同的顏色格式,;將DIB像素的邏輯顏色索引轉(zhuǎn)換成系統(tǒng)調(diào)色板索引,。 看到這么多結(jié)構(gòu),,你是不是已經(jīng)眼花繚亂了,,然而更不幸的還在后面。以上說的DIB是Windows中的DIB,,還有一種DIB是OS/2 DIB,,它和Windows DIB的主要區(qū)別是位圖信息結(jié)構(gòu)(信息頭和顏色表結(jié)構(gòu))。它們的圖像數(shù)據(jù)的存儲方式是完全一樣的,。在OS/2 DIB中,,與WIndows DIB的BITMAPFILEHEADER、BITMAPINFOHEADER,、RGBQUAD相對應的結(jié)構(gòu)分別是BITMAPCOREHEADER,、BITMAPCOREINFO,、和RGBTRIPLE。它們的定義分別如下:
因此再操作之前你應該先根據(jù)BITMAPINFOHEADER的大小來判斷是哪一種DIB,,然后再進行操作,。 由于MFC未提供一個封裝好的易用的DIB類,用戶在使用DIB時將面臨繁重的Windows API編程任務,。不信你看看Microsoft提供的MFC的DibLook例程提就知道了,。所以傳統(tǒng)的圖像處理方法一般都會把這些Win32 SDK中的操作DIB位圖的APIs做一個封裝,作為一個通用的類來使用,,以減少后續(xù)算法編寫中的編程負擔,。 VC++.NET提供了多種常用圖像文件格式(如BMP、TIF,、GIF、JPEG與PNG等)的輸入/輸出模塊,,ATL中的CImage類極大地簡化了圖像數(shù)據(jù)的操作,,因此VC++.NET中的圖像處理應以CImage為基礎。 |
|