python批量解包spine 图集.atlas
python批量解包spine 图集.atlas
·
# -*- coding: utf-8 -*-
import os
import os.path
from PIL import Image
import tkinter as tk
from tkinter import filedialog
from tqdm import tqdm
def premultiply_alpha(image):
'''
若输出的贴图文件应用了预乘alpha
:param image:
:return:
'''
if image.mode != "RGBA":
image = image.convert("RGBA")
for i in range(image.width):
for j in range(image.height):
red, green, blue, alpha = image.getpixel((i,j))
if alpha > 0:
image.putpixel((i,j),tuple([min(max(int(p / alpha * 255),0), 255) for p in (red, green, blue)]+[alpha]))
return image
def split_atlas(fileName, output_path:str=None, atlas_path:str=None):
'''
:param fileName: 文件名
:param output_path: 输出目录
:param atlas_path: 图集.atlas文件
:return:
'''
if output_path is None:
output_path = os.path.join(os.getcwd(), fileName)
if atlas_path is None:
atlas_path = fileName + '.atlas'
with open(atlas_path, 'r',encoding='utf-8-sig') as atlas:
os.makedirs(output_path, exist_ok=True)
for i in range(6):
if i==1:
png_name = atlas.readline().strip("\n")
png_path = os.path.join(os.path.split(atlas_path)[0],png_name)
ori_image = Image.open(png_path)
elif i==2:
big_image_size = atlas.readline()
big_image_width, big_image_height = list(map(int, big_image_size.split(":")[1].split(",")))
big_image = ori_image.resize((big_image_width, big_image_height))
else:
_line = atlas.readline()
while True:
line1 = atlas.readline() # name
if len(line1) == 0:
break
elif len(line1.strip("\n")) == 0:
continue
elif line1.strip("\n").endswith('.png'):
png_name = line1.strip("\n")
png_path = os.path.join(os.path.split(atlas_path)[0], png_name)
ori_image = Image.open(png_path)
for i in range(4):
if i == 0:
big_image_size = atlas.readline()
big_image_width, big_image_height = list(map(int, big_image_size.split(":")[1].split(",")))
big_image = ori_image.resize((big_image_width, big_image_height))
else:
_line = atlas.readline()
else:
line1 = line1.strip("\n")
rotate = atlas.readline().split(":")[1].strip("\n")
xy = atlas.readline() # xy
size = atlas.readline() # size
orig = atlas.readline() # orig
offset = atlas.readline().strip("\n") # offset
index = atlas.readline() # index
rotate = rotate.strip(" ")
if rotate == "true":
rotate_angle = 90
elif rotate == "false":
rotate_angle = 0
else:
rotate_angle = int(rotate)
rotate = rotate_angle > 0
name = line1.replace("\n", "") + ".png"
if '/' in name:
os.makedirs(os.path.join(output_path, '/'.join(name.split('/')[:-1])), exist_ok=True)
width,height = list(map(int,size.split(":")[1].split(",")))
ltx,lty = list(map(int,xy.split(":")[1].split(",")))
origx, origy = list(map(int, orig.split(":")[1].split(",")))
offset_x,offset_y = list(map(int,offset.split(":")[1].split(",")))
if rotate_angle==0 or rotate_angle==180:
rbx = ltx + width
rby = lty + height
elif rotate_angle==90 :
rbx = ltx + height
rby = lty + width
elif rotate_angle==270:
rbx = ltx + height
rby = lty + width
#print(name, width, height, ltx, lty, rbx, rby)
result_image = Image.new("RGBA", (origx, origy))
rect_on_big = big_image.crop((ltx, lty, rbx, rby))
if rotate:
rect_on_big = rect_on_big.rotate(-rotate_angle,expand=True)
if premultiply:
rect_on_big = premultiply_alpha(rect_on_big)
result_image.paste(rect_on_big, (offset_x, origy-height-offset_y))
result_image.save(output_path + '/' + name)
if __name__ == '__main__':
input_path = filedialog.askdirectory(title="选择需要批量解包的目录")
pbar = tqdm(os.listdir(input_path))
for file in pbar:
pbar.set_description(f"Solving {file} ...")
if os.path.isdir(os.path.join(input_path,file)):
unitName = os.path.split(file)[1]
outputPath = os.path.join(input_path,file)
split_atlas(unitName,output_path=outputPath,atlas_path=os.path.join(outputPath,unitName+'.atlas'))
部分素材.png实际尺寸与.atlas内描述的尺寸不一致,直接拉伸即可(代码已包含该操作)
抠抠qun:622095682,欢迎游戏开发爱好者加入交流
参考资料:
python切割图片,读取spine的atlas转json配置(python2)https://blog.csdn.net/wclwonder/article/details/90543862
Spine的纹理压缩和半透显示(什么是预乘Alpha)https://zhuanlan.zhihu.com/p/76077345
正确的spine导出/导入参数匹配http://zh.esotericsoftware.com/spine-unity#Advanced
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献1条内容
所有评论(0)