The Easiest Way to Generate Fancy Avatars in Python

Aymane Mimouni
Sep 11, 2020 · 4 min read

This article is originally published in my personal blog.

This is a really short article, where I will show you how to generate cool avatars from a given string (email, username…) or from your logo using python.

The idea for this article came to mind while I was working on a project where I have to set a default avatar for each user from the backend because I was dealing with a backend feeding two frontends, and maybe more in the future. But if you’re dealing with a single frontend, you would better consider doing it from the frontend, because it’s a lot easier.

Before I start, I want to mention that the professional way to do it, is by not generating the avatar, but instead using static images for default avatars, because It’s quicker, simpler, less error-prone, more future-proof, and ultimately looks better than generating them programmatically.

But, if you want to be really fancy like Google and have random colored circles and initials, you’re in the right place 😎

Let’s get started!

Avatars using initials

# BUILT-IN
import re
import random
# PIP
from cairosvg import svg2png
from xml.sax.saxutils import escape as xml_escape
COLORS = [
['#DF7FD7', '#DF7FD7', '#591854'],
['#E3CAC8', '#DF8A82', '#5E3A37'],
['#E6845E', '#E05118', '#61230B'],
['#E0B050', '#E6CB97', '#614C23'],
['#9878AD', '#492661', '#C59BE0'],
['#787BAD', '#141961', '#9B9FE0'],
['#78A2AD', '#104F61', '#9BD1E0'],
['#78AD8A', '#0A6129', '#9BE0B3'],
['#AD8621', '#6B5621', '#E0AD2B'],
]
INITIALS_SVG_TEMPLATE = """
<svg xmlns="<http://www.w3.org/2000/svg>"
pointer-events="none"
width="200" height="200">
<defs>
<linearGradient id="grad">
<stop offset="0%" stop-color="{color1}" />
<stop offset="100%" stop-color="{color2}" />
</linearGradient>
</defs>
<rect width="200" height="200" rx="0" ry="0" fill="url(#grad)"></rect>
<text text-anchor="middle" y="50%" x="50%" dy="0.35em"
pointer-events="auto" fill="{text_color}" font-family="sans-serif"
style="font-weight: 400; font-size: 80px">{text}</text>
</svg>
""".strip()
INITIALS_SVG_TEMPLATE = re.sub('(\\s+|\\n)', ' ', INITIALS_SVG_TEMPLATE)
def get_png_avatar(text, output_file): initials = ':)' text = text.strip()
if text:
split_text = text.split(' ')
if len(split_text) > 1:
initials = split_text[0][0] + split_text[-1][0]
else:
initials = split_text[0][0]
random_color = random.choice(COLORS)
svg_avatar = INITIALS_SVG_TEMPLATE.format(**{
'color1': random_color[0],
'color2': random_color[1],
'text_color': random_color[2],
'text': xml_escape(initials.upper()),
}).replace('\\n', '')
svg2png(svg_avatar, write_to=output_file)

What I did here is that I take a pre-prepared SVG template, I fill it with the initials, and background color, and that is it!!

Let’s test it,

import string
from io import BytesIO
from PIL import Image

from avatar_generator import get_png_avatar

rawIO = BytesIO()
get_png_avatar('AymaneMx', rawIO)
byteImg = Image.open(rawIO)
filename = ''.join(random.choices(string.ascii_uppercase + string.digits, k=8))
byteImg.save(filename + '.png', 'PNG')

Run, and the result will be a PNG image like this:

Image for post
Image for post

While playing with the SVG template, I discovered that I can make an icon or a logo instead of a text, which brings us to the next part.

Avatars using your Logo

To use your logo, you need only to change the text tag in the previous SVG template with a tag of your logo.

For example, I will use the Twitter logo, I downloaded the SVG version from Twitter Brand Resources.

After opening it with any editor you will see:

