这是一个用于分解TexturePacker导出的大图的工具。

需要包含png图片和.plist文件

使用Python编写的,界面使用的是wxPython库写的。

以下是实现代码:

'''
功能:
分解TexturePacker制作的图集,要求包含plist文件和图片1.制作一个简单的界面来指定要分解的图集(plist文件和图片)1.提供选择plist文件2.提供选择图片文件3.提供保存路径选择
2.根据选择的文件做分解操作1.读取plist文件,并解析2.根据解析出来的数据对图集进行裁剪,并生成新的图片3.将图片保存到指定文件夹中参考:
1.wxpython教程1:https://blog.csdn.net/xufive/article/details/82665460?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166532024216782388061584%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166532024216782388061584&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~top_positive~default-1-82665460-null-null.nonecase&utm_term=wxpython&spm=1018.2226.3001.4450
2.wxpython教程2:https://edu.csdn.net/skill/python/python-3-176?category=9&typeId=17490
3.wxpython教程 - 事件:https://blog.csdn.net/weixin_42161954/article/details/109302843?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2-109302843-blog-113688944.pc_relevant_3mothn_strategy_recovery&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2-109302843-blog-113688944.pc_relevant_3mothn_strategy_recovery&utm_relevant_index=5
4.Python中的Partial函数(偏函数):https://edu.csdn.net/skill/python/python-3-176?category=9&typeId=17490#41__429
5.wxpython教程Wiki:https://wiki.wxpython.org/Passing%20Arguments%20to%20Callbacks
6.with open() 结构:https://blog.csdn.net/m0_48936146/article/details/124360734
7.plist文件解析plistlib:https://www.osgeo.cn/cpython/library/plistlib.html
8.python打包exe:https://blog.csdn.net/m0_64355682/article/details/125043126
8.python打包exe:https://www.cnblogs.com/strides/p/16422602.html
'''from email.mime import image
from functools import partial
from PIL import Image
import wx
import os
import plistlibAPP_TITLE = "TexturePacker分解工具"
APP_ICON = ""
SPLITY_TYPE = "COCOS"# 这里是窗口类
class MainFrame(wx.Frame):__plistPath = None__imgPath = None__savePath = None__saveDir = None# 分解类型,根据TexturePacker导出的引擎定义对于的函数, 注意这里的函数名不能加上前面下划线,否则无法调用__splitFuncDict = {'COCOS':'SplitImage_Cocos',}# 初始化窗口显示界面def __init__(self):'''初始化,这里使用默认的样式默认style是下列项的组合:wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN 但是不需要改变窗口的大小,所以加上 ^ wx.RESIZE_BORDER'''wx.Frame.__init__(self, None, style = wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)# 设置标题,背景色,大小,居中显示self.SetTitle(APP_TITLE)self.SetBackgroundColour(wx.Colour(224, 224, 224))self.SetSize((450, 220))self.Center()# 创建一个Panel,存放控件panel = wx.Panel(self)# plist文件获取# 固定文本显示:label:文本内容,pos:在panel内的位置(x, y)wx.StaticText(panel, label = "Plist文件:", pos = (20, 20))# 文本框,size:控件大小(w, h),-1表示默认大小self.plistTxtBox = wx.TextCtrl(panel, pos = (80, 20), size = (250, -1))# 按钮plistBtn = wx.Button(panel, label = "获取", pos = (340, 20))# 绑定点击事件,使用控件的Bind接口(事件类型,回调函数,对象),partial接口用于给回调事件中传入额外的参数,可以用于判断是哪个按钮的回调plistBtn.Bind(wx.EVT_BUTTON, partial(self.OnSelectBtnClick, bPlist = True))# 图片获取wx.StaticText(panel, label = "图片文件:", pos = (20, 60))self.imgTxtBox = wx.TextCtrl(panel, pos = (80, 60), size = (250, -1))imgBtn = wx.Button(panel, label = "获取", pos = (340, 60))imgBtn.Bind(wx.EVT_BUTTON, partial(self.OnSelectBtnClick, bPlist = False))# 分解保存路径wx.StaticText(panel, label = "保存地址:", pos = (20, 100))self.saveTxtBox = wx.TextCtrl(panel, pos = (80, 100), size = (250, -1))saveBtn = wx.Button(panel, label = "保存", pos = (340, 100))saveBtn.Bind(wx.EVT_BUTTON, self.OnSaveBtnClick, saveBtn)# 分解图片splitBtn = wx.Button(panel, label = "分解", pos = (50, 140))splitBtn.Bind(wx.EVT_BUTTON, self.OnSplitBtnClick, splitBtn)# 选择文件路径按钮点击事件,用于获取Plist、png文件路径def OnSelectBtnClick(self, evt, bPlist):fileWildCard = ""           # 筛选文件类型:描述|*.后缀|下一组...titleTips = ""              # 文件浏览器的标题if bPlist :fileWildCard = "Plist files(*.plist)|*.plist|All files(*.*)|*.*" titleTips = "请选择plist文件"else:fileWildCard = "PNG files(*.png)|*.png|All files(*.*)|*.*" titleTips = "请选择图片文件"# 通过 wx.FileDialog 打开文件浏览器,并选择对应的文件, defaultDir:起始路径fd = wx.FileDialog(self, titleTips, defaultDir = os.getcwd(), wildcard = fileWildCard) # 用户确认后的操作,这一步必须写上,不然弹窗无法正常打开,如果用户取消则该值 = wx.ID_CANCELif fd.ShowModal() == wx.ID_OK :filePath = fd.GetPath()os.chdir(os.path.dirname(filePath))if bPlist :self.__plistPath = filePathself.plistTxtBox.write(self.__plistPath)else:self.__imgPath = filePathself.imgTxtBox.write(self.__imgPath)            # 用完就关了fd.Destroy()# 保存路径按钮点击事件def OnSaveBtnClick(self, evt):fd = wx.DirDialog(self, "请选择保存文件夹", defaultPath = os.getcwd())if fd.ShowModal() == wx.ID_OK :self.__savePath = fd.GetPath()self.saveTxtBox.write(self.__savePath)fd.Destroy()# 分解按钮点击事件def OnSplitBtnClick(self, evt):if self.__plistPath == None or not os.path.exists(self.__plistPath) :wx.MessageBox("请指定有效的Plist文件!", "警告", style = wx.OK)returnif self.__imgPath == None or not os.path.exists(self.__imgPath)  :wx.MessageBox("请指定有效的图片文件!", "警告", style = wx.OK)returnif self.__savePath == None or not os.path.exists(self.__savePath)  :wx.MessageBox("请指定有效的保存路径!", "警告", style = wx.OK)return'''1.读取plist文件内容,并转换为python数据结构2.遍历碎图数据,对大图进行裁剪3.将小图生成到指定的路径'''self.__InitPlistData()# 初始化Plist文件数据def __InitPlistData(self):funcStr = self.__splitFuncDict.get(SPLITY_TYPE, 'Defuault')if funcStr == 'Defuault' :wx.MessageBox(f"没有{SPLITY_TYPE}对应的分解处理接口", "警告", style = wx.OK)return'''with open(文件路径,打开方式:r只读/w只写/a追加) as 文件对象r:   以只读方式打开文件。文件的指针将会放在文件的开头。这是**默认模式**。rb: 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。r+: 打开一个文件用于读写。文件指针将会放在文件的开头。rb+:以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。w:  打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。wb: 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。w+:  打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。wb+:以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。a: 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。ab: 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。a+:  打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。ab+:以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。'''with open(self.__plistPath, "rb") as fp:# 解析Plist文件plistDict = plistlib.load(fp)if plistDict == None :wx.MessageBox("Plist解析失败", "错误", style = wx.OK)return# 获取图片名称,并根据图片名称创建文件夹存储小图imgName = plistDict['metadata']['realTextureFileName']self.__saveDir = os.path.join(self.__savePath, imgName.replace(".png", "")) # 把后缀去掉,然后组合一下碎图的保存路径if not os.path.isdir(self.__saveDir) : # 判断有没有该目录,没有就创建os.mkdir(self.__saveDir) # 创建目录# 打开图片对象srcImage = Image.open(self.__imgPath)# 开始分解,getattr(self, xxx):相当于 self.xxxfunc = getattr(self, funcStr)func(plistDict['frames'], srcImage)# Cocos版本的分解接口def SplitImage_Cocos(self, imgsDic, srcImage):'''大图中的原点是在左上角,右为x正轴,下为y正轴frame:小图在大图中的位置大小(这里是经过Trim去掉空白之后的):{x,y},{w,h}offset:小图经过Trim之后的中心点与原小图的中心点的偏移值,注意这里的坐标系是:右为x正轴,上为y正轴rotated:是否旋转了90°sourceColorRect:原小图经过Trim之后在原图中的位置大小:{x,y},{w,h}sourceSize:原图大小'''# 将json格式的数据转换成数组json2List = lambda x : x.replace('{', '').replace('}', '').split(',')for key, value in imgsDic.items() :# 获取裁剪的位置大小:[x,y,w,h]cutRect = []valueFrame = json2List(value['frame'])frameList = [int(valueFrame[0]), int(valueFrame[1]), int(valueFrame[2]), int(valueFrame[3])]if value['rotated'] == True :cutRect = [frameList[0], frameList[1], frameList[0] + frameList[3], frameList[1] + frameList[2],]else:cutRect = [frameList[0], frameList[1], frameList[0] + frameList[2], frameList[1] + frameList[3],]# 原始的图片大小[w,h]valueSourceSize = json2List(value['sourceSize'])sourceSizeList = [int(valueSourceSize[0]), int(valueSourceSize[1])]# 获取偏移值: [x,y]'''首先大图里的小图是有可能对原图裁剪后的,所以如果要放回原图中的话,需要用(原图的大小 - 裁剪后的图的大小)/ 2,得到一个偏移值小图在原图的位置应该从原点(0,0),即左上角做一个偏移再加上中心点的偏移值就是最终的位置,注意这里因为坐标系问题,y轴应该是减法宽高 = 位置 + 大小'''valueOffset = json2List(value['offset'])offsetList = [int(valueOffset[0]), int(valueOffset[1])]adjust_x = int((sourceSizeList[0] - frameList[2]) / 2)adjust_y = int((sourceSizeList[1] - frameList[3]) / 2)order_x = adjust_x + offsetList[0]order_y = adjust_y - offsetList[1]orderRect = [order_x, order_y, order_x + frameList[2], order_y + frameList[3],]# 存储位置subImgPath = ""if key.endswith('.png') :subImgPath = os.path.join(self.__saveDir, key)else:subImgPath = os.path.join(self.__saveDir, key + ".png")self.GenerateImage(srcImage, cutRect, orderRect, subImgPath)# 创建小图并保存def GenerateImage(self, srcImage, cutRect, orderRect, orderPath):subImage = srcImage.crop(cutRect)orderImage = Image.new("RGBA", [orderRect[2], orderRect[3]])orderImage.paste(subImage, orderRect)orderImage.save(orderPath)# 这里是程序类
class MainApp(wx.App):def OnInit(self):self.SetAppName(APP_TITLE)self.frame = MainFrame()self.frame.Show()return True# 启动应用程序
if __name__ == "__main__":app = MainApp()app.MainLoop()

