[16] fix overlays

This commit is contained in:
meisnate12 2022-06-02 02:32:00 -04:00
parent 3cc24d30ae
commit 5fd0162db8
4 changed files with 80 additions and 37 deletions

View file

@ -1 +1 @@
1.17.0-develop15 1.17.0-develop16

View file

@ -103,7 +103,7 @@ class MyLogger:
self._logger.removeHandler(self.playlists_handler) self._logger.removeHandler(self.playlists_handler)
def add_collection_handler(self, library_key, collection_key): def add_collection_handler(self, library_key, collection_key):
collection_dir = os.path.join(self.log_dir, library_key, COLLECTION_DIR, collection_key) collection_dir = os.path.join(self.log_dir, str(library_key), COLLECTION_DIR, str(collection_key))
os.makedirs(collection_dir, exist_ok=True) os.makedirs(collection_dir, exist_ok=True)
if library_key not in self.collection_handlers: if library_key not in self.collection_handlers:
self.collection_handlers[library_key] = {} self.collection_handlers[library_key] = {}

View file

@ -164,21 +164,24 @@ class Overlays:
logger.error(f"{item_title[:60]:<60} | Overlay Error: No poster found") logger.error(f"{item_title[:60]:<60} | Overlay Error: No poster found")
elif changed_image or overlay_change: elif changed_image or overlay_change:
try: try:
image_width = 1920 if isinstance(item, Episode) else 1000 canvas_width = 1920 if isinstance(item, Episode) else 1000
image_height = 1080 if isinstance(item, Episode) else 1500 canvas_height = 1080 if isinstance(item, Episode) else 1500
new_poster = Image.open(poster.location if poster else has_original) \ new_poster = Image.open(poster.location if poster else has_original) \
.convert("RGB").resize((image_width, image_height), Image.ANTIALIAS) .convert("RGB").resize((canvas_width, canvas_height), Image.ANTIALIAS)
if blur_num > 0: if blur_num > 0:
new_poster = new_poster.filter(ImageFilter.GaussianBlur(blur_num)) new_poster = new_poster.filter(ImageFilter.GaussianBlur(blur_num))
for over_name in normal_overlays: for over_name in normal_overlays:
overlay = properties[over_name] overlay = properties[over_name]
if not overlay.has_coordinates(): if overlay.has_coordinates():
new_poster = new_poster.resize(overlay.image.size, Image.ANTIALIAS) if overlay.portrait is not None:
overlay_image = overlay.image overlay_image = overlay.landscape if isinstance(item, Episode) else overlay.portrait
else:
overlay_image = overlay.landscape if isinstance(item, Episode) else overlay.image
new_poster.paste(overlay_image, (0, 0), overlay_image) new_poster.paste(overlay_image, (0, 0), overlay_image)
overlay_box = overlay.landscape_box if isinstance(item, Episode) else overlay.portrait_box
new_poster.paste(overlay.image, overlay_box, overlay.image)
else:
new_poster = new_poster.resize(overlay.image.size, Image.ANTIALIAS)
new_poster.paste(overlay.image, (0, 0), overlay.image)
for over_name in text_names: for over_name in text_names:
overlay = properties[over_name] overlay = properties[over_name]
text = over_name[5:-1] text = over_name[5:-1]
@ -197,9 +200,9 @@ class Overlays:
text = f"{int(text * 10)}%" text = f"{int(text * 10)}%"
if flat and str(text).endswith(".0"): if flat and str(text).endswith(".0"):
text = str(text)[:-2] text = str(text)[:-2]
overlay_image = overlay.get_overlay_image(str(text), image_width, image_height) overlay_image = overlay.get_overlay_image(str(text), (canvas_width, canvas_height))
else: else:
overlay_image = overlay.landscape if isinstance(item, Episode) else overlay.image overlay_image = overlay.landscape if isinstance(item, Episode) else overlay.portrait
new_poster.paste(overlay_image, (0, 0), overlay_image) new_poster.paste(overlay_image, (0, 0), overlay_image)
temp = os.path.join(self.library.overlay_folder, f"temp.png") temp = os.path.join(self.library.overlay_folder, f"temp.png")
new_poster.save(temp, "PNG") new_poster.save(temp, "PNG")

View file

