Files
k3GPT/main/gen_img_servie.py
2025-11-19 19:42:50 +08:00

287 lines
8.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from PIL import Image, ImageDraw, ImageFont
import os
from parse_html import parse_html_to_ppt,parse_html_to_poster
#处理多行文本
def draw_multiline_text(draw, text, position, max_width, font, fill, line_spacing=10, only_calc=False):
"""
在指定区域内绘制自动换行的文本
参数:
draw - ImageDraw对象
text - 要绘制的文本
position - 起始位置 (x, y)
max_width - 最大行宽
font - 字体对象
fill - 文本颜色
line_spacing - 行间距 (默认10)
"""
x, y = position
lines = []
# 如果文本包含换行符,先按换行符分割
paragraphs = text.split('\n')
for paragraph in paragraphs:
words = []
# 中英文混合处理:将每个字符视为独立的"词"
for char in paragraph:
words.append(char)
# 添加空格字符作为可能的断点
if char.isspace():
words.append('')
space_width = draw.textlength(' ', font=font)
current_line = []
current_width = 0
for word in words:
word_width = draw.textlength(word, font=font)
# 如果当前行宽度加上新词宽度超过最大宽度
if current_width + word_width > max_width and current_line:
# 将当前行添加到行列表
lines.append(''.join(current_line))
current_line = [word]
current_width = word_width
else:
current_line.append(word)
current_width += word_width
# 添加最后一行
if current_line:
lines.append(''.join(current_line))
# 计算行高
_, _, _, line_height = font.getbbox("A")
# 绘制每一行文本
for line in lines:
if not only_calc:
draw.text((x, y), line, fill=fill, font=font)
y += line_height + line_spacing
return y
#绘制表格
def draw_table(draw,headers,data,table_top,table_left,table_width,header_font,data_font,text_color,header_color):
data.pop(0)
cell_height = 65 # 固定单元格高度
rows = len(data)+1
cols = len(headers)
table_height = cell_height * rows
cell_width = table_width // cols
# 绘制表头圆角矩形背景
draw.rounded_rectangle(
(table_left-10, table_top, table_left+table_width+10, table_top+cell_height+15),
radius=40,
fill=header_color, # 深蓝色背景
outline=header_color
)
# # 绘制表头分割线
for i in range(1, cols):
x = table_left + i * cell_width
# 绘制垂直线条,稍微短一点以避开圆角
draw.line(
[(x, table_top + 10), (x, table_top + cell_height)],
fill=(255, 255, 255, 180), # 半透明白色
width=2
)
for col in range(cols):
text = headers[col]
# 使用textbbox计算文本尺寸
text_bbox = draw.textbbox((0, 0), text, font=header_font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
x = table_left + col * cell_width + (cell_width - text_width) // 2
y = table_top + (cell_height - text_height) // 2
draw.text((x, y), text, fill=(255, 255, 230), font=header_font)
#微调一下数据表格的大小和位置下移15
table_top +=15
table_width = table_width - 40
table_left +=20
cell_width = table_width // cols
# 绘制数据行
for row in range(len(data)):
for col in range(cols):
# 计算单元格位置
x1 = table_left + col * cell_width
y1 = table_top + (row + 1) * cell_height
x2 = x1 + cell_width
y2 = y1 + cell_height
# 交替行颜色
if row % 2 == 0:
bg_color = (248, 250, 253) # 浅色行
else:
bg_color = (240, 245, 251) # 更浅的蓝色行
# 绘制单元格背景
draw.rectangle([x1, y1, x2, y2], fill=bg_color)
# 添加数据
text = data[row][col]
# 使用textbbox计算文本尺寸
text_bbox = draw.textbbox((0, 0), text, font=data_font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
x = x1 + 15
# 默认y位置
y = y1 + (cell_height - text_height) // 2
draw.text((x, y), text, fill=text_color, font=data_font)
# 绘制网格线
for i in range(1, rows):
y = table_top + i * cell_height
draw.line(
[(table_left, y), (table_left+table_width, y)],
fill=(225, 232, 243),
width=1
)
for i in range(1, cols):
x = table_left + i * cell_width
draw.line(
[(x, table_top + cell_height), (x, table_top+table_height)],
fill=(225, 232, 243),
width=1
)
#表格边线,三条,, # 深蓝色背景
draw.line(
[(table_left, table_top + cell_height-5), (table_left, table_top+table_height)],
fill=header_color,
width=2
)
draw.line(
[(table_left+table_width, table_top + cell_height-5), (table_left+table_width, table_top+table_height)],
fill=header_color,
width=2
)
draw.line(
[(table_left, table_top + table_height), (table_left+table_width, table_top+table_height)],
fill=header_color,
width=2
)
return table_top+table_height+20
# 辅助函数:获取文本尺寸
def get_text_size(draw,text, font):
bbox = draw.textbbox((0, 0), text, font=font)
return bbox[2] - bbox[0], bbox[3] - bbox[1]
#ppt模板101的图片
def create_ppt_images(main_color=None):
background_colors = [
{"name": "深空蓝", "hex": "#0D4D4B", "rgb": (13, 77, 75)},
{"name": "紫罗兰", "hex": "#4A306D", "rgb": (74, 48, 109)},
{"name": "海军蓝", "hex": "#003366", "rgb": (0, 51, 102)},
{"name": "森林绿", "hex": "#22577A", "rgb": (34, 87, 122)},
{"name": "暗玫瑰红", "hex": "#E0115F", "rgb": (224, 17, 95)},
{"name": "橄榄绿", "hex": "#556B2F", "rgb": (85, 107, 47)},
{"name": "深紫", "hex": "#35063E", "rgb": (53, 6, 62)},
{"name": "宝石蓝", "hex": "#0F52BA", "rgb": (15, 82, 186)},
]
#如果为空则随机选择
if not main_color:
import random
main_color = background_colors[random.randint(0,len(background_colors)-1)]["rgb"]
#1. 主图
#图片尺寸1080p的电脑尺寸
width, height = 1920, 1080
# 创建背景画布
img = Image.new('RGBA', (width, height), (255,255,255,0))
draw = ImageDraw.Draw(img)
# 绘制矩形背景
m_height=600
draw.rectangle(
(0, (height-m_height)//2, width, (height-m_height)//2+m_height),
fill=main_color,
outline=main_color
)
img.save("pic/101_main.png")
#2. 引导图
#图片尺寸1080p的电脑尺寸
width, height = 1920, 450
# 创建背景画布
img = Image.new('RGB', (width, height), (255,255,255))
draw = ImageDraw.Draw(img)
# 绘制矩形背景
draw.rectangle(
(0, 0, width, height),
fill=main_color,
outline=main_color
)
img.save("pic/101_catalog_w.png")
#3. 目录图
#图片尺寸1080p的电脑尺寸
width, height = 600, 1080
# 创建背景画布
img = Image.new('RGB', (width, height), (255,255,255))
draw = ImageDraw.Draw(img)
# 绘制矩形背景
draw.rectangle(
(0, 0, width, height),
fill=main_color,
outline=main_color
)
img.save("pic/101_catalog.png")
#4. 标题图
#图片尺寸1080p的电脑尺寸
width, height = 1920, 120
# 创建背景画布
img = Image.new('RGB', (width, height), (255,255,255))
draw = ImageDraw.Draw(img)
# 绘制矩形背景
draw.rectangle(
(0, 0, width, height),
fill=main_color,
outline=main_color
)
img.save("pic/101_title.png")
return main_color
if __name__=="__main__":
#create_ppt_images("#0F52BA")
create_ppt_images()