|
from PIL import Image, ImageDraw, ImageFont |
|
import copy |
|
import numpy as np |
|
|
|
def wrap_text(text, font, max_width): |
|
lines = [] |
|
words = text.split(' ') |
|
current_line = '' |
|
|
|
for word in words: |
|
if font.getsize(current_line + word)[0] <= max_width: |
|
current_line += word + ' ' |
|
else: |
|
lines.append(current_line) |
|
current_line = word + ' ' |
|
|
|
lines.append(current_line) |
|
return lines |
|
|
|
def create_bubble_frame(image, text, point, font_path='DejaVuSansCondensed-Bold.ttf', font_size_ratio=0.025): |
|
|
|
if type(image) == np.ndarray: |
|
image = Image.fromarray(image) |
|
|
|
image = copy.deepcopy(image) |
|
width, height = image.size |
|
|
|
|
|
total_chars = len(text) |
|
max_text_width = int(0.4 * width) |
|
font_size = int(height * font_size_ratio) |
|
|
|
|
|
font = ImageFont.truetype(font_path, font_size) |
|
|
|
|
|
lines = wrap_text(text, font, max_text_width) |
|
text_width = max([font.getsize(line)[0] for line in lines]) |
|
_, text_height = font.getsize(lines[0]) |
|
text_height = text_height * len(lines) |
|
|
|
|
|
padding = 10 |
|
bubble_width = text_width + 2 * padding |
|
bubble_height = text_height + 2 * padding |
|
|
|
|
|
bubble = Image.new('RGBA', (bubble_width, bubble_height), (255, 255, 255, 0)) |
|
|
|
|
|
draw = ImageDraw.Draw(bubble) |
|
|
|
|
|
|
|
y_text = padding |
|
for line in lines: |
|
draw.text((padding, y_text), line, font=font, fill=(255, 255, 255, 255)) |
|
y_text += font.getsize(line)[1] |
|
|
|
|
|
x, y = point |
|
if x + bubble_width > width: |
|
x = width - bubble_width |
|
if y + bubble_height > height: |
|
y = height - bubble_height |
|
|
|
|
|
image.paste(bubble, (x, y), bubble) |
|
return image |