@ -838,6 +838,10 @@ class YAML:
with open(self.path, 'w', encoding="utf-8") as fp: with open(self.path, 'w', encoding="utf-8") as fp:
self.yaml.dump(self.data, fp) self.yaml.dump(self.data, fp)
portrait_dim = (1000, 1500)
landscape_dim = (1920, 1080)
class Overlay: class Overlay:
def __init__(self, config, library, overlay_data, suppress): def __init__(self, config, library, overlay_data, suppress):
self.config = config self.config = config
@ -848,6 +852,9 @@ class Overlay:
self.updated = False self.updated = False
self.image = None self.image = None
self.landscape = None self.landscape = None
self.landscape_box = None
self.portrait = None
self.portrait_box = None
self.group = None self.group = None
self.weight = None self.weight = None
self.path = None self.path = None
@ -932,10 +939,13 @@ class Overlay:
self.back_line_width = parse("Overlay", "back_line_width", self.data["back_line_width"], datatype="int", parent="overlay") if "back_line_width" in self.data else None self.back_line_width = parse("Overlay", "back_line_width", self.data["back_line_width"], datatype="int", parent="overlay") if "back_line_width" in self.data else None
self.back_line_color = color("back_line_color") self.back_line_color = color("back_line_color")
self.back_padding = parse("Overlay", "back_padding", self.data["back_padding"], datatype="int", parent="overlay", default=0) if "back_padding" in self.data else 0 self.back_padding = parse("Overlay", "back_padding", self.data["back_padding"], datatype="int", parent="overlay", default=0) if "back_padding" in self.data else 0
self.back_width = parse("Overlay", "back_width", self.data["back_width"], datatype="int", parent="overlay") if "back_width" in self.data else None self.back_box = None
self.back_height = parse("Overlay", "back_height", self.data["back_height"], datatype="int", parent="overlay") if "back_height" in self.data else None back_width = parse("Overlay", "back_width", self.data["back_width"], datatype="int", parent="overlay", minimum=0) if "back_width" in self.data else -1
if (self.back_width and not self.back_height) or (self.back_height and not self.back_width): back_height = parse("Overlay", "back_height", self.data["back_height"], datatype="int", parent="overlay", minimum=0) if "back_height" in self.data else -1
if (back_width >= 0 and back_height < 0) or (back_height >= 0 and back_width < 0):
raise Failed(f"Overlay Error: overlay attributes back_width and back_height must be used together") raise Failed(f"Overlay Error: overlay attributes back_width and back_height must be used together")
elif back_width >= 0 and back_height >= 0:
self.back_box = (back_width, back_height)
if (self.back_color or self.back_line_color) and not self.has_coordinates(): if (self.back_color or self.back_line_color) and not self.has_coordinates():
raise Failed(f"Overlay Error: horizontal_offset and vertical_offset are required when using a backdrop") raise Failed(f"Overlay Error: horizontal_offset and vertical_offset are required when using a backdrop")
@ -1003,8 +1013,8 @@ class Overlay:
raise Failed(f"Overlay Error: overlay font_color: {self.data['font_color']} invalid") raise Failed(f"Overlay Error: overlay font_color: {self.data['font_color']} invalid")
text = self.name[5:-1] text = self.name[5:-1]
if text not in [f"{a}{s}" for a in ["audience_rating", "critic_rating", "user_rating"] for s in ["", "%"]]: if text not in [f"{a}{s}" for a in ["audience_rating", "critic_rating", "user_rating"] for s in ["", "%"]]:
self.image = self.get_overlay_image(text, 1000, 1500) self.portrait = self.get_backdrop(text, portrait_dim)
self.landscape = self.get_overlay_image(text, 1920, 1080) self.landscape = self.get_backdrop(text, landscape_dim)
else: else:
if "|" in self.name: if "|" in self.name:
raise Failed(f"Overlay Error: Overlay Name: {self.name} cannot contain '|'") raise Failed(f"Overlay Error: Overlay Name: {self.name} cannot contain '|'")
@ -1019,32 +1029,63 @@ class Overlay:
overlay_size = os.stat(self.path).st_size overlay_size = os.stat(self.path).st_size
self.updated = not image_compare or str(overlay_size) != str(image_compare) self.updated = not image_compare or str(overlay_size) != str(image_compare)
try: try:
temp_image = Image.open(self.path).convert("RGBA") self.image = Image.open(self.path).convert("RGBA")
self.image = self.get_overlay_image(temp_image, 1000, 1500) if self.has_coordinates() else temp_image if self.has_coordinates():
self.landscape = self.get_overlay_image(temp_image, 1920, 1080) if self.has_coordinates() else temp_image self.portrait, self.portrait_box = self.get_backdrop(portrait_dim, self.image.size)
self.landscape, self.landscape_box = self.get_backdrop(landscape_dim, self.image.size)
if self.config.Cache: if self.config.Cache:
self.config.Cache.update_image_map(self.name, f"{self.library.image_table_name}_overlays", self.name, overlay_size) self.config.Cache.update_image_map(self.name, f"{self.library.image_table_name}_overlays", self.name, overlay_size)
except OSError: except OSError:
raise Failed(f"Overlay Error: overlay image {self.path} failed to load") raise Failed(f"Overlay Error: overlay image {self.path} failed to load")
def get_overlay_image(self, text, image_width, image_height): def get_backdrop(self, canvas_box, box, text=None):
overlay_image = Image.new("RGBA", (image_width, image_height), (255, 255, 255, 0)) overlay_image = None
drawing = ImageDraw.Draw(overlay_image) if text is not None:
if isinstance(text, str):
_, _, width, height = self.get_text_size(text) _, _, width, height = self.get_text_size(text)
else: box = (width, height)
width, height = text.size x_cord, y_cord = self.get_coordinates(canvas_box, box)
x_cord, y_cord = self.get_coordinates(image_width, image_height, width, height) if text is not None or self.back_color or self.back_line_color:
overlay_image = Image.new("RGBA", canvas_box, (255, 255, 255, 0))
drawing = ImageDraw.Draw(overlay_image)
if self.back_color or self.back_line_color: if self.back_color or self.back_line_color:
cords = ( cords = (
x_cord - self.back_padding, x_cord - self.back_padding,
y_cord - self.back_padding, y_cord - self.back_padding,
x_cord + (self.back_width if self.back_width else width) + self.back_padding, x_cord + (self.back_box[0] if self.back_box else box[0]) + self.back_padding,
y_cord + (self.back_height if self.back_height else height) + self.back_padding y_cord + (self.back_box[1] if self.back_box else box[1]) + self.back_padding
) )
if self.back_width: if self.back_box:
x_cord = x_cord + (self.back_width - width) // 2 x_cord = x_cord + (self.back_box[0] - box[0]) // 2
y_cord = y_cord + (self.back_height - height) // 2 y_cord = y_cord + (self.back_box[1] - box[1]) // 2
if self.back_radius:
drawing.rounded_rectangle(cords, fill=self.back_color, outline=self.back_line_color, width=self.back_line_width, radius=self.back_radius)
else:
drawing.rectangle(cords, fill=self.back_color, outline=self.back_line_color, width=self.back_line_width)
if text is not None:
drawing.text((x_cord, y_cord), text, font=self.font, fill=self.font_color, anchor="lt")
return overlay_image, (x_cord, y_cord)
def get_overlay_image(self, text, canvas_box):
overlay_image = Image.new("RGBA", canvas_box, (255, 255, 255, 0))
drawing = ImageDraw.Draw(overlay_image)
if isinstance(text, str):
_, _, width, height = self.get_text_size(text)
box = (width, height)
else:
box = text.size
x_cord, y_cord = self.get_coordinates(canvas_box, box)
if self.back_color or self.back_line_color:
cords = (
x_cord - self.back_padding,
y_cord - self.back_padding,
x_cord + (self.back_box[0] if self.back_box else box[0]) + self.back_padding,
y_cord + (self.back_box[1] if self.back_box else box[1]) + self.back_padding
)
if self.back_box:
x_cord = x_cord + (self.back_box[0] - box[0]) // 2
y_cord = y_cord + (self.back_box[1] - box[1]) // 2
if self.back_radius: if self.back_radius:
drawing.rounded_rectangle(cords, fill=self.back_color, outline=self.back_line_color, width=self.back_line_width, radius=self.back_radius) drawing.rounded_rectangle(cords, fill=self.back_color, outline=self.back_line_color, width=self.back_line_width, radius=self.back_radius)
@ -1064,8 +1105,8 @@ class Overlay:
output += f"{self.horizontal_align}{self.horizontal_offset}{self.vertical_offset}{self.vertical_align}" output += f"{self.horizontal_align}{self.horizontal_offset}{self.vertical_offset}{self.vertical_align}"
if self.font_name: if self.font_name:
output += f"{self.font_name}{self.font_size}" output += f"{self.font_name}{self.font_size}"
if self.back_width: if self.back_box:
output += f"{self.back_width}{self.back_height}" output += f"{self.back_box[0]}{self.back_box[1]}"
for value in [self.font_color, self.back_color, self.back_radius, self.back_padding, self.back_line_color, self.back_line_width]: for value in [self.font_color, self.back_color, self.back_radius, self.back_padding, self.back_line_color, self.back_line_width]:
if value is not None: if value is not None:
output += f"{value}" output += f"{value}"
@ -1077,12 +1118,11 @@ class Overlay:
def get_text_size(self, text): def get_text_size(self, text):
return ImageDraw.Draw(Image.new("RGBA", (0, 0))).textbbox((0, 0), text, font=self.font, anchor='lt') return ImageDraw.Draw(Image.new("RGBA", (0, 0))).textbbox((0, 0), text, font=self.font, anchor='lt')
def get_coordinates(self, image_width, image_height, width, height): def get_coordinates(self, canvas_box, box):
if not self.has_coordinates(): if not self.has_coordinates():
return 0, 0 return 0, 0
if self.back_width: if self.back_box:
width = self.back_width box = self.back_box
height = self.back_height
def get_cord(value, image_value, over_value, align): def get_cord(value, image_value, over_value, align):
value = int(image_value * 0.01 * int(value[:-1])) if str(value).endswith("%") else value value = int(image_value * 0.01 * int(value[:-1])) if str(value).endswith("%") else value
@ -1093,5 +1133,5 @@ class Overlay:
else: else:
return value return value
return get_cord(self.horizontal_offset, image_width, width, self.horizontal_align), \ return get_cord(self.horizontal_offset, canvas_box[0], box[0], self.horizontal_align), \
get_cord(self.vertical_offset, image_height, height, self.vertical_align) get_cord(self.vertical_offset, canvas_box[1], box[1], self.vertical_align)