本人新学Python,有什么不对的地方,欢迎各位大佬指正~~

工具 - 分解TexturePacker导出的大图相关推荐

  1. arcgis合并tif影像_微图影像地图导出拼接大图的参数说明

    1. 概述 微图是一款集地图下载与GIS功能于一体的轻量级GIS产品,相较于X3版本的万能地图下载器,它有更丰富的地图数据和更专业的GIS功能. 尽管微图的软件界面已经足够简洁明了,但为了让新用户能更 ...

  2. gis影像格式img转为ecw_微图影像地图导出拼接大图的参数说明

    1. 概述 微图是一款集地图下载与GIS功能于一体的轻量级GIS产品,相较于X3版本的万能地图下载器,它有更丰富的地图数据和更专业的GIS功能. 尽管微图的软件界面已经足够简洁明了,但为了让新用户能更 ...

  3. mysql数据迁移到teradata_Teradata SQL Assistant工具导入与导出

    Teradata SQL Assistant工具导入与导出 1. 使用Teradata SQL Assistant工具导入与导出 当你得到一个EXCEL平面文件数据的时候,你就可以利用Teradata ...

  4. 分享一款非常棒的数据库文档生成工具,可导出md、excel等格式

    1.背景 因为要给朋友项目补数据库文档,文档中需要填写数据库表结构等信息. 找了一个开源的.非常棒的数据库文档生成工具,可以导出word.excel(可编辑).md等格式..亲测,很棒,分享给大家.. ...

  5. TexturePacker 导出 Egret(白鹭引擎)格式的图集和图片字体

    TexturePacker 导出 Egret(白鹭引擎)格式的图集(egretSheet)和图片字体(egretFont)补丁 https://github.com/chengyoujie/Textu ...

  6. python输出所有关键词_【Python工具】ASO100导出竞争对手的所有关键词数据

    本文信息本文由方法SEO顾问发表于2016-10-1316:16:34,共 1733 字,转载请注明:[Python工具]ASO100导出竞争对手的所有关键词数据_[方法SEO顾问],如果我网站的文章 ...

  7. 工具类--Excel 导出poi

    实现功能 --批量导出excel 文件,配置一个sheet多少条数据,根据查询数据量的多少确定生成几个sheet页. pom 文件导入ExcelUtils工具包,依赖于poi包. <!-- ht ...

  8. poi word插入图片_豌豆BI工具看板Word导出技术详解

    Word是最常见的文档编辑工具,当数据分析完成之后,将分析数据的图表在Word中展现,进行汇报或者存档是非常具有现实意义.在此背景之下,全新的Word导出,在豌豆BI 2.1.2 中与大家见面了. 本 ...

  9. 一步一步图文介绍SpriteKit使用TexturePacker导出的纹理集Altas

    1.为什么要使用纹理集? 游戏是一种很耗费资源的应用,特别是在移动设备中的游戏,性能优化是非常重要的 纹理集是将多张小图合成一张大图,使用纹理集有以下优点: 1.减少内存占用,减少磁盘占用: 2.减少 ...

