File size: 6,032 Bytes
b3081c2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
from PIL import Image, ImageDraw, ImageFont,ImageStat,ImageFilter,ImageEnhance
import constants
import os
def wrap_text(draw, text, font, max_width):
words = text.split()
lines = []
current_line = words[0]
for word in words[1:]:
test_line = current_line + " " + word
if draw.textlength(test_line, font) <= max_width:
current_line = test_line
else:
lines.append(current_line)
current_line = word
lines.append(current_line)
return lines
def draw_text_centered(draw, lines, position, font, max_width, padding, fill='yellow'):
y = position[1]
for line in lines:
text_width = draw.textlength(line, font)
x = position[0] + (max_width - text_width) // 2
draw.text((x, y), line, font=font, fill=fill)
y += font.getsize('hg')[1] + padding
def get_wrapped_text_size(draw, lines, font, padding):
line_height = font.getsize('hg')[1]
total_height = len(lines) * (line_height + padding) - padding
max_line_width = max(draw.textlength(line, font) for line in lines)
return total_height, max_line_width
def dynamically_adjust_font(draw, text, font, max_width, max_height, padding):
lines = wrap_text(draw, text, font, max_width)
total_height, _ = get_wrapped_text_size(draw, lines, font, padding)
while total_height > max_height and font.size > 10:
font = ImageFont.truetype(font.path, font.size - 1)
lines = wrap_text(draw, text, font, max_width)
total_height, _ = get_wrapped_text_size(draw, lines, font, padding)
return font, lines
def is_image_dark(image,threshold=128):
"""Determine if the image is predominantly dark, light or in the middle and return a suitable color for overlay"""
grayscale = image.convert('L') # Convert to grayscale
stat = ImageStat.Stat(grayscale)
avg_brightness = stat.mean[0]
if avg_brightness < threshold:
return ('dark','yellow')
else:
return ('light','red')
def add_text_to_image(image_path, text, is_title=True, save_to=None):
# Load the image
image = Image.open(image_path)
# Resize the image
resized_image = image.resize((360, 740))
# Get resized image dimensions
image_width, image_height = resized_image.size
# check if the image is more darker or more lighter
image_brightness_level = is_image_dark(resized_image)
# Create a drawing object
draw = ImageDraw.Draw(resized_image)
# setting up font_paths
font_paths = {
"weaselic" : os.path.join(constants.FONT_BASE_DIR,'Weaselic.ttf'),
"black": os.path.join(constants.FONT_BASE_DIR,'Roboto/Roboto-Black.ttf'),
"bold": os.path.join(constants.FONT_BASE_DIR,'Roboto/Roboto-Bold.ttf'),
"medium": os.path.join(constants.FONT_BASE_DIR,'Roboto/Roboto-Medium.ttf'),
"light": os.path.join(constants.FONT_BASE_DIR,'Roboto/Roboto-Light.ttf'),
"thin": os.path.join(constants.FONT_BASE_DIR,'Roboto/Roboto-Thin.ttf')
}
# Define fonts
fonts = {
"weaselic" : ImageFont.truetype(font_paths['weaselic'], 43),
"black": ImageFont.truetype(font_paths['black'], 40),
"bold": ImageFont.truetype(font_paths['bold'], 35),
"medium": ImageFont.truetype(font_paths['medium'], 40),
"light": ImageFont.truetype(font_paths['light'], 30),
"thin": ImageFont.truetype(font_paths['thin'], 30)
}
padding = 5
margin_between = 50 # Margin between title and description
safe_margin = 10 # Margin from the image edges
if is_title:
font = fonts["bold"]
max_width = image_width - 2 * safe_margin
max_height = (image_height - 2 * safe_margin) // 2
# Dynamically adjust font size and wrap text
font, lines = dynamically_adjust_font(draw, text, font, max_width, max_height, padding)
# Calculate total text height
total_height, _ = get_wrapped_text_size(draw, lines, font, padding)
# Positioning
if total_height > image_height - 2 * safe_margin:
print("Text does not fit within the image boundaries.")
else:
position = (safe_margin, safe_margin + (image_height - total_height) // 2 - 120)
# Draw the rectangle behind the text
rect_x0 = safe_margin
rect_x1 = image_width - safe_margin
rect_y0 = position[1] - padding
rect_y1 = rect_y0 + total_height + 2 * padding
draw.rectangle([(rect_x0, rect_y0), (rect_x1, rect_y1)], fill="yellow")
# Draw wrapped and centered text
draw_text_centered(draw, lines, (safe_margin, rect_y0 + padding), font, rect_x1 - rect_x0, padding, fill='black')
else:
font = fonts["weaselic"]
max_width = image_width - 2 * safe_margin
max_height = (image_height - 2 * safe_margin) // 2
# Dynamically adjust font size and wrap text
font, lines = dynamically_adjust_font(draw, text, font, max_width, max_height, padding)
# Calculate total text height
total_height, _ = get_wrapped_text_size(draw, lines, font, padding)
# Positioning
if total_height > image_height - 2 * safe_margin:
print("Text does not fit within the image boundaries.")
else:
position = (safe_margin, safe_margin + (image_height - total_height) // 2)
# Draw wrapped and centered text
description_color = image_brightness_level[1]
draw_text_centered(draw, lines, position, font, max_width, padding,fill = description_color)
# Save the image if save_to is provided
if save_to:
resized_image.save(save_to)
# Example usage:
if __name__ == '__main__':
title_text = "Top 5 mountains in the world"
description_text = "Mount Everest"
add_text_to_image('wow.png', title_text, is_title=True, save_to='output_title.png')
add_text_to_image('wow.png', description_text, is_title=False, save_to='output_description.png')
|