Update Meme Generator project
This commit is contained in:
@@ -11,24 +11,33 @@ class MemeEngine:
|
||||
"""Initialize meme engine with path to save generated memes."""
|
||||
self.output_path = output_path
|
||||
|
||||
def resize_image(self, img, width=500):
|
||||
"""Resize image to specified width while maintaining aspect ratio."""
|
||||
if img.size[0] > width:
|
||||
ratio = width / (img.size[0] * 1.0)
|
||||
height = ratio * img.size[1]
|
||||
img = img.resize((int(width), int(height)), Image.NEAREST)
|
||||
return img
|
||||
|
||||
def draw_text(self, image, message):
|
||||
"""Draw text on the image."""
|
||||
draw = ImageDraw.Draw(image)
|
||||
font = ImageFont.truetype(
|
||||
"./_data/font/calibri_regular.ttf", int(image.size[1] / 20)
|
||||
)
|
||||
draw.text((20, 20), message, font=font, fill="white")
|
||||
return image
|
||||
|
||||
def make_meme(self, img_path, text, author, width=500) -> str:
|
||||
"""Generate a meme image with given text and author."""
|
||||
output_file = f"{self.output_path}/{random.randint(0,10000)}.jpg"
|
||||
output_file = f"{self.output_path}/{random.randint(0, 10000)}.jpg"
|
||||
message = f"{text}\n- {author}"
|
||||
|
||||
try:
|
||||
with Image.open(img_path) as img:
|
||||
# Resize image while maintaining aspect ratio
|
||||
width = 500 if img.size[0] > 500 else img.size[0]
|
||||
ratio = width / (img.size[0] * 1.0)
|
||||
height = ratio * img.size[1]
|
||||
img = img.resize((int(width), int(height)), Image.NEAREST)
|
||||
draw = ImageDraw.Draw(img)
|
||||
font = ImageFont.truetype(
|
||||
"./_data/font/calibri_regular.ttf", int(height / 20)
|
||||
)
|
||||
draw.text((20, 20), message, font=font, fill="white")
|
||||
img.save(output_file)
|
||||
image_resize = self.resize_image(img, width=width)
|
||||
image_draw = self.draw_text(image_resize, message)
|
||||
image_draw.save(output_file)
|
||||
except Exception as err:
|
||||
print(f"Error: {err}")
|
||||
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
"""MemeEngine package.
|
||||
|
||||
Provides the MemeEngine class for generating meme images from templates.
|
||||
"""
|
||||
|
||||
from .MemeEngine import MemeEngine
|
||||
|
||||
@@ -19,5 +19,6 @@ class IngestorInterface(ABC):
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def parse(cls, path: str) -> List[QuoteModel]:
|
||||
"""Abstract method to parse the file and return a list of QuoteModel objects."""
|
||||
"""Abstract method to parse the file and return a list of QuoteModel
|
||||
objects."""
|
||||
pass
|
||||
|
||||
@@ -23,7 +23,7 @@ class PDFIngestor(IngestorInterface):
|
||||
tmp = f"./tmp/{random.randint(0, 10000)}.txt"
|
||||
try:
|
||||
# pdftotext <input-pdf> <output-text-file>
|
||||
call = subprocess.call(["pdftotext", path, tmp])
|
||||
subprocess.call(["pdftotext", path, tmp])
|
||||
with open(tmp, "r") as file:
|
||||
lines = file.readlines()
|
||||
except FileNotFoundError as err:
|
||||
|
||||
@@ -10,5 +10,5 @@ class QuoteModel:
|
||||
self.author = author
|
||||
|
||||
def __repr__(self):
|
||||
"""String representation of the QuoteModel object."""
|
||||
"""Return a string representation of the QuoteModel."""
|
||||
return f"{self.body} - {self.author}"
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
"""QuoteEngine package.
|
||||
|
||||
Provides tools for parsing and representing quote data.
|
||||
"""
|
||||
|
||||
from .IngestorInterface import IngestorInterface
|
||||
from .CSVIngestor import CSVIngestor
|
||||
from .DocxIngestor import DocxIngestor
|
||||
|
||||
@@ -37,3 +37,16 @@ Open link `http://127.0.0.1:5000` in web browser
|
||||
`DocxIngestor`: Module for ingesting Docx files containing quotes. \
|
||||
`TextIngestor`: Module for ingesting text files containing quotes. \
|
||||
`PDFIngestor`: Module for ingesting PDF files containing quotes.
|
||||
|
||||
### Format checking
|
||||
```sh
|
||||
$ pip install docformatter
|
||||
$ pip install autopep8
|
||||
$ pip install black
|
||||
$ pip install flake8
|
||||
|
||||
$ docformatter -i -r --wrap-summaries 79 --wrap-descriptions 79 .
|
||||
$ autopep8 --in-place --recursive --aggressive .
|
||||
$ black .
|
||||
$ flake8 .
|
||||
```
|
||||
@@ -1,3 +1,5 @@
|
||||
"""Flask app to generate memes."""
|
||||
|
||||
import random
|
||||
import os
|
||||
import requests
|
||||
@@ -6,17 +8,17 @@ from flask import Flask, render_template, abort, request
|
||||
from QuoteEngine import Ingestor
|
||||
from MemeEngine import MemeEngine
|
||||
|
||||
# Create the Flask application object. "__name__" tells Flask where to find templates and static files.
|
||||
# Create the Flask application object. "__name__" tells Flask,
|
||||
# where to find templates and static files.
|
||||
app = Flask(__name__)
|
||||
|
||||
# Create a global MemeEngine instance that will write generated memes into "./static"
|
||||
# so that the images can be served by the web server.
|
||||
# Create a global MemeEngine instance that will write generated memes
|
||||
# into "./static" so that the images can be served by the web server.
|
||||
meme = MemeEngine("./static")
|
||||
|
||||
|
||||
def setup():
|
||||
"""Load all resources"""
|
||||
|
||||
"""Load all resources."""
|
||||
quote_files = [
|
||||
"./_data/DogQuotes/DogQuotesTXT.txt",
|
||||
"./_data/DogQuotes/DogQuotesDOCX.docx",
|
||||
@@ -45,7 +47,7 @@ quotes, imgs = setup()
|
||||
|
||||
@app.route("/")
|
||||
def meme_rand():
|
||||
"""Generate a random meme
|
||||
"""Generate a random meme.
|
||||
|
||||
Steps:
|
||||
- Pick a random image from imgs
|
||||
@@ -63,7 +65,7 @@ def meme_rand():
|
||||
|
||||
@app.route("/create", methods=["GET"])
|
||||
def meme_form():
|
||||
"""User input for meme information
|
||||
"""User input for meme information.
|
||||
|
||||
This route renders a form where the user can input:
|
||||
- image_url: URL of the source image
|
||||
@@ -75,7 +77,7 @@ def meme_form():
|
||||
|
||||
@app.route("/create", methods=["POST"])
|
||||
def meme_post():
|
||||
"""Create a user defined meme
|
||||
"""Create a user defined meme.
|
||||
|
||||
This route:
|
||||
- Reads form data sent via POST from the meme_form page
|
||||
@@ -95,8 +97,8 @@ def meme_post():
|
||||
tmp_file = f"tmp/{random.randint(0, 10000)}.jpg"
|
||||
with open(tmp_file, "wb") as file:
|
||||
file.write(image.content)
|
||||
except:
|
||||
print("Failed to generate meme")
|
||||
except OSError as e:
|
||||
print("Failed to generate meme:", e)
|
||||
path = None
|
||||
if os.path.exists(tmp_file):
|
||||
os.remove(tmp_file)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
"""Generate a meme from an image and a quote."""
|
||||
|
||||
import os
|
||||
import random
|
||||
import argparse
|
||||
@@ -6,7 +8,7 @@ from QuoteEngine import QuoteModel, Ingestor
|
||||
|
||||
|
||||
def generate_meme(path=None, body=None, author=None):
|
||||
"""Generate a meme given an path and a quote"""
|
||||
"""Generate a meme given an path and a quote."""
|
||||
img = None
|
||||
quote = None
|
||||
|
||||
@@ -45,7 +47,8 @@ def generate_meme(path=None, body=None, author=None):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
"""Add path, quote, and author arguments for CLI, then print meme generation."""
|
||||
"""Add path, quote, and author arguments for CLI, then print meme
|
||||
generation."""
|
||||
parser = argparse.ArgumentParser(description="Meme Generator")
|
||||
parser.add_argument("--path", type=str, help="Image path")
|
||||
parser.add_argument("--body", type=str, help="Quote adding to meme")
|
||||
|
||||
Reference in New Issue
Block a user