從網上搜了下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