diff --git a/meme_otron/__main__.py b/meme_otron/__main__.py index d0070d2..29120e4 100644 --- a/meme_otron/__main__.py +++ b/meme_otron/__main__.py @@ -11,8 +11,6 @@ if __name__ == "__main__": meme_db.load_memes() img_factory.load_fonts() - # TODO better arguments reading (-h, -o, -v) - if len(sys.argv) <= 1 or utils.read_argument(sys.argv, "help", "--help", "-h"): print(f"Meme-Otron v{VERSION}" "python -m meme_otron -h\n" diff --git a/meme_otron/img_factory.py b/meme_otron/img_factory.py index 409154a..46a03cb 100644 --- a/meme_otron/img_factory.py +++ b/meme_otron/img_factory.py @@ -26,17 +26,34 @@ def load_fonts(): logger.error(f"Could not load font '{split[0]}'") +def compose_image(images: List[Image.Image]) -> Image.Image: + width = min([img.size[0] for img in images]) + height = sum([img.size[1] for img in images]) + output_image = Image.new('RGB', (width, height)) + current_height = 0 + for img in images: + if img.size[0] != width: + img = img.resize((width, round(img.size[1] * width / img.size[0])), resample=Image.LANCZOS) + output_image.paste(img, (0, current_height)) + current_height += img.size[1] + return output_image + + def build_image(template: str, texts: List[Text], debug: bool = False) -> Optional[Image.Image]: try: img = Image.open(path.join(TEMPLATES_DIR, template)).convert(mode='RGBA') except OSError as e: logger.error(f"Could not read template file '{template}': {e}") return None - draw = ImageDraw.Draw(img) + img = apply_texts(img, texts, debug=debug) + return img + +def apply_texts(img: Image.Image, texts: List[Text], debug: bool = False) -> Image.Image: + img = img.convert(mode='RGBA') + draw = ImageDraw.Draw(img) for text in texts: draw_text(draw, img, text, debug=debug) - return img.convert(mode='RGB') diff --git a/meme_otron/meme_otron.py b/meme_otron/meme_otron.py index 2f42cf5..fedc8e1 100644 --- a/meme_otron/meme_otron.py +++ b/meme_otron/meme_otron.py @@ -1,8 +1,12 @@ import logging +from typing import Optional + +from PIL import Image from .types import Text, Pos -from . import img_factory as imgf -from . import meme_db as db +from . import img_factory +from . import meme_db +from . import utils logger = logging.getLogger("meme_otron") @@ -21,26 +25,29 @@ left_wmark.x_range = [0.005, 0.995] left_wmark.y_range = [0.005, 0.995] -def parse_text(s): - """ - :param (str) s: - :rtype: str - """ - return s.replace("\\n", "\n") - - -def compute(*args, left_wmark_text=None, debug=False): - """ - :param (str) left_wmark_text: - :param (bool) debug: - :param (str) args: - :rtype: PIL.Image.Image - :return: - """ +def compute(*args: str, left_wmark_text: Optional[Text] = None, debug: bool = False) -> Optional[Image.Image]: if len(args) < 1: return None + + parts = utils.split_arguments(args, "-") + images = [] + for part in parts: + images += [compute_part(*part, debug=debug)] + + output_image = img_factory.compose_image(images) + + watermarks = [right_wmark] + if left_wmark_text is not None: + left_wmark.text = left_wmark_text + watermarks += [left_wmark] + output_image = img_factory.apply_texts(output_image, watermarks, debug=debug) + + return output_image + + +def compute_part(*args: str, debug: bool = False) -> Optional[Image.Image]: meme_id = args[0] - meme = db.get_meme(meme_id) + meme = meme_db.get_meme(meme_id) if meme is None: logger.warning(f"Meme template '{meme_id}' not found") return None @@ -49,14 +56,10 @@ def compute(*args, left_wmark_text=None, debug=False): for i in range(len(meme.texts)): if meme.texts[i].text_ref is None: if c < len(args) - 1: - meme.texts[i].text = parse_text(args[c + 1]) + meme.texts[i].text = args[c + 1].replace("\\n", "\n") else: meme.texts[i].text = "" c += 1 else: meme.texts[i].text = meme.texts[meme.texts[i].text_ref].text - meme.texts += [right_wmark] - if left_wmark_text is not None: - left_wmark.text = left_wmark_text - meme.texts += [left_wmark] - return imgf.build_image(meme.template, meme.texts, debug=debug) + return img_factory.build_image(meme.template, meme.texts, debug=debug) diff --git a/meme_otron/utils.py b/meme_otron/utils.py index b801a0d..2d133d9 100644 --- a/meme_otron/utils.py +++ b/meme_otron/utils.py @@ -1,7 +1,7 @@ import re import sys import os.path as path -from typing import List, Optional, Union +from typing import List, Optional, Union, Tuple from Levenshtein import distance @@ -114,14 +114,14 @@ def read_argument(args: List[str], *names: str, valued: bool = False, delete: bo return None -def split_arguments(args: List[str], separator: str) -> List[List[str]]: +def split_arguments(args: Union[List[str], Tuple[str]], separator: str) -> List[List[str]]: output = [[]] for argument in args: if argument == separator: output += [[]] else: output[-1] += [argument] - return [block for block in output if len(block) > 0] + return [part for part in output if len(part) > 0] # endregion