359 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			359 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
| ###-----检测psd是否合格,通过的psd压缩-----
 | ||
| 
 | ||
| import os
 | ||
| import time
 | ||
| import config
 | ||
| from psd_tools import PSDImage
 | ||
| from PIL import Image
 | ||
| import json
 | ||
| import utils
 | ||
| import sys
 | ||
| 
 | ||
| curr = os.path.dirname(sys.argv[0])
 | ||
| if curr != "":
 | ||
|     os.system("cd " + curr)
 | ||
| 
 | ||
| 
 | ||
| def check_psd(psd_path):
 | ||
|     psd_name = os.path.split(psd_path)[1]
 | ||
|     names = psd_name.split('_')
 | ||
|     log(f'开始检测:{psd_name}')
 | ||
|     error_log = []
 | ||
|     if len(names) != 3 and len(names) != 4:
 | ||
|         error_log.append(config.error_log.psd_name_error.value)
 | ||
|     # elif not names[0][0].islower():
 | ||
|     #     error_log.append(f'{psd_name}:{config.error_log.psd_name_error.value}')
 | ||
|     # elif not names[1][0].islower():
 | ||
|     #     error_log.append(f'{psd_name}:{config.error_log.psd_name_error.value}')
 | ||
|     # elif not names[2][0].isdigit():
 | ||
|     #     error_log.append(f'{psd_name}:{config.error_log.psd_name_error.value}')
 | ||
| 
 | ||
|     psd = PSDImage.open(psd_path)
 | ||
| 
 | ||
|     color_mode = get_psd_color_mode(psd_path)
 | ||
|     if color_mode == 'CMYK':
 | ||
|         error_log.append(f'{psd_name}:{config.error_log.psd_cmyk.value}')
 | ||
|         print("PSD 文件的色彩空间是 CMYK")
 | ||
|     # elif color_mode == 'RGB':
 | ||
|     #     print("PSD 文件的色彩空间是 RGB")
 | ||
| 
 | ||
|     psd_width = psd.width
 | ||
|     psd_height = psd.height
 | ||
| 
 | ||
|     if (psd_width != config.psd_standard_width and psd_width != config.psd_standard_width2) or (psd_height != config.psd_standard_height and psd_height != config.psd_standard_height2):
 | ||
|         error_log.append(f'{psd_name}:{config.error_log.psd_size_error.value}')
 | ||
| 
 | ||
|     all_items = []
 | ||
|     all_full = {}
 | ||
|     all_mask = []
 | ||
|     all_tlight = []
 | ||
|     all_tshadow = []
 | ||
|     all_color_it_full = []
 | ||
|     all_color_it_item = []
 | ||
|     is_exist_base = False
 | ||
|     is_exist_titem_group = False
 | ||
|     all_occlusion_degree = []
 | ||
| 
 | ||
|     for layer in psd:
 | ||
|         if ' ' in layer.name:
 | ||
|             error_log.append(f'{psd_name}:{layer.name}:{config.error_log.name_contains_spaces.value}')
 | ||
|         if layer.name == 'nouse' and layer.is_group():
 | ||
|             continue
 | ||
|         if layer.name == 'titem' and layer.is_group():
 | ||
|             is_exist_titem_group = True
 | ||
|             for item_layer in layer:
 | ||
|                 if ' ' in item_layer.name:
 | ||
|                     error_log.append(f'{psd_name}:{item_layer.name}:{config.error_log.name_contains_spaces.value}')
 | ||
|                 # item_names = item_layer.name.split('_')
 | ||
|                 if 'titem' in item_layer.name:
 | ||
|                     if item_layer.name in all_items or item_layer.name in all_color_it_item:
 | ||
|                         error_log.append(f'{psd_name}:{item_layer.name}:{config.error_log.exit_repeat_layer.value}')
 | ||
|                     else:
 | ||
|                         if 'titemcolor' in item_layer.name:
 | ||
