121 lines
4.0 KiB
Python
121 lines
4.0 KiB
Python
|
|
#!/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)
|