animator_extension/scripts/functions/postprocessing.py

103 lines
3.8 KiB
Python

import os
import numpy as np
from PIL import Image, ImageDraw, ImageFont
def paste_prop(img: Image, props: dict, prop_folder: str) -> Image:
if img.mode != 'RGB':
img2 = img.convert('RGBA')
else:
img2 = img
for prop_name in props:
# prop_name | prop filename | x pos | y pos | scale | rotation
prop_filename = os.path.join(prop_folder.strip(), str(props[prop_name][1]).strip())
x = int(props[prop_name][2])
y = int(props[prop_name][3])
scale = float(props[prop_name][4])
rotation = float(props[prop_name][5])
if not os.path.exists(prop_filename):
print("Prop: Cannot locate file: " + prop_filename)
return img
prop = Image.open(prop_filename)
w2, h2 = prop.size
prop2 = prop.resize((int(w2 * scale), int(h2 * scale)), Image.Resampling.LANCZOS).rotate(rotation, expand=True)
w3, h3 = prop2.size
tmplayer = Image.new('RGBA', img.size, (0, 0, 0, 0))
tmplayer.paste(prop2, (int(x - w3 / 2), int(y - h3 / 2)))
img2 = Image.alpha_composite(img2, tmplayer)
return img2# .convert("RGB")
def render_text_block(img: Image, text_blocks: dict) -> Image:
pad = 1 # Rounding and edge padding of the bubble background.
d1 = ImageDraw.Draw(img)
font_size = 20
for text_name in text_blocks:
# textblock_name | text_prompt | x | y | w | h | back_color | white_color | font_filename
text_prompt = str(text_blocks[text_name][1]).strip().replace('\\n', '\n')
x = int(text_blocks[text_name][2])
y = int(text_blocks[text_name][3])
w = int(text_blocks[text_name][4])
h = int(text_blocks[text_name][5])
# Try to convert text to a tuple (255,255,255) or just leave as text "white"
try:
background_colour = eval(text_blocks[text_name][6].strip())
except:
background_colour = text_blocks[text_name][6].strip()
try:
foreground_colour = eval(text_blocks[text_name][7].strip())
except:
foreground_colour = text_blocks[text_name][7].strip()
font_name = str(text_blocks[text_name][8]).strip().lower()
# Auto size the text.
for fs in range(70):
text_block_font = ImageFont.truetype(font_name, fs)
txt_block_size = d1.multiline_textbbox((0, 0), text_prompt, font=text_block_font, align='center')
if txt_block_size[2] - txt_block_size[0] > (w - pad * 2) or \
txt_block_size[3] - txt_block_size[1] > (h - pad * 2):
font_size = fs - 1
break
text_block_font = ImageFont.truetype(font_name, font_size)
# print(f"size:{font_size} loc:{x}, {y} size:{w}, {h}")
txt_block_size = d1.multiline_textbbox((0, 0), text_prompt, font=text_block_font, align='center')
# print(f"txt_block_size:{txt_block_size}")
d1.rounded_rectangle((x, y, x + w, y + h), radius=pad, fill=background_colour)
d1.multiline_text((x + pad, y + pad + (h - txt_block_size[3]) / 2),
text_prompt,
fill=foreground_colour,
font=text_block_font,
align='center')
return img
def morph(img1: Image, img2: Image, count: int) -> list:
"""
count=4
img1:0
0.2 (1/5)
0.4 (2/5)
0.6 (3/5)
0.8 (4/5)
img2:1
"""
# print(f"img1: {img1.mode} img2: {img2.mode}")
arr1 = np.array(img1).astype('float')
diff = (np.array(img2).astype('float') - arr1) / (count+1)
img_list = []
for x in range(0, count):
print(f"x: {x}")
arr1 += diff
img_list.append(Image.fromarray(arr1.astype('uint8'), 'RGBA'))
return img_list