#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 海报生成器模块 """ import os import logging import random from typing import List, Dict, Any, Optional, Union, Tuple from pathlib import Path from PIL import Image from core.config import ConfigManager, PosterConfig from utils.file_io import OutputManager from .templates.base_template import BaseTemplate from .templates.vibrant_template import VibrantTemplate from .templates.business_template import BusinessTemplate from .templates.collage_template import CollageTemplate from .utils import ImageProcessor logger = logging.getLogger(__name__) class PosterGenerator: """ 海报生成器 负责根据文本内容和配置生成海报图像 """ def __init__(self, config_manager: ConfigManager, output_manager: OutputManager): """ 初始化海报生成器 Args: config_manager: 配置管理器 output_manager: 输出管理器 """ self.config_manager = config_manager self.config = config_manager.get_config('poster', PosterConfig) self.output_manager = output_manager self.image_processor = ImageProcessor() # 注册可用的模板 self.templates = { "vibrant": VibrantTemplate, "business": BusinessTemplate, "collage": CollageTemplate, } def generate_poster(self, content: Dict[str, Any], topic_index: Union[int, str], template_name: Optional[str] = None) -> Optional[str]: """ 为指定内容生成海报 Args: content: 内容数据,包含标题、正文等 topic_index: 主题索引,用于文件命名 template_name: 模板名称,如果为None则根据配置选择 Returns: 生成的海报文件路径,如果生成失败则返回None """ logger.info(f"开始为主题 {topic_index} 生成海报...") # 1. 选择模板 if not template_name: template_name = self._select_template() if template_name not in self.templates: logger.error(f"模板 '{template_name}' 不存在") return None template_class = self.templates[template_name] template = template_class(self.config.target_size) # 2. 准备内容 title = content.get('title', '') text_content = content.get('content', '') if not title or not text_content: logger.error("内容缺少标题或正文") return None # 3. 生成海报 try: poster_image = template.generate(title, text_content) # 4. 保存海报 output_dir = self.output_manager.get_topic_dir(topic_index) file_name = f"poster_{template_name}.png" file_path = output_dir / file_name poster_image.save(file_path) logger.info(f"海报已保存到: {file_path}") return str(file_path) except Exception as e: logger.error(f"生成海报时发生错误: {e}", exc_info=True) return None def _select_template(self) -> str: """根据配置选择模板""" selection_method = self.config.template_selection available_templates = self.config.available_templates # 过滤出实际可用的模板 valid_templates = [t for t in available_templates if t in self.templates] if not valid_templates: logger.warning("没有可用的模板,使用默认模板") return next(iter(self.templates.keys())) if selection_method == "random": return random.choice(valid_templates) elif selection_method in valid_templates: return selection_method else: logger.warning(f"无效的模板选择方法 '{selection_method}',使用随机选择") return random.choice(valid_templates)