""" Vektorisierung: PNG → Pfade via potrace. Zerlegt das Bitmap in Konturen, die dann als SVG-Pfade manipuliert werden können. """ from __future__ import annotations import numpy as np try: import potracer HAS_POTRACER = True except ImportError: HAS_POTRACER = False from svgpathtools import Path as SvgPath, CubicBezier, Line from core.logo_model import GlyphGroup def _rgba_to_bitmap(pixels: np.ndarray, threshold: int = 128) -> np.ndarray: """Konvertiert RGBA in ein Schwarz/Weiß-Bitmap für potrace.""" gray = np.mean(pixels[:, :, :3], axis=2) alpha = pixels[:, :, 3] / 255.0 effective = gray * alpha + 255 * (1 - alpha) return (effective < threshold).astype(np.uint8) def _curve_to_svg_segment(segment): """Konvertiert ein potrace-Kurvensegment in ein svgpathtools-Segment.""" tag = segment.tag c = segment.c end = segment.end_point if tag == potracer.CORNER: return [ Line(complex(c[0][0], c[0][1]), complex(c[1][0], c[1][1])), Line(complex(c[1][0], c[1][1]), complex(end[0], end[1])), ] else: start_pt = complex(c[0][0], c[0][1]) cp1 = complex(c[0][0], c[0][1]) cp2 = complex(c[1][0], c[1][1]) end_pt = complex(end[0], end[1]) return [CubicBezier(start_pt, cp1, cp2, end_pt)] def trace_to_paths( pixels: np.ndarray, threshold: int = 128, turd_size: int = 2, alpha_max: float = 1.0, ) -> list[GlyphGroup]: """ Hauptfunktion: Konvertiert ein RGBA-Bild in eine Liste von GlyphGroups. Jede zusammenhängende Kontur wird eine eigene Gruppe. """ if not HAS_POTRACER: raise ImportError( "potracer ist nicht installiert. " "Bitte 'pip install potracer' ausführen." ) bitmap = _rgba_to_bitmap(pixels, threshold) bmp = potracer.Bitmap(bitmap) path_result = bmp.trace( turdsize=turd_size, alphamax=alpha_max, ) groups: list[GlyphGroup] = [] for i, curve in enumerate(path_result): svg_segments = [] for segment in curve.segments: svg_segments.extend(_curve_to_svg_segment(segment)) if not svg_segments: continue svg_path = SvgPath(*svg_segments) bbox = svg_path.bbox() # xmin, xmax, ymin, ymax group = GlyphGroup( label=f"Pfad_{i}", paths=[svg_path], bbox=(bbox[0], bbox[2], bbox[1] - bbox[0], bbox[3] - bbox[2]), ) groups.append(group) return groups