Python PIL 长文本换行,二维码,图片合成

项目新需求,需要在后端进行图片合成,合成方式为“背景图+二维码+长文本”

在网上查了很多有关python图片合成的资料,大多使用的pygame和PIL,在这里我使用的是python3.5下的PIL分支pillow

国内网站对于如何处理长文本换行的问题,很少有讨论,在此将我的解决方案分享出来

本方案的基本思想是:

创建一个可以自适应变化大小的独立图层,
将整个长文本写进去,
分析图层的大小是否能够放入到背景图中,

如果不能就裁剪文本内容,再重复这一步骤,

from PIL import Image,ImageDraw,ImageFont  
import qrcode  
import pygame

backMode = {   #背景图属性,我的背景图上需要添加一个二维码和多个文本框
    "back_url":"timg.jpg",
    "size":(550,363),
    "QR":{    #二维码属性
        "frame":(130,130),    #大小
        "position":(380,200),    #位置
    },
    "text":[{    #文本框属性
        "size":25,    #字号
        "ttf":"FZXBSJW.TTF",    #字体
        "color":"",    #颜色
        "position":(20,40),
        "frame":(300,20),
    },{
        "size":25,
        "ttf":"FZXBSJW.TTF",
        "color":"",
        "position":(20,80),
        "frame":(300,20),
    },{
        "size":25,
        "ttf":"FZXBSJW.TTF",
        "color":"",
        "position":(20,120),
        "frame":(300,20),
    },{
        "size":25,
        "ttf":"FZXBSJW.TTF",
        "color":"",
        "position":(20,160),
        "frame":(300,20),
    },],
}

def make_QR(content, sizeW = 0, sizeH = 0):#创建二维码
    qr = qrcode.QRCode(version=3, box_size=3, border=1, error_correction=qrcode.constants.ERROR_CORRECT_H)
    qr.add_data(content)  
    qr.make(fit=True)  
    img = qr.make_image()
    if sizeW == 0 and sizeH == 0:
        return img
    w, h = img.size 
    if sizeW < w or sizeH < h:
        return None
    img = img.resize((sizeW,sizeH),Image.ANTIALIAS)
    return img
def com_pic(topimg, backimg, position):#合并图片
    nodeA = position
    w, h = topimg.size 
    nodeB = (position[0]+w, position[1]+h)
    backimg.paste(topimg, (nodeA[0], nodeA[1], nodeB[0], nodeB[1]))
    return backimg
def write_line(backimg ,text, tmode):#给单个文本框填充数据
    myfont = ImageFont.truetype(tmode["ttf"],size=tmode["size"])
    draw = ImageDraw.Draw(backimg)
    tend = len(text)
    while True:
        text_size = draw.textsize(text[:tend], font=myfont) #文本图层的尺寸
        #print(text_size)
        if text_size[0] <= tmode["frame"][0]:
            break
        else:
            tend -= 1    #文本太长,调整文本长度
    draw.text((tmode["position"][0], tmode["position"][1]), text[:tend], font=myfont)

    return backimg, tend

def write_text(img , text, tmodeList):#写文本
    tlist = text.split("\n")
    mnum = 0
    draw = ImageDraw.Draw(img)
    for t in tlist:
        tbegin = 0
        tend = len(t)
        while True:
            img, tend = write_line(img, t[tbegin:tend], tmodeList[mnum])
            mnum += 1
            if tbegin + tend == len(t) or mnum == len(tmodeList):
                break
            else:
                tbegin = tbegin + tend
                tend = len(t)
        if mnum == len(tmodeList):
            break
    return img


def make_pic(mode, text, url):
    img = Image.open(mode["back_url"])#读取背景图片
    QR_res = make_QR(url, mode["QR"]["frame"][0], mode["QR"]["frame"][1])#创建二维码
    img = com_pic(QR_res, img, mode["QR"]["position"])#合成1
    img = write_text(img, text, mode["text"])#写文本
    img.save('A.PNG', quality=100)
make_pic(backMode, "晚风窃笑街角 需要为一堆落叶放哨\n冷的月色\n铺垫整场你礼貌的揭晓 不爱我就拉倒", "http://bd.kuwo.cn/yinyue/41230185")
exit()

下面是我使用的原图和生成效果,以及需要注意的内容



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值