plist文件简介
根据百度百科介绍,plist是一种文件形式,通常用于储存用户设置,也可以用于存储捆绑的信息,该功能在旧式的Mac OS中是由资源分支提供的。由于Plist中存储的数据是抽象的,其采用的文件格式可以不止一种。
分析plist文件结构可知,其本质是XML文档,因而我们可以使用XML解析器分析plist文件,读取各个图片的信息并将原图切割即可。
下文例子所用到的Python库
xml.etree
PIL(pillow, 可使用pip install pillow安装)
相应的Python代码
# -*- coding: UTF-8 -*
from xml.etree import ElementTree
from PIL import Image
import argparse
import os
import sys
class PlistParser:
def __init__(self, plistPath, imagePath, outputDirPath):
self.plistPath = plistPath
self.imagePath = imagePath
self.outputDirPath = outputDirPath
def convertTreeToDict(self, tree):
d = {} # 返回值是一个dict
for index, item in enumerate(tree): # 遍历整棵XML树
if item.tag == 'key': # 如果该item的tag为'key'
# 根据下一个结点的tag值不同,放在dict的不同位置上
if tree[index + 1].tag == 'string':
d[item.text] = tree[index + 1].text
elif tree[index + 1].tag == 'true':
d[item.text] = True
elif tree[index + 1].tag == 'false':
d[item.text] = False
elif tree[index + 1].tag == 'dict':
d[item.text] = self.convertTreeToDict(tree[index + 1]) # 递归下去
elif item.tag == 'dict' and item._children[0].text == 'frames':
d = self.convertTreeToDict(item)
return d
def splitImageFromPlist(self):
targetFileDir = self.outputDirPath
if targetFileDir is None:
targetFileDir = self.plistPath.replace('.plist', '')
if not os.path.isdir(targetFileDir): # 如果不存在该目录
os.mkdir(targetFileDir) # 新建一个目录
srcImg = Image.open(self.imagePath) # 打开图像
plistContentStr = open(self.plistPath, 'r').read() # 读取plist文件
plistXMLTree = ElementTree.fromstring(plistContentStr) # 转换成XML树
plistDict = self.convertTreeToDict(plistXMLTree) # 获取dict
for k, v in plistDict['frames'].items():
posi_str = str(v['frame']) # 获取表示位置的str
posi_rect = posi_str.replace('{', '').replace('}', '').split(',')
width = int(posi_rect[3] if v['rotated'] else posi_rect[2])
height = int(posi_rect[2] if v['rotated'] else posi_rect[3])
boundingBox = (
int(posi_rect[0]),
int(posi_rect[1]),
int(posi_rect[0]) + width,
int(posi_rect[1]) + height
)
rectImage = srcImg.crop(boundingBox)
if v['rotated']:
rectImage = rectImage.rotate(90)
# outfile = os.path.join(targetFileDir, k)
outfile = targetFileDir + '\\' + k
dirPath = outfile.partition('/')[0]
if not dirPath.endswith('png') and not os.path.isdir(dirPath):
os.mkdir(dirPath)
rectImage.save(outfile)
# 在该路径中寻找所有plist文件
def findPlistFile(path):
l = []
for x in os.listdir(path):
if os.path.isfile(path + '\\' + x):
if x.endswith('.plist') and not x.startswith('.'):
l.append(path + '\\' + x)
elif os.path.isdir(path + '\\' + x):
l.extend(findPlistFile(path + '\\' + x))
return l
if __name__ == '__main__':
parser = argparse.ArgumentParser(usage='please use plistCutter.py -h to get help information.')
parser.add_argument('-dir', help='Specify a directory file path you would like to find')
args = parser.parse_args()
dir = args.dir
if dir is None and not os.path.isdir(dir):
print('error: %s is not an valid dir or dosen\'t exist.')
sys.exit(1)
l = findPlistFile(dir)
for x in l:
plistPath = x
pngPath = x.replace('.plist', '.png')
if os.path.exists(pngPath):
dirPath = str.format('res\\%s' % x.replace('.plist', '').rpartition('\\')[2])
if not os.path.isdir(dirPath):
os.mkdir(dirPath)
PlistParser(plistPath, pngPath, dirPath).splitImageFromPlist()
print('Done.')
使用方法以及注意
本代码是读取一个目录的路径,找出所有的plist文件,并将所有切割后的图像当在当前目录(py文件所处的目录)的res文件夹中。
注意的是,plist文件名和原图名必须一致,如果不一致需要对代码或者对文件名做一些相应的修改。
使用方式是 python 文件名.py -dir 目录路径。
比如,plist文件都处于目录D:\plists中,将以上代码保存为plistCutter.py,在当前目录使用命令行输入
python plistCutter.py -dir D:\plists
程序运行结束后,在当前目录可以看到一个res文件夹,打开该文件夹就是切割后的所有图像了。
附录:下文例子所使用的plist文件之一
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>frames</key>
<dict>
<key>newtheme_CN.png</key>
<dict>
<key>frame</key>
<string>{{826,52},{410,114}}</string>
<key>offset</key>
<string>{0,5}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{35,18},{410,114}}</string>
<key>sourceSize</key>
<string>{480,160}</string>
</dict>
<key>newtheme_EN.png</key>
<dict>
<key>frame</key>
<string>{{414,50},{410,114}}</string>
<key>offset</key>
<string>{0,5}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{35,18},{410,114}}</string>
<key>sourceSize</key>
<string>{480,160}</string>
</dict>
<key>newtheme_TW.png</key>
<dict>
<key>frame</key>
<string>{{2,46},{410,114}}</string>
<key>offset</key>
<string>{0,5}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{35,18},{410,114}}</string>
<key>sourceSize</key>
<string>{480,160}</string>
</dict>
<key>theend_bg.png</key>
<dict>
<key>frame</key>
<string>{{2888,1032},{960,640}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{960,640}}</string>
<key>sourceSize</key>
<string>{960,640}</string>
</dict>
<key>theend_bg_CN.png</key>
<dict>
<key>frame</key>
<string>{{2568,98},{870,146}}</string>
<key>offset</key>
<string>{7,172}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{52,75},{870,146}}</string>
<key>sourceSize</key>
<string>{960,640}</string>
</dict>
<key>theend_bg_EN.png</key>
<dict>
<key>frame</key>
<string>{{872,192},{848,170}}</string>
<key>offset</key>
<string>{13,170}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{69,65},{848,170}}</string>
<key>sourceSize</key>
<string>{960,640}</string>
</dict>
<key>theend_bg_TW.png</key>
<dict>
<key>frame</key>
<string>{{2,168},{868,148}}</string>
<key>offset</key>
<string>{8,173}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{54,73},{868,148}}</string>
<key>sourceSize</key>
<string>{960,640}</string>
</dict>
<key>theend_home.png</key>
<dict>
<key>frame</key>
<string>{{2130,2},{72,72}}</string>
<key>offset</key>
<string>{-11,10}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{13,14},{72,72}}</string>
<key>sourceSize</key>
<string>{120,120}</string>
</dict>
<key>theend_rate_CN.png</key>
<dict>
<key>frame</key>
<string>{{2596,2},{190,80}}</string>
<key>offset</key>
<string>{-2,2}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{23,18},{190,80}}</string>
<key>sourceSize</key>
<string>{240,120}</string>
</dict>
<key>theend_rate_EN.png</key>
<dict>
<key>frame</key>
<string>{{2396,2},{198,80}}</string>
<key>offset</key>
<string>{3,2}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{24,18},{198,80}}</string>
<key>sourceSize</key>
<string>{240,120}</string>
</dict>
<key>theend_rate_TW.png</key>
<dict>
<key>frame</key>
<string>{{2204,2},{190,80}}</string>
<key>offset</key>
<string>{-2,2}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{23,18},{190,80}}</string>
<key>sourceSize</key>
<string>{240,120}</string>
</dict>
<key>theend_sina_CN.png</key>
<dict>
<key>frame</key>
<string>{{3194,2},{196,80}}</string>
<key>offset</key>
<string>{-5,2}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{17,18},{196,80}}</string>
<key>sourceSize</key>
<string>{240,120}</string>
</dict>
<key>theend_sina_EN.png</key>
<dict>
<key>frame</key>
<string>{{2986,2},{206,80}}</string>
<key>offset</key>
<string>{-1,2}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{16,18},{206,80}}</string>
<key>sourceSize</key>
<string>{240,120}</string>
</dict>
<key>theend_sina_TW.png</key>
<dict>
<key>frame</key>
<string>{{2788,2},{196,80}}</string>
<key>offset</key>
<string>{-5,2}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{17,18},{196,80}}</string>
<key>sourceSize</key>
<string>{240,120}</string>
</dict>
<key>导入萝卜2/theend_tov2_CN.png</key>
<dict>
<key>frame</key>
<string>{{898,418},{894,252}}</string>
<key>offset</key>
<string>{0,151}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,43},{894,252}}</string>
<key>sourceSize</key>
<string>{894,640}</string>
</dict>
<key>导入萝卜2/theend_tov2_EN.png</key>
<dict>
<key>frame</key>
<string>{{2,364},{894,248}}</string>
<key>offset</key>
<string>{0,153}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,43},{894,248}}</string>
<key>sourceSize</key>
<string>{894,640}</string>
</dict>
<key>导入萝卜2/theend_tov2_TW.png</key>
<dict>
<key>frame</key>
<string>{{2678,246},{894,248}}</string>
<key>offset</key>
<string>{0,153}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,43},{894,248}}</string>
<key>sourceSize</key>
<string>{894,640}</string>
</dict>
<key>导入萝卜2/theend_tov2_bg.png</key>
<dict>
<key>frame</key>
<string>{{1926,1032},{960,640}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{960,640}}</string>
<key>sourceSize</key>
<string>{960,640}</string>
</dict>
<key>导入萝卜2/theend_tov2_close_normal.png</key>
<dict>
<key>frame</key>
<string>{{2060,2},{68,68}}</string>
<key>offset</key>
<string>{1,3}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{17,3},{68,68}}</string>
<key>sourceSize</key>
<string>{100,80}</string>
</dict>
<key>导入萝卜2/theend_tov2_close_pressed.png</key>
<dict>
<key>frame</key>
<string>{{1990,2},{68,68}}</string>
<key>offset</key>
<string>{1,3}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{17,3},{68,68}}</string>
<key>sourceSize</key>
<string>{100,80}</string>
</dict>
<key>最终通关/theend2_bg.png</key>
<dict>
<key>frame</key>
<string>{{964,946},{960,640}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{960,640}}</string>
<key>sourceSize</key>
<string>{960,640}</string>
</dict>
<key>最终通关/theend2_bg_CN.png</key>
<dict>
<key>frame</key>
<string>{{3244,496},{726,534}}</string>
<key>offset</key>
<string>{28,-10}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{145,63},{726,534}}</string>
<key>sourceSize</key>
<string>{960,640}</string>
</dict>
<key>最终通关/theend2_bg_EN.png</key>
<dict>
<key>frame</key>
<string>{{1794,418},{720,526}}</string>
<key>offset</key>
<string>{21,-11}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{141,68},{720,526}}</string>
<key>sourceSize</key>
<string>{960,640}</string>
</dict>
<key>最终通关/theend2_bg_TW.png</key>
<dict>
<key>frame</key>
<string>{{2516,496},{726,534}}</string>
<key>offset</key>
<string>{28,-10}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{145,63},{726,534}}</string>
<key>sourceSize</key>
<string>{960,640}</string>
</dict>
<key>最终通关/theend2_close_normal.png</key>
<dict>
<key>frame</key>
<string>{{2060,2},{68,68}}</string>
<key>offset</key>
<string>{1,3}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{17,3},{68,68}}</string>
<key>sourceSize</key>
<string>{100,80}</string>
</dict>
<key>最终通关/theend2_close_pressed.png</key>
<dict>
<key>frame</key>
<string>{{1990,2},{68,68}}</string>
<key>offset</key>
<string>{1,3}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{17,3},{68,68}}</string>
<key>sourceSize</key>
<string>{100,80}</string>
</dict>
<key>最终通关/theend2_tweibo_normal.png</key>
<dict>
<key>frame</key>
<string>{{3392,2},{94,96}}</string>
<key>offset</key>
<string>{1,-4}</string>
<key>rotated</key>
<true/>
<key>sourceColorRect</key>
<string>{{29,31},{94,96}}</string>
<key>sourceSize</key>
<string>{150,150}</string>
</dict>
<key>最终通关/theend2_tweibo_press.png</key>
<dict>
<key>frame</key>
<string>{{3808,2},{138,132}}</string>
<key>offset</key>
<string>{0,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{6,8},{138,132}}</string>
<key>sourceSize</key>
<string>{150,150}</string>
</dict>
<key>最终通关/theend2_wechat_disable.png</key>
<dict>
<key>frame</key>
<string>{{3594,2},{102,102}}</string>
<key>offset</key>
<string>{1,-1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{25,25},{102,102}}</string>
<key>sourceSize</key>
<string>{150,150}</string>
</dict>
<key>最终通关/theend2_wechat_normal.png</key>
<dict>
<key>frame</key>
<string>{{3490,2},{102,102}}</string>
<key>offset</key>
<string>{1,-1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{25,25},{102,102}}</string>
<key>sourceSize</key>
<string>{150,150}</string>
</dict>
<key>最终通关/theend2_wechat_press.png</key>
<dict>
<key>frame</key>
<string>{{3948,2},{134,138}}</string>
<key>offset</key>
<string>{-1,5}</string>
<key>rotated</key>
<true/>
<key>sourceColorRect</key>
<string>{{7,1},{134,138}}</string>
<key>sourceSize</key>
<string>{150,150}</string>
</dict>
<key>最终通关/theend2_weibo_normal.png</key>
<dict>
<key>frame</key>
<string>{{3698,2},{108,108}}</string>
<key>offset</key>
<string>{-2,2}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{19,19},{108,108}}</string>
<key>sourceSize</key>
<string>{150,150}</string>
</dict>
<key>最终通关/theend2_weibo_press.png</key>
<dict>
<key>frame</key>
<string>{{1828,62},{148,140}}</string>
<key>offset</key>
<string>{-1,5}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{148,140}}</string>
<key>sourceSize</key>
<string>{150,150}</string>
</dict>
<key>貌似通关/theend1_bg.png</key>
<dict>
<key>frame</key>
<string>{{2,672},{960,640}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{960,640}}</string>
<key>sourceSize</key>
<string>{960,640}</string>
</dict>
<key>貌似通关/theend1_bg_CN.png</key>
<dict>
<key>frame</key>
<string>{{1978,84},{588,128}}</string>
<key>offset</key>
<string>{0,235}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{186,21},{588,128}}</string>
<key>sourceSize</key>
<string>{960,640}</string>
</dict>
<key>貌似通关/theend1_bg_EN.png</key>
<dict>
<key>frame</key>
<string>{{1722,246},{954,170}}</string>
<key>offset</key>
<string>{-3,235}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{954,170}}</string>
<key>sourceSize</key>
<string>{960,640}</string>
</dict>
<key>貌似通关/theend1_bg_TW.png</key>
<dict>
<key>frame</key>
<string>{{1238,62},{588,128}}</string>
<key>offset</key>
<string>{0,235}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{186,21},{588,128}}</string>
<key>sourceSize</key>
<string>{960,640}</string>
</dict>
<key>貌似通关/theend1_btn_disable.png</key>
<dict>
<key>frame</key>
<string>{{1790,2},{198,58}}</string>
<key>offset</key>
<string>{0,2}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{11,19},{198,58}}</string>
<key>sourceSize</key>
<string>{220,100}</string>
</dict>
<key>貌似通关/theend1_btn_normal.png</key>
<dict>
<key>frame</key>
<string>{{1590,2},{198,58}}</string>
<key>offset</key>
<string>{0,2}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{11,19},{198,58}}</string>
<key>sourceSize</key>
<string>{220,100}</string>
</dict>
<key>貌似通关/theend1_btn_press.png</key>
<dict>
<key>frame</key>
<string>{{1390,2},{198,58}}</string>
<key>offset</key>
<string>{0,2}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{11,19},{198,58}}</string>
<key>sourceSize</key>
<string>{220,100}</string>
</dict>
<key>貌似通关/theend1_close_normal.png</key>
<dict>
<key>frame</key>
<string>{{2060,2},{68,68}}</string>
<key>offset</key>
<string>{1,3}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{17,3},{68,68}}</string>
<key>sourceSize</key>
<string>{100,80}</string>
</dict>
<key>貌似通关/theend1_close_pressed.png</key>
<dict>
<key>frame</key>
<string>{{1990,2},{68,68}}</string>
<key>offset</key>
<string>{1,3}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{17,3},{68,68}}</string>
<key>sourceSize</key>
<string>{100,80}</string>
</dict>
<key>貌似通关/theend1_tweibo_CN.png</key>
<dict>
<key>frame</key>
<string>{{1238,2},{150,48}}</string>
<key>offset</key>
<string>{-2,-2}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{33,28},{150,48}}</string>
<key>sourceSize</key>
<string>{220,100}</string>
</dict>
<key>貌似通关/theend1_tweibo_EN.png</key>
<dict>
<key>frame</key>
<string>{{1086,2},{150,48}}</string>
<key>offset</key>
<string>{1,-2}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{36,28},{150,48}}</string>
<key>sourceSize</key>
<string>{220,100}</string>
</dict>
<key>貌似通关/theend1_tweibo_TW.png</key>
<dict>
<key>frame</key>
<string>{{934,2},{150,48}}</string>
<key>offset</key>
<string>{-2,-2}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{33,28},{150,48}}</string>
<key>sourceSize</key>
<string>{220,100}</string>
</dict>
<key>貌似通关/theend1_wechat_CN.png</key>
<dict>
<key>frame</key>
<string>{{788,2},{144,46}}</string>
<key>offset</key>
<string>{-5,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{33,26},{144,46}}</string>
<key>sourceSize</key>
<string>{220,100}</string>
</dict>
<key>貌似通关/theend1_wechat_EN.png</key>
<dict>
<key>frame</key>
<string>{{650,2},{136,46}}</string>
<key>offset</key>
<string>{0,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{42,26},{136,46}}</string>
<key>sourceSize</key>
<string>{220,100}</string>
</dict>
<key>貌似通关/theend1_wechat_TW.png</key>
<dict>
<key>frame</key>
<string>{{504,2},{144,46}}</string>
<key>offset</key>
<string>{-5,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{33,26},{144,46}}</string>
<key>sourceSize</key>
<string>{220,100}</string>
</dict>
<key>貌似通关/theend1_weibo_CN.png</key>
<dict>
<key>frame</key>
<string>{{338,2},{164,42}}</string>
<key>offset</key>
<string>{-4,2}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{24,27},{164,42}}</string>
<key>sourceSize</key>
<string>{220,100}</string>
</dict>
<key>貌似通关/theend1_weibo_EN.png</key>
<dict>
<key>frame</key>
<string>{{168,2},{168,42}}</string>
<key>offset</key>
<string>{-2,2}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{24,27},{168,42}}</string>
<key>sourceSize</key>
<string>{220,100}</string>
</dict>
<key>貌似通关/theend1_weibo_TW.png</key>
<dict>
<key>frame</key>
<string>{{2,2},{164,42}}</string>
<key>offset</key>
<string>{-4,2}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{24,27},{164,42}}</string>
<key>sourceSize</key>
<string>{220,100}</string>
</dict>
</dict>
<key>metadata</key>
<dict>
<key>format</key>
<integer>2</integer>
<key>realTextureFileName</key>
<string>accomplish-hd.png</string>
<key>size</key>
<string>{4096,4096}</string>
<key>smartupdate</key>
<string>$TexturePacker:SmartUpdate:385f24a324f9dd1d25e26bd65515da44:536e814ddb5dc3875f0d8a8b5df6b8da:d5e849a57a87ef53e500130d77376857$</string>
<key>textureFileName</key>
<string>accomplish-hd.png</string>
</dict>
</dict>
</plist>