基于VC.NET的GDI 编程之CImage(VC图像处理新招)
我们知道,Visual C++的CBitmap类和静态图片控件的功能
是比较弱的,它只能显示出在资源中的图标、位图、光标以
及图元文件的内容,而不像VB中的Image控件可以显示出绝
大多数的外部图像文件(BMP、GIF、JPEG等)。因此,想要在
对话框或其他窗口中显示外部图像文件则只能借助于第三方
提供的控件或代码。现在,MFC和ATL共享的新类CImage为图
像处理提供了许多相应的方法,这使得Visual C++在图像方
面的缺憾一去不复返了。
CImage类概述
CImage是MFC和ATL共享的新类,它能从外部磁盘中调入
一个JPEG、GIF、BMP和PNG格式的图像文件加以显示,而且
这些文件格式可以相互转换。由于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封装了DIB(设备无关位图)的功能,因而可以让
我们能够处理每个位图像素。它具有下列最酷特性:
1、AlphaBlend支持像素级的颜色混合,从而实现透明
和半透明的效果。
2、PlgBlt能使一个矩形区域的位图映射到一个平行四
边形区域中,而且还可能使用位屏蔽操作。
3、TransparentBlt在目标区域中产生透明图像
,SetTransparentColor用来设置某种颜色是透明色。
4、MaskBlt在目标区域中产生源位图与屏蔽位图合成的
效果。
使用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,aguidFileT
ypes,
_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("保存图像文件失败!");
}
柔化和锐化处理
在图像处理中,我们通常用一些数学手段,对图像进行
除去噪声、强调或抽取轮廓特征等图像空间的变换。所谓
"图像空间的变换"是借助于一个称之为模板的局部像素域来
完成的,不同的模板具有不同的图像效果。
1. 柔化
图像的柔化是除去图像中点状噪声的一个有效方法。所
谓柔化,是指使图像上任何一个像素与其相邻像素的颜色值
的大小不会出现陡突的一种处理方法。设在一个3 x 3的模
板中其系数为:
中间有底纹的表示中心元素,即用那个元素作为处理后
的元素。很明显,上述模板(称之为Box模板)是将图像上每
个像素用它近旁(包括它本身)的9个像素的平均值取代。这
样处理的结果在除噪的同时,也降低图像的对比度,使图像
的轮廓模糊。为了避免这一缺陷,我们对各点引入加权系数
,将原来的模板改为:
新的模板可一方面除去点状噪声,同时能较好地保留原
图像的对比度,因此该模板得到了广泛的应用。由于这个模
板是通过二维高斯(Gauss)函数得到的,故称为高斯模板。
2. 锐化
锐化和柔化恰恰相反,它通过增强高频分量减少图像中
的模糊,因此又称为高通滤波。锐化处理在增强图像边缘效
果的同时增加了图像的噪声。常用的锐化模板是拉普拉斯模
板:
用此模板处理后的图像,轮廓线条将明显得到增强。轮
廓线以外的部分将变得较暗,而轮廓线部分将变得比较明亮
。
使用程序对模板进行运算时,要考虑到溢出点的处理。
所谓溢出点,指的是大于255或小于0的点。处理时,可令大
于255的点取255,而小于0的点取其正值。
3. 实现代码
实现柔化和锐化时,我们先调用CImage::GetPixel来依
次读取相应的像素,然后用柔化和锐化模板进行处理,最后
调用CImage::SetPixel函数将处理后的像素写回到CImage对
象中。具体的代码如下:
void FilterImage(CImage* image, int nType)
{
if (image->IsNull())
return;
int smoothGauss[9] = {1,2,1,2,4,2,1,2,1}; // 高斯
模板
int sharpLaplacian[9] = {-1,-1,-1,-1,9,-1,-1,-1,-
1}; // 拉普拉斯模板
int opTemp[9];
float aver; // 系数
if ( nType > 1) nType = 0;
switch( nType ){
case 0: // 高斯模板
aver = (float)(1.0/16.0);
memcpy( opTemp, smoothGauss, 9*sizeof(int));
break;
case 1: // 拉普拉斯模板
aver = 1.0;
memcpy( opTemp, sharpLaplacian,
9*sizeof(int));
break;
}
int i,j;
int nWidth = image->GetWidth();
int nHeight = image->GetHeight();
for (i = 1; i < nWidth-1; i++){
for (j = 1; j < nHeight-1; j++){
int rr = 0, gg = 0, bb = 0;
int index = 0;
for (int col = -1; col <= 1; col++){
for (int row = -1; row <= 1; row++){
COLORREF clr = image->GetPixel( i+row,
j+col);
rr += GetRValue(clr) * opTemp[index];
gg += GetGValue(clr) * opTemp[index];
bb += GetBValue(clr) * opTemp[index];
index++;
}
}
rr = (int)(rr*aver);
gg = (int)(gg*aver);
bb = (int)(bb*aver);
// 处理溢出点
if ( rr > 255 ) rr = 255;
else if ( rr < 0 ) rr = -rr;
if ( gg > 255 ) gg = 255;
else if ( gg < 0 ) gg = -gg;
if ( bb > 255 ) bb = 255;
else if ( bb < 0 ) bb = -bb;
// 错位重写以避免前一个像素被新的像素覆盖
image->SetPixel( i-1, j-1, RGB(rr,gg,bb));
}
}
}
图7.22是使用上述代码将某个图像处理后的结果。
变成黑白图片
由于许多图像文件使用颜色表来发挥显示设备的色彩显
示能力,因而将一张彩色图片变成黑色图片时需要调用
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);
}
}
至此,我们介绍了GDI+和CImage的一般使用方法和技巧
。当然,它们本身还有许多更深入的方法,由于篇幅所限
,这里不再一一讨论。
下面列出Ciamge的相关函数:
CImage Members
Operators
operator HBITMAP
Returns the Windows handle attached to the CImage
object.
Construction
CImage
The constructor.
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.
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 constructed CImage object.
CreateEx
Creates a DIB section bitmap (with additional
parameters) and attaches it to the previously
constructed CImage object.
Destroy
Detaches the bitmap from the CImage object and
destroys the bitmap.
Detach
Detaches the bitmap from a CImage object.
Draw
Copies a bitmap from a source rectangle into a
destination rectangle. Draw stretches or compresses
the bitmap to fit the dimensions of the destination
rectangle, if necessary, and handles alpha blending
and transparent colors.
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.
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.
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.
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.
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.
ReleaseGDIPlus
Releases resources used by GDI+. Must be called to
free resources created by a global CImage object.
Save
Saves an image as the specified type. Save cannot
specify image options.
SetColorTable
Sets red, green, blue RGB) color values in a range
of entries in the color table of the DIB section.
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.
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.
本文档为【基于VC.NET的GDI 编程之CImage】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。