File size: 2,286 Bytes
3f820d9 | 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 | """Renders a plain typed/printed name as an RGBA stamp (case_type "2b": no handwriting).
Produces a tightly-cropped RGBA image shaped exactly like a
:class:`~src.rendering.signature_preprocessor.SignaturePreprocessor` output,
so it can flow through the existing
:class:`~src.placement.placement_engine.PlacementEngine` and
:class:`~src.rendering.renderer.Renderer` unchanged.
"""
from __future__ import annotations
import numpy as np
from PIL import Image, ImageDraw, ImageFont
from src.utils.logging_utils import get_logger
logger = get_logger(__name__)
_FONT_CANDIDATES: tuple[str, ...] = (
"C:/Windows/Fonts/arial.ttf",
"C:/Windows/Fonts/calibri.ttf",
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
"/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
"/System/Library/Fonts/Helvetica.ttc",
)
_FONT_SIZE_PX = 64
_PAD_PX = 6
def _load_font(size: int = _FONT_SIZE_PX) -> "ImageFont.ImageFont":
for path in _FONT_CANDIDATES:
try:
return ImageFont.truetype(path, size)
except OSError:
continue
logger.warning("No truetype font found; falling back to PIL's bitmap default font.")
return ImageFont.load_default()
def render_printed_name_stamp(name: str, ink_color: tuple[int, int, int] = (15, 15, 20)) -> np.ndarray:
"""Render ``name`` as plain typed text, returned as a tightly-cropped RGBA stamp.
Args:
name: The printed/typed name to render (no handwriting stroke texture).
ink_color: Flat RGB color for the text (matches the pipeline's ink color pool).
Returns:
An ``(H, W, 4)`` uint8 RGBA array: opaque text on a transparent background.
"""
font = _load_font()
scratch = Image.new("RGBA", (8, 8), (0, 0, 0, 0))
scratch_draw = ImageDraw.Draw(scratch)
text_bbox = scratch_draw.textbbox((0, 0), name, font=font)
text_w = max(text_bbox[2] - text_bbox[0], 1)
text_h = max(text_bbox[3] - text_bbox[1], 1)
canvas_w, canvas_h = text_w + 2 * _PAD_PX, text_h + 2 * _PAD_PX
image = Image.new("RGBA", (canvas_w, canvas_h), (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
draw.text((_PAD_PX - text_bbox[0], _PAD_PX - text_bbox[1]), name, font=font, fill=(*ink_color, 255))
return np.array(image, dtype=np.uint8)
|