find-object-art/check_zip_psd.py

405 lines
16 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

###-----检测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
# print(f'{psd.size}')
# 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}')
titem_name = 'titem'
tfull_name = 'tfull'
tmask_name = 'tmask'
tlight_name = 'tlight'
tshadow_name = 'tshadow'
group_name = 'group_'
all_items = []
all_full = {}
all_mask = []
all_tlight = []
all_tshadow = []
all_group = []
# 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_name 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_name 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 group_name in layer.name:
if not layer.is_group():
error_log.append(f'{psd_name}:{layer.name}:{config.error_log.group_name_error.value}')
elif layer.name in all_group:
error_log.append(f'{psd_name}:{layer.name}:{config.error_log.exit_repeat_group.value}')
else:
all_group.append(layer.name)
is_exit_full = False
for child_layer in layer:
if child_layer.is_group():
error_log.append(f'{psd_name}:{child_layer.name}:{config.error_log.child_layer_is_group.value}')
else:
if tfull_name in child_layer.name:
if child_layer.name in all_full.keys():
error_log.append(f'{psd_name}:{child_layer.name}:{config.error_log.exit_repeat_layer.value}')
else:
all_full[child_layer.name] = (child_layer.left, child_layer.top, child_layer.width, child_layer.height)
is_exit_full = True
elif tmask_name in child_layer.name:
if child_layer.name in all_mask:
error_log.append(f'{psd_name}:{child_layer.name}:{config.error_log.exit_repeat_layer.value}')
else:
all_mask.append(child_layer.name)
elif tshadow_name in child_layer.name:
if child_layer.name in all_tshadow:
error_log.append(f'{psd_name}:{child_layer.name}:{config.error_log.exit_repeat_layer.value}')
else:
all_tshadow.append(child_layer.name)
elif tlight_name in child_layer.name:
if child_layer.name in all_tlight:
error_log.append(f'{psd_name}:{child_layer.name}:{config.error_log.exit_repeat_layer.value}')
else:
all_tlight.append(child_layer.name)
else:
error_log.append(
f'{psd_name}:{child_layer.name}:{config.error_log.child_layer_unknown.value}')
if not is_exit_full:
error_log.append(f'{psd_name}:{layer.name}:{config.error_log.group_tfull_not_exit.value}')
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')
def find_layer_by_name(layers, target_name):
"""递归搜索图层中指定名称的图层"""
for layer in layers:
if layer.name == target_name:
return layer
if layer.is_group(): # 检查是否为组
found = find_layer_by_name(layer, target_name)
if found:
return found
return None
# 计算mask和full的遮罩百分比
for cur_mask in all_mask:
# img_mask = psd.composite(layer_filter=lambda mask_layer: mask_layer.name == cur_mask)
layer_mask = find_layer_by_name(psd,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)
layer_full = find_layer_by_name(psd, full_name)
if layer_mask is None or layer_full is None:
error_log.append(f'{psd_name}:{cur_mask}:{config.error_log.not_find_mask_full.value}')
break
img_mask = psd.composite(layer_mask)
img_full = psd.composite(layer_full)
# 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)