gitea_ap_art_assets/export_outline.py

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