# 读取文件的方法 import json import os import win32api import win32con import pywintypes import shutil import re class PublicTools: """ 一些公用的基础方法 """ def delete_path(self, path): """ 删除指定路径的文件或者是文件夹 """ # 检查路径是否存在 if not os.path.exists(path): return # 检查路径是文件还是文件夹 if os.path.isfile(path): # 是文件,执行删除 try: os.remove(path) except Exception as e: raise e elif os.path.isdir(path): # 是文件夹,执行删除 try: shutil.rmtree(path) except Exception as e: raise e else: raise def list_files_by_extension(self, folder_path, extension): """ 读取指定文件夹下面的所有的指定拓展文件命的文件列表 """ file_list = [] for root, dirs, files in os.walk(folder_path): for file in files: if file.endswith(extension): file_list.append(os.path.join(root, file)) elif file.endswith(extension.upper()): file_list.append(os.path.join(root, file)) return file_list def get_fonts_from_registry(self, key_path): """ 获取注册表中安装的字体文件 """ font_names = [] try: key = win32api.RegOpenKeyEx( ( win32con.HKEY_LOCAL_MACHINE if "HKEY_LOCAL_MACHINE" in key_path else win32con.HKEY_CURRENT_USER ), key_path.split("\\", 1)[1], 0, win32con.KEY_READ, ) i = 0 while True: try: value = win32api.RegEnumValue(key, i) font_name = value[0] # 使用正则表达式移除括号及其内容 font_name = re.sub(r"\s*\([^)]*\)$", "", font_name) font_names.append(font_name) i += 1 except pywintypes.error as e: if e.winerror == 259: # 没有更多的数据 break else: raise finally: try: win32api.RegCloseKey(key) except: pass return font_names def get_installed_fonts(self): """ 获取字体文件名称并返回 """ system_fonts = self.get_fonts_from_registry( "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts" ) user_fonts = self.get_fonts_from_registry( "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts" ) all_fonts = list(set(system_fonts + user_fonts)) # 合并并去重 return all_fonts # 将RRGGBB转换为BBGGRR def convert_rrggbb_to_bbggrr(self, rrggbb): """ 将RRGGBB转换为BBGGRR """ if len(rrggbb) == 7: rr = rrggbb[1:3] gg = rrggbb[3:5] bb = rrggbb[5:7] return bb + gg + rr else: return "Invalid input" def write_to_file(self, arr, filename): with open(filename, "w",encoding='utf-8') as f: for item in arr: f.write("%s\n" % item) # 读取文件 def read_file(fileType): txt_path = input(f"输入{fileType}文件路径:") txt_path = remove_prefix_and_suffix(txt_path, '"', '"') while txt_path.strip() == "": txt_path = input(f"输入{fileType}文件路径:") while os.path.exists(txt_path) == False: print("文件路径不存在错误:") txt_path = input(f"输入{fileType}文件路径:") txt_path = remove_prefix_and_suffix(txt_path, '"', '"') return txt_path def format_time_ms(milliseconds): """ 时间转换将ms->小时:分钟:秒.毫秒格式 """ seconds = milliseconds / 1000 # 计算小时、分钟和秒 hours = int(seconds // 3600) minutes = int((seconds % 3600) // 60) seconds = seconds % 60 # 格式化字符串 # 使用`%02d`确保小时和分钟总是显示为两位数,`%.2f`确保秒数显示两位小数 formatted_time = f"{hours}:{minutes:02d}:{seconds:05.2f}" return formatted_time # 删除满足条件的开头和结尾 def remove_prefix_and_suffix(input_str, prefix_to_remove, suffix_to_remove): if input_str.startswith(prefix_to_remove): # 删除开头 input_str = input_str[len(prefix_to_remove) :] if input_str.endswith(suffix_to_remove): # 删除结尾 input_str = input_str[: -len(suffix_to_remove)] return input_str # 判断文件夹下面是不是有特定的文件夹 def check_if_folder_exists(parent_folder, target_folder_name): # 获取文件夹列表 subfolders = [f.name for f in os.scandir(parent_folder) if f.is_dir()] # 检查特定文件夹是否存在 if target_folder_name in subfolders: return True else: return False # 检查指定文件夹中是否存在特定文件。 def file_exists_in_folder(folder_path: str, file_name: str) -> bool: # 构建完整的文件路径 file_path = os.path.join(folder_path, file_name) # 返回文件是否存在 return os.path.isfile(file_path) # 秒数转换,保留一位小数 def convert_to_seconds(number, count): seconds = number / 1000000 rounded_number = round(seconds, count) return rounded_number def is_empty(obj): if obj is None: return True elif isinstance(obj, str): return len(obj) == 0 elif isinstance(obj, list): return len(obj) == 0 elif isinstance(obj, dict): return len(obj) == 0 return False def opt_dict(obj, key, default=None): if obj is None: return default if key in obj: v = obj[key] if not is_empty(v): return v return default def read_config(path, webui=True): with open(path, "r", encoding="utf-8") as f: runtime_config = json.load(f) if "config" not in runtime_config: print("no filed 'config' in json") return None config = runtime_config["config"] if "webui" not in config: print("no filed 'webui' in 'config'") return None setting_config_path = config["setting"] if not os.path.exists(setting_config_path): setting_config_path = "config/" + setting_config_path if not os.path.exists(setting_config_path): setting_config_path = "../" + setting_config_path # read config with open(setting_config_path, "r", encoding="utf-8") as f: setting_config = json.load(f) # set workspace parent:根目录 if "workspace" in setting_config: setting_config["workspace"]["parent"] = runtime_config["workspace"] else: setting_config["workspace"] = {"parent": runtime_config["workspace"]} setting_config["video"] = opt_dict(runtime_config, "video") # merge setting config if "setting" in config: setting_config.update(runtime_config["setting"]) # webui config if webui: webui_config_path = config["webui"] if not os.path.exists(webui_config_path): webui_config_path = "config/webui/" + webui_config_path if not os.path.exists(webui_config_path): webui_config_path = "../" + webui_config_path with open(webui_config_path, "r", encoding="utf-8") as f: webui_config = json.load(f) # merge webui config if "webui" in runtime_config: webui_config.update(runtime_config["webui"]) return webui_config, setting_config return setting_config TAG_MODE_NONE = "" # 工作路径 class Workspace: def __init__( self, root: str, input: str, output: str, input_crop: str, output_crop: str, input_tag: str, input_mask: str, input_crop_mask: str, crop_info: str, ): self.root = root self.input = input self.output = output self.input_crop = input_crop self.output_crop = output_crop self.input_tag = input_tag self.input_mask = input_mask self.input_crop_mask = input_crop_mask self.crop_info = crop_info # 定义一个倍数函数 def round_up(num, mul): return (num // mul + 1) * mul class SettingConfig: def __init__(self, config: dict, workParent): self.config = config self.webui_work_api = None self.workParent = workParent def to_dict(self): return self.__dict__ def get_tag_mode(self): tag_cfg = opt_dict(self.config, "tag") return opt_dict(tag_cfg, "mode", TAG_MODE_NONE) def get_tag_actions(self): tag_cfg = opt_dict(self.config, "tag") return opt_dict(tag_cfg, "actions", []) def get_workspace_config(self) -> Workspace: workspace_config = opt_dict(self.config, "workspace") tmp_config = opt_dict(workspace_config, "tmp") input = opt_dict(workspace_config, "input", "input") output = opt_dict(workspace_config, "output", "output") workspace_parent = self.workParent tmp_parent = opt_dict(tmp_config, "parent", "tmp") input_crop = opt_dict(tmp_config, "input_crop", "input_crop") output_crop = opt_dict(tmp_config, "output_crop", "output_crop") input_tag = opt_dict(tmp_config, "input_tag", "input_crop") input_mask = opt_dict(tmp_config, "input_mask", "input_mask") input_crop_mask = opt_dict(tmp_config, "input_crop_mask", "input_crop_mask") crop_info = opt_dict(tmp_config, "crop_info", "crop_info.txt") tmp_path = os.path.join(workspace_parent, tmp_parent) return Workspace( workspace_parent, os.path.join(workspace_parent, input), os.path.join(workspace_parent, output), os.path.join(tmp_path, input_crop), os.path.join(tmp_path, output_crop), os.path.join(tmp_path, input_tag), os.path.join(tmp_path, input_mask), os.path.join(tmp_path, input_crop_mask), os.path.join(tmp_path, crop_info), ) def enable_tag(self): tag_cfg = opt_dict(self.config, "tag") return opt_dict(tag_cfg, "enable", True)