|                             all_color_it_item.append(item_layer.name)
 | ||
|                         else:
 | ||
|                             all_items.append(item_layer.name)
 | ||
|                 else:
 | ||
|                     error_log.append(f'{psd_name}:{item_layer.name}:{config.error_log.psd_item_name_error.value}')
 | ||
|         elif not layer.is_group() and 'tfull' in layer.name:
 | ||
|             if layer.name in all_full.keys() or layer.name in all_color_it_full:
 | ||
|                 error_log.append(f'{psd_name}:{layer.name}:{config.error_log.exit_repeat_layer.value}')
 | ||
|             else:
 | ||
|                 if 'tfullcolor' in layer.name:
 | ||
|                     all_color_it_full.append(layer.name)
 | ||
|                 else:
 | ||
|                     all_full[layer.name] = (layer.left, layer.top, layer.width, layer.height)
 | ||
|         elif not layer.is_group() and 'tmask' in layer.name:
 | ||
|             if layer.name in all_mask:
 | ||
|                 error_log.append(f'{psd_name}:{layer.name}:{config.error_log.exit_repeat_layer.value}')
 | ||
|             else:
 | ||
|                 all_mask.append(layer.name)
 | ||
|         elif not layer.is_group() and 'tlight' in layer.name:
 | ||
|             if layer.name in all_tlight:
 | ||
|                 error_log.append(f'{psd_name}:{layer.name}:{config.error_log.exit_repeat_layer.value}')
 | ||
|             else:
 | ||
|                 all_tlight.append(layer.name)
 | ||
|         elif not layer.is_group() and 'tshadow' in layer.name:
 | ||
|             if layer.name in all_tshadow:
 | ||
|                 error_log.append(f'{psd_name}:{layer.name}:{config.error_log.exit_repeat_layer.value}')
 | ||
|             else:
 | ||
|                 all_tshadow.append(layer.name)
 | ||
|         elif layer.name == 'base':
 | ||
|             if is_exist_base:
 | ||
|                 error_log.append(f'{psd_name}:{config.error_log.exit_more_base.value}')
 | ||
|             else:
 | ||
|                 is_exist_base = True
 | ||
|         else:
 | ||
|             error_log.append(f'{psd_name}:{layer.name}:{config.error_log.layer_not_need.value}')
 | ||
| 
 | ||
|     if not is_exist_base:
 | ||
|         error_log.append(f'{psd_name}:{config.error_log.psd_not_exit_base.value}')
 | ||
|     if not is_exist_titem_group:
 | ||
|         error_log.append(f'{psd_name}:{config.error_log.item_group_not_exit.value}')
 | ||
| 
 | ||
|     all_item_count = len(all_items)
 | ||
|     if len(all_full) != all_item_count or (
 | ||
|             len(all_color_it_item) != 0 and len(all_color_it_item) != all_item_count) or (
 | ||
|             len(all_color_it_full) != 0 and len(all_color_it_full) != all_item_count):
 | ||
|         error_log.append(f'{psd_name}:{config.error_log.item_or_full_num_error.value}')
 | ||
| 
 | ||
|     for item in all_items:
 | ||
|         full_name = item.replace('item', 'full')
 | ||
|         if full_name not in all_full.keys():
 | ||
|             error_log.append(f'{psd_name}:{item}:{config.error_log.psd_not_full.value}')
 | ||
|     if len(all_color_it_item) > 0 and len(all_color_it_full) > 0:
 | ||
|         for item in all_items:
 | ||
|             fullcolor_name = item.replace('item', 'fullcolor')
 | ||
|             itemcolor_name = item.replace('item', 'itemcolor')
 | ||
|             if fullcolor_name not in all_color_it_full:
 | ||
|                 error_log.append(f'{psd_name}:{item}:{config.error_log.psd_not_fullcolor.value}')
 | ||
|             if itemcolor_name not in all_color_it_item:
 | ||
