I want to use Pygame's freetype module to load a colorful emoji via its unicode. Unfortunately I only get a monochrome image with the outline of the emoji:
Minimal, Reproducible Example:
import pygame
import pygame.freetype
pygame.init()
window = pygame.display.set_mode((200, 200))
seguisy80 = pygame.freetype.SysFont("segoeuisymbol", 100)
emoji, rect = seguisy80.render('😃', "black")
rect.center = window.get_rect().center
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill("lightgray")
window.blit(emoji, rect)
pygame.display.flip()
pygame.quit()
How can I modify this code to get a full RGBA color image of an emoji?
Unfortunately, colored font loading is not natively supported in Pygame. However, there is a workaround. First you need a colored emoji font. For example, you can download one here: Apple Color Emoji for Linux.
Load this font using https://freetype.org/. Install freetype-py
:
pip3 install freetype-py
For Windows users, it should be mentioned that the installed package does not support the font and results in an "unimplemented feature" exception. Download the package from Unofficial Windows Binaries for Python Extension Packages and install it. e.g.:
pip3 install freetype_py-2.2.0-cp310-cp310-win_amd64.whl
Now you're prepared and can load an emoji from the font.Emojis and their Unicode can be found here: Emoticons (Unicode block). Copy the emoji or use the unicode and load the glyph:
import freetype
face = freetype.Face("AppleColorEmoji.ttf")
face.set_char_size(int(face.available_sizes[-1].size))
face.load_char('😀', freetype.FT_LOAD_COLOR) # or face.load_char('\U0001F603', freetype.FT_LOAD_COLOR)
The loaded glyph now needs to be turned into a pygame.Surface
. To do this, use NumPy.
How this works in detail is explained in the answer to the question: How do I convert an OpenCV (cv2) image (BGR and BGRA) to a pygame.Surface object.
import numpy as np
ft_bitmap = face.glyph.bitmap
bitmap = np.array(ft_bitmap.buffer, dtype=np.uint8).reshape((ft_bitmap.rows, ft_bitmap.width, 4))
bitmap[:, :, [0, 2]] = bitmap[:, :, [2, 0]]
emoji = pygame.image.frombuffer(bitmap.flatten(), (ft_bitmap.width, ft_bitmap.rows), 'RGBA')
See also Text and font - Unicode
Minimal example:
import pygame
import freetype
import numpy as np
class Emojis:
def __init__(self):
self. face = freetype.Face("AppleColorEmoji.ttf")
self.face.set_char_size(int(self.face.available_sizes[-1].size))
def create_surface(self, unicode):
self.face.load_char(unicode, freetype.FT_LOAD_COLOR)
ft_bitmap = self.face.glyph.bitmap
bitmap = np.array(ft_bitmap.buffer, dtype=np.uint8).reshape((ft_bitmap.rows, ft_bitmap.width, 4))
bitmap[:, :, [0, 2]] = bitmap[:, :, [2, 0]]
return pygame.image.frombuffer(bitmap.flatten(), (ft_bitmap.width, ft_bitmap.rows), 'RGBA')
pygame.init()
window = pygame.display.set_mode((200, 200))
emojis = Emojis()
emoji = emojis.create_surface('😃')
#emoji = emojis.create_surface('\U0001F603')
rect = emoji.get_rect(center = window.get_rect().center)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill("lightgray")
window.blit(emoji, rect)
pygame.display.flip()
pygame.quit()