simple memes piping
This commit is contained in:
@@ -11,8 +11,6 @@ if __name__ == "__main__":
|
|||||||
meme_db.load_memes()
|
meme_db.load_memes()
|
||||||
img_factory.load_fonts()
|
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"):
|
if len(sys.argv) <= 1 or utils.read_argument(sys.argv, "help", "--help", "-h"):
|
||||||
print(f"Meme-Otron v{VERSION}"
|
print(f"Meme-Otron v{VERSION}"
|
||||||
"python -m meme_otron -h\n"
|
"python -m meme_otron -h\n"
|
||||||
|
|||||||
@@ -26,17 +26,34 @@ def load_fonts():
|
|||||||
logger.error(f"Could not load font '{split[0]}'")
|
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]:
|
def build_image(template: str, texts: List[Text], debug: bool = False) -> Optional[Image.Image]:
|
||||||
try:
|
try:
|
||||||
img = Image.open(path.join(TEMPLATES_DIR, template)).convert(mode='RGBA')
|
img = Image.open(path.join(TEMPLATES_DIR, template)).convert(mode='RGBA')
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
logger.error(f"Could not read template file '{template}': {e}")
|
logger.error(f"Could not read template file '{template}': {e}")
|
||||||
return None
|
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:
|
for text in texts:
|
||||||
draw_text(draw, img, text, debug=debug)
|
draw_text(draw, img, text, debug=debug)
|
||||||
|
|
||||||
return img.convert(mode='RGB')
|
return img.convert(mode='RGB')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+28
-25
@@ -1,8 +1,12 @@
|
|||||||
import logging
|
import logging
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
from .types import Text, Pos
|
from .types import Text, Pos
|
||||||
from . import img_factory as imgf
|
from . import img_factory
|
||||||
from . import meme_db as db
|
from . import meme_db
|
||||||
|
from . import utils
|
||||||
|
|
||||||
logger = logging.getLogger("meme_otron")
|
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]
|
left_wmark.y_range = [0.005, 0.995]
|
||||||
|
|
||||||
|
|
||||||
def parse_text(s):
|
def compute(*args: str, left_wmark_text: Optional[Text] = None, debug: bool = False) -> Optional[Image.Image]:
|
||||||
"""
|
|
||||||
: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:
|
|
||||||
"""
|
|
||||||
if len(args) < 1:
|
if len(args) < 1:
|
||||||
return None
|
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_id = args[0]
|
||||||
meme = db.get_meme(meme_id)
|
meme = meme_db.get_meme(meme_id)
|
||||||
if meme is None:
|
if meme is None:
|
||||||
logger.warning(f"Meme template '{meme_id}' not found")
|
logger.warning(f"Meme template '{meme_id}' not found")
|
||||||
return None
|
return None
|
||||||
@@ -49,14 +56,10 @@ def compute(*args, left_wmark_text=None, debug=False):
|
|||||||
for i in range(len(meme.texts)):
|
for i in range(len(meme.texts)):
|
||||||
if meme.texts[i].text_ref is None:
|
if meme.texts[i].text_ref is None:
|
||||||
if c < len(args) - 1:
|
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:
|
else:
|
||||||
meme.texts[i].text = ""
|
meme.texts[i].text = ""
|
||||||
c += 1
|
c += 1
|
||||||
else:
|
else:
|
||||||
meme.texts[i].text = meme.texts[meme.texts[i].text_ref].text
|
meme.texts[i].text = meme.texts[meme.texts[i].text_ref].text
|
||||||
meme.texts += [right_wmark]
|
return img_factory.build_image(meme.template, meme.texts, debug=debug)
|
||||||
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)
|
|
||||||
|
|||||||
+3
-3
@@ -1,7 +1,7 @@
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import os.path as path
|
import os.path as path
|
||||||
from typing import List, Optional, Union
|
from typing import List, Optional, Union, Tuple
|
||||||
from Levenshtein import distance
|
from Levenshtein import distance
|
||||||
|
|
||||||
|
|
||||||
@@ -114,14 +114,14 @@ def read_argument(args: List[str], *names: str, valued: bool = False, delete: bo
|
|||||||
return None
|
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 = [[]]
|
output = [[]]
|
||||||
for argument in args:
|
for argument in args:
|
||||||
if argument == separator:
|
if argument == separator:
|
||||||
output += [[]]
|
output += [[]]
|
||||||
else:
|
else:
|
||||||
output[-1] += [argument]
|
output[-1] += [argument]
|
||||||
return [block for block in output if len(block) > 0]
|
return [part for part in output if len(part) > 0]
|
||||||
|
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|||||||
Reference in New Issue
Block a user