kavehtaheri commited on
Commit
8018ca1
·
verified ·
1 Parent(s): 01469b7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +82 -47
app.py CHANGED
@@ -76,82 +76,117 @@ def render_translated_overlay(original_image: Image.Image, text_to_overlay: str,
76
  font_size = 100
77
  final_wrapped_lines = []
78
 
79
- # ### --- FIX --- ###: Process RTL text BEFORE line wrapping
80
- # First, reshape and process the entire text for proper RTL handling
81
- try:
82
- reshaped_text = arabic_reshaper.reshape(text_to_overlay)
83
- processed_text = get_display(reshaped_text)
84
- except Exception as e:
85
- print(f"RTL processing error: {e}")
86
- processed_text = text_to_overlay # Fallback to original text
87
-
88
- while font_size > 10:
89
- font = ImageFont.truetype(PERSIAN_FONT_PATH, font_size)
90
-
91
- # ### --- FIX --- ###: Split by spaces but work with processed RTL text
92
- words = processed_text.split()
93
- if not words:
94
- break
95
-
96
- raw_lines = []
97
- current_line = ""
98
 
99
  for word in words:
100
- test_line = (current_line + " " + word).strip()
101
- # Test the width with the actual text that will be rendered
102
- line_width = draw.textbbox((0, 0), test_line, font=font)[2]
 
 
 
 
 
 
 
 
 
103
 
104
- if line_width <= target_width:
105
- current_line = test_line
106
  else:
107
- if current_line: # Only append if current_line is not empty
108
- raw_lines.append(current_line)
109
- current_line = word
 
110
 
111
- if current_line: # Don't forget the last line
112
- raw_lines.append(current_line)
 
113
 
114
- # Calculate total height
 
 
 
 
 
 
 
 
 
115
  total_height = 0
116
- for line in raw_lines:
117
- line_bbox = draw.textbbox((0, 0), line, font=font)
118
- line_height = line_bbox[3] - line_bbox[1]
119
- total_height += line_height
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
  if total_height <= overlay_height * 0.9:
122
- final_wrapped_lines = raw_lines
123
  break
124
  else:
125
  font_size -= 2
126
 
127
- if not final_wrapped_lines and raw_lines: # Fallback
128
- final_wrapped_lines = raw_lines
129
 
130
- # ### --- FIX --- ###: Render with proper spacing
131
  final_font = ImageFont.truetype(PERSIAN_FONT_PATH, font_size)
132
  line_spacing = font_size * 0.3
133
 
134
- # Calculate line heights properly
135
  line_heights = []
 
 
136
  for line in final_wrapped_lines:
137
- line_bbox = draw.textbbox((0, 0), line, font=final_font)
138
- line_height = line_bbox[3] - line_bbox[1]
139
- line_heights.append(line_height)
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
- total_text_height = sum(line_heights) + (len(final_wrapped_lines) - 1) * line_spacing
142
  y_start = (overlay_height - total_text_height) / 2
143
 
 
144
  current_y = y_start
145
- for i, line in enumerate(final_wrapped_lines):
146
  # Calculate line width and center position
147
- line_bbox = draw.textbbox((0, 0), line, font=final_font)
148
  line_width = line_bbox[2] - line_bbox[0]
149
  x_position = (overlay_width - line_width) / 2
150
 
151
  # Draw shadow for better readability
152
- draw.text((x_position + 1, current_y + 1), line, font=final_font, fill=(0, 0, 0, 180))
153
  # Draw main text
154
- draw.text((x_position, current_y), line, font=final_font, fill=(255, 255, 255, 255))
155
 
156
  current_y += line_heights[i] + line_spacing
157
 
 
76
  font_size = 100
77
  final_wrapped_lines = []
78
 
79
+ # ### --- COMPLETE FIX --- ###: Handle RTL text properly
80
+ def wrap_persian_text(text, font, max_width):
81
+ """Properly wrap Persian text maintaining RTL flow"""
82
+ words = text.split() # Split ORIGINAL text, not processed text
83
+ lines = []
84
+ current_line_words = []
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
  for word in words:
87
+ # Test with current line + new word
88
+ test_words = current_line_words + [word]
89
+ test_line = ' '.join(test_words)
90
+
91
+ # Process this test line for RTL to get actual display width
92
+ try:
93
+ reshaped_test = arabic_reshaper.reshape(test_line)
94
+ display_test = get_display(reshaped_test)
95
+ test_width = draw.textbbox((0, 0), display_test, font=font)[2]
96
+ except:
97
+ # Fallback if RTL processing fails
98
+ test_width = draw.textbbox((0, 0), test_line, font=font)[2]
99
 
100
+ if test_width <= max_width:
101
+ current_line_words.append(word)
102
  else:
103
+ # Save current line and start new one
104
+ if current_line_words:
105
+ lines.append(' '.join(current_line_words))
106
+ current_line_words = [word]
107
 
108
+ # Don't forget the last line
109
+ if current_line_words:
110
+ lines.append(' '.join(current_line_words))
111
 
112
+ return lines
113
+
114
+ # Find the right font size
115
+ while font_size > 10:
116
+ font = ImageFont.truetype(PERSIAN_FONT_PATH, font_size)
117
+
118
+ # Wrap text with current font size
119
+ wrapped_lines = wrap_persian_text(text_to_overlay, font, target_width)
120
+
121
+ # Calculate total height needed
122
  total_height = 0
123
+ for line in wrapped_lines:
124
+ try:
125
+ # Process each line for RTL to get accurate height
126
+ reshaped_line = arabic_reshaper.reshape(line)
127
+ display_line = get_display(reshaped_line)
128
+ line_bbox = draw.textbbox((0, 0), display_line, font=font)
129
+ line_height = line_bbox[3] - line_bbox[1]
130
+ total_height += line_height
131
+ except:
132
+ # Fallback height calculation
133
+ line_bbox = draw.textbbox((0, 0), line, font=font)
134
+ line_height = line_bbox[3] - line_bbox[1]
135
+ total_height += line_height
136
+
137
+ # Add spacing between lines
138
+ total_height += (len(wrapped_lines) - 1) * (font_size * 0.3)
139
 
140
  if total_height <= overlay_height * 0.9:
141
+ final_wrapped_lines = wrapped_lines
142
  break
143
  else:
144
  font_size -= 2
145
 
146
+ if not final_wrapped_lines: # Fallback
147
+ final_wrapped_lines = [text_to_overlay]
148
 
149
+ # ### --- RENDER TEXT WITH PROPER RTL --- ###
150
  final_font = ImageFont.truetype(PERSIAN_FONT_PATH, font_size)
151
  line_spacing = font_size * 0.3
152
 
153
+ # Calculate line heights and positions
154
  line_heights = []
155
+ processed_lines = [] # Store the RTL-processed lines
156
+
157
  for line in final_wrapped_lines:
158
+ try:
159
+ # Process each line individually for RTL
160
+ reshaped_line = arabic_reshaper.reshape(line)
161
+ display_line = get_display(reshaped_line)
162
+ processed_lines.append(display_line)
163
+
164
+ line_bbox = draw.textbbox((0, 0), display_line, font=final_font)
165
+ line_height = line_bbox[3] - line_bbox[1]
166
+ line_heights.append(line_height)
167
+ except Exception as e:
168
+ print(f"RTL processing failed for line '{line}': {e}")
169
+ # Fallback to original line
170
+ processed_lines.append(line)
171
+ line_bbox = draw.textbbox((0, 0), line, font=final_font)
172
+ line_height = line_bbox[3] - line_bbox[1]
173
+ line_heights.append(line_height)
174
 
175
+ total_text_height = sum(line_heights) + (len(processed_lines) - 1) * line_spacing
176
  y_start = (overlay_height - total_text_height) / 2
177
 
178
+ # Draw each line
179
  current_y = y_start
180
+ for i, display_line in enumerate(processed_lines):
181
  # Calculate line width and center position
182
+ line_bbox = draw.textbbox((0, 0), display_line, font=final_font)
183
  line_width = line_bbox[2] - line_bbox[0]
184
  x_position = (overlay_width - line_width) / 2
185
 
186
  # Draw shadow for better readability
187
+ draw.text((x_position + 1, current_y + 1), display_line, font=final_font, fill=(0, 0, 0, 180))
188
  # Draw main text
189
+ draw.text((x_position, current_y), display_line, font=final_font, fill=(255, 255, 255, 255))
190
 
191
  current_y += line_heights[i] + line_spacing
192