diff --git a/fonts/ComicNeue-Regular.ttf b/fonts/ComicNeue-Regular.ttf deleted file mode 100755 index 6525a27..0000000 Binary files a/fonts/ComicNeue-Regular.ttf and /dev/null differ diff --git a/fonts/ComicRelief-Regular.ttf b/fonts/ComicRelief-Regular.ttf deleted file mode 100755 index d49aabc..0000000 Binary files a/fonts/ComicRelief-Regular.ttf and /dev/null differ diff --git a/fonts/Komika.ttf b/fonts/Komika.ttf new file mode 100644 index 0000000..15bab8e Binary files /dev/null and b/fonts/Komika.ttf differ diff --git a/fonts/Laffayette_Comic_Pro.ttf b/fonts/Laffayette_Comic_Pro.ttf new file mode 100644 index 0000000..9b9a0f9 Binary files /dev/null and b/fonts/Laffayette_Comic_Pro.ttf differ diff --git a/fonts/animeace2_bld.ttf b/fonts/animeace2_bld.ttf new file mode 100644 index 0000000..79df8b3 Binary files /dev/null and b/fonts/animeace2_bld.ttf differ diff --git a/fonts/animeace2_ital.ttf b/fonts/animeace2_ital.ttf new file mode 100644 index 0000000..ad50ee2 Binary files /dev/null and b/fonts/animeace2_ital.ttf differ diff --git a/fonts/animeace2_reg.ttf b/fonts/animeace2_reg.ttf new file mode 100644 index 0000000..6521ab5 Binary files /dev/null and b/fonts/animeace2_reg.ttf differ diff --git a/manga-renderer.py b/manga-renderer.py index f108d9f..5e70093 100644 --- a/manga-renderer.py +++ b/manga-renderer.py @@ -11,8 +11,8 @@ Strategy: 2. Detect the original font size from the OCR bounding boxes. 3. Dynamically wrap and scale down the translated text if it exceeds the bubble dimensions. 4. Render the translated text centered inside the bubble bounding box. - 5. Uses uniform line heights to prevent accent collisions. - 6. Adds a white stroke to the text to cover any residual original characters. + 5. Uses uniform line heights (ascent + descent) to prevent Catalan accent collisions (È, À). + 6. Adds a dynamic white stroke to the text to cover any residual original characters. """ import json @@ -25,26 +25,19 @@ from typing import Dict, List, Tuple, Optional, Set, Any # ============================================================ # CONFIG — edit these paths to match your setup # ============================================================ -IMAGE_PATH = "003.jpg" -BUBBLES_PATH = "bubbles.json" -TRANSLATIONS_PATH = "output_003.txt" -OUTPUT_PATH = "translated_page_003.png" +IMAGE_PATH = "004.png" +BUBBLES_PATH = "bubbles_004.json" +TRANSLATIONS_PATH = "output_004.txt" +OUTPUT_PATH = "translated_page_004.png" -# Font candidates — first one that loads wins +# Font candidates — Prioritizes Laffayette for Catalan, with safe fallbacks FONT_CANDIDATES = [ + "fonts/animeace2_reg.ttf", "fonts/ComicNeue-Bold.ttf", - # Mac fallbacks - "/System/Library/Fonts/Supplemental/Comic Sans MS Bold.ttf", - "/System/Library/Fonts/Supplemental/Arial Bold.ttf", - # Windows fallbacks - "C:\\Windows\\Fonts\\comicbd.ttf", - "C:\\Windows\\Fonts\\arialbd.ttf", - # Linux fallbacks - "/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf", ] -DEFAULT_FONT_SIZE = 24 -MIN_FONT_SIZE = 12 +DEFAULT_FONT_SIZE = 18 +MIN_FONT_SIZE = 8 QUAD_PAD = 4 # extra pixels added around each quad before white-fill # ============================================================ @@ -105,9 +98,7 @@ def parse_translations(filepath: str) -> Dict[int, str]: return translations def parse_bubbles(filepath: str): - """ - Returns the full JSON data. - """ + """Returns the full JSON data.""" with open(filepath, "r", encoding="utf-8") as f: data = json.load(f) return data @@ -205,7 +196,7 @@ def fit_text_dynamically( wrapped_lines = textwrap.wrap(text, width=chars_per_line) - # Use uniform font metrics for height instead of per-line bounding boxes + # Use uniform font metrics for height to protect accents like È line_spacing = max(2, int(font_size * 0.15)) if hasattr(font, 'getmetrics'): ascent, descent = font.getmetrics() @@ -246,7 +237,7 @@ def render_text( ): """ Draws the translated text centered in the line_union_bbox of each bubble. - Adds a white stroke (outline) to cover any residual original characters. + Adds a dynamic white stroke (outline) to cover any residual original characters. """ image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB) pil_img = Image.fromarray(image_rgb) @@ -280,7 +271,7 @@ def render_text( target_size = get_original_font_size(val) wrapped_lines, font, line_spacing, final_size = fit_text_dynamically(text, font_path, bw, bh, target_size) - # Use uniform typographic line height for rendering + # Use uniform typographic line height for rendering to protect accents if hasattr(font, 'getmetrics'): ascent, descent = font.getmetrics() line_h = ascent + descent @@ -290,6 +281,8 @@ def render_text( total_text_height = (line_h * len(wrapped_lines)) + (line_spacing * max(0, len(wrapped_lines) - 1)) current_y = by + (bh - total_text_height) // 2 + + # Dynamic outline thickness based on the final scaled font size outline_thickness = max(2, int(final_size * 0.10)) for i, line in enumerate(wrapped_lines): @@ -301,6 +294,7 @@ def render_text( current_x = bx + (bw - lw) // 2 + # Draw text with white stroke for artifact coverage draw.text( (current_x, current_y), line, diff --git a/manga-translator.py b/manga-translator.py index 684c7c3..66cb56c 100644 --- a/manga-translator.py +++ b/manga-translator.py @@ -1108,8 +1108,8 @@ def translate_manga_text( if __name__ == "__main__": translate_manga_text( - image_path="003.jpg", - source_lang="es", + image_path="004.png", + source_lang="en", target_lang="ca", confidence_threshold=0.05, min_text_length=1,