<svg xmlns="http://www.w3.org/2000/svg" id="Logo_FIXED" data-name="Logo — FIXED" viewBox="0 0 400 400">
<defs>
<style>.cls-1{fill:none;}.cls-2{fill:#1da1f2;}</style>
</defs>
<title>Twitter_Logo_Blue</title>
<rect class="cls-1" width="400" height="400"/>
<path class="cls-2"
d="M153.62,301.59c94.34,0,145.94-78.16,145.94-145.94,0-2.22,0-4.43-.15-6.63A104.36,104.36,0,0,0,325,122.47a102.38,102.38,0,0,1-29.46,8.07,51.47,51.47,0,0,0,22.55-28.37,102.79,102.79,0,0,1-32.57,12.45,51.34,51.34,0,0,0-87.41,46.78A145.62,145.62,0,0,1,92.4,107.81a51.33,51.33,0,0,0,15.88,68.47A50.91,50.91,0,0,1,85,169.86c0,.21,0,.43,0,.65a51.31,51.31,0,0,0,41.15,50.28,51.21,51.21,0,0,1-23.16.88,51.35,51.35,0,0,0,47.92,35.62,102.92,102.92,0,0,1-63.7,22A104.41,104.41,0,0,1,75,278.55a145.21,145.21,0,0,0,78.62,23"/>
</svg>

As you may notice, the path tag is the one responsible for the logo/icon.

So, let’s copy that in our SVG template, group it in a g tag, and addfill argument so we can change the color;

LOGO_SVG_TEMPLATE = """
<svg xmlns="<http://www.w3.org/2000/svg>" width="400px" height="400px" viewBox="0 0 400 400">
<rect class="cls-1" width="400" height="400" fill="{color1}" />
<g width="400px" height="400px">
<path
fill="{logo_color}"
d="M153.62,301.59c94.34,0,145.94-78.16,145.94-145.94,0-2.22,0-4.43-.15-6.63A104.36,104.36,0,0,0,325,122.47a102.38,102.38,0,0,1-29.46,8.07,51.47,51.47,0,0,0,22.55-28.37,102.79,102.79,0,0,1-32.57,12.45,51.34,51.34,0,0,0-87.41,46.78A145.62,145.62,0,0,1,92.4,107.81a51.33,51.33,0,0,0,15.88,68.47A50.91,50.91,0,0,1,85,169.86c0,.21,0,.43,0,.65a51.31,51.31,0,0,0,41.15,50.28,51.21,51.21,0,0,1-23.16.88,51.35,51.35,0,0,0,47.92,35.62,102.92,102.92,0,0,1-63.7,22A104.41,104.41,0,0,1,75,278.55a145.21,145.21,0,0,0,78.62,23"
/>
</g>

</svg>
""".strip()
LOGO_SVG_TEMPLATE = re.sub('(\\s+|\\n)', ' ', LOGO_SVG_TEMPLATE)
def get_png_avatar_from_logo(output_file): random_color = random.choice(COLORS) svg_avatar = LOGO_SVG_TEMPLATE.format(**{
'color1': random_color[0],
'logo_color': random_color[2],
}).replace('\\n', '')
svg2png(svg_avatar, write_to=output_file)

Run a test,

rawIO = BytesIO()
filename = ''.join(random.choices(string.ascii_uppercase + string.digits, k=8))
get_png_avatar_from_logo(rawIO)
byteImg = Image.open(rawIO)
byteImg.save(filename + '.png', 'PNG')

The result will be something like this:

Image for post

Now, you are maybe wondering how can I get an SVG file of my logo?

The answer to that is that you can ask your designer gently for it, or you can do it yourself, using Photoshop/Illustrator by exporting your logo as an SVG file.

But the simple way, (which is why you’re here) is by using an online tool as online-convert, I use it for my shitty logo, and here is the result;

Image for post

Isn’t so fancy!!

That’s it!

Here you can check out the code, you will find also its Django integration.

👉 https://github.com/aymaneMx/default-avatars

The Startup

Medium's largest active publication, followed by +756K people. Follow to join our community.

Aymane Mimouni

Written by

Software Engineer | helps clients bring their ideas to life | aymaneMx.com

The Startup

Medium's largest active publication, followed by +756K people. Follow to join our community.

Aymane Mimouni

Written by

Software Engineer | helps clients bring their ideas to life | aymaneMx.com

The Startup

Medium's largest active publication, followed by +756K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store