238 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Python
		
	
	
#!/usr/bin/python
 | 
						|
#encoding:utf-8
 | 
						|
 | 
						|
import os, sys
 | 
						|
import time
 | 
						|
 | 
						|
import cv2
 | 
						|
from psd_tools import PSDImage
 | 
						|
from PIL import Image, ImageFilter
 | 
						|
import numpy as np
 | 
						|
 | 
						|
import shutil
 | 
						|
 | 
						|
curr_dir = os.path.split(os.path.abspath(__file__))[0]
 | 
						|
sys.path.append(os.path.join(curr_dir,'../../'))
 | 
						|
 | 
						|
import utils
 | 
						|
import json
 | 
						|
import draw_outline
 | 
						|
 | 
						|
levels_root_path = os.path.join(curr_dir, "temp/Levels/")
 | 
						|
external_root_path = os.path.join(curr_dir, "external")
 | 
						|
 | 
						|
version_path = os.path.join(curr_dir, "psd_outline_version.json")
 | 
						|
 | 
						|
 | 
						|
PSD_DESIGN_WIDTH = 2080
 | 
						|
PSD_DESIGN_HEIGTH = 2560
 | 
						|
 | 
						|
TOTAL_OFFSET_ORIGIN = 16
 | 
						|
TOTAL_OFFSET = TOTAL_OFFSET_ORIGIN
 | 
						|
 | 
						|
#缩略图尺寸
 | 
						|
thumbnail_width = 480
 | 
						|
 | 
						|
scale = 0
 | 
						|
 | 
						|
versions = {}
 | 
						|
 | 
						|
def del_lines(psd_name):
 | 
						|
    dir_name = os.path.join(external_root_path, psd_name, "line")
 | 
						|
    if not os.path.exists(dir_name):
 | 
						|
        os.makedirs(dir_name)
 | 
						|
    # .system("rm -rf {}".format(dir_name))
 | 
						|
    shutil.rmtree(dir_name)
 | 
						|
 | 
						|
# def get_or_create_line_png(psd_name, num, sub, width, height):
 | 
						|
#     dir_name = os.path.join(external_root_path, psd_name, "line")
 | 
						|
#     line_path = os.path.join(dir_name, f"line_{num}_{sub}.png")
 | 
						|
#     if not os.path.exists(dir_name):
 | 
						|
#         os.makedirs(dir_name)
 | 
						|
 | 
						|
#     if not os.path.exists(line_path):
 | 
						|
#         draw_outline.generate_picture(line_path, height + TOTAL_OFFSET, width + TOTAL_OFFSET)
 | 
						|
#     return line_path
 | 
						|
 | 
						|
def crop_image(path, dest_path, new_height, new_width):
 | 
						|
    re_img = Image.open(path)
 | 
						|
    re_img = Image.fromarray(np.uint8(re_img))
 | 
						|
    scalex = thumbnail_width / re_img.width
 | 
						|
    scaley = thumbnail_width / re_img.height
 | 
						|
    scale = max(scalex, scaley)
 | 
						|
 | 
						|
    re_img = re_img.resize((int(re_img.width * scale), int(re_img.height * scale)), Image.ANTIALIAS)
 | 
						|
    width, height = re_img.size
 | 
						|
    left = (width - new_width)/2
 | 
						|
    top = (height - new_height)/2
 | 
						|
    right = (width + new_width)/2
 | 
						|
    bottom = (height + new_height)/2
 | 
						|
    crop_im = re_img.crop((left, top, right, bottom))
 | 
						|
    crop_im.save(dest_path, "png")
 | 
						|
 | 
						|
