plist解包

首页 / 代码库 / 正文

us:D:\python37\python .\go.py C:\Users\38795\Desktop\TextureTailor-1.0\testplist plist

#!python
import os
import sys
from PIL import Image
from xml.etree import ElementTree
import json
import plistlib


if Image is None:
    print('library <<<pillow>>> is not install. please run cmd #[ pip install pillow ] first!')
    exit(-1)

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 == 'dict':
                d[item.text] = tree_to_dict(tree[index + 1])
    return d

def get_data_extension_by_format(format):
    if format == 'json':
        return '.json'
    else: return '.plist'

def get_data_filename(filename, format):
    data_filename = filename + get_data_extension_by_format(format)
    return data_filename

def frames_from_data(filename, format):
    data_filename = get_data_filename(filename, format)
    if format == 'plist':
        root = ElementTree.fromstring(open(data_filename, 'r').read())
        plist_dict = tree_to_dict(root[0])
        to_list = lambda x: x.replace('{', '').replace('}', '').split(',')
        frames = plist_dict['frames'].items()
        for k, v in frames:
            frame = v
            rectlist = to_list(frame['frame'])
            width = int(rectlist[3] if frame['rotated'] else rectlist[2])
            height = int(rectlist[2] if frame['rotated'] else rectlist[3])
            frame['box'] = (
                int(rectlist[0]),
                int(rectlist[1]),
                int(rectlist[0]) + width,
                int(rectlist[1]) + height
            )
            real_rectlist = to_list(frame['sourceSize'])
            real_width = int(real_rectlist[1] if frame['rotated'] else real_rectlist[0])
            real_height = int(real_rectlist[0] if frame['rotated'] else real_rectlist[1])
            real_sizelist = [real_width, real_height]
            frame['real_sizelist'] = real_sizelist
            offsetlist = to_list(frame['offset'])
            offset_x = int(offsetlist[1] if frame['rotated'] else offsetlist[0])
            offset_y = int(offsetlist[0] if frame['rotated'] else offsetlist[1])
            frame['result_box'] = (
                int((real_sizelist[0] - width) / 2 + offset_x),
                int((real_sizelist[1] - height) / 2 + offset_y),
                int((real_sizelist[0] + width) / 2 + offset_x),
                int((real_sizelist[1] + height) / 2 + offset_y)
            )
        return frames
    elif format == 'json':
        json_data = open(data_filename)
        data = json.load(json_data)
        frames = {}
        for f in data['frames']:
            x = int(f['frame']['x'])
            y = int(f['frame']['y'])
            w = int(f['frame']['h'] if f['rotated'] else f['frame']['w'])
            h = int(f['frame']['w'] if f['rotated'] else f['frame']['h'])
            real_w = int(f['sourceSize']['h'] if f['rotated'] else f['sourceSize']['w'])
            real_h = int(f['sourceSize']['w'] if f['rotated'] else f['sourceSize']['h'])
            d = {
                'box': (
                    x,
                    y,
                    x + w,
                    y + h
                ),
                'real_sizelist': [
                    real_w,
                    real_h
                ],
                'result_box': (
                    int((real_w - w) / 2),
                    int((real_h - h) / 2),
                    int((real_w + w) / 2),
                    int((real_h + h) / 2)
                ),
                'rotated': f['rotated']
            }
            frames[f['filename']] = d
        json_data.close()
        return frames.items()
    elif format == 'cocos':
        pl = plistlib.readPlist(data_filename)
        data = pl['frames'].items()
        frames = {}
        for k, f in data:
            x = int(f['x'])
            y = int(f['y'])
            w = int(f['width'])
            h = int(f['height'])
            real_w = int(f['originalWidth'])
            real_h = int(f['originalHeight'])
            d = {
                'box': (
                    x,
                    y,
                    x + w,
                    y + h
                ),
                'real_sizelist': [
                    real_w,
                    real_h
                ],
                'result_box': (
                    int((real_w - w) / 2),
                    int((real_h - h) / 2),
                    int((real_w + w) / 2),
                    int((real_h + h) / 2)
                ),
                'rotated': False
            }
            frames[k] = d
        return frames.items()
    else:
        print('Wrong data format on parsing: '' + format + ''!')
        exit(1)


def gen_png_from_data(filename, format):
    big_image = Image.open(filename + '.png')
    frames = frames_from_data(filename, format)
    for k, v in frames:
        frame = v
        box = frame['box']
        outfile = (filename + '/' + k).replace('gift_', '')
        rect_on_big = big_image.crop(box)
        real_sizelist = frame['real_sizelist']
        # make folder and get output file name
        dirname = os.path.dirname(outfile)
        if not os.path.isdir(dirname):
            os.makedirs(dirname)

        # if frame['rotated']:
        #     rect_on_big = rect_on_big.rotate(angle=90, expand=1)
        # rect_on_big.save(outfile)

        result_image = Image.new('RGBA', real_sizelist, (0, 0, 0, 0))
        result_box = frame['result_box']
        result_image.paste(rect_on_big, result_box, mask=0)
        if frame['rotated']:
            result_image = result_image.rotate(angle=90, expand=1)
        result_image.save(outfile)
        print(outfile, "generated")

def find_all_file_with_extensions(filepath, ext):
    #遍历filepath下所有文件,包括子目录
    files = os.listdir(filepath)
    ret = []
    for fi in files:
        fi_d = os.path.join(filepath,fi)
        if os.path.isdir(fi_d):
            tmp = find_all_file_with_extensions(fi_d, ext)
            for v in tmp:
                ret.append(v)
        else:
            file_ext = os.path.splitext(fi_d)
            if file_ext[1] == ext:
                ret.append(fi_d)
            else:
                print('skip file [' + fi_d + ']');
    return ret

def unpack_file(filename, format = 'plist'):
    if format == 'plist':
        print('.plist data format passed')
    elif format == 'json':
        print('.json data format passed')
    elif format == 'cocos':
        print('.cocos data format passed')
    else:
        print('Wrong data format passed '' + format + ''!')
        exit(1)

    data_filename = get_data_filename(filename, format)
    png_filename = filename + '.png'
    if os.path.exists(data_filename) and os.path.exists(png_filename):
        gen_png_from_data(filename, format)
    else:
        print('Make sure you have both ' + data_filename + ' and ' + png_filename + ' files in the same directory')

def print_usage():
    print(sys.argv[0] + '<file name without extension or folder path> <format (plist|cocos|json)>')

if __name__ == '__main__':
    if sys.argv.__len__() <= 2:
        print_usage()
        exit(-1)
    if os.path.isdir(sys.argv[1]):
        filelst = find_all_file_with_extensions(sys.argv[1], get_data_extension_by_format(sys.argv[2]))
        for file in filelst:
            unpack_file(os.path.splitext(file)[0], sys.argv[2])
    else:
        unpack_file(sys.argv[1], sys.argv[2])
无标签

鲁公网安备 37131202371610号