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