def export_outline(path):
 | 
						|
    global scale
 | 
						|
    global versions
 | 
						|
    global TOTAL_OFFSET
 | 
						|
 | 
						|
    file_name = os.path.split(path)[1]
 | 
						|
 | 
						|
    psd = PSDImage.open(path)
 | 
						|
 | 
						|
    max_width = 0
 | 
						|
    max_height = 0
 | 
						|
 | 
						|
    (filepath, filename) = os.path.split(path)
 | 
						|
    (psd_filename, filename_ext) = os.path.splitext(filename)
 | 
						|
    #只取前缀
 | 
						|
    filename_only = psd_filename.split("_")[0]
 | 
						|
 | 
						|
    #删除所有线条文件,重新生成
 | 
						|
    del_lines(psd_filename)
 | 
						|
 | 
						|
    for item in psd.descendants():
 | 
						|
        if not item.is_group():
 | 
						|
            nArr = item.name.split('_')
 | 
						|
 | 
						|
            if item.name == "base":
 | 
						|
                max_width = item.width
 | 
						|
                max_height = item.height
 | 
						|
                break
 | 
						|
 | 
						|
    TOTAL_OFFSET = int(TOTAL_OFFSET_ORIGIN * (max_width / PSD_DESIGN_WIDTH))
 | 
						|
 | 
						|
    for item in psd.descendants():
 | 
						|
        if not item.is_group():
 | 
						|
            item.visible = True
 | 
						|
            #按照原始比例导出
 | 
						|
            scale = 1
 | 
						|
 | 
						|
            nArr = item.name.split("_")
 | 
						|
            folder_path = ""
 | 
						|
            base_folder_name = ""
 | 
						|
            file_path = ""
 | 
						|
            save_path_pre = ""
 | 
						|
            item_name = item.name
 | 
						|
            mid_path = filename_only
 | 
						|
            if nArr[0] == "base" or nArr[0] == "line" or nArr[0] == "finish" or nArr[0] == "auto" or nArr[0] == "role":
 | 
						|
                continue
 | 
						|
            elif nArr[0] == "patch":
 | 
						|
                base_folder_name = "Atlas"
 | 
						|
                save_path_pre = levels_root_path
 | 
						|
            elif nArr[0] == "thumbnail":
 | 
						|
                continue
 | 
						|
 | 
						|
            folder_path = os.path.join(save_path_pre, mid_path, base_folder_name)
 | 
						|
            if not os.path.exists(folder_path):
 | 
						|
                os.makedirs(folder_path)
 | 
						|
            file_path = os.path.join(folder_path,  "{}.png".format(item_name))
 | 
						|
 | 
						|
            item.composite().save(file_path, compress_level=1, format='PNG', use_channel="RGBA", quality=95)
 | 
						|
 | 
						|
            # #缩略图不需要压缩
 | 
						|
            if nArr[0] != "thumbnail":
 | 
						|
                #根据设计分辨率重置尺寸
 | 
						|
                img = Image.open(file_path).convert('RGBA')
 | 
						|
                img = img.filter(ImageFilter.GaussianBlur(radius=1))
 | 
						|
                #防止无改变
 | 
						|
                img = img.resize((int(item.width * scale) + 1, int(item.height * scale) + 1), Image.ANTIALIAS)
 | 
						|
                img.save(file_path, "png")
 | 
						|
                #防止无改变
 | 
						|
                img = img.resize((int(item.width * scale), int(item.height * scale)), Image.ANTIALIAS)
 | 
						|
                # img.save(file_path, "png")
 | 
						|
 | 
						|
                # 打开图像文件并转换为 NumPy 数组
 | 
						|
                image = np.array(img.convert("RGBA"))
 | 
						|
 | 
						|
                # 获取 alpha 通道数据
 | 
						|
                alpha = image[:, :, 3]
 | 
						|
 | 
						|
                # 将 alpha 值小于等于 10 的像素的 alpha 值设为 0
 | 
						|
                alpha[alpha <= 20] = 0
 | 
						|
 | 
						|
                # 将修改后的 alpha 通道数据保存回原始数组
 | 
						|
                image[:, :, 3] = alpha
 | 
						|
 | 
						|
                # 将修改后的 NumPy 数组转换回图像并保存
 | 
						|
                Image.fromarray(image).save(file_path)
 | 
						|
 | 
						|
            if nArr[0] == "patch":
 | 
						|
                outline_file_path = draw_outline.draw_outline(file_path, TOTAL_OFFSET, int(nArr[2]))
 | 
						|
                
 | 
						|
                dir_name = os.path.join(external_root_path, psd_filename, "line")
 | 
						|
                if not os.path.exists(dir_name):
 | 
						|
                    os.makedirs(dir_name)
 | 
						|
                line_path = os.path.join(dir_name, f"line_{nArr[1]}_{nArr[2]}.png")
 | 
						|
 | 
						|
                shutil.copy(outline_file_path, line_path)
 | 
						|
                # draw_outline.paste(outline_file_path, line_path, 0, 0)
 | 
						|
 | 
						|
    shutil.rmtree(levels_root_path)
 | 
						|
 | 
						|
