Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial emoji support #882

Merged
merged 2 commits into from
Nov 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Revision History

## 11.1b1

- Added emoji support.

## 11.0

- Removed support for legacy `alt` query parameter for custom backgrounds.
Expand Down
2 changes: 2 additions & 0 deletions app/models/text.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import re
from dataclasses import dataclass

import emoji
from sanic.log import logger
from spongemock import spongemock

Expand Down Expand Up @@ -87,6 +88,7 @@ def normalize(self, text: str | None) -> str:
return text

def stylize(self, text: str, **kwargs) -> str:
text = emoji.emojize(text, language="alias")
lines = [line for line in kwargs.get("lines", [text]) if line.strip()]

if self.style == "none":
Expand Down
Empty file added app/tests/images/.flag
Empty file.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion app/tests/test_utils_images.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ async def test_custom_style_rotated(images):


def test_special_characters(images, template):
lines = ["Special? 100% #these-memes", "template_rating: 9/10"]
lines = ["Special? 👋 100% #these-memes", "template_rating: 9/10"]
utils.images.save(template, lines, directory=images)


Expand Down
1 change: 1 addition & 0 deletions app/types.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Literal, Union

from PIL.Image import Image as ImageType # noqa
from PIL.ImageDraw import ImageDraw as DrawType # noqa
from PIL.ImageFont import FreeTypeFont as FontType # noqa

Box = tuple[int, int, int, int]
Expand Down
57 changes: 36 additions & 21 deletions app/utils/images.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from __future__ import annotations

import io
from contextlib import contextmanager
from pathlib import Path
from typing import Iterator, cast

import emoji
import webp
from PIL import (
Image,
Expand All @@ -14,11 +16,12 @@
ImageSequence,
UnidentifiedImageError,
)
from pilmoji import Pilmoji
from sanic.log import logger

from .. import settings
from ..models import Font, Template, Text
from ..types import Align, Dimensions, FontType, ImageType, Offset, Point
from ..types import Align, Dimensions, DrawType, FontType, ImageType, Offset, Point

EXCEPTIONS = (
OSError,
Expand Down Expand Up @@ -253,16 +256,17 @@ def render_image(
draw.rectangle(xy, outline=outline)

rows = text.count("\n") + 1
draw.text(
(-offset[0], -offset[1]),
text,
text_fill,
font,
spacing=-offset[1] / (rows * 2),
align=align,
stroke_width=stroke_width,
stroke_fill=stroke_fill,
)
with emoji_support(box, draw, text) as draw:
draw.text(
(-offset[0], -offset[1]),
text,
text_fill,
font,
spacing=-offset[1] / (rows * 2),
align=align,
stroke_width=stroke_width,
stroke_fill=stroke_fill,
)

box = box.rotate(angle, resample=Image.Resampling.BICUBIC, expand=True)
image.paste(box, point, box)
Expand Down Expand Up @@ -386,16 +390,17 @@ def render_animation(
draw.rectangle(xy, outline=outline)

rows = text.count("\n") + 1
draw.text(
(-offset[0], -offset[1]),
text,
text_fill,
font,
spacing=-offset[1] / (rows * 2),
align=align,
stroke_width=stroke_width,
stroke_fill=stroke_fill,
)
with emoji_support(box, draw, text) as draw:
draw.text(
(-offset[0], -offset[1]),
text,
text_fill,
font,
spacing=-offset[1] / (rows * 2),
align=align,
stroke_width=stroke_width,
stroke_fill=stroke_fill,
)

try:
box = box.rotate(angle, resample=Image.Resampling.LANCZOS, expand=True)
Expand Down Expand Up @@ -554,6 +559,16 @@ def add_counter(
return Image.alpha_composite(image, box)


@contextmanager
def emoji_support(image: ImageType, draw: DrawType, text: str):
if emoji.emoji_count(text):
pilmoji = Pilmoji(image, render_discord_emoji=False, emoji_scale_factor=0.8)
yield pilmoji
pilmoji.close()
else:
yield draw


def get_image_elements(
template: Template,
lines: list[str],
Expand Down
82 changes: 38 additions & 44 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[tool.poetry]

name = "memegen"
version = "11.0"
version = "11.1b1"
description = "The free and open source API to generate memes."
authors = ["Jace Browning <[email protected]>"]
license = "MIT"
Expand All @@ -10,7 +10,7 @@ packages = [{ include = "app" }]

[tool.poetry.dependencies]

python = "3.12.5"
python = "~3.12.2"

# Sanic
sanic = "~24.6" # run 'poetry update sanic-ext sanic-testing' when changing this
Expand All @@ -23,6 +23,7 @@ pygments = "^2.15.0"

# Images
pillow = "^10.4" # run 'poetry update types-pillow' when changing this
pilmoji = { git = "https://github.com/jay3332/pilmoji", branch = "2.0" }
spongemock = "~0.3.4"

# Utilities
Expand Down