提示:文章寫完後,目錄可以自動生成,如何生成可參考右邊的幫助文檔
文章目錄
- 前言
- 一、為什麼需要圖集打包?
- 二、使用python批量拆解plist格式檔案
-
- 1.引入庫
- 2.具體實作代碼
- 三、使用python批量拆解laya引擎圖集檔案
- 四、使用python批量拆解Egret引擎圖集檔案
- 附Gitee傳送位址
- Creator拆圖工具
- 總結
前言
因為學習需要制作遊戲,經常會在網上尋找一些資源進行學習,而一般資源分積分下載下傳源資源或者線上扒取别人的圖集資源。是以很多時候需要對一張合集圖進行拆分,今天主要講解有描述檔案的圖集拆分。
我常接觸的圖集格式一般是
CocosCreator TexturePacker .plst 格式的圖集
LayaBox .json ,atlas引擎自帶貼圖合集格式
Egret 引擎的.json圖集格式
一、為什麼需要圖集打包?
做過遊戲開發的童靴都知道紋理打包,用于下載下傳節約流量減少io操作。也能讓渲染合批提升性能。市面上常用打包工具TexturePacker,還有一些引擎自帶圖集打包的工具。
二、使用python批量拆解plist格式檔案
1.引入庫
代碼如下(示例):
Python庫主要依賴PIL下Image模闆對圖檔的操作
import os,sys
from xml.etree import ElementTree
from PIL import Image
reload(sys)
sys.setdefaultencoding('utf8')
2.具體實作代碼
代碼如下(示例):
#!python
# coding: utf-8
import os,sys
from xml.etree import ElementTree
from PIL import Image
reload(sys)
sys.setdefaultencoding('utf8')
def tree_to_dict(tree):
d = {}
for index, item in enumerate(tree):
if item.tag == 'key':
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 == 'integer':
d[item.text] = int(tree[index + 1].text)
elif tree[index+1].tag == 'dict':
d[item.text] = tree_to_dict(tree[index+1])
return d
def read_rect(dict):
return [dict['x'],dict['y'],dict['width'],dict['height']];
def gen_png_from_plist(filename, outPath):
plist_filename = filename + '.plist'
png_filename = filename + '.png'
if checkPath(plist_filename) == False or checkPath(png_filename) ==False:
print("don't find %s png or plist"%filename)
return
#擷取大圖
big_image = Image.open(png_filename)
#讀取plist
root = ElementTree.fromstring(open(plist_filename, 'r').read())
plist_dict = tree_to_dict(root[0])
to_list = lambda x: x.replace('{','').replace('}','').split(',')
to_int = lambda x:int(x)
for k,v in plist_dict['frames'].items():
if v.has_key('textureRect'):
textureRect = to_list(v['textureRect'])
elif v.has_key('frame'):
textureRect = to_list(v['frame'])
else:
textureRect = read_rect(v)
#獲得圖像尺寸
if v.has_key('spriteSize'):
spriteSize = v['spriteSize']
elif v.has_key('sourceSize'):
spriteSize = v['sourceSize']
elif v.has_key('spriteSourceSize'):
spriteSize = v['spriteSourceSize']
elif v.has_key("width"):
spriteSize = str(v['width']) + ',' + str(v['height'])
spriteSize = to_list(spriteSize)
spriteSize = map(to_int, spriteSize)
result_box = textureRect
#防止寬高小于0導緻錯誤
if spriteSize[0] <= 0 or spriteSize[1]<0 :
print "< 0"
continue
result_image = Image.new('RGBA', spriteSize, (0,0,0,0))
if (v.has_key('textureRotated') and v['textureRotated']) or (v.has_key('rotated') and v['rotated']):
result_box[0] = int(textureRect[0])
result_box[1] = int(textureRect[1])
result_box[2] = int(textureRect[0] + spriteSize[1])
result_box[3] = int(textureRect[1] + spriteSize[0])
else:
result_box[0] = int(textureRect[0])
result_box[1] = int(textureRect[1])
result_box[2] = int(textureRect[0] + spriteSize[0])
result_box[3] = int(textureRect[1] + spriteSize[1])
#獲得小圖
rect_on_big = big_image.crop(result_box)
# 有旋轉
if (v.has_key('textureRotated') and v['textureRotated']) or (v.has_key('rotated') and v['rotated']):
rect_on_big = rect_on_big.transpose(Image.ROTATE_90)
result_image.paste(rect_on_big)
if not os.path.isdir(outPath):
os.mkdir(outPath)
k = k.replace('/', '_')
outfile = (outPath+'/' + k).replace('gift_', '')
#print k
if outfile.find('.png') == -1:
outfile = outfile + '.png'
print outfile, "generated"
result_image.save(outfile)
def read_dir( path, outPath):
for name in os.listdir( path ):
if os.path.isdir( os.path.join(path, name) ):
find_file(os.path.join(path, name),outPath )
else:
portion = os.path.splitext(name)
if portion[1] == '.plist':
fileName = os.path.join(path, portion[0])
outDir = os.path.join(outPath, portion[0]);
gen_png_from_plist(fileName , outDir)
def checkPath(path):
if not os.path.exists( path ):
print "not find 1 %s"%path
return False
return True
if __name__ == '__main__':
if len( sys.argv ) < 2:
dirName = raw_input("Enter your DirName: ")
else:
dirName = sys.argv[1]
if len( sys.argv ) < 3:
outPath = raw_input("Enter your outPath: ")
else:
outPath = sys.argv[2]
outPath = os.path.join( os.getcwd(), outPath )
if not os.path.isdir( outPath ):
os.mkdir( outPath )
path = os.path.join(os.getcwd(),dirName)
if checkPath(path):
read_dir(path,outPath)
三、使用python批量拆解laya引擎圖集檔案
# coding: utf-8
import os
import sys
import json
import time
from PIL import Image
def checkPath(path):
if not os.path.exists( path ):
print "not find 1 %s"%path
return False
return True
def splitImage(path, fileName, outPath ):
# 檢查JSON檔案
jsonPath = os.path.join(path, "%s.json"%fileName )
if not os.path.exists( jsonPath ):
jsonPath = os.path.join( path, "%s.atlas"%(fileName ))
if not os.path.exists( jsonPath ):
print "not find 0 {}".format(jsonPath)
return
# 檢查PNG檔案
pngPath = os.path.join( path, "%s.png"%fileName )
if checkPath(pngPath) == False:
return
# 檢查輸出目錄
outPath = os.path.join( path, outPath )
if not os.path.isdir( outPath ):
os.mkdir( outPath )
# 取JSON檔案
f = open( jsonPath, 'r' )
fileStr = f.read()
f.close()
jsonData = json.loads( fileStr )
#檢查image集合
meta = jsonData.get( "meta" )
imageStr = meta.get( "image" )
#拆分檔案名
images = imageStr.split(",")
#拆分檔案名
images = imageStr.split(",")
imgList = []
#打開多個檔案準備切割
for img in images:
pngPath = os.path.join( path, img )
pngPath = pngPath.replace("~","-")
if not os.path.exists( pngPath ):
print "not find 2 %s"%pngPath
break;
imgList.append(Image.open( pngPath, 'r' ))
# 開始切圖
lastIdx = 0
frames = jsonData.get( "frames" )
for fn in frames.keys():
data = frames.get( fn )
frame = data.get( "frame" )
idx = frame.get( "idx" )
x = frame.get("x")
y = frame.get("y")
w = frame.get("w")
h = frame.get("h")
box = ( x, y, x+w, y+h )
outFile = os.path.join( outPath, fn )
imgData = imgList[idx].crop( box )
imgData.save( outFile, 'png' )
#讀取指定目錄
def find_file( path, outPath):
for name in os.listdir( path ):
if os.path.isdir( os.path.join(path, name) ):
find_file(os.path.join(path, name),outPath )
else:
portion = os.path.splitext(name)
if portion[1] == '.atlas' or portion[1] == '.json':
fileName = os.path.join(path, portion[0])
outDir = os.path.join(outPath, portion[0]);
splitImage(path,fileName , outDir)
if __name__=='__main__':
# 取得參數
if len( sys.argv ) < 2:
target = raw_input("Enter your DirName: ")
else:
target = sys.argv[1]
if len( sys.argv ) < 3:
outPath = raw_input("Enter your outPath: ")
else:
outPath = sys.argv[2]
outPath = os.path.join( os.getcwd(), outPath )
if not os.path.isdir( outPath ):
os.mkdir( outPath )
path = os.path.join(os.getcwd(),target)
if checkPath(path):
find_file(path,outPath)
四、使用python批量拆解Egret引擎圖集檔案
# coding: utf-8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
import os
import json
import time
from PIL import Image
def checkPath(path):
if not os.path.exists( path ):
print "not find 1 %s"%path
return False
return True
def splitImage(path, fileName, outPath ):
# 檢查JSON檔案
jsonPath = os.path.join( path, "%s.json"%fileName )
if not os.path.exists( jsonPath ):
print "not find %s"%jsonPath
return
# 檢查PNG檔案
pngPath = os.path.join( path, "%s.png"%fileName )
if not os.path.exists( pngPath ):
print "not find %s"%pngPath
return
# 檢查輸出目錄
if not os.path.isdir( outPath ):
os.mkdir( outPath )
# 取JSON檔案
f = open( jsonPath, 'r' )
fileStr = f.read()
f.close()
jsonData = json.loads( fileStr )
#檢查image集合
imgList = []
imageStr = jsonData.get( "file" )
img = Image.open(os.path.join(path,imageStr),'r')
imgList.append(img)
# 開始切圖
frames = jsonData.get( "frames" )
for fn in frames.keys():
data = frames.get( fn )
x = data.get("x")
y = data.get("y")
w = data.get("w")
h = data.get("h")
box = ( x, y, x+w, y+h )
outFile = os.path.join( outPath, fn )
imgData = imgList[0].crop( box )
# if imgData.mode == "P":
# imgData = imgData.convert('RGB')
outFile = outFile + ".png"
imgData.save( outFile )
#讀取指定目錄
def find_file( path, outPath):
for name in os.listdir( path ):
if os.path.isdir( os.path.join(path, name) ):
find_file(os.path.join(path, name),outPath )
else:
portion = os.path.splitext(name)
if portion[1] == '.json':
fileName = portion[0]
outDir = os.path.join(outPath, portion[0]);
splitImage( path ,fileName, outDir )
if __name__=='__main__':
# 取得參數
if len( sys.argv ) < 2:
dirName = raw_input("Enter your dirName: ")
else:
dirName = sys.argv[1]
if len( sys.argv ) < 3:
outPath = raw_input("Enter your outPath: ")
else:
outPath = sys.argv[2]
outPath = os.path.join( os.getcwd(), outPath )
if not os.path.isdir( outPath ):
os.mkdir( outPath )
path = os.path.join(os.getcwd(),dirName)
if checkPath(path):
# 開始切圖
find_file(path, outPath)
附Gitee傳送位址
倉庫傳送門
Creator拆圖工具
小弟因為平時使用creator開發比較多,是以在creator擴充商店上架了一個免費的插件工具目前隻做了windows系統的,歡迎各位下載下傳使用
總結
希望能幫到有需要的人。謝謝