from PIL import Image import os from config import Config from logger import logger class ImageProcessor: @staticmethod def resize_by_ratio(img, ratio_width, ratio_height): """等比例缩放至目标比例(最长边适配)""" w, h = img.size target_ratio = ratio_width / ratio_height current_ratio = w / h if current_ratio > target_ratio: new_w = int(h * target_ratio) new_h = h else: new_w = w new_h = int(w / target_ratio) return img.resize((new_w, new_h), Image.Resampling.LANCZOS) @staticmethod def resize_by_pixel(img, target_width, target_height): """等比例缩放至不超过目标像素(保持比例,以较长边为准)""" w, h = img.size ratio_w = target_width / w ratio_h = target_height / h ratio = min(ratio_w, ratio_h) new_w = int(w * ratio) new_h = int(h * ratio) return img.resize((new_w, new_h), Image.Resampling.LANCZOS) @staticmethod def convert_image(input_path, output_path, target_format, quality=None): """转换图片格式,可选缩放(尺寸解析在外部处理)""" try: with Image.open(input_path) as img: # 转换模式(RGBA转RGB对于JPEG) if target_format.lower() in ['jpg', 'jpeg'] and img.mode in ('RGBA', 'P'): rgb_img = Image.new('RGB', img.size, (255, 255, 255)) rgb_img.paste(img, mask=img.split()[-1] if img.mode == 'RGBA' else None) img = rgb_img save_kwargs = {} if target_format.lower() in ['jpg', 'jpeg', 'webp']: save_kwargs['quality'] = quality if quality is not None else Config.DEFAULT_QUALITY img.save(output_path, format=target_format.upper(), **save_kwargs) logger.info(f"转换成功: {input_path} -> {output_path}") return True except Exception as e: logger.error(f"转换失败 {input_path}: {e}") return False