使用 PIL 函数以一定角度添加文本叠加

Adding a text overlay at angle with PIL function

从此开始

期望的效果将是以下描述的任何一种情况:

但是,我无法克服此错误:images do not match 来自 image.paste 调用

我敢肯定还有其他方法可以创建这种效果,但感觉最干净的方法是制作一个新层并将该层粘贴到原始图像上

round() 被使用,因为我收到错误 int is the expected argument, received float 没有它们。

from PIL import Image, ImageOps, ImageFont, ImageDraw
def addText( img: Image, text: str, position: dict = {}):
    """ 
        example position dict:
        {
            "x": 0.79,
            "y": 0.17,
            "angle": 0.06
        }
    """
    i_w, i_h = img.size

    x = round(i_w * position.get("x", 0.23))
    y = round(i_h * position.get("y", 0.87))
    angle = (
        position.get("angle", 0) * 180
    )  # converts unit radians to degrees i.e. { 1 unit = pi radians= 180 degrees }
    
    
    font_px_height = round(i_h * 0.0475)
    font = ImageFont.truetype("fonts/OpenSans-Semibold.ttf", font_px_height)     
    t_w, t_h = font.getsize(text)
    print(f"font.size {t_w} {t_h}")
     
    
    layer = Image.new("RGBA", (round(t_w * 1.05), round(t_h)))
    

    draw_layer = ImageDraw.Draw(layer)
    draw_layer.rounded_rectangle(
        (0, 0, round(t_w * 1.05), round(t_h)),
        round(t_h / 10)
    )
    draw_layer.text((0, 0), text, fill=(0, 0, 0), font=font)
    

    layer = layer.rotate(angle, expand=1)
    l_w, l_h = layer.size
    l_w = round(l_w)
    l_h = round(l_h)
    layer.show()

    
    img.paste(
        sticker,
        (
            round(x - l_w / 2),
            round(y - l_h / 2),
            round(x + l_w / 2),
            round(y + l_h / 2),
        ),
        sticker,
    )
    return img



try:
    with Image.open(
        "./test.jpg"
    ) as im:
        alt_im = addText(
            im,
            "hello world",
            {"x": 0.23, "y": 0.87, "angle": 0.06},
            )
        alt_im.save("out.jpg")
except Exception as ex:
    print("*Exception output", ex)
        

所以我最终使用了一个 bodge,在计算过程中只使用 相等的 数字,这样它们每次都会计算出 ints。删除所有提及的 round() 并将其替换为 evenize()

def evenize(*args):
    evenized_numbers = []
    for _n in args:
        n = int(_n)
        if (n % 2) != 0:
            n += 1
        evenized_numbers.append(n)
    if len(evenized_numbers) > 1:
        return tuple(evenized_numbers)
    else:
        return evenized_numbers[0]

很有魅力