2

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?

Rabbid76
  • 202,892
  • 27
  • 131
  • 174

2 Answers2

1

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()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
1

I just created a small package to make that easy.

You can just

pip install pygame-emojis

and then


from pygame_emojis import load_emoji

# Choose the size
size = (64, 64)

# Load the emoji as a pygame.Surface
surface = load_emoji('', size)

It download open source emojis as svg files.

Hope this helps.

Oily
  • 538
  • 3
  • 11
  • That's a nice answer, but it's not an answer to this question. The question is how to use the emojis from an existing ttf font, not how to load the emojis from an SVG file. Pygame can load SVG natively, but cannot draw colored ttf fonts. I'm sorry, but that doesn't help. You have misinterpreted the question. – Rabbid76 Aug 21 '22 at 20:08
  • The question is actually "How to load colorful emojis in pygame?", which this answers quite well. – Hugh Perkins Nov 25 '22 at 17:12
  • I'd also note that providing an installable github repo with an opensource repo, just as Oily is doing, is quite nice, given that stackexchange itself basically ensures that any code included in stackexchange answers is *NOT* licensed for use. – Hugh Perkins Nov 25 '22 at 17:36
  • Hi @Oily I'm trying to use your package: I've pip-installed the package, I run the snippet above, but I get the error: `FileNotFoundError: No file available for emoji `. I think it didn't download the .svg as it should have. Is there any way to force such download? – Stefano Bragaglia Apr 18 '23 at 16:03
  • @StefanoBragaglia Thanks for reporting, could you raise an issue on the github repo, with a small piece of code that creates the bug ? I will be happy to help you fix it. https://github.com/ScienceGamez/pygame_emojis/issues – Oily Apr 20 '23 at 12:03
  • Sure, I'm at an onsite event and I haven't access to my home computer, but the code I tried to run is exactly the code from pygame-cards tutorial (https://pygame-cards.readthedocs.io/en/latest/tutorial.html). Anyway I'll open a ticket! – Stefano Bragaglia Apr 20 '23 at 16:20