使用 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]
很有魅力
从此开始
期望的效果将是以下描述的任何一种情况:
但是,我无法克服此错误: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]
很有魅力