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')