Spaces:
Sleeping
Sleeping
| import cv2 | |
| import textwrap | |
| from PIL import Image, ImageDraw, ImageFont | |
| import numpy as np | |
| def add_text( | |
| image, | |
| text, | |
| contour, | |
| font_path, | |
| initial_font_size=42, | |
| padding=10, | |
| line_spacing=1.25 | |
| ): | |
| """ | |
| Renderiza texto dentro de uma bolha usando o CONTOUR como referência. | |
| Prioriza quebra de linhas antes de reduzir a fonte. | |
| """ | |
| # --- Extrai bounding box do contorno --- | |
| x, y, w, h = cv2.boundingRect(contour) | |
| img_pil = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) | |
| draw = ImageDraw.Draw(img_pil) | |
| font_size = initial_font_size | |
| wrapping_ratio = 0.9 | |
| while font_size > 10: | |
| font = ImageFont.truetype(font_path, font_size) | |
| max_chars_per_line = max( | |
| 1, int((w - 2 * padding) / (font_size * wrapping_ratio)) | |
| ) | |
| lines = textwrap.wrap(text, width=max_chars_per_line) | |
| # Evita linha única quando há espaço vertical | |
| min_lines = 2 if h > font_size * 2.5 else 1 | |
| if len(lines) < min_lines: | |
| wrapping_ratio -= 0.03 | |
| continue | |
| max_line_width = 0 | |
| total_height = 0 | |
| for line in lines: | |
| bbox_text = draw.textbbox((0, 0), line, font=font) | |
| lw = bbox_text[2] - bbox_text[0] | |
| lh = bbox_text[3] - bbox_text[1] | |
| max_line_width = max(max_line_width, lw) | |
| total_height += lh | |
| total_height = int(total_height * line_spacing) | |
| if ( | |
| total_height <= (h - 2 * padding) | |
| and max_line_width <= (w - 2 * padding) | |
| ): | |
| break | |
| if max_line_width > (w - 2 * padding): | |
| wrapping_ratio -= 0.02 | |
| else: | |
| font_size -= 1 | |
| # --- Centralização --- | |
| current_y = y + padding + (h - total_height) // 2 | |
| for line in lines: | |
| bbox_text = draw.textbbox((0, 0), line, font=font) | |
| lw = bbox_text[2] - bbox_text[0] | |
| lh = bbox_text[3] - bbox_text[1] | |
| text_x = x + (w - lw) // 2 | |
| draw.text((text_x, current_y), line, fill=(0, 0, 0), font=font) | |
| current_y += int(lh * line_spacing) | |
| return cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR) | |