CImage类

来源:互联网 发布:口袋妖怪配信数据导入 编辑:程序博客网 时间:2024/04/29 03:40

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才能正常使用。

 

源于:

http://msdn.microsoft.com/zh-cn/library/bwea7by5(VS.80).aspx

 

http://blog.sina.com.cn/s/print_4e24fcb801008u5z.html

 

 

CImage 类的成员

最近常用CImage类,所以把他的类成员写出来,方便查询。
CImage 成员
操作符
operator HBITMAP返回绑定到CImage对象的Windows句柄.

Construction

CImage构造函数.

Operations

AlphaBlend

Displays bitmaps that have transparent or semitransparent pixels.    

显示包含透明或半透明像素的位图。

Attach

Attaches an HBITMAP to a CImage object. Can be used with either non-DIB section bitmaps or DIB section bitmaps.

将一个HBITMAP绑定到一个CImage对象。既可以用于DIB类型位图也可以用于非DIB类型位图。

BitBlt

Copies a bitmap from the source device context to this current device context.

从源设备描述表复制位图到当前设备描述表。

Create

Creates a DIB section bitmap and attaches it to the previously constructedCImage object.

创建一个DIB类型位图并将它绑定到前边构造好的CImage对象。

CreateEx

Creates a DIB section bitmap (with additional parameters) and attaches it to the previously constructed CImage object.

创建一个DIB类型的位图(使用额外的参数)并将它绑定到前边构造好的CImage对象。

Destroy

Detaches the bitmap from the CImage object and destroys the bitmap.

解除位图和CImage对象的绑定并销毁位图。

Detach

Detaches the bitmap from a CImage object.

解除位图和CImage对象的绑定。

Draw

Copies a bitmap from a source rectangle into a destination rectangle. Drawstretches or compresses the bitmap to fit the dimensions of the destination rectangle, if necessary, and handles alpha blending and transparent colors.

从源矩形区域复制一个位图到目标矩形区域。Draw拉伸或压缩位图以适应目标矩形区域的尺寸,如果必要,将处理alpha混合和透明色。

GetBits

Retrieves a pointer to the actual pixel values of the bitmap.

得到指向位图一个实际像素值的指针。

GetBPP

Retrieves the bits per pixel.

得到每个像素的比特位。

GetColorTable

Retrieves red, green, blue (RGB) color values from a range of entries in the color table.

从颜色表中的入口范围得到红,绿,蓝(RGB)颜色值。

GetDC

Retrieves the device context into which the current bitmap is selected.

得到选入当前位图的设备描述表。

GetExporterFilterString

Finds the available image formats and their descriptions.

获得可用的图像格式和描述。

GetImporterFilterString

Finds the available image formats and their descriptions.

获得可用的图像格式和描述。

GetHeight

Retrieves the height of the current image in pixels.

得到当前图像高度的像素值。

GetMaxColorTableEntries

Retrieves the maximum number of entries in the color table.

得到颜色表中入口的最大值。

GetPitch

Retrieves the pitch of the current image, in bytes.

得到代表目前图像斜度的字节数。

GetPixelAddress

Retrieves the address of a given pixel.

得到给定像素的地址。

GetPixel

Retrieves the color of the pixel specified by x and y.

得到指定x和y的像素的颜色。

GetTransparentColor

Retrieves the position of the transparent color in the color table.

得到颜色表中透明色的位置。

GetWidth

Retrieves the width of the current image in pixels.

得到当前图像宽度的像素值。

IsDibSection

Determines if the attached bitmap is a DIB section.

判断绑定的位图是否是DIB类型。

IsIndexed

Indicates that a bitmap's colors are mapped to an indexed palette.

表明位图的颜色映射到一个索引的调色板。

IsNull

Indicates if a source bitmap is currently loaded.

表明源位图当前是否装载。

IsTransparencySupported

Indicates whether the application supports transparent bitmaps and was compiled for Windows 2000 or later.

表明应用程序是否支持透明位图并为Windows 2000及以后版本编译。

