Emoji renderer for Pillow with Discord emoji support and multiple emoji sources
npx @tessl/cli install tessl/pypi-pilmoji@2.0.0Pilmoji is an emoji renderer for Pillow (Python Imaging Library) that enables rendering both Unicode emojis and Discord custom emojis within images. It offers comprehensive multi-line text rendering capabilities with fine-grained control over emoji positioning, scaling, and supports multiple emoji sources including Twemoji, Microsoft, Apple, and custom sources through subclassing.
pip install pilmoji or pip install pilmoji[requests] for enhanced HTTP performancefrom pilmoji import PilmojiFor emoji sources:
from pilmoji.source import MicrosoftEmojiSource, AppleEmojiSource, TwemojiFor helpers and utilities:
from pilmoji import Node, NodeType, getsize, to_nodesfrom pilmoji import Pilmoji
from PIL import Image, ImageFont
# Create an image
image = Image.new('RGB', (550, 80), (255, 255, 255))
font = ImageFont.truetype('arial.ttf', 24)
# Text with emojis
text = '''
Hello, world! π Here are some emojis: π¨ π π
I also support Discord emoji: <:rooThink:596576798351949847>
'''
# Render text with emoji support
with Pilmoji(image) as pilmoji:
pilmoji.text((10, 10), text.strip(), (0, 0, 0), font)
image.show()Pilmoji uses a modular architecture built around three core components:
This design enables flexible emoji rendering pipelines that can be easily customized with different emoji styles, caching strategies, and rendering parameters while maintaining compatibility with existing Pillow workflows.
Core emoji rendering functionality through the Pilmoji class, providing context manager support, resource management, and comprehensive text rendering with emoji substitution capabilities.
class Pilmoji:
def __init__(
self,
image: Image.Image,
*,
source: Union[BaseSource, Type[BaseSource]] = Twemoji,
cache: bool = True,
draw: Optional[ImageDraw.ImageDraw] = None,
render_discord_emoji: bool = True,
emoji_scale_factor: float = 1.0,
emoji_position_offset: Tuple[int, int] = (0, 0)
) -> None: ...
def text(
self,
xy: Tuple[int, int],
text: str,
fill: ColorT = None,
font: FontT = None,
anchor: str = None,
spacing: int = 4,
node_spacing: int = 0,
align: str = "left",
direction: str = None,
features: str = None,
language: str = None,
stroke_width: int = 0,
stroke_fill: ColorT = None,
embedded_color: bool = False,
*args,
emoji_scale_factor: float = None,
emoji_position_offset: Tuple[int, int] = None,
**kwargs
) -> None: ...
def getsize(
self,
text: str,
font: FontT = None,
*,
spacing: int = 4,
emoji_scale_factor: float = None
) -> Tuple[int, int]: ...Comprehensive system for fetching emoji images from various providers including Twitter, Apple, Microsoft, Google, and custom sources, with built-in Discord emoji support and HTTP optimization.
class BaseSource(ABC):
def get_emoji(self, emoji: str, /) -> Optional[BytesIO]: ...
def get_discord_emoji(self, id: int, /) -> Optional[BytesIO]: ...
class Twemoji(EmojiCDNSource): ...
class AppleEmojiSource(EmojiCDNSource): ...
class MicrosoftEmojiSource(EmojiCDNSource): ...
class GoogleEmojiSource(EmojiCDNSource): ...
class SamsungEmojiSource(EmojiCDNSource): ...
class WhatsAppEmojiSource(EmojiCDNSource): ...
class FacebookEmojiSource(EmojiCDNSource): ...
class MessengerEmojiSource(EmojiCDNSource): ...
class JoyPixelsEmojiSource(EmojiCDNSource): ...
class OpenmojiEmojiSource(EmojiCDNSource): ...
class EmojidexEmojiSource(EmojiCDNSource): ...
class MozillaEmojiSource(EmojiCDNSource): ...Helper functions for text analysis, emoji detection, node parsing, and text measurement with emoji support, enabling advanced text layout and processing workflows.
def to_nodes(text: str, /) -> List[List[Node]]: ...
def getsize(
text: str,
font: FontT = None,
*,
spacing: int = 4,
emoji_scale_factor: float = 1
) -> Tuple[int, int]: ...
class Node(NamedTuple):
type: NodeType
content: str
class NodeType(Enum):
text = 0
emoji = 1
discord_emoji = 2
EMOJI_REGEX: re.Pattern[str] # Pre-compiled regex for emoji detection# Type aliases for font and color parameters
FontT = Union[ImageFont.ImageFont, ImageFont.FreeTypeFont, ImageFont.TransposedFont]
ColorT = Union[int, Tuple[int, int, int], Tuple[int, int, int, int], str]
SupportsInt = Union[int, Any] # For Discord emoji IDs
# Standard library imports for complete type definitions
from typing import Union, Tuple, Optional, Type, List, Any
from enum import Enum
from collections.abc import SupportsInt
import re
from io import BytesIO
from abc import ABC