Last active
February 26, 2024 20:32
-
-
Save kubinka0505/e2d52058e05646b21c04f6fbe1222b38 to your computer and use it in GitHub Desktop.
[does not work, don't use] Simple script providing multiline text draw with emoji support (Pillow & emojicdn)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Simple script providing multiline text draw with emoji support (Pillow & emojicdn)""" | |
import io | |
from requests import get | |
from textwrap import wrap | |
from urllib.parse import quote_plus | |
from emoji import emojize, demojize, UNICODE_EMOJI | |
from PIL import Image, ImageDraw, ImageFont, UnidentifiedImageError | |
#-----# | |
__author__ = "kubinka0505" | |
__date__ = "07.01.2021" | |
__version__ = "0.5" | |
__credits__ = __author__ | |
__status__ = "Development" | |
__license__ = "Apache 2.0" | |
__changelog__ = { | |
"0.1": ["Initial release"], | |
"0.2": [ | |
"Increased code readability", | |
"Easier alignment manipulation", | |
"Modified Lines → Images system", | |
], | |
"0.3": ["Typo fixes"], | |
"0.4": ["Typo fixes"], | |
"0.5": ["Fixed an issue where the text line spacing was incorrect if it contained characters of different heights"], | |
} | |
#-----# | |
class EmojiUtils: | |
"""Various emoji utility.""" | |
#---# | |
def __init__(self, Name: str): | |
"""Emoji have to start and end with the semicolons!""" | |
self.Name = Name | |
#---# | |
def get_image(self, Style: int = 5) -> Image.open: | |
"""Gets Emoji image from "emojicdn.elk.sh" API using style lists from its GitHub main page.""" | |
Styles = { | |
0: 'apple', 1: 'google', 2: 'microsoft', 3: 'samsung', | |
4: 'whatsapp', 5: 'twitter', 6: 'facebook', | |
7: 'joypixels', 8: 'openmoji', 9: 'emojidex', | |
10: 'lg', 11: 'htc', 12: 'mozilla' | |
} | |
#---# | |
Emoji_Image = Image.open(get( | |
"https://emojicdn.elk.sh/{0}?style={1}".format( | |
quote_plus(emojize(self.Name, use_aliases = True)), | |
str(Styles[Style]).lower() | |
), stream = True | |
).raw | |
) | |
#---# | |
ImageIO = io.BytesIO() | |
Emoji_Image.save(ImageIO, "PNG") | |
ImageIO.seek(0) | |
return Image.open(io.BytesIO(ImageIO.read())) | |
ImageIO.close() | |
#---# | |
def is_available(Name: str): | |
"""Checks if emoji is available to use.""" | |
return emojize(Name, use_aliases = True) in UNICODE_EMOJI | |
#---# | |
def search(Name: str): | |
"""Searches for emojis by `self.Name`.""" | |
return [x for x in UNICODE_EMOJI.values() if x.__contains__(Name[1:-1])] | |
#----------# | |
Image_Size = (5000, 5000) | |
Text = r":snake:" | |
Text_Wrap = 12 | |
Text_Color = "#000000" | |
Font_Path = r"Font.otf" | |
Font_Size = 250 | |
Emoji_Style = "apple" | |
#----------# | |
# Supported emojis (+ aliases (?)) lists | |
# https://www.webfx.com/tools/emoji-cheat-sheet/ | |
# | |
# Supported emoji styles | |
# https://github.com/benborgers/emojicdn#emoji-style | |
# | |
# Check if emoji is available: | |
# ```python | |
# >>> Emoji = ":thinking:" | |
# >>> Emoji = EmojiUtils.search(Emoji)[0] | |
# >>> | |
# >>> EmojiUtils.is_available(Emoji) | |
# True | |
# ``` | |
#----------# | |
Base = Image.new("RGBA", Image_Size, (0,) * 4) | |
Text = wrap(emojize(Text, use_aliases = True), Text_Wrap) | |
Font = ImageFont.truetype(Font_Path, Font_Size) | |
__Styles = {Value: Key for Key, Value in enumerate(EmojiUtils.get_image.__code__.co_consts[1:14])} | |
Images_List = [] | |
Expanded_Images_List = [] | |
Spacing_Y = 0 | |
for Line in Text: | |
Line_Image = Base.copy() | |
Line_ImageDraw = ImageDraw.Draw(Line_Image) | |
Spacing_X = 0 | |
#---# | |
for Character in Line: | |
if Character in UNICODE_EMOJI: | |
try: | |
Emoji = EmojiUtils(demojize(Character)).get_image(__Styles[Emoji_Style]) | |
except UnidentifiedImageError as Error: | |
raise SystemExit("{0}: The `{1}` emoji is not supported on the {2} style. Image processing aborted.".format( | |
Error.__class__.__name__, | |
demojize(Character), | |
Emoji_Style.title(), | |
) | |
) | |
#---# | |
Emoji = Emoji.resize( | |
(Font.getsize("|")[1],) * 2, | |
Image.LANCZOS | |
) | |
#---# | |
Line_Image.paste( | |
Emoji, | |
(Spacing_X, 0), | |
Emoji | |
) | |
Spacing_X += Emoji.size[0] | |
Character = Character.replace(Character, "") | |
#---# | |
Line_ImageDraw.text( | |
xy = (Spacing_X, 0), | |
text = Character, | |
font = Font, | |
fill = tuple(int(Text_Color.lstrip("#")[x:x+2], 16) for x in (0, 2, 4)) | |
) | |
#---# | |
Spacing_X += Font.getsize(Character)[0] | |
#---# | |
Spacing_Y += Font.getsize(Line)[1] | |
Line_Image = Line_Image.crop(Line_Image.getbbox()) | |
Images_List.append(Line_Image) | |
#---# | |
for IMG in Images_List: | |
Text_Image = Image.new("RGBA", (IMG.size[0], IMG.size[1] + Font.getsize("|")[1]), (0,) * 4) | |
Text_Image.paste(IMG, (0, Font.getsize("|")[1]), IMG) | |
Expanded_Images_List.append(Text_Image) | |
Spacing_Y = 0 | |
for IMG in Expanded_Images_List: | |
Base.paste(IMG, ((Base.size[0] - IMG.size[0]) // 2, Spacing_Y), IMG) | |
Spacing_Y += IMG.size[1] // 3 * 2 # Change values for line height | |
#---# | |
Base = Base.crop(Base.getbbox()) | |
Base.show() |
since requirements are not matching, do not use this snippet and move to pilmoji instead (no text-align center, wont contribute)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is it possible to make bidirectional text (containing RTL text) work with this? I have a script for non-emoji normal bidirectional rendering (which I forked off the internet): https://github.com/NightMachinary/.shells/blob/9b6bac7871958d6ac594681e2c7c7282dbe022d9/scripts/python/text2img.py