Telegram emoji display

Ville Klar



Ever wanted to have a dedicated device for receiving emojis? Me neither! But I decided to make one anyway. The basic functional principle of this contraption is perhaps best illustrated in the video below. If you want to build your own emoji receiver all the source files are on my gitlab.

In short, this project is an internet connected device that receives emojis and displays them on a TFT-display. Instead of setting up a dedicated emoji-receiving-server and developing a custom client for it, most of the heavy lifting is done by a Telegram bot. The URL of my bot is:, feel free to send me emojis πŸ“¨. The thing part is made up of an esp32 development board (Wemos D1 ESP32) and an ILI9341 display board with an SD card slot. To be honest, I was really surprised when I first started looking into this idea that I couldn’t (readily) find a tutorial on this already. The allure of emoji, bots and IoT this seems like a wonderful triple whammy and therefore justifies writing this post.


The electronics are fairly straightforward (and low-cost) with the display and SD card connected to the ESP32 via the same SPI bus. I apologize for the seemingly obfuscated schematic below (case of cbf).



This whole project requires less than 200 lines of original software as almost all of the required functionality is available through abstractions in various arduino libraries. More specifically, the Universal-Arduino-Telgram-Bot library by Brian Lough and a bunch of graphics related libraries by Adafruit. The Adafruit ImageReader library in particular makes the firmware nice and concise. As mentioned earlier, I put all the source files on gitlab so I encourage the curious to delve deeper over there.

Generating emoji bitmaps

The Adafruit ImageReader library works only with uncompressed bitmaps. After a bit of fuzzing around with ImageMagick, the correct incantation for producing renderable images seemed to be -define bmp:format=bmp3 -compress none . Now we just need some emoji graphics to show. There are several different options but the Twemoji by Twitter and noto-emoji by Google seem to be easiest to get as a full-ish set in vector format. Additionally, both of these sets have permissive licences πŸ₯³.

While ImageMagick is capable of converting .svg directly into .bmp, this takes quite some time (probaly since ImageMagick is not really intended for vector graphics). A far faster approach is to first convert into .png using rsvg-convert from libRSVG and the use mogrify to convert into .bmp with suitable dimensions. We need to resize all the emojis to 240 by 240 pixels which leaves us with 120 x 240 pixels to display the name of the emoji sender. Both of the commands below assume that your working directory is the one containing all the emojis graphics as .svg.

for f in *.svg; do rsvg-convert -d 300 -p 300 -w 240 -h 240 -f png -o "${f%.svg}.png" "$f"; done
mogrify -define bmp:format=bmp3 -compress none -resize 240x240 -format bmp  -background white -alpha remove -alpha off *.png
#For noto-emoji you also need to bulk rename
rename 'emoji_u' '' emoji_u*

Once all the emojis are converted and transferred to the SD card, we need a simple way of accessing / addressing them. I went with a fairly simple lookup table (const array of structs) which contains the emoji and the path of the corresponding bitmap. Given that I’m not too worried about having low latency emoji-retrieval, this solution was sufficiently responsive (the slowest part is still writing to the display after finding the correct path). The bitmaps are named after the codepoints (with modifiers separated with a hyphen) of the emojis. Some cleanup was necessary regarding variation selectors U+FE0F, but mostly the emojis were well-behaved. A python script for generating the header file is provided in the repository.

#define NUM_EMOJI 3301

typedef struct
{	char emoji[29];
	char path[48];
const EmojiLUT Emoji[NUM_EMOJI] = {
// etc. etc.

Further development

I guess some might also find communication based solely on singular emojis a bit constricting. Adding support for text messages would be easy enough (even with emoji support since those assets are available). An IoT telegram-bot powered connected photoframe is probably also something that might be interesting. The bitmap rendering is a bit slow and I guess the format is not the most ubiquitous one. Recently, Larry Bank aka bitbank2 released an optimized JPEG decoder for Arduino. I would highly recommend looking into that library for anyone working on emoji-receivers. He also has an AnimatedGIF library, which seems interesting as well. Given that there are inexpensive esp32 camera boards, a esp32-based photo sending system could also be possible.