图片的合并与分解

摘要:本文及其附带源码利用GID+ Bitmap实现了将一张图片分解为多张指定尺寸的图片,以及将多张图片合并为一张。

关键字:GDI+、图片合并、分解

环境:VS2005/WinXP/SP2/1280*800分辨率

  事情的起因是这样的:我的一个VC6工程 res 路径下存在一些图片,它们是在绘制 ToolBar的时候生成的,基本是多个16*16或32*32的小图片拼凑而成的一张大图片,我需要用到其中的某几个小图片,单独存为BMP或者ICO,但是找了几个做图标的软件,都没有这个功能。问了坛子里的一些朋友,好像也没有这种简单的现成的工具,于是一咬牙一跺脚,自己写吧。顺便把多个图片合并也写进去了,目前只是测试了自己需要的部分(仅BMP格式),和源码一起放出来,希望对你有用,不够用自己去改哈。

程序界面截图:



程序编译环境:VS2005 VC++ MFC UNICODE

  在程序的实现过程中,没有去分析 BMP 的结构,而是直接调用了GDI+ Bitmap,我只是想使用,不想太多的深入。所以代码阅读起来很简单,核心代码就那么2~3行。

这里我假设读者是第一次使用GDI+ 来进行逐步说明。如果你在这方面是姚明的手――高手@_@,请忽略。

1、包含GDI+ 的头文件和库

我们需要包含 GDI+ 头文件,包含 lib,使用 Gdiplus 的别名。为了省事,我放到了 stdafx.h 里。

//请在主框架里GdiplusStartup / GdiplusShutdown#include //GDI+ 声明,可以GDI/GDI+ 混合使用#pragma comment(lib, "gdiplus.lib")using namespace Gdiplus;

  你也可以在 工程属性->链接器->输入->附加依赖项 里包含 gdiplus.lib 文件,也可以不使用别名,那么定义GDI+ 对象的时候,就要带上域名,如 Gdiplus::Bitmap, 这里建议还是 using namespace.

2、初始化和释放GDI+ 调用

  首先定义一个ULONG_PTR的成员变量 m_gdiplusToken ,这是一个DWORD数据类型,该成员变量用来保存GDI+ 被初始化后在应用程序中的GDI+ 标识,以便能在应用程序退出后,引用该标识来调用Gdiplus:: GdiplusShutdown来关闭GDI+。细节请参考CBmp2MApp里的相关代码。

ULONG_PTR m_gdiplusToken; //GDI+

然后在 BOOL CBmp2MApp::InitInstance() 里开始初始化 GDI+ 环境。

//初始化GID+GdiplusStartupInput gdiplusStartupInput;GdiplusStartup( &m_gdiplusToken,&gdiplusStartupInput,NULL );

  最后,在int CBmp2MApp::ExitInstance()里,我们来释放GDI+ 的调用。注意:在向导生成的缺省项目中,这个函数是没有的,我们需要重载它。在类视图里选择CBmp2MApp,然后在属性里点重写,就可以看到。(是不是太罗嗦了^_^)

int CBmp2MApp::ExitInstance() {//释放GDI+ 调用GdiplusShutdown( m_gdiplusToken );return CWinApp::ExitInstance();}

3、图片的分解

  分解一张图为多张,这是程序的缺省模式。如源码中的注释,我只考虑了横向分解,没有考虑纵向的情况,也没有考虑智能的获取图片的尺寸问题,缺省就是16*16,如果你的图片是32*32或其他的模式,请手动更改。但你点击选择文件,成功选择一个合适的图片文件之后,界面应该是下图所示的样子。如果不想改变拆分图片的存储路径,你可以直接点确定了,不出意外的话,会打开一个文件夹界面,然后里边有N张存储成功可供使用的图片了。

核心函数就是下面的这个:

//分解,目前仅考虑 BMP 格式void CBmp2MDlg::ImageUnPack(LPCTSTR sPath,LPCTSTR sType,int x,int y){if( NULL==m_bitmap ) return; //must!//Bitmap *bmp = m_bitmap;int w = bmp->GetWidth();int h = bmp->GetHeight();CLSID clsid;GetEncoderClsid( sType,&clsid );CString ss;int i,k=1;for( i=0;i<w;i+=x,k++ ) //只考虑横向{//新建指定大小的图片Bitmap bt(x,y);//从它得到绘制设备Graphics *gc = Graphics::FromImage( &bt );//从原图片上截取指定大小的图片贴到这个新建的图片的上面gc->DrawImage( bmp,RectF(0,0,x,y),i,0,x,y,UnitPixel ); //ss.Format( _T("%s%s_%d.%s"),sPath,m_sFileTitle,k,GetType(sType) );//保存到指定路径bt.Save( ss,&clsid,NULL );//delete gc;gc = NULL;}ShellExecute( NULL,_T("open"),sPath,NULL,NULL,SW_SHOW );}

就是按照输入的大小先创建一张空图片,然后计算位置,从源图片上的截取这个位置上的图贴过来,然后保存。

4、图片的合并

合并多张图为一张,就是上面的逆过程了。核心函数就是 ImagePack 请去参考源码。

就是这么个小工具,希望在你想用的时候能节省一点时间。你可以任意去扩充它,比如:增加图片预览的功能,保存的命名规则,或者拖曳 ListCtrl 让各图片按你预想的顺序排到一张大图上……等等。

posted @ 2010-04-17 11:31  7069202a  阅读(481)  评论(0编辑  收藏  举报