CImage的学习

CImage的学习程序代码下载处 http download csdn net source 2098910 下载处 http hi baidu com wangleitongx blog item 9063b03e5e20 html 备注 这个程序是在 xp 系统 vs2008 下做的 当初测试没出什么问题 昨天 2014 11 11 我下了程序在 win7 下面测试 出现了评

程序代码下载处:http://download.csdn.net/source/

下载处:http://hi.baidu.com/wangleitongxing/blog/item/9063b03e5e20f3c97c1e71c8.html

备注:这个程序是在xp系统,vs2008下做的,当初测试没出什么问题。

昨天(2014-11-11)我下了程序在win7下面测试,出现了评论里说的问题,解决方法我已经写在评论里面了。主要是因为路径的问题。大家参照着修改测下应该就没问题了。

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)在view类中添加成员变量CImage m_Image;

CEx_ImageView类添加ID_FILE_OPEN的COMMAND事件映射程序,并添加下列代码:

程序代码:

voidCEx_ImageView::OnFileOpen()//Cyan:添加

{

    // TODO: 在此添加命令处理程序代码

    CString strFilter;

    CSimpleArray<GUID>aguidFileTypes;

    HRESULT hResult;  //获取CImage支持的图像文件的过滤字符串

    hResult=m_Image.GetExporterFilterString(strFilter,aguidFileTypes,_T(“All Image Files”));

    if(FAILED(hResult))

    {

        MessageBox(_T(“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(_T(调用图像文件失败!”));

        return;

    }

    //设置主窗口标题栏内容

    CString str;

    str.LoadString(AFX_IDS_APP_TITLE);

    AfxGetMainWnd()->SetWindowTextW(str+_T(“-“)+dlg.GetFileName());

    Invalidate();//强制调用OnDraw函数

}

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

程序代码:

voidCEx_ImageView::OnDraw(CDC*pDC)

{

    CEx_ImageDoc* pDoc = GetDocument();

    ASSERT_VALID(pDoc);

    //if (!pDoc)

        //return;

    // TODO: 在此处为本机数据添加绘制代码

    // Cyan:添加

    if(!m_Image.IsNull())

    {

        m_Image.Draw(pDC->m_hDC,0,0);

    }

}

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

程序代码:

public:   CImage m_Image;(Cyan:我觉得设置成私有成员比较好)

 (6)编译并运行。单击”打开”工具按钮,在弹出的对话框中指定一个图像文件后,单击”打开”按钮。

将图片用其它格式保存

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事件映射程序,并添加下列代码:

程序代码:

voidCEx_ImageView::OnFileSaveAs()  //Cyan:添加

{

    // TODO: 在此添加命令处理程序代码

    if(m_Image.IsNull())

    {

        MessageBox(_T(请打开要另存的图像!”));

        return;

    }

    CString strFilter;

    strFilter=“bmp位图文件|*.bmp|JPEG图像文件|*.jpg|GIF图像文件|*.gif|PNG图像文件|*.png||”;

    CFileDialog dlg(FALSE,NULL,NULL,NULL,strFilter);

    if(IDOK!=dlg.DoModal())

        return;

    //如果没有指定文件扩展名,则为其添加一个

    CString strFileName,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+_T(“.”)+strExtension;

    }

    //图像保存

    HRESULT hResult=m_Image.Save(strFileName);

    if(FAILED(hResult))

    {

        MessageBox(_T(保存图像文件失败!”));

    }

}

彩色图像转换成灰度图像

由于许多图像文件使用颜色表来发挥显示设备的色彩显示能力,因而将一张彩色图片变成黑色图片时需要调用CImage::IsIndexed来判断是否使用颜色表,若是则修改颜色表,否则直接将像素进行颜色设置。例如下面的代码:

程序代码:

voidCEx_ImageView::OnToGray()//Cyan:添加

{

    // TODO: 在此添加命令处理程序代码

    if(m_Image.IsNull())

        return;

    if(!m_Image.IsIndexed())

    {

        //直接修改像素颜色

        COLORREF pixel;

        int maxY=m_Image.GetHeight();

        int maxX=m_Image.GetWidth();

        byte r,g,b,avg;

        for(int x=0;x<maxX;x++)

        {

             for(int y=0;y<maxY;y++)

             {

                  pixel=m_Image.GetPixel(x,y);

                  r=GetRValue(pixel);

                  g=GetGValue(pixel);

                  b=GetBValue(pixel);

                  avg=(int)(((int)r+g+b)/3);

                  m_Image.SetPixelRGB(x,y,avg,avg,avg);

             }       

        }

    }

    else

    {

        //获取并修改颜色表

        int maxColors=m_Image.GetMaxColorTableEntries();

        RGBQUAD* lpColorTable;

        lpColorTable=newRGBQUAD[maxColors];

        m_Image.GetColorTable(0,maxColors,lpColorTable);

        for(int i=0;i<maxColors;i++)

        {

             int avg=(lpColorTable[i].rgbRed+lpColorTable[i].rgbGreen+lpColorTable[i].rgbBlue)/3;

             lpColorTable[i].rgbRed=avg;

             lpColorTable[i].rgbGreen=avg;

             lpColorTable[i].rgbBlue=avg;

        }

        m_Image.SetColorTable(0,maxColors,lpColorTable);

        delete(lpColorTable);

    }

    Invalidate();//强制调用OnDraw

} 

程序代码下载处:http://download.csdn.net/source/

下载处:http://hi.baidu.com/wangleitongxing/blog/item/9063b03e5e20f3c97c1e71c8.html

备注:这个程序是在xp系统,vs2008下做的,当初测试没出什么问题。

昨天(2014-11-11)我下了程序在win7下面测试,出现了评论里说的问题,解决方法我已经写在评论里面了。主要是因为路径的问题。大家参照着修改测下应该就没问题了。

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)在view类中添加成员变量CImage m_Image;

