从网上搜了下Python将文字转图片的文章,没看到符合需求的——几乎都是将文本缩放到一行。所以就找了个做参考,自己写了字体、行宽固定,高度随文本长度变化的方法,贡献出来供大家copy,代码如下:
1 # -*- coding: utf-8 -*- 2 """ 3 Created on Thu Mar 17 11:18:16 2022 4 5 @author: Administrator 6 """ 7 import math 8 from PIL import Image,ImageFont,ImageDraw 9 10 font_conf = { 11 'type':'simkai.ttf', 12 'size':20, 13 'rgb':tuple([0,0,0]) 14 } 15 bg_conf = { 16 'rgb':tuple([255,255,255]) 17 } 18 margin=50 19 20 def CreateMutiLinesPic(text,line_size,pic_path=None): 21 """ 22 Create a fixed-width picture with the height depend on the length of the text 23 24 Parameters 25 ---------- 26 text: words to render in picture 27 28 line_size: words length per line 29 30 pic_path: the path of the new picture to save in if it is not None 31 32 Returns 33 ------- 34 None 35 """ 36 line_count=math.ceil(len(text)/line_size) 37 38 font = ImageFont.truetype(font_conf['type'],font_conf['size']) 39 40 # calculate the picture size 41 fwidth,fheight = font.getsize('中'*line_size) 42 owidth,oheight = font.getoffset('中'*line_size) 43 pic_size=[margin*2+fwidth+owidth,margin*2+(fheight+oheight)*line_count] 44 45 # create new picture 46 pic = Image.new('RGB', pic_size,bg_conf['rgb']) 47 draw = ImageDraw.Draw(pic) 48 for i in range(line_count): 49 # draw lines 50 draw.text((margin,margin+(fheight+oheight)*i), text[i*line_size:(i+1)*line_size], font_conf['rgb'], font) 51 if pic_path: 52 pic.save(pic_path) 53 pic.show() 54 55 def CreatePic(text,imgPath=None,size=[500,500],margin=margin,backgroundRGB=bg_conf['rgb'],fontType=font_conf['type'],fontRGB=font_conf['rgb']): 56 """ 57 Create a fixed-size picture, and scale the text to fill in one line 58 59 Parameters 60 ---------- 61 text: words to render in picture 62 63 imgPath: the path of the new picture to save in if it is not None 64 65 size: the picture size 66 67 ... 68 69 Returns 70 ------- 71 None ;save. 72 """ 73 size=tuple(size) 74 backgroundRGB=tuple(backgroundRGB) 75 fontRGB=tuple(fontRGB) 76 77 image = Image.new('RGB', size, backgroundRGB) # 设置画布大小及背景色 78 iwidth, iheight = image.size # 获取画布高宽 79 80 # 计算字节数,RGB双字,英文单字。都转为双字计算 81 size=len(text.encode('gbk'))/2 82 # 计算字体大小,每两个字号按字节长度翻倍。 83 fontSize=math.ceil((iwidth-(margin*2))/size) 84 85 font = ImageFont.truetype(fontType, fontSize) # 设置字体及字号 86 draw = ImageDraw.Draw(image) 87 88 fwidth, fheight = draw.textsize(text, font) # 获取文字高宽 89 owidth, oheight = font.getoffset(text) 90 91 fontx = (iwidth - fwidth - owidth) / 2 92 fonty = (iheight - fheight - oheight) / 2 93 draw.text((fontx, fonty), text, fontRGB, font) 94 95 draw.text((fontx, fonty), text, fontRGB, font) 96 if imgPath: 97 image.save(imgPath) # 保存图片 98 image.show() 99 text='接到一个需求,将给出的文字自动生成图片。要求白底黑字,根据图片尺寸两边预留固定尺寸,文字自动居中。这里的一个难点就是计算文字的字号。思路:根据宋体实验找了一下规律,每两个字号渲染尺寸会按双字节加一倍。也就是计算出双字个数,通过宽度剪去双边预留尺寸,再除以双字节个数就是字号。' 100 CreatePic(text)# others function 101 CreateMutiLinesPic(text, 30)# my function
参考文章地址:
原文的方法CreatePic,可以根据文字长短缩放,缺点是只能在一行,文字长度很长的话会模糊成线。
图1 原文单行方法
根据原文的示例结合自己的需求,我改进了方法,让字体大小和行字数固定,高度随文本增长,这样更符合日常习惯。
图2 多行方法 字体20 每行字数30
图3 多行方法 字体20 每行字数10