diff --git a/app/utils/photo_stamp.py b/app/utils/photo_stamp.py index 7abc8e9..54185a6 100644 --- a/app/utils/photo_stamp.py +++ b/app/utils/photo_stamp.py @@ -216,40 +216,44 @@ def _draw_overlay(img, lines): width, height = img.size # Scale everything off the short edge so portrait and landscape match. base = min(width, height) - font_size = max(14, int(base * 0.035)) - pad = max(8, int(base * 0.018)) + font_size = max(11, int(base * 0.020)) + pad = max(6, int(base * 0.012)) font = _load_font(font_size) - draw = ImageDraw.Draw(img) + measure = ImageDraw.Draw(img) # Measure the block. heights, widths = [], [] for line in lines: - box = draw.textbbox((0, 0), line, font=font) + box = measure.textbbox((0, 0), line, font=font) widths.append(box[2] - box[0]) heights.append(box[3] - box[1]) line_gap = max(2, int(font_size * 0.25)) text_h = sum(heights) + line_gap * (len(lines) - 1) bar_h = text_h + pad * 2 - # Translucent black bar, composited so it works on RGB too. - bar = Image.new('RGBA', (width, bar_h), (0, 0, 0, 150)) + # Draw the whole overlay on a transparent layer so both the bar AND the + # text carry alpha, then composite once. Keeps the photo readable through + # the stamp instead of masking it behind a solid strip. + layer = Image.new('RGBA', (width, bar_h), (0, 0, 0, 0)) + draw = ImageDraw.Draw(layer) + draw.rectangle((0, 0, width, bar_h), fill=(0, 0, 0, 80)) + + y = pad + for line, h in zip(lines, heights): + # Faint dark outline still keeps the text legible over a bright photo. + for dx, dy in ((-1, 0), (1, 0), (0, -1), (0, 1)): + draw.text((pad + dx, y + dy), line, font=font, fill=(0, 0, 0, 90)) + draw.text((pad, y), line, font=font, fill=(255, 255, 255, 165)) + y += h + line_gap + if img.mode == 'RGBA': - img.alpha_composite(bar, (0, height - bar_h)) + img.alpha_composite(layer, (0, height - bar_h)) else: img.paste(Image.alpha_composite( - img.crop((0, height - bar_h, width, height)).convert('RGBA'), bar + img.crop((0, height - bar_h, width, height)).convert('RGBA'), layer ).convert('RGB'), (0, height - bar_h)) - draw = ImageDraw.Draw(img) - y = height - bar_h + pad - for line, h in zip(lines, heights): - # Thin dark outline keeps the text legible over a bright photo. - for dx, dy in ((-1, 0), (1, 0), (0, -1), (0, 1)): - draw.text((pad + dx, y + dy), line, font=font, fill=(0, 0, 0)) - draw.text((pad, y), line, font=font, fill=(255, 255, 255)) - y += h + line_gap - return img