Jolly

使用python生成小程序分享海报
记得之前工作业务上有实现生成小程序分享海报的需求,但是相比小程序端canvas生成海报还是复杂的多,这里使用的是P...
扫描右侧二维码阅读全文
09
2020/07

使用python生成小程序分享海报

记得之前工作业务上有实现生成小程序分享海报的需求,但是相比小程序端canvas生成海报还是复杂的多,这里使用的是PIL来画图拼接,最后生成图片,最后保存在本地或者上传到云存储以便后续使用,具体看业务需求。

话不多说,这里使用的是python语言,以下为代码

import uuid
import json
import os
import requests
import config
import base64
from PIL import Image, ImageDraw, ImageFont


class PosterImage:
    """海报"""

    qr_code_base_url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token='

    def __init__(self, avatar, backdrop_path):
        self.avatar = avatar
        self.backdrop_path = backdrop_path
        self.qr_code_url = self.qr_code_base_url + (你的access_token)
        self.backdrop = Image.open(self.backdrop_path)
        self.generate_copy_backdrop()

    def get_qr_code(self, content: str):
        """生成二维码 pil对象"""

    def get_stream(self, url, user_id, role, kwargs=None):
        """获取二维码字节码"""
        json_data = {'scene': '',
                     'page': '',
                     'width': 280,
                     'auto_color': False,
                     'is_hyaline': False}

        # 提交到微信地址
        result = requests.post(url, json=json_data, timeout=3, verify=False)
        self.stream = result.content

    def get_avatar(self):
        """获取微信头像"""
        self.stream = requests.get(url=self.avatar).content

    def save_stream(self):
        """将流数据保存至本地文件内,返回文件名"""
        prefix = uuid.uuid1().hex
        file_name = f'{prefix}.png'
        file_path = 'qr_code/' + file_name
        import os
        path = os.getcwd()+'/plugins/public/'
        file_path = os.path.join(path, file_path)
        with open(file_path, 'wb') as f:
            f.write(self.stream)
        return file_path

    def open_material(self, path):
        """打开素材
        qr_code:背景
        qr_code:小程序页面二维码
        """
        try:
            self.material = Image.open(path)
            return self.material
        except(OSError, NameError):
            print('OSError, Path:', path)

    def generate_copy_backdrop(self):
        """生成背景图拷贝对象,对背景图的操作不会影响原对象"""
        self.copy_backdrop = self.backdrop.copy().convert('RGB')
        self.copy_backdrop_draw = ImageDraw.Draw(self.copy_backdrop)

    def set_font(self, css_path: str = None, fill: tuple = (0, 0, 0), size: int = 36):
        """设定字体"""
        import os
        path = os.getcwd()
        path = os.path.join(path, "static/Alibaba-PuHuiTi-Bold.ttf")
        self.font = ImageFont.truetype(path, size=size)
        self.font_fill = fill

    def synthesis(self, img, x: float, y: float, size=None):
        """合成图片
        :param img: pil对象
        :param size: 图形尺寸
        :param x: 横向坐标
        :param y: 纵向坐标
        """
        if size:
            img = img.resize((size, size), Image.ANTIALIAS)
        self.copy_backdrop.paste(img, (x, y))

    def write(self, content, x: float, y: float):
        """写入内容,写入前可以通过self.set_font 设定字体
        :param content: 文字内容
        :param x: 横向坐标
        :param y: 纵向坐标
        """
        self.copy_backdrop_draw.text((x, y), text=content, fill=self.font_fill, font=self.font)


def create_post():
    """生成分享海报"""

    import os
    path = os.getcwd()
    path = os.path.join(path, "static/backdrop.png")
    poster_image = PosterImage(avatar=avatar, backdrop_path=path)

    # 获取二维码/合成二维码
    poster_image.get_stream(url=poster_image.qr_code_url, user_id=user_id, role=role)
    poster_image.open_material(poster_image.save_stream())
    poster_image.synthesis(poster_image.material, x=505, y=855, size=195)

    # 获取微信头像/合成头像
    if user.avatar:
        poster_image.get_avatar()
        poster_image.open_material(poster_image.save_stream())
        poster_image.synthesis(poster_image.material, x=65, y=895, size=120)

    # 获取昵称
    if user.nickname:
        poster_image.set_font()
        poster_image.write(nickname, x=205, y=900)

    filename = f'{uuid.uuid1().hex}.jpg'

    path = os.getcwd()+'/plugins/public/'
    poster_image_path = os.path.join(path, 'post_image/' + filename)

    poster_image.copy_backdrop.save(poster_image_path)

    # todo 将海报直传oss 或者保存本地
    

其实这段代码没有很复杂,只是将构建好的图像不断的合成,难点的话就是相对应的方法调用,还有代码里出现的很多x和y坐标,这个是你的图片元素的位置,你可以放置任意的图像进行合成,相当于不断的在一个画布上堆东西,api还是很丰富的,可以旋转,遮罩,放大缩小等。具体使用还需要你自己摸索。

Last modification:July 9th, 2020 at 09:34 am
🌓