LoadFromResource

Loads an image from the specified resource.

从指定的资源装载一个图像。

Load

Loads an image from the specified file.

从指定的文件装载一个图像。

MaskBlt

Combines the color data for the source and destination bitmaps using the specified mask and raster operation.

使用指定的掩码和栅格操作混合源位图和目标位图的颜色数据。

PlgBlt

Performs a bit-block transfer from a rectangle in a source device context into a parallelogram in a destination device context.

实现从一个源设备描述表传送一个比特块到目标设备描述表的一个平行四边形区域。

ReleaseDC

Releases the device context that was retrieved with CImage::GetDC.

释放用CImage::GetDC得到的设备描述表。

ReleaseGDIPlus

Releases resources used by GDI+. Must be called to free resources created by a global CImage object.

释放GDI+使用的资源。必须调用以便释放由全局CImage对象创建的资源。

Save

Saves an image as the specified type. Save cannot specify image options.

用指定的类型保存图像。Save不能指定图像选项。

SetColorTable

Sets red, green, blue RGB) color values in a range of entries in the color table of the DIB section.

设置DIB类型颜色表中入口范围的红,绿,蓝(RGB)颜色值。

SetPixelIndexed

Sets the pixel at the specified coordinates to the color at the specified index of the palette.

设置指定坐标的像素为调色板中指定索引的颜色值。

SetPixelRGB

Sets the pixel at the specified coordinates to the specified red, green, blue (RGB) value.

设置指定坐标的像素为指定的红,绿,蓝(RGB)值。

SetPixel

Sets the pixel at the specified coordinates to the specified color.

设置指定坐标的像素为指定的颜色值。

SetTransparentColor

Sets the index of the color to be treated as transparent. Only one color in a palette can be transparent.

设置被作为透明色处理的颜色的索引值。

StretchBlt

Copies a bitmap from a source rectangle into a destination rectangle, stretching or compressing the bitmap to fit the dimensions of the destination rectangle, if necessary.

从源矩形区域复制一个位图到目标矩形区域,如果必要,将拉伸或压缩位图以适应目标矩形区域的尺寸。

TransparentBlt

Copies a bitmap with transparent color from the source device context to this current device context.

从源设备描述表复制一个带透明色的位图到当前设备描述表。

 

使用CImage的一般方法

  使用CImage的一般方法是这样的过程:

  (1) 打开应用程序的stdafx.h文件添加CImage类的包含文件:

[cpp] view plaincopy
  1. #include <atlimage.h>  

  (2) 定义一个CImage类对象,然后调用CImage::Load方法装载一个外部图像文件。

  (3) 调用CImage::Draw方法绘制图像。Draw方法具有如下定义:

 

[cpp] view plaincopy
  1. BOOL Draw( HDC hDestDC, int xDest, int yDest,  
  2. int nDestWidth, int nDestHeight, int xSrc, int ySrc,  
  3. int nSrcWidth, int nSrcHeight );  
  4. BOOL Draw( HDC hDestDC, const RECT& rectDest, const RECT& rectSrc );  
  5. BOOL Draw( HDC hDestDC, int xDest, int yDest );  
  6. BOOL Draw( HDC hDestDC, const POINT& pointDest );  
  7. BOOL Draw( HDC hDestDC, int xDest, int yDest,  
  8. int nDestWidth, int nDestHeight );  
  9. 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事件映射程序,并添加下列代码:

 