CEx_ImageView类添加ID_FILE_OPEN的COMMAND事件映射程序,并添加下列代码:

程序代码:

voidCEx_ImageView::OnFileOpen()//Cyan:添加

{

    // TODO: 在此添加命令处理程序代码

    CString strFilter;

    CSimpleArray<GUID>aguidFileTypes;

    HRESULT hResult;  //获取CImage支持的图像文件的过滤字符串

    hResult=m_Image.GetExporterFilterString(strFilter,aguidFileTypes,_T(“All Image Files”));

    if(FAILED(hResult))

    {

        MessageBox(_T(“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(_T(调用图像文件失败!”));

        return;

    }

    //设置主窗口标题栏内容

    CString str;

    str.LoadString(AFX_IDS_APP_TITLE);

    AfxGetMainWnd()->SetWindowTextW(str+_T(“-“)+dlg.GetFileName());

    Invalidate();//强制调用OnDraw函数

}

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

程序代码:

voidCEx_ImageView::OnDraw(CDC*pDC)

{

    CEx_ImageDoc* pDoc = GetDocument();

    ASSERT_VALID(pDoc);

    //if (!pDoc)

        //return;

    // TODO: 在此处为本机数据添加绘制代码

    // Cyan:添加

    if(!m_Image.IsNull())

    {

        m_Image.Draw(pDC->m_hDC,0,0);

    }

}

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

程序代码:

public:   CImage m_Image;(Cyan:我觉得设置成私有成员比较好)

 (6)编译并运行。单击”打开”工具按钮,在弹出的对话框中指定一个图像文件后,单击”打开”按钮。

将图片用其它格式保存

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事件映射程序,并添加下列代码:

程序代码:

voidCEx_ImageView::OnFileSaveAs()  //Cyan:添加

{

    // TODO: 在此添加命令处理程序代码

    if(m_Image.IsNull())

    {

        MessageBox(_T(请打开要另存的图像!”));

        return;

    }

    CString strFilter;

    strFilter=“bmp位图文件|*.bmp|JPEG图像文件|*.jpg|GIF图像文件|*.gif|PNG图像文件|*.png||”;

    CFileDialog dlg(FALSE,NULL,NULL,NULL,strFilter);

    if(IDOK!=dlg.DoModal())

        return;

    //如果没有指定文件扩展名,则为其添加一个

    CString strFileName,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+_T(“.”)+strExtension;

    }

    //图像保存

    HRESULT hResult=m_Image.Save(strFileName);

    if(FAILED(hResult))

    {

        MessageBox(_T(保存图像文件失败!”));

    }

}

彩色图像转换成灰度图像

由于许多图像文件使用颜色表来发挥显示设备的色彩显示能力,因而将一张彩色图片变成黑色图片时需要调用CImage::IsIndexed来判断是否使用颜色表,若是则修改颜色表,否则直接将像素进行颜色设置。例如下面的代码:

程序代码:

voidCEx_ImageView::OnToGray()//Cyan:添加

{

    // TODO: 在此添加命令处理程序代码

    if(m_Image.IsNull())

        return;

    if(!m_Image.IsIndexed())

    {

        //直接修改像素颜色

        COLORREF pixel;

        int maxY=m_Image.GetHeight();

        int maxX=m_Image.GetWidth();

        byte r,g,b,avg;

        for(int x=0;x<maxX;x++)

        {

             for(int y=0;y<maxY;y++)

             {

                  pixel=m_Image.GetPixel(x,y);

                  r=GetRValue(pixel);

                  g=GetGValue(pixel);

                  b=GetBValue(pixel);

                  avg=(int)(((int)r+g+b)/3);

                  m_Image.SetPixelRGB(x,y,avg,avg,avg);

             }       

        }

    }

    else

    {

        //获取并修改颜色表

        int maxColors=m_Image.GetMaxColorTableEntries();

        RGBQUAD* lpColorTable;

        lpColorTable=newRGBQUAD[maxColors];

        m_Image.GetColorTable(0,maxColors,lpColorTable);

        for(int i=0;i<maxColors;i++)

        {

             int avg=(lpColorTable[i].rgbRed+lpColorTable[i].rgbGreen+lpColorTable[i].rgbBlue)/3;

             lpColorTable[i].rgbRed=avg;

             lpColorTable[i].rgbGreen=avg;

             lpColorTable[i].rgbBlue=avg;

        }

        m_Image.SetColorTable(0,maxColors,lpColorTable);

        delete(lpColorTable);

    }

    Invalidate();//强制调用OnDraw

}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/231596.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 60mph和kmh换算_mph和kmh换算(mph换算器)

    60mph和kmh换算_mph和kmh换算(mph换算器)mph是英里每时的意思吗?如何换算成千米每时?mph是米/小时的意思mitersperhour也可写成m/hAkm/h=A*1000m/hmph是英里每时的意思吗?如何换算成千米每时?MILESPERHOUR英里每小时英里的计速单位,1MPH=1.609KM/H玩极品飞车12,上面的速度是mph,怎么换算啊1英里=5280英尺=63360英寸=1…

    2022年6月28日
    67
  • Jquery 400报错

    Jquery 400报错问题:前端能够完整传递数据,后台不能相应的接收到所有的数据解决思路:1,前端传送的数据格式和后端接收的数据格式不一一对应,400报错2,修改前端界面的name属性,name的属性与后台的接收字段名称,3,如果使用实体接收数据的话,未接收到数据,则是数据类型的问题,传递过来的数据默认是String类型的数据,但是实体中有integer或者timestamp格式4,如果使用参数集合接收数据,…

    2022年6月7日
    36
  • Linux安装nmap命令

    Linux安装nmap命令在线安装yuminstallnmap本地安装rpm软件包的安装可以使用程序rpm来完成。执行下面的命令:rpm-ivhyour-package.rpm

    2022年5月8日
    44
  • bat启动命令行_cmd打开bat文件

    bat启动命令行_cmd打开bat文件写了个win环境本地启动的java项目,又不想每次去win+R再开启powershell(win10环境)所以百度了一下bat脚本参考了大佬的文章:https://www.cnblogs.com/LiuYanYGZ/p/12078984.html只需要简单的命令就可以了:startcmd/kechoHello,World!##执行完毕以后,新开的窗…

    2022年9月23日
    3
  • tomcat文件上传大小限制_tomcat调整内存大小

    tomcat文件上传大小限制_tomcat调整内存大小1.Get方法长度限制HttpGet方法提交的数据大小长度并没有限制,HTTP协议规范没有对URL长度进行限制。这个限制是特定的浏览器及服务器对它的限制。如:IE对URL长度的限制是2083字节(2K+35)。下面就是对各种浏览器和服务器的最大处理能力做一些说明.MicrosoftInternetExplorer(Browser)IE浏览器对URL的最大限制为2083个字符,如果超过这个数…

    2022年8月24日
    13
  • CentOS7安装MySQL(完整版)

    CentOS7安装MySQL(完整版)在CentOS中默认安装有MariaDB,这个是MySQL的分支,但为了需要,还是要在系统中安装MySQL,而且安装完成之后可以直接覆盖掉MariaDB。1下载并安装MySQL官方的YumRepository[root@localhost~]#wget-i-chttp://dev.mysql.com/get/mysql57-community-release-…

    2022年4月28日
    30

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号