File size: 5,281 Bytes
fbfdc25
 
 
f52a68c
fbfdc25
 
 
79e5b91
a29ec48
9e08a6d
 
 
 
 
 
 
fbfdc25
f52a68c
9e08a6d
65c3bfa
54ab095
 
a29ec48
54ab095
 
35b1a5a
 
54ab095
 
 
 
35b1a5a
54ab095
fbfdc25
 
 
 
 
65c3bfa
19de2fe
fbfdc25
65c3bfa
a29ec48
 
 
 
 
 
 
 
dfae7ec
65c3bfa
 
dfae7ec
 
 
65c3bfa
fbfdc25
65c3bfa
 
 
 
 
dfae7ec
65c3bfa
 
dfae7ec
 
65c3bfa
 
f52a68c
65c3bfa
 
 
 
 
 
dfae7ec
 
 
 
65c3bfa
 
a29ec48
 
65c3bfa
 
a29ec48
65c3bfa
 
 
a29ec48
65c3bfa
a29ec48
65c3bfa
 
 
 
 
dfae7ec
65c3bfa
a29ec48
65c3bfa
a29ec48
65c3bfa
fbfdc25
 
f52a68c
fbfdc25
a29ec48
f52a68c
 
fbfdc25
 
 
a29ec48
fbfdc25
 
9e08a6d
fbfdc25
 
a29ec48
54ab095
fbfdc25
 
9e08a6d
a29ec48
 
35b1a5a
fbfdc25
 
 
35b1a5a
9e08a6d
54ab095
fbfdc25
 
dfae7ec
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
import gradio as gr
from PIL import Image, ImageDraw, ImageFont
import arabic_reshaper
from bidi.algorithm import get_display 
import requests
from io import BytesIO
import os

# Your COLOR_MAP dictionary remains the same
COLOR_MAP = {
    "Black": (0, 0, 0),
    "White": (255, 255, 255),
    "Gray": (128, 128, 128),
    "Red": (255, 0, 0),
    "Blue": (0, 0, 255),
}

# --- REVISED AND FINAL FUNCTION ---
def overlay_text_on_image(persian_text, url, upload, username, text_color):
    # --- Stage 1: Image Loading (No changes) ---
    if url and url.strip():
        if not url.startswith(('http://', 'https://')):
            url = 'https://' + url
        try:
            response = requests.get(url)
            response.raise_for_status()
            img = Image.open(BytesIO(response.content))
        except Exception as e:
            raise ValueError(f"Failed to load image from URL: {e}")
    elif upload:
        img = Image.open(upload)
    else:
        raise ValueError("Please provide either an image URL or upload an image.")
    
    img = img.resize((1080, 1080), Image.LANCZOS)
    draw = ImageDraw.Draw(img)
    width, height = img.size
    
    # --- Stage 2: Font and Color Setup (No changes) ---
    font_path = "Vazir.ttf" 
    if not os.path.exists(font_path):
        print("Warning: Vazirmatn font not found. Falling back to default.")
        possible_fonts = [
            "Vazir.ttf",
            "/usr/share/fonts/truetype/noto/NotoNaskhArabic-Regular.ttf",
            "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
        ]
        font_path = next((f for f in possible_fonts if os.path.exists(f)), "DejaVuSans.ttf")

    selected_color = COLOR_MAP.get(text_color, (0, 0, 0))
    lines = [line for line in persian_text.split('\n') if line.strip()]
    reshaped_lines = [arabic_reshaper.reshape(line) for line in lines]

    # --- Stage 3: UNIFORM FONT SIZE CALCULATION (No changes in logic) ---
    initial_font_size = 80
    max_width = width * 0.90
    uniform_font_size = initial_font_size
    
    longest_line = ""
    if reshaped_lines:
        temp_font = ImageFont.truetype(font_path, uniform_font_size)
        longest_line = max(reshaped_lines, key=lambda line: draw.textlength(line, font=temp_font))
    
    while uniform_font_size > 20:
        font = ImageFont.truetype(font_path, uniform_font_size)
        if draw.textlength(longest_line, font=font) <= max_width:
            break
        uniform_font_size -= 2
    
    final_font = ImageFont.truetype(font_path, uniform_font_size)

    # --- Stage 4: Text Block Height Calculation and Centering ---
    line_spacing = 20
    total_text_height = 0
    line_heights = []
    
    for line in reshaped_lines:
        # *** THE ONLY CHANGE IS ON THIS LINE ***
        # Replaced getbbox with textbbox for older Pillow compatibility
        line_bbox = draw.textbbox((0, 0), line, font=final_font)
        
        line_height = line_bbox[3] - line_bbox[1]
        line_heights.append(line_height)
        total_text_height += line_height

    total_text_height += (len(reshaped_lines) - 1) * line_spacing if len(reshaped_lines) > 1 else 0
    y_start = (height - total_text_height) / 2
    
    # --- Stage 5: Drawing the Text ---
    current_y = y_start
    for i, line in enumerate(reshaped_lines):
        x_center = width / 2
        line_y_center = current_y + line_heights[i] / 2
        
        draw.text(
            (x_center, line_y_center), 
            line, 
            font=final_font, 
            fill=selected_color, 
            anchor="mm"
        )
        
        current_y += line_heights[i] + line_spacing

    # --- Stage 6: Username Drawing (No changes) ---
    username_font_size = 40
    username_font = ImageFont.truetype(font_path, username_font_size)
    display_username = get_display(arabic_reshaper.reshape(f"@{username}"))
    
    username_x = width / 2
    username_y = height - 50
    draw.text((username_x, username_y), display_username, font=username_font, fill=selected_color, anchor="mb")
    
    return img

# --- Your Gradio Interface Code (No changes needed here) ---
with gr.Blocks() as demo:
    gr.Markdown("# Persian Quote Overlay for Instagram Posts")
    gr.Markdown("Paste an image URL from another HF Space or upload an image, enter Persian text (quote, supports multi-line), choose text color, and username. The app overlays the text centered with dynamic font sizing and places the username at the bottom center.")
    
    with gr.Row():
        persian_text = gr.Textbox(label="Persian Quote Text (Multi-line supported)", lines=5)
        image_input = gr.Textbox(label="Image URL (e.g., from another HF Space)")
        username = gr.Textbox(label="Channel Username (e.g., mychannel)")
    
    with gr.Row():
        text_color = gr.Dropdown(label="Text Color", choices=list(COLOR_MAP.keys()), value="Black")
        image_upload = gr.Image(label="Optional: Upload Image (if not using URL)", type="filepath")
    
    output_image = gr.Image(label="Output Image")
    
    submit_btn = gr.Button("Generate Overlay")
    submit_btn.click(overlay_text_on_image, 
                     inputs=[persian_text, image_input, image_upload, username, text_color], 
                     outputs=output_image)

demo.launch()