|                 error_log.append(f'{psd_name}:{item}:{config.error_log.psd_not_itemcolor.value}')
 | ||
| 
 | ||
|     # if not os.path.exists('./test'):
 | ||
|     #     os.mkdir('./test')
 | ||
| 
 | ||
|     # 计算mask和full的遮罩百分比
 | ||
|     for cur_mask in all_mask:
 | ||
|         img_mask = psd.composite(layer_filter=lambda mask_layer: mask_layer.name == cur_mask)
 | ||
|         full_name = cur_mask.replace('mask', 'full')
 | ||
|         cur_full_rect = None
 | ||
|         if full_name in all_full.keys():
 | ||
|             cur_full_rect = all_full[full_name]
 | ||
|             img_full = psd.composite(layer_filter=lambda full_layer: full_layer.name == full_name)
 | ||
|             # img_mask.save(f'./test/{cur_mask}.png')
 | ||
|             # img_full.save(f'./test/{full_name}.png')
 | ||
|             per = get_item_mask_contact_ratio(img_full, img_mask, cur_full_rect)
 | ||
|             all_occlusion_degree.append(f'{cur_mask}遮挡{full_name}百分比:{per}\n')
 | ||
|             # print(f'{cur_mask}遮挡{full_name}百分比:{per}')
 | ||
|         else:
 | ||
|             error_log.append(f'{psd_name}:{cur_mask}:{config.error_log.psd_mask_not_full.value}')
 | ||
| 
 | ||
|     is_error = len(error_log) > 0
 | ||
|     is_error_text = '否' if is_error else '是'
 | ||
|     if is_error:
 | ||
|         error_psd_dic[psd_name] = error_log
 | ||
|     log(f'{psd_name}:检测完毕,是否检测通过:{is_error_text}')
 | ||
|     for clog in error_log:
 | ||
|         log(clog)
 | ||
| 
 | ||
|     if not is_error:
 | ||
|         occlusion_degree_file_path = f'./OcclusionDegree/{psd_name}.txt'
 | ||
|         if not os.path.exists('./OcclusionDegree/'):
 | ||
|             os.mkdir('./OcclusionDegree/')
 | ||
|         if not os.path.exists(occlusion_degree_file_path):
 | ||
|             with open(occlusion_degree_file_path, 'w') as occlusion_degree_file:
 | ||
|                 for text in all_occlusion_degree:
 | ||
|                     occlusion_degree_file.writelines(text)
 | ||
|                 pass
 | ||
| 
 | ||
|     return len(error_log) == 0
 | ||
| 
 | ||
| 
 | ||
| def get_item_mask_contact_ratio(full_image, mask_image, full_rect):
 | ||
|     # full_image = full_image.convert('RGBA')
 | ||
|     # mask_image = mask_image.convert('RGBA')
 | ||
|     x, y, w, h = full_rect
 | ||
|     full_pix_count = 0
 | ||
|     mask_pix_count = 0
 | ||
|     for cur_x in range(x, x + w):
 | ||
|         for cur_y in range(y, y + h):
 | ||
|             full_pix = full_image.getpixel((cur_x, cur_y))
 | ||
|             mask_pix = mask_image.getpixel((cur_x, cur_y))
 | ||
|             if not full_pix == (255, 255, 255, 0):
 | ||
|                 full_pix_count += 1
 | ||
|                 if not mask_pix == (255, 255, 255, 0) and not mask_pix == full_pix:
 | ||
|                     mask_pix_count += 1
 | ||
|     # print(f'mask_pix_count::: {mask_pix_count}')
 | ||
|     # print(f'full_pix_count  {full_pix_count}')
 | ||
|     percentage = "{:.2%}".format(float(mask_pix_count) / float(full_pix_count))
 | ||
|     return percentage
 | ||
| 
 | ||
| 
 | ||
| def log(content, new_line=True):
 | ||
|     curr_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
 | ||
