图片的合并与分解

<script type="text/JavaScript"> </script> <script src="http://a.alimama.cn/inf.js" type="text/javascript"></script>

摘要:本文及其附带源码利用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 让各图片按你预想的顺序排到一张大图上……等等。

<script type="text/JavaScript"> </script> <script src="http://a.alimama.cn/inf.js" type="text/javascript"></script>

Atlas 是一种一次展示多个小图像的方法,它将一个大图像分解为由多个较小图像组成的网格。这种方法通常用于创建图像资源集合,以便在游戏开发、电影制作等领域中使用。 使用 Atlas 分解图片的主要目的是为了优化图像资源的加载和渲染性能。将多个小图像合并为一个大图像可以减少内存占用和渲染调用次数,提高应用程序的运行效率。 分解图片的过程一般包括以下步骤: 1. 首先,确定需要分解的大图像,这个大图像通常包含了多个小图像。 2. 根据需要,可以在小图像之间添加一些间隙或边框等装饰元素,以便在应用程序中更好地区分各个小图像。 3. 将小图像按照规定的大小和网格排列方式,从大图像中切割出来。可以使用图像编辑软件,如 Photoshop,或者使用编程语言中的图像处理工具来完成这一步骤。 4. 将切割好的小图像保存为独立的图像文件,并分配唯一的标识符。 5. 创建一个用于管理小图像的 Atlas 文件。这个文件包含了每个小图像的位置信息和标识符等相关信息。常见的 Atlas 文件格式包括 XML、JSON 等。 6. 在应用程序中,通过加载 Atlas 文件和对应的小图像文件,可以根据需要将小图像显示在屏幕上。通过读取 Atlas 文件中的位置信息,可以实现对每个小图像的精准定位和渲染。 通过使用 Atlas 分解图片,我们可以更加灵活地管理和使用图像资源,在提高应用程序性能的同时,也能够减少资源的占用和加载时间,给用户带来更好的体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值