|
|
|
import os |
|
from datetime import datetime |
|
from PIL import Image,ImageFilter,ImageFont,ImageDraw |
|
import matplotlib.pyplot as plt |
|
import math |
|
from PIL import Image, ImageDraw, ImageFont |
|
import textwrap |
|
import random |
|
|
|
post_img = "res_post.jpg" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def longTextCut(text, line_words): |
|
"""cut the text to len / given_num lines""" |
|
total_len = len(text) |
|
num_line = math.ceil(total_len/line_words) |
|
num_line = max(num_line, 1) |
|
res = [] |
|
for i in range(num_line): |
|
start_inx = int(i*line_words) |
|
end_inx = int(line_words* (i+1)) |
|
sub_seq = text[start_inx : end_inx] |
|
res.append(sub_seq) |
|
lines = textwrap.wrap(text, width=line_words) |
|
return res |
|
return lines |
|
|
|
|
|
|
|
|
|
def reshape_texts(lines, line_words): |
|
new_lines = [] |
|
for it in lines: |
|
sub_lines = it.split("\n") |
|
split_lines = [] |
|
for inx, sub_it in enumerate(sub_lines): |
|
if len(sub_it) > line_words: |
|
relen_text = longTextCut(sub_it, line_words) |
|
split_lines.extend(relen_text) |
|
else: |
|
split_lines.append(sub_it) |
|
new_lines.extend(split_lines) |
|
return new_lines |
|
|
|
|
|
|
|
def reshape_texts_end(lines, line_words): |
|
new_lines = [] |
|
for it in lines: |
|
sub_lines = it.split("。") |
|
|
|
|
|
split_lines = [] |
|
for inx, sub_it in enumerate(sub_lines): |
|
if len(sub_it) > line_words: |
|
relen_text = longTextCut(sub_it, line_words) |
|
split_lines.extend(relen_text) |
|
else: |
|
split_lines.append(sub_it) |
|
new_lines.extend(split_lines) |
|
return new_lines |
|
|
|
|
|
|
|
|
|
|
|
class MyGaussianBlur(ImageFilter.Filter): |
|
name = "GaussianBlur" |
|
def __init__(self, radius=2, bounds=None): |
|
self.radius = radius |
|
self.bounds = bounds |
|
def filter(self, image): |
|
if self.bounds: |
|
clips = image.crop(self.bounds).gaussian_blur(self.radius) |
|
image.paste(clips, self.bounds) |
|
return image |
|
else: |
|
return image.gaussian_blur(self.radius) |
|
|
|
|
|
|
|
class myPost: |
|
def __init__(self, front_img=None, |
|
img = r'./broadcast/kaobianBottem.jpeg' |
|
): |
|
self.frontground = Image.open(front_img) if front_img else None |
|
|
|
|
|
|
|
|
|
self.img= Image.open(img) if type(img) is str else Image.fromarray(img) |
|
self.icon=None |
|
|
|
|
|
|
|
self.width, self.height=self.img.size |
|
|
|
|
|
def loadIcon(self, point=(50,50)): |
|
"""point=(x,y)""" |
|
pass |
|
|
|
def get_width_height(self): |
|
return self.width,self.height |
|
|
|
def getLinesCount(self, sz, spacing): |
|
words = int(self.width / sz) - 2 |
|
rows = int( self.height / (sz + spacing)) |
|
return (words, rows) |
|
|
|
|
|
def drawBlur(self): |
|
backflur = self.frontground.resize((self.width,self.height), resample=3).filter(MyGaussianBlur(radius=35)) |
|
self.img.paste(backflur,(0, 0)) |
|
|
|
|
|
def drawFrontground(self): |
|
"""添加一个前景图壁纸,高斯虚化 |
|
""" |
|
if not self.frontground: |
|
return |
|
x=0 |
|
y=int(self.height*2/3.3) |
|
srcwidth,srcheight=self.frontground.size |
|
height=int(srcheight * self.width / srcwidth) |
|
|
|
frontground = self.frontground.resize((self.width, height),Image.Resampling.LANCZOS) |
|
|
|
alpha_layer = Image.new('L', (self.width, height), 0) |
|
draw = ImageDraw.Draw(alpha_layer) |
|
sz = (self.width/2-100, 0, self.width-30, height) |
|
|
|
draw.ellipse(sz, fill=150) |
|
self.img.paste(frontground,(x,y),alpha_layer) |
|
|
|
def get_res(self): |
|
return self.img |
|
|
|
def postTextLine(self, title="Text--test", font="./simsun.ttc", sz=50, x=40, y=90, color = "red"): |
|
"""main title""" |
|
draw = ImageDraw.Draw(self.img) |
|
font = ImageFont.truetype(font=font, size=sz) |
|
draw.text((x,y), title, font=font, fill=color) |
|
|
|
def postBoxText(self, texts=["Text--test\n sub text"], font="./simsun.ttc", sz=50, x=40, y=390, |
|
color = "red", spacing=40, ali = "left", bac_color=None): |
|
"""lines""" |
|
|
|
draw = ImageDraw.Draw(self.img) |
|
font = ImageFont.truetype(font=font, size=sz) |
|
|
|
text = "\n".join(texts) |
|
bbox = draw.multiline_textbbox((0, 0), text, font=font, spacing=spacing) |
|
|
|
|
|
width = bbox[2] - bbox[0] |
|
width += int(width * 0.3) |
|
height = bbox[3] - bbox[1] |
|
height += int(height * 0.3) |
|
if bac_color is not None: |
|
draw.rectangle((x-int(width * 0.15), y-int(height * 0.15), x + width, y + height), fill=bac_color) |
|
|
|
|
|
|
|
|
|
|
|
draw.multiline_text((x, y), text, fill=color, font=font, align=ali, spacing=spacing) |
|
|
|
|
|
def postText(self, texts=["Text--test\n sub text"], font="./simsun.ttc", sz=50, x=40, y=390, |
|
color = "red", spacing=20): |
|
draw = ImageDraw.Draw(self.img) |
|
|
|
font = ImageFont.truetype(font=font, size=sz) |
|
|
|
text = "\n".join(texts) |
|
draw.multiline_text((x, y), text, fill=color, font=font, align="left", spacing=spacing) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def drawCard(self): |
|
if frontground: |
|
self.drawFrontground() |
|
self.postText(title, texts, sz = 40) |
|
|
|
def drawCardExample(self): |
|
self.drawFrontground() |
|
self.postTextLine(title="Text--test", font="./simsun.ttc", sz=size, x=40, y=90, color = "red") |
|
self.postTextLine(title="content of sub text", font="./simsun.ttc", sz=size, x=40, y=90, color = "green") |
|
def show(self): |
|
pass |
|
|
|
|
|
def saveCard(self, path_name): |
|
save_name = path_name |
|
|
|
self.img.save(save_name) |
|
return save_name |
|
|
|
def generatePost(lines = [""], front_img=None, bac_img="./kaobianBottem.jpeg", fn_name = "test_v1.png"): |
|
"""给定背景,前景,文字,size,生成单张图, 并环肥内存中的图对象""" |
|
postcard=myPost(front_img=front_img, img = bac_img) |
|
line_words, rows = postcard.getLinesCount(sz, spacing) |
|
texts = reshape_texts(lines, line_words) |
|
print("总行数",len(texts)) |
|
postcard.drawFrontground() |
|
postcard.postText(texts[0], texts[1:], sz = 40) |
|
save_name=postcard.saveCard(fn_name) |
|
|
|
generated_image = postcard.get_res() |
|
return generated_image |
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
title = "大王叫我来巡山并发布公告,解决就业问题山中有老虎猴子承办问" |
|
lines = ['四、报名及网上缴费','本次公开考试招聘采取网络报名方式进行,不组织现场报名。报名时间:2023年3月10日至3月17日24:00。', |
|
'报名网站:广元人事考试网(http://gypta.e21cn.com/)。'] |
|
|
|
|
|
|
|
|
|
result_post_file = "post_v1.png" |
|
bac_img = "./kaobianBottem.jpeg" |
|
|
|
bing_post = "bingpost/" |
|
imgs_ = os.listdir(bing_post) |
|
imgs_ = [i for i in imgs_ if i.endswith("png")] |
|
ch_img = random.choice(imgs_) |
|
front_img = os.path.join(bing_post, ch_img) |
|
|
|
postcard=myPost(front_img=front_img, img = bac_img) |
|
postcard.drawFrontground() |
|
|
|
sz=80 |
|
spacing=20 |
|
words, rows = postcard.getLinesCount(sz=sz, spacing=spacing) |
|
title_text = longTextCut(title, words) |
|
title_text = textwrap.wrap(title, width=words) |
|
|
|
print(title_text) |
|
postcard.postText(title_text, font="./simsun.ttc", sz = sz, |
|
x=40, y=150, color = "blue", spacing=20) |
|
|
|
sz=50 |
|
spacing=20 |
|
words, rows = postcard.getLinesCount(sz=sz, spacing=spacing) |
|
texts = longTextCut(lines[1], words) |
|
print(texts) |
|
postcard.postText(texts, font="./simsun.ttc", sz = sz, |
|
x=40, y=490, color = "green", spacing=spacing) |
|
|
|
|
|
texts = reshape_texts(lines, words) |
|
print("texts 长文本 总行数",len(texts)) |
|
postcard.postText([lines[0]], font="./simsun.ttc", sz = int(sz*1.5),x=40, y=790, color = "red", spacing=spacing) |
|
postcard.postText(texts, font="./simsun.ttc", sz = sz,x=40, y=990, color = "green", spacing=spacing) |
|
save_name=postcard.saveCard(result_post_file) |
|
print(save_name) |
|
|
|
|
|
|