diff --git a/api/config/poster_config_manager.py b/api/config/poster_config_manager.py index 337d6d3..0ef0693 100644 --- a/api/config/poster_config_manager.py +++ b/api/config/poster_config_manager.py @@ -71,7 +71,7 @@ class PosterConfigManager: "id": template_id, "name": template_info.get("name", template_id), "description": template_info.get("description", ""), - "size": template_info.get("size", [900, 1200]), + "size": template_info.get("size", [1350, 1800]), "required_fields": template_info.get("required_fields", []), "optional_fields": template_info.get("optional_fields", []) } diff --git a/api/config/poster_prompts.yaml b/api/config/poster_prompts.yaml index 9f5bd54..a7b69ea 100644 --- a/api/config/poster_prompts.yaml +++ b/api/config/poster_prompts.yaml @@ -80,7 +80,7 @@ templates: vibrant: name: "Vibrant活力模板" description: "适合旅游景点、娱乐活动的活力海报模板" - size: [900, 1200] + size: [1350, 1800] required_fields: ["title", "slogan", "price", "ticket_type", "content_items"] optional_fields: ["remarks", "tag", "pagination"] prompt_key: "vibrant" diff --git a/api/models/vibrant_poster.py b/api/models/vibrant_poster.py index c1b6218..44347a5 100644 --- a/api/models/vibrant_poster.py +++ b/api/models/vibrant_poster.py @@ -26,7 +26,7 @@ class TemplateInfo(BaseModel): "id": "vibrant", "name": "Vibrant活力模板", "description": "适合旅游景点、娱乐活动的活力海报模板", - "size": [900, 1200], + "size": [1350, 1800], "required_fields": ["title", "slogan", "price", "ticket_type", "content_items"], "optional_fields": ["remarks", "tag", "pagination"] } @@ -189,7 +189,7 @@ class PosterGenerationResponse(BaseAPIResponse): "metadata": { "image_used": "/data/images/ocean_park.jpg", "generation_method": "ai_generated", - "template_size": [900, 1200], + "template_size": [1350, 1800], "processing_time": 3.2 } } @@ -243,7 +243,7 @@ class TemplateListResponse(BaseAPIResponse): "id": "vibrant", "name": "Vibrant活力模板", "description": "适合旅游景点、娱乐活动的活力海报模板", - "size": [900, 1200], + "size": [1350, 1800], "required_fields": ["title", "slogan", "price"], "optional_fields": ["remarks", "tag"] } diff --git a/api/services/__pycache__/poster.cpython-312.pyc b/api/services/__pycache__/poster.cpython-312.pyc index 59e7092..b5ce636 100644 Binary files a/api/services/__pycache__/poster.cpython-312.pyc and b/api/services/__pycache__/poster.cpython-312.pyc differ diff --git a/api/services/poster.py b/api/services/poster.py index 330747f..0a6360a 100644 --- a/api/services/poster.py +++ b/api/services/poster.py @@ -232,7 +232,7 @@ class PosterService: # # 3. 图片解码 images = None # 获取模板的默认尺寸,如果获取不到则使用标准尺寸 - template_size = getattr(template_handler, 'size', (900, 1200)) + template_size = getattr(template_handler, 'size', (1350, 1800)) if images_base64 and len(images_base64) > 0: try: @@ -694,7 +694,7 @@ class PosterService: """ try: # 获取图像尺寸 - image_size = [images.width, images.height] if hasattr(images, 'width') else [900, 1200] + image_size = [images.width, images.height] if hasattr(images, 'width') else [1350, 1800] # 生成Fabric.js JSON数据 fabric_json = self._generate_fabric_json(content, template_id, image_size, images) diff --git a/api/services/poster_service.py b/api/services/poster_service.py index 90df043..76cb094 100644 --- a/api/services/poster_service.py +++ b/api/services/poster_service.py @@ -54,7 +54,7 @@ class UnifiedPosterService: id=template_id, name=template_info.get("name", template_id), description=template_info.get("description", ""), - size=template_info.get("size", [900, 1200]), + size=template_info.get("size", [1350, 1800]), required_fields=template_info.get("required_fields", []), optional_fields=template_info.get("optional_fields", []) ) diff --git a/config/poster_gen.json b/config/poster_gen.json index f02c981..ff7f279 100644 --- a/config/poster_gen.json +++ b/config/poster_gen.json @@ -27,7 +27,7 @@ "topic_index": 0, "variant_index": 1, "template": "business", - "size": [900, 1200], + "size": [1350, 1800], "generate_text": false, "params": { "top_image_path": "resource/data/images/hotel1.jpg", @@ -52,7 +52,7 @@ "topic_index": 1, "variant_index": 0, "template": "collage", - "size": [900, 1200], + "size": [1350, 1800], "generate_text": false, "params": { "image_paths": [ diff --git a/core/config/__pycache__/models.cpython-312.pyc b/core/config/__pycache__/models.cpython-312.pyc index 16b50c2..e1f56c6 100644 Binary files a/core/config/__pycache__/models.cpython-312.pyc and b/core/config/__pycache__/models.cpython-312.pyc differ diff --git a/core/config/models.py b/core/config/models.py index 030aeb1..ec675a2 100644 --- a/core/config/models.py +++ b/core/config/models.py @@ -157,7 +157,7 @@ class AIModelConfig(BaseConfig): class PosterConfig(BaseConfig): """海报生成配置""" - target_size: List[int] = Field(default_factory=lambda: [900, 1200]) + target_size: List[int] = Field(default_factory=lambda: [1350, 1800]) additional_images_enabled: bool = True template_selection: str = "random" # random, business, vibrant, original available_templates: List[str] = Field(default_factory=lambda: ["original", "business", "vibrant"]) diff --git a/demo_refactored_templates.py b/demo_refactored_templates.py index e44c886..77c27bf 100644 --- a/demo_refactored_templates.py +++ b/demo_refactored_templates.py @@ -1164,7 +1164,7 @@ class ImageProcessor: class BaseTemplate(ABC): """海报模板基类""" - def __init__(self, size: Tuple[int, int] = (900, 1200)): + def __init__(self, size: Tuple[int, int] = (1350, 1800)): """ 初始化基础模板 @@ -1562,7 +1562,7 @@ class BaseTemplate(ABC): class VibrantTemplate(BaseTemplate): """活力风格海报模板(基于海洋模块)""" - def __init__(self, size: Tuple[int, int] = (900, 1200)): + def __init__(self, size: Tuple[int, int] = (1350, 1800)): """ 初始化活力模板 @@ -2384,7 +2384,7 @@ class VibrantTemplate(BaseTemplate): "备注和标签支持", "智能字体大小调整" ], - "recommended_size": (900, 1200), + "recommended_size": (1350, 1800), "final_size": (1350, 1800), "style": "海洋活力风格", "theme_colors": list(self.ocean_config['ocean_colors'].keys()), @@ -2458,12 +2458,12 @@ class VibrantTemplate(BaseTemplate): class BusinessTemplate(BaseTemplate): """商务风格海报模板(基于酒店模块)""" - def __init__(self, size: Tuple[int, int] = (900, 1200)): + def __init__(self, size: Tuple[int, int] = (1350, 1800)): """ 初始化商务模板 Args: - size: 海报尺寸,默认为酒店模块的尺寸 (900, 1200) + size: 海报尺寸,默认为酒店模块的尺寸 (1350, 1800) """ super().__init__(size) diff --git a/poster/templates/__pycache__/base_template.cpython-312.pyc b/poster/templates/__pycache__/base_template.cpython-312.pyc index 2626a2a..d97869c 100644 Binary files a/poster/templates/__pycache__/base_template.cpython-312.pyc and b/poster/templates/__pycache__/base_template.cpython-312.pyc differ diff --git a/poster/templates/__pycache__/business_template.cpython-312.pyc b/poster/templates/__pycache__/business_template.cpython-312.pyc index 9f29339..e8f2575 100644 Binary files a/poster/templates/__pycache__/business_template.cpython-312.pyc and b/poster/templates/__pycache__/business_template.cpython-312.pyc differ diff --git a/poster/templates/__pycache__/vibrant_template.cpython-312.pyc b/poster/templates/__pycache__/vibrant_template.cpython-312.pyc index 923852a..260d23d 100644 Binary files a/poster/templates/__pycache__/vibrant_template.cpython-312.pyc and b/poster/templates/__pycache__/vibrant_template.cpython-312.pyc differ diff --git a/poster/templates/base_template.py b/poster/templates/base_template.py index 3632a48..ee1e8e4 100644 --- a/poster/templates/base_template.py +++ b/poster/templates/base_template.py @@ -22,7 +22,7 @@ class BaseTemplate(ABC): 定义了模板的通用接口和基础功能。 """ - def __init__(self, size: Tuple[int, int] = (900, 1200), font_dir: str = "/root/autodl-tmp/TCC_RESTRUCT/assets/font"): + def __init__(self, size: Tuple[int, int] = (1350, 1800), font_dir: str = "/root/autodl-tmp/TCC_RESTRUCT/assets/font"): self.width, self.height = size self.size = size self.image_processor = ImageProcessor() diff --git a/poster/templates/business_template.py b/poster/templates/business_template.py index a913e75..e944017 100644 --- a/poster/templates/business_template.py +++ b/poster/templates/business_template.py @@ -26,7 +26,7 @@ class BusinessTemplate(BaseTemplate): 特点是上下图片融合,中间为信息展示区,整体风格沉稳、专业。 """ - def __init__(self, size: Tuple[int, int] = (900, 1200)): + def __init__(self, size: Tuple[int, int] = (1350, 1800)): super().__init__(size) self.config = { 'total_parts': 4.0, diff --git a/poster/templates/vibrant_template.py b/poster/templates/vibrant_template.py index b1c7d2b..e377de4 100644 --- a/poster/templates/vibrant_template.py +++ b/poster/templates/vibrant_template.py @@ -22,7 +22,7 @@ class VibrantTemplate(BaseTemplate): 活力风格模板,适用于色彩鲜艳、内容丰富的场景,如旅游、美食分享。 特点是底部有毛玻璃效果的文案区域。 """ - def __init__(self, size: Tuple[int, int] = (900, 1200)): + def __init__(self, size: Tuple[int, int] = (1350, 1800)): super().__init__(size) self.config = { 'colors': { @@ -38,7 +38,7 @@ class VibrantTemplate(BaseTemplate): 'glass_effect': { 'max_opacity': 240, 'blur_radius': 22, - 'transition_height': 80, + 'transition_height': 120, 'intensity_multiplier': 1.5 }, } @@ -71,7 +71,7 @@ class VibrantTemplate(BaseTemplate): **kwargs): """ 生成Vibrant风格海报,支持统一渲染 - + Args: images (List): 主图 content (Optional[Dict[str, Any]]): 包含所有文本信息的字典 @@ -148,8 +148,7 @@ class VibrantTemplate(BaseTemplate): canvas = self._create_composite_image(main_image, gradient_start, theme_color) canvas = self._render_texts(canvas, content, gradient_start) - final_image = canvas.resize((1350, 1800), Image.LANCZOS) - return final_image + return canvas def _get_default_content(self) -> Dict[str, Any]: """获取默认的测试内容""" @@ -174,24 +173,24 @@ class VibrantTemplate(BaseTemplate): def _estimate_content_height(self, content: Dict[str, Any]) -> int: """预估内容高度""" - standard_margin = 25 - title_height = 100 - subtitle_height = 80 - button_height = 40 + standard_margin = 38 + title_height = 150 + subtitle_height = 120 + button_height = 60 content_items = content.get("content_items", []) - content_line_height = 32 + content_line_height = 48 content_list_height = len(content_items) * content_line_height - price_height = 90 - ticket_height = 60 + price_height = 135 + ticket_height = 90 remarks = content.get("remarks", []) if isinstance(remarks, str): remarks = [remarks] - remarks_height = len(remarks) * 25 + 10 - footer_height = 40 + remarks_height = len(remarks) * 38 + 15 + footer_height = 60 total_height = ( 20 + title_height + standard_margin + subtitle_height + standard_margin + - button_height + 15 + content_list_height + price_height + ticket_height + - remarks_height + footer_height + 30 + button_height + 23 + content_list_height + price_height + ticket_height + + remarks_height + footer_height + 45 ) return total_height @@ -211,7 +210,7 @@ class VibrantTemplate(BaseTemplate): except: continue if gradient_start is None: - bottom_margin = 60 + bottom_margin = 90 gradient_start = max(height - estimated_height - bottom_margin, height // 2) return gradient_start @@ -297,7 +296,7 @@ class VibrantTemplate(BaseTemplate): return top_color, bottom_color def _calculate_optimal_font_size_enhanced(self, text: str, target_width: int, - max_size: int = 120, min_size: int = 10) -> Tuple[int, int]: + max_size: int = 180, min_size: int = 15) -> Tuple[int, int]: """ 计算文本的最佳字体大小,使其宽度接近目标宽度(增强版本,与demo一致) @@ -382,7 +381,7 @@ class VibrantTemplate(BaseTemplate): left_margin, right_margin = self._calculate_content_margins(content, width, center_x) - footer_y = height - 30 + footer_y = height - 45 self._render_footer(draw, content, footer_y, left_margin, right_margin) title_y = gradient_start + 40 @@ -404,7 +403,7 @@ class VibrantTemplate(BaseTemplate): title_text = content.get("title", "") title_target_width = int(width * 0.95) title_size, title_width = self._calculate_optimal_font_size_enhanced( - title_text, title_target_width, min_size=40, max_size=130 + title_text, title_target_width, min_size=60, max_size=195 ) title_x = center_x - title_width // 2 @@ -412,26 +411,26 @@ class VibrantTemplate(BaseTemplate): slogan_text = content.get("slogan", "") subtitle_target_width = int(width * 0.9) subtitle_size, subtitle_width = self._calculate_optimal_font_size_enhanced( - slogan_text, subtitle_target_width, max_size=50, min_size=20 + slogan_text, subtitle_target_width, max_size=75, min_size=30 ) subtitle_x = center_x - subtitle_width // 2 # 计算内容区域边距 - 减小额外的边距,让内容区域更宽 - padding = 20 # 从30减小到20 + padding = 30 # 从30减小到20,现在按1.5倍调整到30 content_left_margin = min(title_x, subtitle_x) - padding content_right_margin = max(title_x + title_width, subtitle_x + subtitle_width) + padding # 确保边距不超出合理范围,但允许更宽的内容区域 - content_left_margin = max(40, content_left_margin) - content_right_margin = min(width - 40, content_right_margin) + content_left_margin = max(60, content_left_margin) + content_right_margin = min(width - 60, content_right_margin) # 如果内容区域太窄,强制使用更宽的区域 min_content_width = int(width * 0.75) # 至少使用75%的宽度 current_width = content_right_margin - content_left_margin if current_width < min_content_width: extra_width = min_content_width - current_width - content_left_margin = max(30, content_left_margin - extra_width // 2) - content_right_margin = min(width - 30, content_right_margin + extra_width // 2) + content_left_margin = max(45, content_left_margin - extra_width // 2) + content_right_margin = min(width - 45, content_right_margin + extra_width // 2) return content_left_margin, content_right_margin @@ -450,7 +449,7 @@ class VibrantTemplate(BaseTemplate): title_text = content.get("title", "默认标题") title_target_width = int((right - left) * 0.98) title_size, title_actual_width = self._calculate_optimal_font_size_enhanced( - title_text, title_target_width, max_size=140, min_size=40 + title_text, title_target_width, max_size=210, min_size=60 ) title_font = self.text_renderer._load_default_font(title_size) @@ -463,14 +462,14 @@ class VibrantTemplate(BaseTemplate): subtitle_text = content.get("slogan", "") subtitle_target_width = int((right - left) * 0.95) subtitle_size, subtitle_actual_width = self._calculate_optimal_font_size_enhanced( - subtitle_text, subtitle_target_width, max_size=75, min_size=20 + subtitle_text, subtitle_target_width, max_size=113, min_size=30 ) subtitle_font = self.text_renderer._load_default_font(subtitle_size) sub_text_w, sub_text_h = self.text_renderer.get_text_size(subtitle_text, subtitle_font) subtitle_x = center_x - sub_text_w // 2 - title_spacing = 30 + title_spacing = 45 # 在标题下方添加装饰线 line_y = y + text_h + 5 @@ -490,7 +489,7 @@ class VibrantTemplate(BaseTemplate): button_text = content.get("content_button", "套餐内容") button_width, _ = self.text_renderer.get_text_size(button_text, button_font) button_width += 40 - button_height = 50 + button_height = 75 self.text_renderer.draw_rounded_rectangle(draw=draw, position=(x, y), size=(button_width, button_height), radius=20, fill_color=(0, 140, 210, 180), outline_color=(255, 255, 255, 255), outline_width=1) draw.text((x + 20, y + (button_height - 30) // 2), button_text, font=button_font, fill=(255, 255, 255)) @@ -513,7 +512,7 @@ class VibrantTemplate(BaseTemplate): price_text = str(content.get('price', '')) # 确保价格是字符串类型 price_target_width = int((right_margin - x) * 0.7) price_size, price_actual_width = self._calculate_optimal_font_size_enhanced( - price_text, price_target_width, max_size=120, min_size=40 + price_text, price_target_width, max_size=180, min_size=60 ) price_font = self.text_renderer._load_default_font(price_size) @@ -533,7 +532,7 @@ class VibrantTemplate(BaseTemplate): ticket_text = content.get("ticket_type", "") ticket_target_width = int((right_margin - x) * 0.7) ticket_size, ticket_actual_width = self._calculate_optimal_font_size_enhanced( - ticket_text, ticket_target_width, max_size=60, min_size=30 + ticket_text, ticket_target_width, max_size=90, min_size=45 ) ticket_font = self.text_renderer._load_default_font(ticket_size) ticket_x = right_margin - ticket_actual_width @@ -596,10 +595,10 @@ class VibrantTemplate(BaseTemplate): # === 第一步:创建与常规模式完全相同的最终结果作为Reference === canvas = self._create_composite_image(main_image, gradient_start, theme_color) canvas = self._render_texts(canvas, content, gradient_start) - final_canvas = canvas.resize((1350, 1800), Image.LANCZOS) + final_canvas = canvas # === 第二步:为PSD创建可编辑的图层版本 === - final_size = (1350, 1800) + final_size = self.size psd = PSDImage.new("RGBA", final_size, color=(0, 0, 0, 0)) logger.info(f"创建PSD文档,尺寸: {final_size}") @@ -690,7 +689,7 @@ class VibrantTemplate(BaseTemplate): # 4. 左栏内容层 title_y = gradient_start + 40 - subtitle_height = 80 + 30 # 预估副标题高度 + subtitle_height = 120 + 30 # 预估副标题高度 content_start_y = title_y + subtitle_height + 30 content_area_width = right_margin - left_margin left_column_width = int(content_area_width * 0.5) @@ -702,7 +701,7 @@ class VibrantTemplate(BaseTemplate): layers["Right Content"] = self._create_right_column_layer(content, content_start_y, right_column_x, right_margin, canvas_size) # 6. 页脚层 - footer_y = height - 30 + footer_y = height - 45 layers["Footer Info"] = self._create_footer_layer(content, footer_y, left_margin, right_margin, canvas_size) except Exception as e: @@ -724,7 +723,7 @@ class VibrantTemplate(BaseTemplate): left_margin, right_margin = self._calculate_content_margins(content, width, center_x) # 页脚 - footer_y = height - 30 + footer_y = height - 45 self._render_footer(draw, content, footer_y, left_margin, right_margin) # 标题和副标题 @@ -759,7 +758,7 @@ class VibrantTemplate(BaseTemplate): left_margin, right_margin = self._calculate_content_margins(content, width, center_x) # 页脚 - footer_y = height - 30 + footer_y = height - 45 self._render_footer(draw, content, footer_y, left_margin, right_margin) # 标题和副标题 @@ -797,7 +796,7 @@ class VibrantTemplate(BaseTemplate): title_text = content.get("title", "默认标题") title_target_width = int((right_margin - left_margin) * 0.98) title_size, title_actual_width = self._calculate_optimal_font_size_enhanced( - title_text, title_target_width, max_size=140, min_size=40 + title_text, title_target_width, max_size=210, min_size=60 ) try: title_font = ImageFont.truetype(self.chinese_font_path, title_size) @@ -818,7 +817,7 @@ class VibrantTemplate(BaseTemplate): if subtitle_text: subtitle_target_width = int((right_margin - left_margin) * 0.95) subtitle_size, subtitle_actual_width = self._calculate_optimal_font_size_enhanced( - subtitle_text, subtitle_target_width, max_size=75, min_size=20 + subtitle_text, subtitle_target_width, max_size=113, min_size=30 ) try: subtitle_font = ImageFont.truetype(self.chinese_font_path, subtitle_size) @@ -836,7 +835,7 @@ class VibrantTemplate(BaseTemplate): footer_canvas = Image.new('RGBA', canvas_size, (0, 0, 0, 0)) footer_draw = ImageDraw.Draw(footer_canvas) - footer_y = height - 30 + footer_y = height - 45 try: footer_font = ImageFont.truetype(self.chinese_font_path, 18) except: @@ -899,7 +898,7 @@ class VibrantTemplate(BaseTemplate): # 使用指定的中文字体 title_size, title_actual_width = self._calculate_optimal_font_size_enhanced( - title_text, title_target_width, max_size=140, min_size=40 + title_text, title_target_width, max_size=210, min_size=60 ) try: @@ -941,7 +940,7 @@ class VibrantTemplate(BaseTemplate): subtitle_target_width = int((right_margin - left_margin) * 0.95) subtitle_size, subtitle_actual_width = self._calculate_optimal_font_size_enhanced( - subtitle_text, subtitle_target_width, max_size=75, min_size=20 + subtitle_text, subtitle_target_width, max_size=113, min_size=30 ) # 使用指定的中文字体 @@ -981,7 +980,7 @@ class VibrantTemplate(BaseTemplate): title_text = content.get("title", "默认标题") title_target_width = int((right_margin - left_margin) * 0.98) title_size, title_actual_width = self._calculate_optimal_font_size_enhanced( - title_text, title_target_width, max_size=140, min_size=40 + title_text, title_target_width, max_size=210, min_size=60 ) # 使用中文字体计算标题尺寸 @@ -1027,7 +1026,7 @@ class VibrantTemplate(BaseTemplate): bbox = button_font.getbbox(button_text) button_text_width = bbox[2] - bbox[0] button_width = button_text_width + 40 - button_height = 50 + button_height = 75 # 绘制简单的矩形按钮 draw.rounded_rectangle([x, y, x + button_width, y + button_height], @@ -1070,7 +1069,7 @@ class VibrantTemplate(BaseTemplate): if price_text: price_target_width = int((right_margin - x) * 0.7) price_size, price_actual_width = self._calculate_optimal_font_size_enhanced( - price_text, price_target_width, max_size=120, min_size=40 + price_text, price_target_width, max_size=180, min_size=60 ) try: @@ -1101,7 +1100,7 @@ class VibrantTemplate(BaseTemplate): if ticket_text: ticket_target_width = int((right_margin - x) * 0.7) ticket_size, ticket_actual_width = self._calculate_optimal_font_size_enhanced( - ticket_text, ticket_target_width, max_size=60, min_size=30 + ticket_text, ticket_target_width, max_size=90, min_size=45 ) try: @@ -1228,7 +1227,7 @@ class VibrantTemplate(BaseTemplate): title_text = content.get("title", "") title_target_width = int((right_margin - left_margin) * 0.98) title_size, title_actual_width = self._calculate_optimal_font_size_enhanced( - title_text, title_target_width, max_size=140, min_size=40 + title_text, title_target_width, max_size=210, min_size=60 ) title_x = center_x - title_actual_width // 2 title_y = gradient_start + 40 @@ -1237,7 +1236,7 @@ class VibrantTemplate(BaseTemplate): subtitle_text = content.get("slogan", "") subtitle_target_width = int((right_margin - left_margin) * 0.95) subtitle_size, subtitle_actual_width = self._calculate_optimal_font_size_enhanced( - subtitle_text, subtitle_target_width, max_size=75, min_size=20 + subtitle_text, subtitle_target_width, max_size=113, min_size=30 ) subtitle_x = center_x - subtitle_actual_width // 2 subtitle_y = title_y + 100 + 30 # 标题高度 + 间距 @@ -1252,14 +1251,14 @@ class VibrantTemplate(BaseTemplate): price_text = str(content.get('price', '')) price_target_width = int((right_margin - right_column_x) * 0.7) price_size, price_actual_width = self._calculate_optimal_font_size_enhanced( - price_text, price_target_width, max_size=120, min_size=40 + price_text, price_target_width, max_size=180, min_size=60 ) # 票种布局计算 ticket_text = content.get("ticket_type", "") ticket_target_width = int((right_margin - right_column_x) * 0.7) ticket_size, ticket_actual_width = self._calculate_optimal_font_size_enhanced( - ticket_text, ticket_target_width, max_size=60, min_size=30 + ticket_text, ticket_target_width, max_size=90, min_size=45 ) layout_params = { @@ -1315,10 +1314,9 @@ class VibrantTemplate(BaseTemplate): """使用统一布局参数渲染PNG""" canvas = self._create_composite_image(main_image, gradient_start, theme_color) canvas = self._render_texts(canvas, content, gradient_start) - final_image = canvas.resize((1350, 1800), Image.LANCZOS) return { - "image": final_image, + "image": canvas, "layout_params": layout_params, "format": "png" } @@ -1327,7 +1325,7 @@ class VibrantTemplate(BaseTemplate): theme_color: Optional[str], gradient_start: int, layout_params: Dict[str, Any]) -> Dict[str, Any]: """使用统一布局参数渲染JSON""" - final_width, final_height = 1350, 1800 + final_width, final_height = self.size fabric_objects = [] # 1. 背景图片 @@ -1454,7 +1452,7 @@ class VibrantTemplate(BaseTemplate): "height": 100, "text": layout_params["title_text"], "fontSize": layout_params["title_size"], - "fontFamily": "Arial Black", + "fontFamily": "兰亭粗黑简", "fontWeight": "bold", "fill": "white", "textAlign": "center", @@ -1479,7 +1477,7 @@ class VibrantTemplate(BaseTemplate): "height": 80, "text": layout_params["subtitle_text"], "fontSize": layout_params["subtitle_size"], - "fontFamily": "Arial", + "fontFamily": "兰亭粗黑简", "fill": "white", "textAlign": "center", "lineHeight": 1.3, @@ -1511,9 +1509,9 @@ class VibrantTemplate(BaseTemplate): "y2": 0, "stroke": "rgba(215, 215, 215, 0.3)", "strokeWidth": 3, - "opacity": 1, - "angle": 0, - "scaleX": 1, + "opacity": 1, + "angle": 0, + "scaleX": 1, "scaleY": 1, "selectable": False, "evented": False @@ -1533,33 +1531,33 @@ class VibrantTemplate(BaseTemplate): "strokeWidth": 1, "rx": 20, "ry": 20, - "opacity": 1, - "angle": 0, - "scaleX": 1, + "opacity": 1, + "angle": 0, + "scaleX": 1, "scaleY": 1, "selectable": False, "evented": False - } + } text_objects.append(button_obj) button_text_obj = { - "type": "textbox", + "type": "textbox", "left": layout_params["left_margin"] + 20, "top": layout_params["content_start_y"] + 10, "width": 160, - "height": 30, + "height": 30, "text": button_text, - "fontSize": 30, - "fontFamily": "Arial", + "fontSize": 45, + "fontFamily": "兰亭粗黑简", "fontWeight": "bold", "fill": "white", - "textAlign": "center", + "textAlign": "center", "lineHeight": 1.0, - "opacity": 1, - "angle": 0, - "scaleX": 1, - "scaleY": 1 - } + "opacity": 1, + "angle": 0, + "scaleX": 1, + "scaleY": 1 + } text_objects.append(button_text_obj) # 5. 左栏内容列表 @@ -1573,14 +1571,14 @@ class VibrantTemplate(BaseTemplate): "width": layout_params["left_column_width"], "height": 35, "text": f"• {item}", - "fontSize": 28, - "fontFamily": "Arial", + "fontSize": 42, + "fontFamily": "兰亭粗黑简", "fill": "white", "textAlign": "left", "lineHeight": 1.2, - "opacity": 1, - "angle": 0, - "scaleX": 1, + "opacity": 1, + "angle": 0, + "scaleX": 1, "scaleY": 1 } text_objects.append(item_obj) @@ -1596,15 +1594,15 @@ class VibrantTemplate(BaseTemplate): "height": 80, "text": layout_params["price_text"], "fontSize": layout_params["price_size"], - "fontFamily": "Arial Black", + "fontFamily": "兰亭粗黑简", "fontWeight": "bold", "fill": "white", "textAlign": "right", "lineHeight": 1.0, "opacity": 1, - "angle": 0, - "scaleX": 1, - "scaleY": 1, + "angle": 0, + "scaleX": 1, + "scaleY": 1, "shadow": { "color": "rgba(0, 0, 0, 0.5)", "blur": 2, @@ -1616,20 +1614,20 @@ class VibrantTemplate(BaseTemplate): # CNY起后缀 suffix_obj = { - "type": "textbox", + "type": "textbox", "left": price_x + layout_params["price_width"], "top": layout_params["content_start_y"] + 50, "width": 60, "height": 30, "text": "CNY起", "fontSize": int(layout_params["price_size"] * 0.3), - "fontFamily": "Arial", - "fill": "white", - "textAlign": "left", + "fontFamily": "兰亭粗黑简", + "fill": "white", + "textAlign": "left", "lineHeight": 1.0, - "opacity": 1, - "angle": 0, - "scaleX": 1, + "opacity": 1, + "angle": 0, + "scaleX": 1, "scaleY": 1 } text_objects.append(suffix_obj) @@ -1646,10 +1644,10 @@ class VibrantTemplate(BaseTemplate): "y2": 0, "stroke": "rgba(255, 255, 255, 0.3)", "strokeWidth": 2, - "opacity": 1, - "angle": 0, - "scaleX": 1, - "scaleY": 1, + "opacity": 1, + "angle": 0, + "scaleX": 1, + "scaleY": 1, "selectable": False, "evented": False } @@ -1659,22 +1657,22 @@ class VibrantTemplate(BaseTemplate): if layout_params["ticket_text"]: ticket_x = layout_params["right_margin"] - layout_params["ticket_width"] ticket_obj = { - "type": "textbox", + "type": "textbox", "left": ticket_x, "top": layout_params["content_start_y"] + 115, "width": layout_params["ticket_width"], "height": 60, "text": layout_params["ticket_text"], "fontSize": layout_params["ticket_size"], - "fontFamily": "Arial", + "fontFamily": "兰亭粗黑简", "fontWeight": "bold", - "fill": "white", + "fill": "white", "textAlign": "right", "lineHeight": 1.0, - "opacity": 1, - "angle": 0, - "scaleX": 1, - "scaleY": 1, + "opacity": 1, + "angle": 0, + "scaleX": 1, + "scaleY": 1, "shadow": { "color": "rgba(0, 0, 0, 0.5)", "blur": 2, @@ -1696,8 +1694,8 @@ class VibrantTemplate(BaseTemplate): "width": layout_params["right_margin"] - layout_params["right_column_x"], "height": 20, "text": remark, - "fontSize": 16, - "fontFamily": "Arial", + "fontSize": 24, + "fontFamily": "兰亭粗黑简", "fill": "rgba(255, 255, 255, 0.8)", "textAlign": "right", "lineHeight": 1.0, @@ -1712,44 +1710,44 @@ class VibrantTemplate(BaseTemplate): footer_y = layout_params["footer_y"] if tag := content.get("tag"): tag_obj = { - "type": "textbox", + "type": "textbox", "left": layout_params["left_margin"], "top": footer_y, "width": 200, "height": 25, "text": tag, - "fontSize": 18, - "fontFamily": "Arial", + "fontSize": 27, + "fontFamily": "兰亭粗黑简", "fill": "white", - "textAlign": "left", + "textAlign": "left", "lineHeight": 1.0, - "opacity": 1, - "angle": 0, - "scaleX": 1, + "opacity": 1, + "angle": 0, + "scaleX": 1, "scaleY": 1 } text_objects.append(tag_obj) if pagination := content.get("pagination"): pagination_obj = { - "type": "textbox", + "type": "textbox", "left": layout_params["right_margin"] - 200, - "top": footer_y, + "top": footer_y, "width": 200, "height": 25, "text": pagination, - "fontSize": 18, - "fontFamily": "Arial", + "fontSize": 27, + "fontFamily": "兰亭粗黑简", "fill": "white", "textAlign": "right", "lineHeight": 1.0, - "opacity": 1, - "angle": 0, - "scaleX": 1, + "opacity": 1, + "angle": 0, + "scaleX": 1, "scaleY": 1 } text_objects.append(pagination_obj) - + except Exception as e: logger.error(f"创建精确文本对象失败: {e}") diff --git a/poster_template.py b/poster_template.py index 0b75ea2..27418eb 100644 --- a/poster_template.py +++ b/poster_template.py @@ -1040,7 +1040,7 @@ class ImageCollageCreator: 参数: input_dir: 输入图片目录路径 style: 拼贴样式,如不指定则随机选择 - target_size: 目标尺寸,默认为(900, 1200) + target_size: 目标尺寸,默认为(1350, 1800) 返回: tuple: (拼贴图, 选择的图片名称列表),如果创建失败则返回(None, []) @@ -1049,7 +1049,7 @@ class ImageCollageCreator: try: # 设置默认尺寸为3:4比例 if target_size is None: - target_size = (900, 1200) # 3:4比例 + target_size = (1350, 1800) # 3:4比例 # 如果没有指定样式,随机选择一种 if style is None or style not in self.collage_styles: @@ -1914,7 +1914,7 @@ class PosterNotesCreator: np.random.seed(seed) # 调用core.simple_collage模块处理图像 - target_size = (900, 1200) # 3:4比例 + target_size = (1350, 1800) # 3:4比例 collage_images, used_image_filenames = process_collage( temp_dir, style=style, @@ -2070,7 +2070,7 @@ class PosterNotesCreator: np.random.seed(seed) # 调用core.simple_collage模块处理图像 - target_size = (900, 1200) # 3:4比例 + target_size = (1350, 1800) # 3:4比例 collage_images, used_image_filenames = process_collage( temp_dir, style=style, @@ -3274,13 +3274,13 @@ def select_additional_images( collage_style ) -def process_directory(directory_path, style=None, target_size=(900, 1200), output_count=1): +def process_directory(directory_path, style=None, target_size=(1350, 1800), output_count=1): """ 处理指定目录中的图片,创建指定数量的拼贴图。 参数: directory_path: 包含图片的目录路径 - target_size: 拼贴图目标尺寸,默认为 (900, 1200) + target_size: 拼贴图目标尺寸,默认为 (1350, 1800) output_count: 需要生成的拼贴图数量,默认为 1 返回: @@ -3371,7 +3371,7 @@ def main(): logging.info("方法 1: 使用 process_directory 函数生成拼贴图...") collages_1, used_image_names_1 = process_directory( directory_path=test_directory, - target_size=(900, 1200), # 默认 3:4 比例 + target_size=(1350, 1800), # 默认 3:4 比例 output_count=2 # 创建 2 张不同的拼贴图 ) diff --git a/test_size_adjustment_result.png b/test_size_adjustment_result.png new file mode 100644 index 0000000..cdbe95e Binary files /dev/null and b/test_size_adjustment_result.png differ diff --git a/utils/__pycache__/image_processor.cpython-312.pyc b/utils/__pycache__/image_processor.cpython-312.pyc index ae811b1..9ced660 100644 Binary files a/utils/__pycache__/image_processor.cpython-312.pyc and b/utils/__pycache__/image_processor.cpython-312.pyc differ diff --git a/utils/image_processor.py b/utils/image_processor.py index aa31fa7..11bf762 100644 --- a/utils/image_processor.py +++ b/utils/image_processor.py @@ -185,7 +185,7 @@ class ImageProcessor: return image @staticmethod - def create_collage_from_paths(image_paths: List[str], target_size: Tuple[int, int] = (900, 1200)) -> Optional[Image.Image]: + def create_collage_from_paths(image_paths: List[str], target_size: Tuple[int, int] = (1350, 1800)) -> Optional[Image.Image]: """ 从图像路径列表创建拼图 @@ -257,7 +257,7 @@ class ImageProcessor: @staticmethod def process_images_for_poster(image_paths: List[str], - target_size: Tuple[int, int] = (900, 1200), + target_size: Tuple[int, int] = (1350, 1800), create_collage: bool = False) -> Dict[str, Any]: """ 处理图像用于海报生成