###生成version文件
 | 
						|
def make_version_file(remake):
 | 
						|
    version_file = os.path.join(curr_dir, version_path);
 | 
						|
    
 | 
						|
    if remake:
 | 
						|
        if os.path.exists(version_file):
 | 
						|
            os.remove(version_file)
 | 
						|
    
 | 
						|
    if not os.path.exists(version_file):
 | 
						|
        with open(version_file, "w") as f:
 | 
						|
            json.dump({}, f)
 | 
						|
 | 
						|
###加载版本文件
 | 
						|
def load_version():
 | 
						|
    global versions
 | 
						|
    make_version_file(False);
 | 
						|
    version_file = os.path.join(curr_dir, version_path);
 | 
						|
    with open(version_file, "r") as f:
 | 
						|
        try:
 | 
						|
            versions = json.load(f)
 | 
						|
        except:
 | 
						|
            #删除版本文件并重新生成
 | 
						|
            make_version_file(True);
 | 
						|
 | 
						|
def write_version():
 | 
						|
    version_file = os.path.join(curr_dir, version_path);
 | 
						|
    with open(version_file, "w") as f:
 | 
						|
        json.dump(versions, f)
 | 
						|
 | 
						|
def parse_psd(path):
 | 
						|
    load_version()
 | 
						|
    for root , dirs, files in os.walk(path):
 | 
						|
        for name in files:
 | 
						|
            if name.endswith(".psd") or name.endswith(".zip"):
 | 
						|
                src_filename = os.path.join(root, name)
 | 
						|
                
 | 
						|
                file_name = os.path.split(src_filename)[1]
 | 
						|
 | 
						|
                key = file_name.split("_")[0]
 | 
						|
                hash_old = ""
 | 
						|
                if key in versions:
 | 
						|
                    hash_old = versions[key]
 | 
						|
 | 
						|
                hash_now = utils.calc_hash(src_filename)
 | 
						|
 | 
						|
                if hash_old != hash_now:
 | 
						|
                    #如果是压缩文件,则先解压
 | 
						|
                    if name.endswith(".zip"):
 | 
						|
                        psd_zip_filename = os.path.join(root, name)
 | 
						|
                        utils.unzip_file(psd_zip_filename)
 | 
						|
                        psd_filename = "{}.psd".format(os.path.splitext(os.path.join(root, name))[0])
 | 
						|
                    else:
 | 
						|
                        psd_filename = src_filename
 | 
						|
 | 
						|
                    try:
 | 
						|
                        export_outline(psd_filename)
 | 
						|
                        versions[key] = hash_now
 | 
						|
                        write_version();
 | 
						|
                    except Exception as e:
 | 
						|
                        print(name + " 解析失败:" + repr(e))
 | 
						|
                    finally:
 | 
						|
                        #最后删除psd文件
 | 
						|
                        if psd_filename != "":
 | 
						|
                            os.remove(psd_filename)
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    parse_psd("./") |