Visual C++的CBitmap類的功能是比較弱的,它只能顯示出在資源中的圖標、位圖、光標以及圖元文件的內容,而不像VB中的Image控件可以顯示出絕大多數的外部圖像文件(BMP、GIF、JPEG等)。如果想要在對話框或其他窗口中顯示外部圖像文件則只能借助於第三方提供的控件或代碼,未免過於繁瑣.
現在,.net引入了一個功能非常強大的新類 ----- CImage.有了CImage類,Visual C++在圖像方面的缺憾將一去不復返。CImage是MFC和ATL共享的新類,它能從外部磁盤中調入一個JPEG、GIF、BMP和PNG格式的圖像文件加以顯示,而且這些文件格式可以相互轉換。例如通過簡單的幾句,就可以實現CImage類和CBitmap類實例的:
HBITMAP hBitmap=image.Detach();
CBitmap bmp;
bmp.Attach(hBitmap);
這樣一來,就又回歸到以前操縱CBitmap的方式了.CImage本身封裝了DIB(設備無關位圖)的功能,因而能夠處理每個位圖像素。
它具有下列最酷特性:
1、AlphaBlend支持像素級的顏色混合,從而實現透明和半透明的效果。
2、PlgBlt能使一個矩形區域的位圖映射到一個平行四邊形區域中,而且還可能使用位屏蔽操作。
3、TransparentBlt在目標區域中產生透明圖像,SetTransparentColor用來設置某種顏色是透明色。
4、MaskBlt在目標區域中產生源位圖與屏蔽位圖合成的效果。
由於CImage在不同的Windows操作系統中其某些性能是不一樣的,因此在使用時要特別注意。例如,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用來指定繪制的目標設備環境句柄,(xDest, yDest)和pointDest用來指定圖像顯示的位置,這個位置和源圖像的左上角點相對應。nDestWidth和nDestHeight分別指定圖像要顯示的高度和寬度,xSrc、ySrc、nSrcWidth和nSrcHeight用來指定要顯示的源圖像的某個部分所在的位置和大小。 rectDest和rectSrc分別用來指定目標設備環境上和源圖像所要顯示的某個部分的位置和大小。
需要說明的是,Draw方法綜合了StretchBlt、TransparentBlt和AlphaBlend函數的功能。默認時,Draw的功能和 StretchBlt相同。但當圖像含有透明色或Alpha通道時,它的功能又和TransparentBlt、AlphaBlend相同。因此,在一般情況下,我們都應該盡量調用CImage::Draw方法來繪制圖像。
例如,下面的示例Ex_Image是實現這樣的功能:當選擇"文件"ò"打開"菜單命令后,彈出一個文件打開對話框。當選定一個圖像文件后,就會在窗口客戶區中顯示該圖像文件內容。這個示例的具體步驟如下:
(1) 創建一個默認的單文檔程序項目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函數處,添加下列代碼:
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文件,添加一個公共的成員數據m_Image:
public:
CImage m_Image;
(6) 編譯並運行。單擊"打開"工具按鈕,在彈出的對話框中指定一個圖像文件后,單擊"打開"按鈕,其結果如圖7.21所示。
將圖片用其它格式保存
CImage::Save方法能將一個圖像文件按另一種格式來保存,它的原型如下:
HRESULT Save( LPCTSTR pszFileName, REFGUID guidFileType= GUID_NULL);
其中,pszFileName用來指定一個文件名,guidFileType用來指定要保存的圖像文件格式,當為GUID_NULL時,其文件格式由文件的擴展名來決定,這也是該函數的默認值。它還可以是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時,其文件格式由文件的擴展名來決定,這也是該函數的默認值。它還可以是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::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+環境中,我們可以直接使用GDI+ ,沒多少必要再使用CImage類
但是,如果再GDI環境中,我們要想使用GDI+,有點麻煩,還得加入頭文件,加入啟動GDI+的代碼和關閉GDI+的代碼,顯得太羅嗦了,GDI 的CBitmap 處理功能又有局限,只能處理BMP格式的圖片。 怎么辦?這時,我們便可使用CImage類,因為這個類本身封裝了GDI+得使用環境,所以無需我們手動設置,簡化了我們的操作。 同時,又可以利用GDI+中強大的圖片處理功能,及可以簡便的與CBitmap對象進行轉換 ,大大方便了在GDI環境下,進行各種圖片處理工作 。
其實,將其稱作 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?
- // CImage可加載的圖片文件有JPG,BMP,TIF.PNG等格式 而CBitmap只能加載BMP圖片文件
- if(!PathFileExists(imgFilePath))
- return NULL;
- CImage nImage;
- nImage.Load(imgFilePath);
- return nImage.Detach(); //返回HBITMAP 可用CBitmap 處理 也可用CImage處理
2 與CBitmap轉換
[cpp] view plaincopyprint?
- CImage nImage;
- nImage.Load(imgFilePath);
- HBITMAP hBitmap=nImage.Detach(); // 獲得位圖句柄 用以轉換
- // 轉換方式一:
- CBitmap bmp;
- bmp.DeleteObject();
- bmp.Attach(hBitmap); // 轉換為CBitmap對象
- // 轉換方式二:
- CBitmap *pBitmap=CBitmap::FromHandle(nImage.m_hBitmap);
3 獲得CImage對象的cdc
[cpp] view plaincopyprint?
- CDC *pDC=CDC::FromHandle(nImage.GetDC());
- // Use pDC here
- nImage.ReleaseDC();
4 顯示位圖
思路: 將CImage對象 繪制在對應的DC中
所使用的函數 BitBlt StretchBlt Draw等
以Draw舉例:
[cpp] view plaincopyprint?
- BOOL Draw(
- HDC hDestDC,
- int xDest,
- int yDest,
- int nDestWidth,
- int nDestHeight,
- int xSrc,
- int ySrc,
- int nSrcWidth,
- int nSrcHeight
- ) const throw( );
- BOOL Draw(
- HDC hDestDC,
- const RECT& rectDest,
- const RECT& rectSrc
- ) const throw( );
- BOOL Draw(
- HDC hDestDC,
- int xDest,
- int yDest
- ) const throw( );
- BOOL Draw(
- HDC hDestDC,
- const POINT& pointDest
- ) const throw( );
- BOOL Draw(
- HDC hDestDC,
- int xDest,
- int yDest,
- int nDestWidth,
- int nDestHeight
- ) const throw( );
- BOOL Draw(
- HDC hDestDC,
- const RECT& rectDest
- ) const throw( );
Draw performs the same operation as StretchBlt, unless the image contains a transparent color or alpha channel. In that case,Draw performs 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?
- CImage img;
- img.Load("1.jpg");
- if (!img.IsNull())
- {
- img.Draw(pDC->m_hDC,CRect(0,0,100,100));
- }
EXAMPLE 2: 畫在另一個位圖中
[cpp] view plaincopyprint?
- CImage img;
- img.Load(filePath);
- // 獲得CImage對象的 CDC
- HDC hDC=img.GetDC();
- CDC *pDC=CDC::FromHandle(hDC);
- CBitmap bmp;// 只是創建了位圖對象,但還沒有將位圖對象與位圖資源聯系起來
- bmp.CreateCompatibleBitmap(pDC,nWidth,nHeight); // 創建新的位圖資源
- CDC memDC;
- memDC.CreateCompatibleDC(pDC);
- CBitmap *pOld=memDC.SelectObject(&bmp);
- // 將img圖像繪制到bmp中
- ::SetStretchBltMode(memDC.m_hDC,HALFTONE);
- ::SetBrushOrgEx(memDC.m_hDC,0,0,NULL);
- img.StretchBlt(memDC.m_hDC,CRect(0,0,nWidth,nHeight)/*DestRect*/,CRect(0,0,nWidth,nHeight)/*SourceRect*/,SRCCOPY);
- HBITMAP hBitmap=(HBITMAP)memDC.SelectObject(pOld->m_hObject); // 獲得新創建的位圖資源句柄
- img.ReleaseDC();
5 將位圖資源與對象進行分離
[cpp] view plaincopyprint?
- inline HBITMAP CImage::Detach() throw()
- {
- HBITMAP hBitmap;
- ATLASSUME( m_hBitmap != NULL );
- ATLASSUME( m_hDC == NULL );
- hBitmap = m_hBitmap;
- m_hBitmap = NULL;
- m_pBits = NULL;
- m_nWidth = 0;
- m_nHeight = 0;
- m_nBPP = 0;
- m_nPitch = 0;
- m_iTransparentColor = -1;
- m_bHasAlphaChannel = false;
- m_bIsDIBSection = false;
- return( hBitmap );
- }
6 釋放資源
CBitmap 使用DeleteObject()來主動釋放掉位圖資源
CImage 沒有DeleteObject()函數 ,而是用Destroy()函數來主動釋放位圖資源
[cpp] view plaincopyprint?
- inline void CImage::Destroy() throw()
- {
- HBITMAP hBitmap;
- if( m_hBitmap != NULL )
- {
- hBitmap = Detach();
- ::DeleteObject( hBitmap ); //釋放位圖資源
- }
- }
CBitmap 析構時,會自動釋放掉所占用的位圖資源
CImage 析構時,也會自動釋放掉所占用的位圖資源
[cpp] view plaincopyprint?
- inline CImage::~CImage() throw()
- {
- Destroy(); //釋放掉所占用的位圖資源
- s_initGDIPlus.DecreaseCImageCount();
- }
7 讀寫圖像數據
主要用到3個函數 :
1 )GetBits() 獲得數據區的指針
Retrieves a pointer to the actual bit values of a given pixel in a bitmap.
void* GetBits( ) throw( );
[cpp] view plaincopyprint?
- inline void* CImage::GetBits() throw()
- {
- ATLASSUME( m_hBitmap != NULL );
- ATLASSERT( IsDIBSection() );
- return( m_pBits );
- }
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()取得的指針不一定是圖片數據的起始行,必須結合GetPitch()的值來確定起始行位置
2)GetPitch()
[cpp] view plaincopyprint?
- inline int CImage::GetPitch() const throw()
- {
- ATLASSUME( m_hBitmap != NULL );
- ATLASSERT( IsDIBSection() );
- return( m_nPitch );
- }
獲得圖像數據每一行的字節數
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()獲得的指針指向第一行
圖像數據首行地址:
[cpp] view plaincopyprint?
- BYTE *pData=NULL;
- if(img.GetPitch()<0)
- pData=(BYTE*)img.GetBits()+(img.GetPitch()*(img.GetHeight()-1));
- else
- pData=(BYTE*)img.GetBits();
或
[cpp] view plaincopyprint?
- BYTE *pData=NULL;
- if(img.GetPitch()<0)
- pData=(BYTE *)img.GetPixelAddress(img.GetHeight()-1,0);
- else
- pData=(BYTE *)img.GetPixelAddress(0,0);
3)GetBPP() 返回每個像素所占的bit數
[cpp] view plaincopyprint?
- inline int CImage::GetBPP() const throw()
- {
- ATLASSUME( m_hBitmap != NULL );
- return( m_nBPP );
- }
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?
- void CMyImage::Negatives(void)
- {
- int i, j;
- //圖像每一行的字節數
- int nRowBytes = GetPitch();
- int nWidth = GetWidth();
- int nHeight = GetHeight();
- //每個像素所占的字節數
- int nClrCount = GetBPP() / 8;
- LPBYTE p;
- for(int index = 0; index < nClrCount; index++)
- {
- p = (LPBYTE)GetBits();
- for(i = 0; i < nHeight; i++)
- {
- for(j = 0; j < nWidth; j++)
- {
- p[j*nClrCount + index] = 255 - p[j*nClrCount + index];
- }
- //如果nRowBytes>0 則從開始到結尾
- //如果nRowBytes<0, 則從結尾到開始
- p += nRowBytes;
- }
- }
- }
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?
- inline HRESULT CImage::Save( LPCTSTR pszFileName, REFGUID guidFileType ) const throw()
- {
- if( !InitGDIPlus() )
- {
- return( E_FAIL );
- }
- UINT nEncoders;
- UINT nBytes;
- Gdiplus::Status status;
- status = Gdiplus::GetImageEncodersSize( &nEncoders, &nBytes );
- if( status != Gdiplus::Ok )
- {
- return( E_FAIL );
- }
- USES_CONVERSION_EX;
- Gdiplus::ImageCodecInfo* pEncoders = static_cast< Gdiplus::ImageCodecInfo* >( _ATL_SAFE_ALLOCA(nBytes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) );
- if( pEncoders == NULL )
- return E_OUTOFMEMORY;
- status = Gdiplus::GetImageEncoders( nEncoders, nBytes, pEncoders );
- if( status != Gdiplus::Ok )
- {
- return( E_FAIL );
- }
- CLSID clsidEncoder = CLSID_NULL;
- if( guidFileType == GUID_NULL )
- {
- // Determine clsid from extension
- clsidEncoder = FindCodecForExtension( ::PathFindExtension( pszFileName ), pEncoders, nEncoders );
- }
- else
- {
- // Determine clsid from file type
- clsidEncoder = FindCodecForFileType( guidFileType, pEncoders, nEncoders );
- }
- if( clsidEncoder == CLSID_NULL )
- {
- return( E_FAIL );
- }
- LPCWSTR pwszFileName = T2CW_EX( pszFileName, _ATL_SAFE_ALLOCA_DEF_THRESHOLD );
- #ifndef _UNICODE
- if( pwszFileName == NULL )
- return E_OUTOFMEMORY;
- #endif // _UNICODE
- if( m_bHasAlphaChannel )
- {
- ATLASSUME( m_nBPP == 32 );
- Gdiplus::Bitmap bm( m_nWidth, m_nHeight, m_nPitch, PixelFormat32bppARGB, static_cast< BYTE* >( m_pBits ) );
- status = bm.Save( pwszFileName, &clsidEncoder, NULL );
- if( status != Gdiplus::Ok )
- {
- return( E_FAIL );
- }
- }
- else
- {
- Gdiplus::Bitmap bm( m_hBitmap, NULL );
- status = bm.Save( pwszFileName, &clsidEncoder, NULL );
- if( status != Gdiplus::Ok )
- {
- return( E_FAIL );
- }
- }
- return( S_OK );
- }
- pStream
-
A pointer to a stream containing the file name for the image.
- pszFileName
-
A pointer to the file name for the image.
- guidFileType
-
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?
- Copy Code
- // Demonstrating saving various file formats
- int _tmain(int argc, _TCHAR* argv[])
- {
- CImage myimage;
- // load existing image
- myimage.Load("image.bmp");
- // save an image in BMP format
- myimage.Save("c:\image1.bmp");
- // save an image in BMP format
- myimage.Save("c:\image2",ImageFormatBMP);
- // save an image in JPEG format
- myimage.Save("c:\image3.jpg");
- // save an image in BMP format, even though jpg file extension is used
- myimage.Save("c:\image4.jpg",ImageFormatBMP);
- return 0;
- }
9 應用實例: 將兩個圖像合並為一個新的圖像
[cpp] view plaincopyprint?
- //圖像路徑
- CString img1Path;
- CString img2Path;
- CString img3Path;
- img1Path=_T("1.bmp");
- img2Path=_T("2.bmp");
- img3Path=_T("3.bmp"); // 將 圖片1、2 合並成圖片3
- CImage img1,img2,img3;
- img1.Load(img1Path);
- img2.Load(img2Path);
- CBitmap bmp;
- CDC memDC;
- HDC hDC=NULL;
- CDC *pDC=NULL;
- CBitmap *pOld=NULL;
- HBITMAP hBitmap=NULL;
- //創建位圖
- hDC=img1.GetDC();
- pDC=CDC::FromHandle(hDC);
- bmp.DeleteObject();
- bmp.CreateCompatibleBitmap(pDC,img1.GetWidth()/2,img1.GetHeight());
- memDC.DeleteDC();
- memDC.CreateCompatibleDC(pDC);
- pOld=memDC.SelectObject(&bmp);
- ::SetStretchBltMode(memDC.m_hDC,HALFTONE);
- ::SetBrushOrgEx(memDC.m_hDC,0,0,NULL);
- // 背景置白色
- CRgn rectRgn;
- rectRgn.CreateRectRgn(0,0,img1.GetWidth()/2,img1.GetHeight());
- CBrush brush;
- brush.CreateSolidBrush(RGB(255,255,255));
- memDC.FillRgn(&rectRgn,&brush);
- //畫圖
- img1.StretchBlt(memDC.m_hDC,CRect(0,0,img1.GetWidth()/2,img1.GetHeight()/2),CRect(0,0,img1.GetWidth(),img1.GetHeight()),SRCCOPY);
- img2.StretchBlt(memDC.m_hDC,CRect(0,img1.GetHeight()/2,img1.GetWidth()/2,img1.GetHeight()),CRect(0,0,img2.GetWidth(),img2.GetHeight()),SRCCOPY);
- hBitmap=(HBITMAP)memDC.SelectObject(pOld->m_hObject);
- img3.Attach(hBitmap);// 載入位圖資源
- img3.Save(img3Path); // 保存新的位圖
- img1.ReleaseDC();
- img1.Destroy();
- img2.Destroy();
- img3.Destroy();