python图集拆解(spine图集,plist图集)

网上有零散拆解图集的工具,没有整合的,也没有批量处理的,最近抽空,搞了一个整合并可以批量处理的工具,希望对大家有用。

加载配置文件

# 读取配置文件
con = configparser.ConfigParser()
# 读取当前目录下的config文件
con.read("config.ini",encoding="utf-8")
items=con.items('path')
# 解析出需要进行图片拆解的目录
pathOrigin = items[0][1]
# 需要存储解析后的目录
pathDes = items[1][1]

遍历源图片目录下的所有图片,根据类型辨别解析方式

# 遍历文件夹,如果是文件夹,在再往内部遍历
def recursive_listdir(path):
    files = os.listdir(path)
    for file in files:
        file_path = os.path.join(path, file)
        if os.path.isfile(file_path):
            if fileType == "atlas" :
                # 拆解spine的atlas文件
                SplitPng.split_atlas(file_path,pathDes)
            elif fileType == "plist":
                # 拆解plist文件
                SplitPng.split_plist(file_path,pathDes) 
        elif os.path.isdir(file_path):
            # 如果是子目录,继续往里面遍历
            recursive_listdir(file_path)

(spine)配置文件的解析

import re

# 读取spine的配置文件
def read_data(filepath):
    list = []
    arr = []
    with open(filepath,'r') as f:
        for lines in f.readlines():
            str = ''.join(lines.split())
            find = re.match(".*\.png.*",str)
            # 文件里面如果有png,说明是一张图片的新开始
            if find != None :
                arr = [str]
                list.append(arr)
            else:
                arr.append(str)
    return list

# 数据已经从文件中读取为列表形式,当前需要把数据进行整合,那些数据是一个图片的
def parse_data(arr):
    list = []
    for index in range(len(arr)):
        inputarr = arr[index]
        temparr = [inputarr[0]]
        list.append(temparr)

        print("---------------------------------")
        for index1 in range(5,len(inputarr)-1,7):
            # 图片名称
            spicinfo = {}
            temparr.append(spicinfo)
            spicinfo['name'] = inputarr[index1].replace('/','\\')
            for index2 in range(7):
                attri = inputarr[index1 + index2].split(':')
                if re.match('.*rotate.*',attri[0]) != None:
                    # 是否旋转
                    spicinfo['rotate'] = attri[1]
                elif re.match('.*size.*',attri[0]):
                    # 图集上单张图片的尺寸
                    spicinfo['size'] = attri[1].split(',')
                elif re.match('.*xy.*',attri[0]):
                    # 图集上单张图片的位置
                    spicinfo['position'] = attri[1].split(',')
                elif re.match('.*offset.*',attri[0]):
                    # 图集上单张图片在源图片上的偏移量
                    spicinfo['offset'] = attri[1].split(',')
                    # print(attri[0],"offset---------------")
                elif re.match('.*orig.*',attri[0]):
                    # 原始图片的尺寸
                    spicinfo['orisize'] = attri[1].split(',')
    return list   

# 外部调用(读取配置文件)
def read_atlas(filepath):
    list = read_data(filepath)
    return parse_data(list)

读取plist文件配置,这里仅支持了两个版本的plist,都是比较新的版本

from plistlib import load,FMT_XML
import json
import re

# 读取图片信息和图集上各个图片的数据
def read_data(filepath):
    print(filepath)
    with open(filepath,"rb") as fp:
        plist = load(fp,fmt=FMT_XML)
        # frames = plist["frames"]
        return plist["metadata"],plist["frames"]

# 将 '{12,12}'变为数组 [12,12]
def get_arr_by_str(str):
    mdata = re.search("([-]*[\d]+),([-]*[\d]+)",str)
    # print("bbbbb:",mdata.group(),str)
    if mdata != None :
        return mdata.group().split(',')
    return False

# 从map中获取某个key的值
def get_val_from_dic(dic,key):
    if key in dic:
        return dic[key]
    return False

# 从图集配置中,获取旋转角度
def get_rotate(dic,org):
    tempval = get_val_from_dic(dic,'rotated')
    if not tempval :
        tempval = get_val_from_dic(dic,'textureRotated')
    if tempval :
        org['rotate'] = str(tempval).lower()
    else:
        org['rotate'] = 'false'

# 从图集配置中,获取图片的原始尺寸
def get_origin_size(dic,org):
    tempval = get_val_from_dic(dic,'spriteSourceSize')
    if not tempval :
        tempval = get_val_from_dic(dic,'sourceSize')
    if tempval :
        org['orisize'] = get_arr_by_str(tempval)

# 从图集配置中,获取图片的原始尺寸
def get_offset(dic,org):
    tempval = get_val_from_dic(dic,'spriteOffset')
    if not tempval :
        tempval = get_val_from_dic(dic,'sourceColorRect')
        str = tempval.replace('{','')
        str = str.replace('}','')
        arr = str.split(',')
        tempval = arr[0]+','+arr[1]

    if tempval :
        org['offset'] = get_arr_by_str(tempval)