|     if new_line:
 | ||
|         print(curr_time + ' ' + content)
 | ||
|     else:
 | ||
|         print(curr_time + ' ' + content, end=' ')
 | ||
| 
 | ||
| 
 | ||
| ###生成version文件
 | ||
| def make_version_file(remake):
 | ||
|     version_file = 'version.json';
 | ||
| 
 | ||
|     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, sort_keys=True, indent=4)
 | ||
| 
 | ||
| 
 | ||
| ###加载版本文件
 | ||
| def load_version():
 | ||
|     global versions
 | ||
|     make_version_file(False);
 | ||
|     with open('version.json', 'r') as f:
 | ||
|         try:
 | ||
|             versions = json.load(f)
 | ||
|         except:
 | ||
|             # 删除版本文件并重新生成
 | ||
|             make_version_file(True);
 | ||
| 
 | ||
| 
 | ||
| def write_version():
 | ||
|     with open('version.json', 'w') as f:
 | ||
|         json.dump(versions, f, sort_keys=True, indent=4)
 | ||
| 
 | ||
| 
 | ||
| def convert_2_zip_file(path, is_name_end_zip=False):
 | ||
|     file_info_arr = os.path.split(path)
 | ||
|     file_path = file_info_arr[0]
 | ||
|     psd_name = os.path.split(path)[1].replace('.psd', '')
 | ||
|     psd_type = psd_name.split('_')[0]
 | ||
|     if is_name_end_zip:
 | ||
|         psd_path = os.path.join('./', file_info_arr[1])
 | ||
|         os.chdir(file_path)
 | ||
|         # 检测成功,压缩到zip
 | ||
|         utils.zip_file(psd_path, f'./{psd_name}.zip')
 | ||
|         os.remove(psd_path)
 | ||
|         os.chdir('../')
 | ||
|         os.chdir('../')
 | ||
|     else:
 | ||
|         zip_out_path = os.path.join('./Level', psd_type)
 | ||
|         if not os.path.exists(zip_out_path):
 | ||
|             os.mkdir(zip_out_path)
 | ||
|         psd_path = os.path.join('./', file_info_arr[1])
 | ||
|         os.chdir(file_path)
 | ||
|         # 检测成功,压缩到zip
 | ||
|         utils.zip_file(psd_path, f'../{zip_out_path}/{psd_name}.zip')
 | ||
|         os.remove(psd_path)
 | ||
|         os.chdir('../')
 | ||
| 
 | ||
| def get_psd_color_mode(psd_path):
 | ||
|     with open(psd_path, "rb") as f:
 | ||
|         # 读取文件头信息
 | ||
|         header = f.read(24)
 | ||
| 
 | ||
|         # 获取颜色模式字节
 | ||
|         color_mode_byte = header[10]
 | ||
| 
 | ||
|         if color_mode_byte == 0:
 | ||
|             return "Bitmap"
 | ||
|         elif color_mode_byte == 2:
 | ||
|             return "RGB"
 | ||
|         elif color_mode_byte == 4:
 | ||
|             return "CMYK"
 | ||
|         else:
 | ||
|             return "Unknown"
 | ||
| 
 | ||
| 
 | ||
| if __name__ == '__main__':
 | ||
|     global all_psd_count
 | ||
|     all_psd_count = 0
 | ||
|     global pass_psd_count
 | ||
|     pass_psd_count = 0
 | ||
|     global no_change_psd_count
 | ||
|     no_change_psd_count = 0
 | ||
|     global error_psd_dic
 | ||
|     error_psd_dic = {}
 | ||
|     global zip_fail_count
 | ||
|     zip_fail_count = 0
 | ||
|     global re_zip_count
 | ||
|     re_zip_count = 0
 | ||
| 
 | ||
|     load_version()
 | ||
|     psd_name_list = []
 | ||
|     is_force = sys.argv[1] if len(sys.argv) > 1 else False
 | ||
