mirror of
https://github.com/meisnate12/Plex-Meta-Manager
synced 2024-11-22 12:33:10 +00:00
[16] fix overlays
This commit is contained in:
parent
3cc24d30ae
commit
5fd0162db8
4 changed files with 80 additions and 37 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
1.17.0-develop15
|
||||
1.17.0-develop16
|
||||
|
|
|
@ -103,7 +103,7 @@ class MyLogger:
|
|||
self._logger.removeHandler(self.playlists_handler)
|
||||
|
||||
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)
|
||||
if library_key not in self.collection_handlers:
|
||||
self.collection_handlers[library_key] = {}
|
||||
|
|
|
@ -164,21 +164,24 @@ class Overlays:
|
|||
logger.error(f"{item_title[:60]:<60} | Overlay Error: No poster found")
|
||||
elif changed_image or overlay_change:
|
||||
try:
|
||||
image_width = 1920 if isinstance(item, Episode) else 1000
|
||||
image_height = 1080 if isinstance(item, Episode) else 1500
|
||||
canvas_width = 1920 if isinstance(item, Episode) else 1000
|
||||
canvas_height = 1080 if isinstance(item, Episode) else 1500
|
||||
|
||||
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:
|
||||
new_poster = new_poster.filter(ImageFilter.GaussianBlur(blur_num))
|
||||
for over_name in normal_overlays:
|
||||
overlay = properties[over_name]
|
||||
if not overlay.has_coordinates():
|
||||
new_poster = new_poster.resize(overlay.image.size, Image.ANTIALIAS)
|
||||
overlay_image = overlay.image
|
||||
if overlay.has_coordinates():
|
||||
if overlay.portrait is not None:
|
||||
overlay_image = overlay.landscape if isinstance(item, Episode) else overlay.portrait
|
||||
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:
|
||||
overlay_image = overlay.landscape if isinstance(item, Episode) else overlay.image
|
||||
new_poster.paste(overlay_image, (0, 0), overlay_image)
|
||||
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:
|
||||
overlay = properties[over_name]
|
||||
text = over_name[5:-1]
|
||||
|
@ -197,9 +200,9 @@ class Overlays:
|
|||
text = f"{int(text * 10)}%"
|
||||
if flat and str(text).endswith(".0"):
|
||||
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:
|
||||
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)
|
||||
temp = os.path.join(self.library.overlay_folder, f"temp.png")
|
||||
new_poster.save(temp, "PNG")
|
||||
|
|
|
@ -838,6 +838,10 @@ class YAML:
|
|||
with open(self.path, 'w', encoding="utf-8") as fp:
|
||||
self.yaml.dump(self.data, fp)
|
||||
|
||||
|
||||
portrait_dim = (1000, 1500)
|
||||
landscape_dim = (1920, 1080)
|
||||
|
||||
class Overlay:
|
||||
def __init__(self, config, library, overlay_data, suppress):
|
||||
self.config = config
|
||||
|
@ -848,6 +852,9 @@ class Overlay:
|
|||
self.updated = False
|
||||
self.image = None
|
||||
self.landscape = None
|
||||
self.landscape_box = None
|
||||
self.portrait = None
|
||||
self.portrait_box = None
|
||||
self.group = None
|
||||
self.weight = 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_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_width = parse("Overlay", "back_width", self.data["back_width"], datatype="int", parent="overlay") if "back_width" in self.data else None
|
||||
self.back_height = parse("Overlay", "back_height", self.data["back_height"], datatype="int", parent="overlay") if "back_height" in self.data else None
|
||||
if (self.back_width and not self.back_height) or (self.back_height and not self.back_width):
|
||||
self.back_box = 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
|
||||
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")
|
||||
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():
|
||||
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")
|
||||
text = self.name[5:-1]
|
||||
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.landscape = self.get_overlay_image(text, 1920, 1080)
|
||||
self.portrait = self.get_backdrop(text, portrait_dim)
|
||||
self.landscape = self.get_backdrop(text, landscape_dim)
|
||||
else:
|
||||
if "|" in self.name:
|
||||
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
|
||||
self.updated = not image_compare or str(overlay_size) != str(image_compare)
|
||||
try:
|
||||
temp_image = Image.open(self.path).convert("RGBA")
|
||||
self.image = self.get_overlay_image(temp_image, 1000, 1500) if self.has_coordinates() else temp_image
|
||||
self.landscape = self.get_overlay_image(temp_image, 1920, 1080) if self.has_coordinates() else temp_image
|
||||
self.image = Image.open(self.path).convert("RGBA")
|
||||
if self.has_coordinates():
|
||||
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:
|
||||
self.config.Cache.update_image_map(self.name, f"{self.library.image_table_name}_overlays", self.name, overlay_size)
|
||||
except OSError:
|
||||
raise Failed(f"Overlay Error: overlay image {self.path} failed to load")
|
||||
|
||||
def get_overlay_image(self, text, image_width, image_height):
|
||||
overlay_image = Image.new("RGBA", (image_width, image_height), (255, 255, 255, 0))
|
||||
def get_backdrop(self, canvas_box, box, text=None):
|
||||
overlay_image = None
|
||||
if text is not None:
|
||||
_, _, width, height = self.get_text_size(text)
|
||||
box = (width, height)
|
||||
x_cord, y_cord = self.get_coordinates(canvas_box, box)
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
width, height = text.size
|
||||
x_cord, y_cord = self.get_coordinates(image_width, image_height, width, height)
|
||||
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_width if self.back_width else width) + self.back_padding,
|
||||
y_cord + (self.back_height if self.back_height else height) + 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_width:
|
||||
x_cord = x_cord + (self.back_width - width) // 2
|
||||
y_cord = y_cord + (self.back_height - height) // 2
|
||||
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:
|
||||
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}"
|
||||
if self.font_name:
|
||||
output += f"{self.font_name}{self.font_size}"
|
||||
if self.back_width:
|
||||
output += f"{self.back_width}{self.back_height}"
|
||||
if self.back_box:
|
||||
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]:
|
||||
if value is not None:
|
||||
output += f"{value}"
|
||||
|
@ -1077,12 +1118,11 @@ class Overlay:
|
|||
def get_text_size(self, text):
|
||||
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():
|
||||
return 0, 0
|
||||
if self.back_width:
|
||||
width = self.back_width
|
||||
height = self.back_height
|
||||
if self.back_box:
|
||||
box = self.back_box
|
||||
|
||||
def get_cord(value, image_value, over_value, align):
|
||||
value = int(image_value * 0.01 * int(value[:-1])) if str(value).endswith("%") else value
|
||||
|
@ -1093,5 +1133,5 @@ class Overlay:
|
|||
else:
|
||||
return value
|
||||
|
||||
return get_cord(self.horizontal_offset, image_width, width, self.horizontal_align), \
|
||||
get_cord(self.vertical_offset, image_height, height, self.vertical_align)
|
||||
return get_cord(self.horizontal_offset, canvas_box[0], box[0], self.horizontal_align), \
|
||||
get_cord(self.vertical_offset, canvas_box[1], box[1], self.vertical_align)
|
||||
|
|
Loading…
Reference in a new issue