#!/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("./")