最新文章

  1. 22种代码坏味道及重构手段
  2. oracle sequence 不同 会话 不连续_序列 Sequence
  3. mysql -- 死锁
  4. java 自动化测试报告_Java自动化测试框架-10 - TestNG之测试结果篇
  5. 为什么我们要使用min-height和max-height样式属性?
  6. C++ 实现简易 log 日志系统
  7. Q96:PT(1):方格纹理(Checker)(1)——3D Checker
  8. oracle 10g下载百度云地址
  9. pxe(hanewin)安装ubuntu-七侠镇莫小贝
  10. 2008下搭建easypanel(康乐)虚拟主机控制面板
  11. 计算机保持在线的几种方法,获取网络电影实际地址的几种方法.doc
  12. iPhone音频开发之:转换和录音(第二部分)
  13. 婚礼纪 java面试
  14. 美国贝勒大学计算机科学专业怎么样,美国贝勒大学怎么样
  15. 记录一下微信、QQ、微博分享web网页功能
  16. linux系统换硬件要重装,换cpu要重装系统吗?电脑更换cpu需要重装系统吗
  17. html中列表前的序号用带圆圈的数字表示及存在的问题
  18. 解决无字幕问题--射手影音VS迅雷影音
  19. 火狐浏览器不能访问ftp服务器的文件夹,火狐浏览器计划后续版本禁用网页引用FTP子资源...
  20. 华为OD机试 - 最大平分数组(Java JS Python)

热门文章

  1. rtos系统c语言,让我们来学习RTOS,自己写RTOS
  2. 学会map、reduce、filter这三个函数,让你Python代码看起来更有逼格!
  3. wordpress教程之函数讲解
  4. 【置顶】资源分享【更新2022.10.17】
  5. 【问题】Ubuntu20.04桌面某些图标不显示
  6. 华清远见-重庆中心-数据库阶段技术总结/知识点梳理/个人总结
  7. 和自己赛跑的人 —不要怕、不后悔!
  8. WebShell箱子简介与原理
  9. 火车头采集器文章组合聚合
  10. java 利用飞信,Java利用飞信API给自己或者好友发信息