# 从图集配置中,获取图片在图集上的位置
def get_position_size(dic,org):
    tempval = get_val_from_dic(dic,'frame')
    if not tempval :
        tempval = get_val_from_dic(dic,'textureRect')
    if tempval :
        tempval = tempval.replace('{','')
        tempval = tempval.replace('}','')
        arr = tempval.split(',')
        org['position'] = [arr[0],arr[1]]
        org['size'] = [arr[2],arr[3]]

def parse_data(metadata,arr):
    list = []
    # 获取图片的名称
    frames = [metadata['realTextureFileName']]
    list.append(frames)
    # print(list)
    for key in arr:
        # print(key,arr[key])
        frame = {}
        frames.append(frame)

        frame['name'] = key.split('.')[0]
        data = arr[key]

        # 获取旋转数据
        get_rotate(data,frame)
        # 获取图片原始尺寸
        get_origin_size(data,frame)
        # 获取图片的偏移量
        get_offset(data,frame)
        # 获取图片的位置
        get_position_size(data,frame)

    return list

def read_plist(filepath):
    metadata,list = read_data(filepath)
    return parse_data(metadata,list)

开始拆解图片并保存

import AtlasFileReader
import PlistFileReader
import os
from PIL import Image

def create_dir(filepath):
    arr = filepath.split('\\')
    path = arr[0]
    # 逐级遍历,如果文件夹没有,则进行创建
    for index in range(1,len(arr)):
        path = path +'\\'+ arr[index]
        if not os.path.exists(path) :
            os.mkdir(path)

# 检测图片中是否包含路径,如果存在路径,则进行文件夹的创建
def check_create_dir(pathdir,name):
    # 如果名字中包含\,说明需要创建文件夹
    name = name.replace('/','\\')
    arrname = name.split('\\')
    temppath = pathdir
    print("检测是否创建文件夹:",pathdir,name)
    if len(arrname) > 1 :
        for pathindex in range(len(arrname)-1) :
            temppath = temppath + '\\' + arrname[pathindex]
    print("进行目录创建:",temppath)
    create_dir(temppath)

# 进行图片拆解
def split_png(filepath,arr,pathdes,isatlas):
    # 读取图片的路径,filename中只有文件名,而没有文件的类型
    filename = os.path.basename(filepath).split('.')[0]
    abspath = os.path.dirname(filepath)
    for index in range(len(arr)):
        arr1 = arr[index]
        # 拼接读取图片的路径
        path = abspath+'\\'+arr1[0]
        print("加载图片进行拆解:",path)
        # 判断是否有文件
        if not os.path.exists(path) :
            print('未找到资源:',path)
            continue
        img = Image.open(path)
        # 遍历这个图片上的各个小图的信息
        for index1 in range(1,len(arr1)):
            data = arr1[index1]
            # 取出一个大图中,某个小图的配置数据
            name = data['name']
            # 创建文件夹
            check_create_dir(pathdes+'\\'+filename,name)

            # 构建截图区域
            pos = data['position']
            offset = data['offset']
            size = data['size']
            # 在图集上是否进行了旋转
            rotate = data['rotate']
            orisize = data['orisize']

            # 在图集上的位置
            x = int(pos[0])
            y = int(pos[1])
            # 在图集上的图片尺寸,有可能是去除了透明区域
            w = int(size[0])
            h = int(size[1])
            # 原始的图片尺寸
            ow = int(orisize[0])
            oh = int(orisize[1])
            # 图集上的图片在原始图片上的偏移量
            ox = int(offset[0])
            oy = int(offset[1])

            # 开始保存图片
            if rotate == 'true':
                # 根据原始图片尺寸,进行创建,验收模式,尺寸,验收默认值
                resImg = Image.new("RGBA",(oh,ow),(0,0,0,0))
                # 图集上的区域
                box = (x,y,x+h,y+w)
                recImg = img.crop(box)
                # 将图集上的图片,粘贴到原始图片尺寸上,需要加上偏移量,目标位置的起点与终点位置,并非x,y,width,heigh
                # 而是 lx,ly,rx,ry
                lx = oy
                ly = ox
                rx = lx + h
                ry = ly + w
                resImg.paste(recImg,(lx,ly,rx,ry))
                if isatlas :
                    resImg = resImg.transpose(Image.ROTATE_270)
                else:
                    resImg = resImg.transpose(Image.ROTATE_90)
                    
                resImg.save(pathdes+'\\'+filename+'\\'+name+'.png')
            else:
                # 根据原始图片尺寸,进行创建,验收模式,尺寸,验收默认值
                resImg = Image.new("RGBA",(ow,oh),(0,0,0,0))
                # 图集上的区域
                box = (x,y,x+w,y+h)
                recImg = img.crop(box)
                lx = ox
                ly = oy
                rx = lx + w
                ry = ly + h
                resImg.paste(recImg,(lx,ly,rx,ry))
                resImg.save(pathdes+'\\'+filename+'\\'+name+'.png')

# 外部调用,解析atlas文件
def split_atlas(filepath,pathdes):
    list = AtlasFileReader.read_atlas(filepath)
    split_png(filepath,list,pathdes,True)

# 外部调用,解析plist文件
def split_plist(filepath,pathdes):
    list = PlistFileReader.read_plist(filepath)
    split_png(filepath,list,pathdes,False)

下载地址:https://download.csdn.net/download/wushi333333/88540646

有问题,可以发邮件给:wushi333333@163.com或者V:wuahi333333

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值