fix overlays

This commit is contained in:
2025-10-13 09:57:59 +02:00
parent ad55572aa8
commit 9a6543c530
14 changed files with 289 additions and 7 deletions

View File

@@ -39,6 +39,92 @@ def generate_texture_image(props, width, height):
pass
from PIL import Image, ImageDraw, ImageFont
# Determine resampling filters compatible with current Pillow version
resampling_module = getattr(Image, 'Resampling', None)
lanczos_filter = getattr(resampling_module, 'LANCZOS', getattr(Image, 'LANCZOS', Image.BICUBIC))
bicubic_filter = getattr(resampling_module, 'BICUBIC', getattr(Image, 'BICUBIC', Image.BILINEAR))
def _iter_enabled_overlays():
"""Yield (overlay, image_path) tuples for overlays that should be applied."""
overlays = getattr(props, 'image_overlays', [])
try:
overlay_list = list(overlays)
except TypeError:
overlay_list = []
for overlay in overlay_list:
if not getattr(overlay, 'enabled', True):
continue
image_path = getattr(overlay, 'image_path', '')
if not image_path:
continue
yield overlay, image_path
def _calculate_overlay_position(overlay, overlay_size):
"""Calculate top-left pixel position for an overlay image."""
overlay_width, overlay_height = overlay_size
canvas_width = width
canvas_height = height
mode = getattr(overlay, 'positioning_mode', 'ABSOLUTE') or 'ABSOLUTE'
x_norm = float(getattr(overlay, 'x_position', 0.5) or 0.5)
y_norm = float(getattr(overlay, 'y_position', 0.5) or 0.5)
center_x = x_norm * canvas_width
center_y = y_norm * canvas_height
spacing_ratio = max(0.0, float(getattr(overlay, 'text_spacing', 0.0) or 0.0)) / 100.0
if mode == 'APPEND':
center_x = (canvas_width * 0.5) + (spacing_ratio * canvas_width) + (overlay_width / 2.0)
elif mode == 'PREPEND':
center_x = (canvas_width * 0.5) - (spacing_ratio * canvas_width) - (overlay_width / 2.0)
x = int(round(center_x - overlay_width / 2.0))
y = int(round(center_y - overlay_height / 2.0))
max_x = max(0, canvas_width - overlay_width)
max_y = max(0, canvas_height - overlay_height)
x = max(0, min(max_x, x))
y = max(0, min(max_y, y))
return x, y
def _apply_image_overlays(pil_canvas):
"""Composite enabled image overlays onto the base canvas."""
overlays_to_apply = sorted(
_iter_enabled_overlays(),
key=lambda item: getattr(item[0], 'z_index', 0)
)
for overlay, image_path in overlays_to_apply:
try:
with Image.open(image_path) as raw_overlay:
overlay_img = raw_overlay.convert('RGBA')
except Exception as overlay_error:
print(f"WARNING: Failed to load overlay image '{image_path}': {overlay_error}")
continue
scale = float(getattr(overlay, 'scale', 1.0) or 1.0)
if scale <= 0:
continue
if scale != 1.0:
new_size = (
max(1, int(round(overlay_img.width * scale))),
max(1, int(round(overlay_img.height * scale)))
)
if new_size != overlay_img.size:
overlay_img = overlay_img.resize(new_size, lanczos_filter)
rotation = float(getattr(overlay, 'rotation', 0.0) or 0.0)
if rotation % 360:
overlay_img = overlay_img.rotate(-rotation, expand=True, resample=bicubic_filter)
x_pos, y_pos = _calculate_overlay_position(overlay, overlay_img.size)
overlay_layer = Image.new('RGBA', (width, height), (0, 0, 0, 0))
overlay_layer.paste(overlay_img, (x_pos, y_pos), overlay_img)
pil_canvas = Image.alpha_composite(pil_canvas, overlay_layer)
return pil_canvas
# Create PIL image with transparent background
if props.background_transparent:
pass
@@ -242,6 +328,9 @@ def generate_texture_image(props, width, height):
draw.text((x, y), full_text, font=font, fill=text_color)
else:
pass
# Apply any configured image overlays before converting to Blender pixels
pil_img = _apply_image_overlays(pil_img)
# Convert PIL image to Blender format (flip vertically to fix mirroring)
pil_img = pil_img.transpose(Image.FLIP_TOP_BOTTOM) # Fix mirroring issue