[cpp] view plaincopy
  1. void CEx_ImageView::OnFileOpen()  
  2. {  
  3.     CString strFilter;  
  4.     CSimpleArray<GUID> aguidFileTypes;  
  5.     HRESULT hResult;  
  6.       
  7.     // 获取CImage支持的图像文件的过滤字符串  
  8.     hResult = m_Image.GetExporterFilterString(strFilter,aguidFileTypes,  
  9.         _T( "All Image Files") );  
  10.     if (FAILED(hResult))   
  11.     {  
  12.         MessageBox("GetExporterFilter调用失败!");  
  13.         return;  
  14.     }  
  15.     CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);  
  16.     if(IDOK != dlg.DoModal())   
  17.         return;  
  18.       
  19.     m_Image.Destroy();  
  20.     // 将外部图像文件装载到CImage对象中  
  21.     hResult = m_Image.Load(dlg.GetFileName());  
  22.     if (FAILED(hResult))   
  23.     {  
  24.         MessageBox("调用图像文件失败!");  
  25.         return;  
  26.     }  
  27.       
  28.     // 设置主窗口标题栏内容  
  29.     CString str;  
  30.     str.LoadString(AFX_IDS_APP_TITLE);  
  31.     AfxGetMainWnd()->SetWindowText(str + " - " +dlg.GetFileName());  
  32.       
  33.     Invalidate(); // 强制调用OnDraw  
  34. }  

  (4) 定位到CEx_ImageView::OnDraw函数处,添加下列代码:

 

[cpp] view plaincopy
  1. void CEx_ImageView::OnDraw(CDC* pDC)  
  2. {  
  3.     CEx_ImageDoc* pDoc = GetDocument();  
  4.     ASSERT_VALID(pDoc);  
  5.     if (!m_Image.IsNull())   
  6.     {  
  7.         m_Image.Draw(pDC->m_hDC,0,0);  
  8.     }  
  9. }  

  (5) 打开Ex_ImageView.h文件,添加一个公共的成员数据m_Image:

 

[cpp] view plaincopy
  1. public:  
  2.     CImage m_Image;  


  (6) 编译并运行。单击"打开"工具按钮,在弹出的对话框中指定一个图像文件后,单击"打开"按钮,其结果如图7.21所示。

将图片用其它格式保存

  CImage::Save方法能将一个图像文件按另一种格式来保存,它的原型如下:

[cpp] view plaincopy
  1. 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事件映射程序,并添加下列代码:
[cpp] view plaincopy
  1. void CEx_ImageView::OnFileSaveAs()  
  2. {  
  3.     if (m_Image.IsNull())   
  4.     {  
  5.         MessageBox("你还没有打开一个要保存的图像文件!");  
  6.         return;  
  7.     }  
  8.       
  9.     CString strFilter;  
  10.     strFilter = "位图文件|*.bmp|JPEG 图像文件|*.jpg| /  
  11.         GIF 图像文件|*.gif|PNG 图像文件|*.png||";  
  12.     CFileDialog dlg(FALSE,NULL,NULL,NULL,strFilter);  
  13.     if ( IDOK != dlg.DoModal())   
  14.         return;  
  15.       
  16.     // 如果用户没有指定文件扩展名,则为其添加一个  
  17.     CString strFileName;  
  18.     CString strExtension;  
  19.       
  20.     strFileName = dlg.m_ofn.lpstrFile;  
  21.     if (dlg.m_ofn.nFileExtension == 0)   
  22.     {  
  23.         switch (dlg.m_ofn.nFilterIndex)  
  24.         {  
  25.         case 1:  
  26.             strExtension = "bmp"break;  
  27.         case 2:  
  28.             strExtension = "jpg"break;  
  29.         case 3:  
  30.             strExtension = "gif"break;  
  31.         case 4:  
  32.             strExtension = "png"break;  
  33.         default:  
  34.             break;  
  35.         }  
  36.         strFileName = strFileName + '.' + strExtension;  
  37.     }  
  38.       
  39.     // 图像保存  
  40.     HRESULT hResult = m_Image.Save(strFileName);  
  41.     if (FAILED(hResult))   
  42.         MessageBox("保存图像文件失败!");  
  43. }  

将图片用其它格式保存

  CImage::Save方法能将一个图像文件按另一种格式来保存,它的原型如下:

[cpp] view plaincopy
  1. 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事件映射程序,并添加下列代码:
