CImage类 from http://www.cnblogs.com/afarmer/archive/2012/03/31/2427273.html
CImage類
Visual C++的CBitmap類的功能是比較弱的,它只能顯示出在資源中的圖標、位圖、光標以及圖元文件的內容,而不像VB中的Image控件可以顯示出絕大多數(shù)的外部圖像文件(BMP、GIF、JPEG等)。如果想要在對話框或其他窗口中顯示外部圖像文件則只能借助于第三方提供的控件或代碼,未免過于繁瑣.
現(xiàn)在,.net引入了一個功能非常強大的新類 ----- CImage.有了CImage類,Visual C++在圖像方面的缺憾將一去不復返。CImage是MFC和ATL共享的新類,它能從外部磁盤中調入一個JPEG、GIF、BMP和PNG格式的圖像文件加以顯示,而且這些文件格式可以相互轉換。例如通過簡單的幾句,就可以實現(xiàn)CImage類和CBitmap類實例的:
HBITMAP hBitmap=image.Detach();?
CBitmap?bmp;?
bmp.Attach(hBitmap);
這樣一來,就又回歸到以前操縱CBitmap的方式了.CImage本身封裝了DIB(設備無關位圖)的功能,因而能夠處理每個位圖像素。
它具有下列最酷特性:?
1、AlphaBlend支持像素級的顏色混合,從而實現(xiàn)透明和半透明的效果。?
2、PlgBlt能使一個矩形區(qū)域的位圖映射到一個平行四邊形區(qū)域中,而且還可能使用位屏蔽操作。?
3、TransparentBlt在目標區(qū)域中產生透明圖像,SetTransparentColor用來設置某種顏色是透明色。?
4、MaskBlt在目標區(qū)域中產生源位圖與屏蔽位圖合成的效果。
由于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的一般方法?
使用CImage的一般方法是這樣的過程:?
(1) 打開應用程序的stdafx.h文件添加CImage類的包含文件:?
#include <atlimage.h>?
(2) 定義一個CImage類對象,然后調用CImage::Load方法裝載一個外部圖像文件。?
(3) 調用CImage::Draw方法繪制圖像。Draw方法具有如下定義:
BOOL Draw( HDC hDestDC, int xDest, int yDest,?
int nDestWidth, int nDestHeight, int xSrc, int ySrc,?
int nSrcWidth, int nSrcHeight );?
BOOL Draw( HDC hDestDC, const RECT& rectDest, const RECT& rectSrc );?
BOOL Draw( HDC hDestDC, int xDest, int yDest );?
BOOL Draw( HDC hDestDC, const POINT& pointDest );?
BOOL Draw( HDC hDestDC, int xDest, int yDest,?
int nDestWidth, int nDestHeight );?
BOOL Draw( HDC hDestDC, const RECT& rectDest );
其中,hDestDC用來指定繪制的目標設備環(huán)境句柄,(xDest, yDest)和pointDest用來指定圖像顯示的位置,這個位置和源圖像的左上角點相對應。nDestWidth和nDestHeight分別指定圖像要顯示的高度和寬度,xSrc、ySrc、nSrcWidth和nSrcHeight用來指定要顯示的源圖像的某個部分所在的位置和大小。 rectDest和rectSrc分別用來指定目標設備環(huán)境上和源圖像所要顯示的某個部分的位置和大小。?
需要說明的是,Draw方法綜合了StretchBlt、TransparentBlt和AlphaBlend函數(shù)的功能。默認時,Draw的功能和 StretchBlt相同。但當圖像含有透明色或Alpha通道時,它的功能又和TransparentBlt、AlphaBlend相同。因此,在一般情況下,我們都應該盡量調用CImage::Draw方法來繪制圖像。?
例如,下面的示例Ex_Image是實現(xiàn)這樣的功能:當選擇"文件"ò"打開"菜單命令后,彈出一個文件打開對話框。當選定一個圖像文件后,就會在窗口客戶區(qū)中顯示該圖像文件內容。這個示例的具體步驟如下:?
(1) 創(chuàng)建一個默認的單文檔程序項目Ex_Image。?
(2) 打開stdafx.h文件中添加CImage類的包含文件atlimage.h。?
(3) 在CEx_ImageView類添加ID_FILE_OPEN的COMMAND事件映射程序,并添加下列代碼:
void CEx_ImageView::OnFileOpen()?
{?
CString strFilter;?
CSimpleArray<GUID> aguidFileTypes;?
HRESULT hResult;?
// 獲取CImage支持的圖像文件的過濾字符串?
hResult = m_Image.GetExporterFilterString(strFilter,aguidFileTypes,?
_T( "All Image Files") );?
if (FAILED(hResult)) {?
MessageBox("GetExporterFilter調用失敗!");?
return;?
}?
CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);?
if(IDOK != dlg.DoModal())?
return;?
m_Image.Destroy();?
// 將外部圖像文件裝載到CImage對象中?
hResult = m_Image.Load(dlg.GetFileName());?
if (FAILED(hResult)) {?
MessageBox("調用圖像文件失敗!");?
return;?
}?
// 設置主窗口標題欄內容?
CString str;?
str.LoadString(AFX_IDS_APP_TITLE);?
AfxGetMainWnd()->SetWindowText(str + " - " +dlg.GetFileName());?
Invalidate(); // 強制調用OnDraw?
}
(4) 定位到CEx_ImageView::OnDraw函數(shù)處,添加下列代碼:
void CEx_ImageView::OnDraw(CDC* pDC)?
{?
CEx_ImageDoc* pDoc = GetDocument();?
ASSERT_VALID(pDoc);?
if (!m_Image.IsNull()) {?
m_Image.Draw(pDC->m_hDC,0,0);?
}?
}
(5) 打開Ex_ImageView.h文件,添加一個公共的成員數(shù)據(jù)m_Image:
public:?
CImage m_Image;
(6) 編譯并運行。單擊"打開"工具按鈕,在彈出的對話框中指定一個圖像文件后,單擊"打開"按鈕,其結果如圖7.21所示。?
將圖片用其它格式保存?
CImage::Save方法能將一個圖像文件按另一種格式來保存,它的原型如下:
HRESULT Save( LPCTSTR pszFileName, REFGUID guidFileType= GUID_NULL);
其中,pszFileName用來指定一個文件名,guidFileType用來指定要保存的圖像文件格式,當為GUID_NULL時,其文件格式由文件的擴展名來決定,這也是該函數(shù)的默認值。它還可以是GUID_BMPFile(BMP文件格式)、GUID_PNGFile(PNG文件格式)、 GUID_JPEGFile(JPEG文件格式)和GUID_GIFFile(GIF文件格式)。?
例如,下面的過程是在Ex_Image示例基礎上進行的,我們在CEx_ImageView類添加ID_FILE_SAVE_AS的COMMAND事件映射程序,并添加下列代碼:
void CEx_ImageView::OnFileSaveAs()?
{?
if (m_Image.IsNull()) {?
MessageBox("你還沒有打開一個要保存的圖像文件!");?
return;?
}?
CString strFilter;?
strFilter = "位圖文件|*.bmp|JPEG 圖像文件|*.jpg| \?
GIF 圖像文件|*.gif|PNG 圖像文件|*.png||";?
CFileDialog dlg(FALSE,NULL,NULL,NULL,strFilter);?
if ( IDOK != dlg.DoModal())?
return;?
// 如果用戶沒有指定文件擴展名,則為其添加一個?
CString strFileName;?
CString strExtension;?
strFileName = dlg.m_ofn.lpstrFile;?
if (dlg.m_ofn.nFileExtension == 0)?
{?
switch (dlg.m_ofn.nFilterIndex)?
{?
case 1:?
strExtension = "bmp"; break;?
case 2:?
strExtension = "jpg"; break;?
case 3:?
strExtension = "gif"; break;?
case 4:?
strExtension = "png"; break;?
default:?
break;?
}?
strFileName = strFileName + '.' + strExtension;?
}?
// 圖像保存?
HRESULT hResult = m_Image.Save(strFileName);?
if (FAILED(hResult))?
MessageBox("保存圖像文件失敗!");
將圖片用其它格式保存?
CImage::Save方法能將一個圖像文件按另一種格式來保存,它的原型如下:
HRESULT Save( LPCTSTR pszFileName, REFGUID guidFileType= GUID_NULL);
其中,pszFileName用來指定一個文件名,guidFileType用來指定要保存的圖像文件格式,當為GUID_NULL時,其文件格式由文件的擴展名來決定,這也是該函數(shù)的默認值。它還可以是GUID_BMPFile(BMP文件格式)、GUID_PNGFile(PNG文件格式)、 GUID_JPEGFile(JPEG文件格式)和GUID_GIFFile(GIF文件格式)。?
例如,下面的過程是在Ex_Image示例基礎上進行的,我們在CEx_ImageView類添加ID_FILE_SAVE_AS的COMMAND事件映射程序,并添加下列代碼:
void CEx_ImageView::OnFileSaveAs()?
{?
if (m_Image.IsNull()) {?
MessageBox("你還沒有打開一個要保存的圖像文件!");?
return;?
}?
CString strFilter;?
strFilter = "位圖文件|*.bmp|JPEG 圖像文件|*.jpg| \?
GIF 圖像文件|*.gif|PNG 圖像文件|*.png||";?
CFileDialog dlg(FALSE,NULL,NULL,NULL,strFilter);?
if ( IDOK != dlg.DoModal())?
return;?
// 如果用戶沒有指定文件擴展名,則為其添加一個?
CString strFileName;?
CString strExtension;?
strFileName = dlg.m_ofn.lpstrFile;?
if (dlg.m_ofn.nFileExtension == 0)?
{?
switch (dlg.m_ofn.nFilterIndex)?
{?
case 1:?
strExtension = "bmp"; break;?
case 2:?
strExtension = "jpg"; break;?
case 3:?
strExtension = "gif"; break;?
case 4:?
strExtension = "png"; break;?
default:?
break;?
}?
strFileName = strFileName + '.' + strExtension;?
}?
// 圖像保存?
HRESULT hResult = m_Image.Save(strFileName);?
if (FAILED(hResult))?
MessageBox("保存圖像文件失敗!");?
變成黑白圖片?
由于許多圖像文件使用顏色表來發(fā)揮顯示設備的色彩顯示能力,因而將一張彩色圖片變成黑色圖片時需要調用CImage::IsIndexed來判斷是否使用顏色表,若是則修改顏色表,否則直接將像素進行顏色設置。例如下面的代碼:
void CEx_ImageView::MakeBlackAndwhite(CImage* image)?
{?
if (image->IsNull()) return;?
if (!image->IsIndexed()) {?
// 直接修改像素顏色?
COLORREF pixel;?
int maxY = image->GetHeight(), maxX = image->GetWidth();?
byte r,g,b,avg;?
for (int x=0; x<maxX; x++) {?
for (int y=0; y<maxY; y++) {?
pixel = image->GetPixel(x,y);?
r = GetRValue(pixel);?
g = GetGValue(pixel);?
b = GetBValue(pixel);?
avg = (int)((r + g + b)/3);?
image->SetPixelRGB(x,y,avg,avg,avg);?
}?
}?
} else {?
// 獲取并修改顏色表?
int MaxColors = image->GetMaxColorTableEntries();?
RGBQUAD* ColorTable;?
ColorTable = new RGBQUAD[MaxColors];?
image->GetColorTable(0,MaxColors,ColorTable);?
for (int i=0; i<MaxColors; i++)?
{?
int avg = (ColorTable[i].rgbBlue + ColorTable[i].rgbGreen + ColorTable[i].rgbRed)/3;?
ColorTable[i].rgbBlue = avg;?
ColorTable[i].rgbGreen = avg;?
ColorTable[i].rgbRed = avg;?
}?
image->SetColorTable(0,MaxColors,ColorTable);?
delete(ColorTable);?
}?
}
?
轉自:http://hi.baidu.com/cauciee/blog/item/3053490994877438e8248822.html
?
GDI 總結三: CImage類使用
分類:?圖形圖像處理2011-12-21 09:16 427人閱讀?評論(1)?收藏?舉報
前言
CImage類是基于GDI+的,但是這里為什么要講歸于GDI?
???????? 主要是基于這樣的考慮: 在GDI+環(huán)境中,我們可以直接使用GDI+ ,沒多少必要再使用CImage類
?????????????????????????????????????????????????????? 但是,如果再GDI環(huán)境中,我們要想使用GDI+,有點麻煩,還得加入頭文件,加入啟動GDI+的代碼和關閉GDI+的代碼,顯得太羅嗦了,GDI? 的CBitmap 處理功能又有局限,只能處理BMP格式的圖片。 怎么辦?這時,我們便可使用CImage類,因為這個類本身封裝了GDI+得使用環(huán)境,所以無需我們手動設置,簡化了我們的操作。? 同時,又可以利用GDI+中強大的圖片處理功能,及可以簡便的與CBitmap對象進行轉換 ,大大方便了在GDI環(huán)境下,進行各種圖片處理工作 。
??????????????????????????????????????????????????????? 其實,將其稱作 GDI/ GDI+ 混合編程,這樣才更確切些。
為什么引入CImage類?
?
??? CBitmap 類只能處理BMP格式的圖片,非常受限。
??? 而CImage可以處理JPGE GIF BMP PNG多種格式圖片,擴展了圖片處理功能 且能與CBitmap 進行轉換( 因為所載入的位圖句柄都是HBITMAP,所以可相互轉換),因此引入CImage類進行圖像處理
???? CImage?provides enhanced bitmap support, including the ability to load and save images in JPEG, GIF, BMP, and Portable Network Graphics (PNG) formats
CImage類介紹
?
???? CImage是MFC和ATL共享的新類,它能從外部磁盤中調入一個JPEG、GIF、BMP和PNG格式的圖像文件加以顯示,而且這些文件格式可以相互轉換。
???? CImage是VC.NET中定義的一種MFC/ATL共享類,也是ATL的一種工具類,它提供增強型的(DDB和DIB)位圖支持,可以裝入、顯示、轉換和保存多種格式的圖像文件,包括BMP、GIF、JPG、PNG、TIF等。CImage是一個獨立的類,沒有基類。(CImage類是基于GDI+的,從VC.NET起引進,VC 6.0中沒有。)
????? ATL(Active Template Library,活動模板庫)是一套基于模板的 C++ 類,用以簡化小而快的 COM 對象的編寫。
為了在MFC程序中使用CImage類,必須包含ATL的圖像頭文件atlimage.h:(在VS08 SP1中不用包含)
???? #include <atlimage.h>
1? 加載位圖文件
?
[cpp]?view plaincopyprint?
2 與CBitmap轉換
?
?
[cpp]?view plaincopyprint?
3 獲得CImage對象的cdc
[cpp]?view plaincopyprint?
4 顯示位圖
?? 思路: 將CImage對象 繪制在對應的DC中
?? 所使用的函數(shù) BitBlt?? StretchBlt? Draw等
?? 以Draw舉例:
[cpp]?view plaincopyprint?
Draw?performs the same operation as?StretchBlt, unless the image contains a transparent color or alpha channel. In that case,Drawperforms the same operation as eitherTransparentBlt?orAlphaBlend?as required.
For versions of?Draw?that do not specify a source rectangle, the entire source image is the default. For the version ofDraw?that does not specify a size for the destination rectangle, the size of the source image is the default and no stretching or shrinking occurs.
EXAMPLE 1:
?
[cpp]?view plaincopyprint?
EXAMPLE 2: 畫在另一個位圖中
[cpp]?view plaincopyprint?
5 將位圖資源與對象進行分離
?
[cpp]?view plaincopyprint?
6 釋放資源
CBitmap 使用DeleteObject()來主動釋放掉位圖資源
CImage?? 沒有DeleteObject()函數(shù) ,而是用Destroy()函數(shù)來主動釋放位圖資源
[cpp]?view plaincopyprint?
CBitmap 析構時,會自動釋放掉所占用的位圖資源
CImage 析構時,也會自動釋放掉所占用的位圖資源
[cpp]?view plaincopyprint?
7 讀寫圖像數(shù)據(jù)
?
主要用到3個函數(shù) :
?
1 )GetBits() 獲得數(shù)據(jù)區(qū)的指針
?
Retrieves a pointer to the actual bit values of a given pixel in a bitmap.
void* GetBits( ) throw( );[cpp]?view plaincopyprint?
A pointer to the bitmap buffer. If the bitmap is a bottom-up DIB, the pointer points near the end of the buffer. If the bitmap is a top-down DIB, the pointer points to the first byte of the buffer.
Using this pointer, along with the value returned by?GetPitch, you can locate and change individual pixels in an image.
注意: 由GetBits()取得的指針不一定是圖片數(shù)據(jù)的起始行,必須結合GetPitch()的值來確定起始行位置
2)GetPitch()
[cpp]?view plaincopyprint?
獲得圖像數(shù)據(jù)每一行的字節(jié)數(shù)
The pitch of the image. If the return value is negative, the bitmap is a bottom-up DIB and its origin is the lower left corner. If the return value is positive, the bitmap is a top-down DIB and its origin is the upper left corner.
GetBits 與 GetPitch 關系:
當GetPitch()<0時,GetBits()獲得的指針指向最后一行
當GetPitch()>0時,GetBits()獲得的指針指向第一行
圖像數(shù)據(jù)首行地址:
[cpp]?view plaincopyprint?
或
[cpp]?view plaincopyprint?
3)GetBPP() 返回每個像素所占的bit數(shù)
[cpp]?view plaincopyprint?
The number of bits per pixel.
This value determines the number of bits that define each pixel and the maximum number of colors in the bitmap
一個綜合例子:
[cpp]?view plaincopyprint?
8 保存到圖像文件中
Saves an image as the specified file name and type.
HRESULT Save( IStream* pStream, REFGUID guidFileType ) const throw(); HRESULT Save( LPCTSTR pszFileName, REFGUID guidFileType=GUID_NULL )[cpp]?view plaincopyprint?
A pointer to a stream containing the file name for the image.
A pointer to the file name for the image.
The file type to save the image as. Can be one of the following:
-
ImageFormatBMP?? An uncompressed bitmap image.
-
ImageFormatPNG?? A Portable Network Graphic (PNG) compressed image.
-
ImageFormatJPEG?? A JPEG compressed image.
-
ImageFormatGIF?? A GIF compressed image.
Call this function to save the image using a specified name and type. If the guidFileType parameter is not included, the file name's file extension will be used to determine the image format. If no extension is provided, the image will be saved in BMP format.
MSDN例子:
[cpp]?view plaincopyprint?
9 應用實例: 將兩個圖像合并為一個新的圖像
?
[cpp]?view plaincopyprint?
轉載于:https://www.cnblogs.com/songtzu/archive/2013/01/03/2843400.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結
以上是生活随笔為你收集整理的CImage类 from http://www.cnblogs.com/afarmer/archive/2012/03/31/2427273.html的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【IntelliJ】IntelliJ I
- 下一篇: 模拟CA系统