|     # is_force = True
 | ||
|     for root, dirs, files in os.walk('./'):
 | ||
|         for name in files:
 | ||
|             cur_file_path = os.path.join(root, name)
 | ||
| 
 | ||
|             if name.endswith('.psd'):
 | ||
|                 all_psd_count += 1
 | ||
| 
 | ||
|             if name.endswith('.psd') or name.endswith('.zip'):
 | ||
|                 file_info_arr = os.path.split(cur_file_path)
 | ||
|                 file_path = file_info_arr[0]
 | ||
|                 psd_name = file_info_arr[1]
 | ||
|                 if psd_name not in psd_name_list:
 | ||
|                     psd_name_list.append(psd_name)
 | ||
|                 else:
 | ||
|                     log("存在重复名称关卡:{}".format(psd_name))
 | ||
|             else:
 | ||
|                 continue
 | ||
| 
 | ||
|             if name.endswith('.psd') or (name.endswith('.zip') and is_force):
 | ||
|                 file_info_arr = os.path.split(cur_file_path)
 | ||
|                 file_path = file_info_arr[0]
 | ||
|                 psd_name = file_info_arr[1]
 | ||
| 
 | ||
|                 hash_old = ""
 | ||
|                 if psd_name in versions:
 | ||
|                     hash_old = versions[psd_name]
 | ||
| 
 | ||
|                 is_zip = name.endswith('.zip')
 | ||
|                 if os.path.exists(cur_file_path):
 | ||
|                     hash_now = ""
 | ||
|                     if name.endswith('.psd'):
 | ||
|                         hash_now = utils.calc_hash(cur_file_path)
 | ||
|                     if hash_now != hash_old or is_force:
 | ||
|                         psd_file_path = cur_file_path
 | ||
|                         if is_zip:
 | ||
|                             utils.unzip_file(cur_file_path)
 | ||
|                             psd_file_path = "{}.psd".format(os.path.splitext(psd_file_path)[0])
 | ||
|                             hash_now = utils.calc_hash(psd_file_path)
 | ||
|                         try:
 | ||
|                             is_passed = check_psd(psd_file_path)
 | ||
|                             if is_passed:
 | ||
|                                 # 检测成功,压缩到zip
 | ||
|                                 convert_2_zip_file(psd_file_path, is_zip)
 | ||
|                                 if is_zip:
 | ||
|                                     re_zip_count += 1
 | ||
|                                 versions[psd_name] = hash_now
 | ||
|                                 write_version()
 | ||
|                                 if name.endswith('.psd'):
 | ||
|                                     pass_psd_count += 1
 | ||
|                         except Exception as e:
 | ||
|                             zip_fail_count += 1
 | ||
|                             log(f'检测或者压缩失败::{psd_file_path},{e}')
 | ||
|                             error_psd_dic[psd_name] = [f'{psd_file_path},{e}']
 | ||
|                     elif hash_now == hash_old:
 | ||
|                         no_change_psd_count += 1
 | ||
|                         convert_2_zip_file(cur_file_path, is_zip)
 | ||
|     log(f'psd压缩完毕,总共psd数量:{all_psd_count}')
 | ||
|     log(f'成功压缩新增psd个数:{pass_psd_count}')
 | ||
|     log(f'成功压缩无改动psd个数:{no_change_psd_count}')
 | ||
|     log(f'未检测通过psd个数:{len(error_psd_dic)}')
 | ||
|     log(f'重新压缩psd数量:{re_zip_count}')
 | ||
|     log(f'压缩失败个数:{zip_fail_count}')
 | ||
|     if len(error_psd_dic) > 0:
 | ||
|         log(f'以下psd出现问题:')
 | ||
|         for error_psd_name, error_psd_log in error_psd_dic.items():
 | ||
|             log(f'psd名称:{error_psd_name}')
 | ||
|             for error_log in error_psd_log:
 | ||
|                 log(error_log)
 |