[cpp] view plaincopy
  1. void CEx_ImageView::OnFileSaveAs()  
  2. {  
  3.     if (m_Image.IsNull())   
  4.     {  
  5.         MessageBox("你还没有打开一个要保存的图像文件!");  
  6.         return;  
  7.     }  
  8.       
  9.     CString strFilter;  
  10.     strFilter = "位图文件|*.bmp|JPEG 图像文件|*.jpg| /  
  11.         GIF 图像文件|*.gif|PNG 图像文件|*.png||";  
  12.     CFileDialog dlg(FALSE,NULL,NULL,NULL,strFilter);  
  13.     if ( IDOK != dlg.DoModal())   
  14.         return;  
  15.       
  16.     // 如果用户没有指定文件扩展名,则为其添加一个  
  17.     CString strFileName;  
  18.     CString strExtension;  
  19.       
  20.     strFileName = dlg.m_ofn.lpstrFile;  
  21.     if (dlg.m_ofn.nFileExtension == 0)   
  22.     {  
  23.         switch (dlg.m_ofn.nFilterIndex)  
  24.         {  
  25.         case 1:  
  26.             strExtension = "bmp"break;  
  27.         case 2:  
  28.             strExtension = "jpg"break;  
  29.         case 3:  
  30.             strExtension = "gif"break;  
  31.         case 4:  
  32.             strExtension = "png"break;  
  33.         default:  
  34.             break;  
  35.         }  
  36.         strFileName = strFileName + '.' + strExtension;  
  37.     }  
  38.       
  39.     // 图像保存  
  40.     HRESULT hResult = m_Image.Save(strFileName);  
  41.     if (FAILED(hResult))   
  42.         MessageBox("保存图像文件失败!");  
  43. }  

变成黑白图片

  由于许多图像文件使用颜色表来发挥显示设备的色彩显示能力,因而将一张彩色图片变成黑色图片时需要调用CImage::IsIndexed来判断是否使用颜色表,若是则修改颜色表,否则直接将像素进行颜色设置。例如下面的代码:
[cpp] view plaincopy
  1. void CEx_ImageView::MakeBlackAndwhite(CImage* image)  
  2. {  
  3.     if (image->IsNull()) return;  
  4.       
  5.     if (!image->IsIndexed())  
  6.     {  
  7.         // 直接修改像素颜色  
  8.         COLORREF pixel;  
  9.         int maxY = image->GetHeight(), maxX = image->GetWidth();  
  10.         byte r,g,b,avg;  
  11.         for (int x=0; x<maxX; x++)   
  12.         {  
  13.             for (int y=0; y<maxY; y++)  
  14.             {  
  15.                 pixel = image->GetPixel(x,y);  
  16.                 r = GetRValue(pixel);  
  17.                 g = GetGValue(pixel);  
  18.                 b = GetBValue(pixel);  
  19.                 avg = (int)((r + g + b)/3);  
  20.                 image->SetPixelRGB(x,y,avg,avg,avg);  
  21.             }  
  22.         }  
  23.     }   
  24.     else   
  25.     {  
  26.         // 获取并修改颜色表  
  27.         int MaxColors = image->GetMaxColorTableEntries();  
  28.         RGBQUAD* ColorTable;  
  29.         ColorTable = new RGBQUAD[MaxColors];  
  30.         image->GetColorTable(0,MaxColors,ColorTable);  
  31.         for (int i=0; i<MaxColors; i++)  
  32.         {  
  33.             int avg = (ColorTable[i].rgbBlue + ColorTable[i].rgbGreen + ColorTable[i].rgbRed)/3;  
  34.             ColorTable[i].rgbBlue = avg;  
  35.             ColorTable[i].rgbGreen = avg;  
  36.             ColorTable[i].rgbRed = avg;  
  37.         }  
  38.         image->SetColorTable(0,MaxColors,ColorTable);  
  39.         delete(ColorTable);  
  40.     }  
  41. }  

  至此,我们介绍了GDI+和CImage的一般使用方法和技巧。当然,它们本身还有许多更深入的方法,由于篇幅所限,这里不再一一讨论。

原创粉丝点击