Write Text To Image In Python (Simple Examples)

Welcome to a tutorial on how to write text on images in Python. Need to add some text to an image?

We can use the Pillow Imaging Library to write text onto images in Python:

  • from PIL import Image, ImageFont, ImageDraw
  • img = Image.open("IMG.JPG")
  • draw = ImageDraw.draw(img)
  • font = ImageFont.truetype("FONT.TTF", 18)
  • pos = (0, 0)
  • color = (255, 255, 255)
  • draw.text(pos, "TEXT", fill=color, font=font)
  • img.save("SAVE.WEBP")

That covers the quick basics, but read on if you need more examples!

ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

 

TLDR – QUICK SLIDES

Fullscreen Mode – Click Here

 

TABLE OF CONTENTS

 

DOWNLOAD & NOTES

Firstly, here is the download link to the example code as promised.

 

QUICK NOTES

  • Download and unzip into your project folder.
  • Create a virtual environment “as usual”.
    • virtualenv venv
    • Windows – venv\scripts\activate
    • Mac/Linux – venv/bin/activate
  • Install pillow – pip install pillow.
  • Run the examples.
If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

EXAMPLE CODE DOWNLOAD

Click here to download all the example source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

 

PYTHON WRITE TEXT ON IMAGE

All right, let us now get into the examples of writing text onto images in Python.

 

1) SIMPLE WRITE TEXT

1_basic.py
# (A) IMPORT PILLOW
from PIL import Image, ImageFont, ImageDraw 
 
# (B) SETTINGS
sImg = "demo.webp"        # source image
sSave = "demoA.webp"      # save as
sText = "FRIED RICE"      # text to write
sFont = "Expectative.ttf" # font file
sSize = 32                # font size
sColor = (255, 255, 255)  # text color
sPos = (10, 10)           # write text at this position
 
# (C) WRITE TEXT TO IMAGE + SAVE
iOpen = Image.open(sImg)
iDraw = ImageDraw.Draw(iOpen)
iFont = ImageFont.truetype(sFont, sSize)
iDraw.text(sPos, sText, fill=sColor, font=iFont)
iOpen.save(sSave)

This is pretty much the “long-winded” version of the introduction snippet. Shouldn’t be much trouble once you trace through the code, it’s pretty much just:

  • Open the image – iOpen = Image.open(SOURCE)
  • Draw on the image – iDraw = ImageDraw.Draw(iOpen)
  • Write text on the image – iDraw.text(POSITION, TEXT, fill=COLOR, font=FONT)
  • Save it – iOpen.save(TARGET)

 

 

2) MORE TEXT OPTIONS

2_more.py
# (A) IMPORT PILLOW
from PIL import Image, ImageFont, ImageDraw
 
# (B) SETTINGS
sImg = "demo.webp"        # source image
sSave = "demoB.webp"      # save as
sText = "EGG\nFRIED RICE" # text to write
sFont = "Expectative.ttf" # font file
sSize = 32                # font size
sColor = (0, 0, 255, 32)  # text color with opacity (alpha)
sPos = (10, 10)           # write text at this position
sSpace = 20               # line spacing
sAlign = "center"         # text align - left, right, center
sStrokeW = 3              # stroke width
sStrokeC = (255, 0, 0)    # stroke color
 
# (C) WRITE TEXT TO IMAGE + SAVE
iOpen = Image.open(sImg).convert("RGBA")
iDraw = ImageDraw.Draw(iOpen)
iFont = ImageFont.truetype(sFont, sSize)
iDraw.text(sPos, sText, fill=sColor, font=iFont, spacing=sSpace, align=sAlign, stroke_width=sStrokeW, stroke_fill=sStrokeC)
iOpen.save(sSave)

Now, there is a lot more we can do with the Pillow library… I will just go through a few of the common ones here:

  • For multi-line text:
    • Just add a line break – sText = "EGG\nFRIED RICE".
    • In iDraw.text() – We can also specify align="left|center|right", and set the line spacing – spacing=N.
  • To set “transparent text”:
    • Take note of sColor = (0, 0, 255, 32), the last parameter being the alpha (opacity).
    • It is necessary to convert into RGBA, or the opacity will not register – iOpen = Image.open(sImg).convert("RGBA").
  • To stroke the text (add text outline):
    • In iDraw.text(), we define stroke_width=N and stroke_fill=(RGBA).

 

 

3) CENTER TEXT ON IMAGE

3_center.py
# (A) IMPORT PILLOW
from PIL import Image, ImageFont, ImageDraw 
import math
 
# (B) SETTINGS
sImg = "demo.webp"        # source image
sSave = "demoC.webp"      # save as
sText = "EGG\nFRIED RICE" # text to write
sFont = "Expectative.ttf" # font file
sSize = 32                # font size
sColor = (255, 255, 255)  # text color
sStrokeW = 3              # stroke width
sStrokeC = (0, 0, 0)      # stroke color
 
# (C) IMAGE DRAW + FONT
iOpen = Image.open(sImg)
iDraw = ImageDraw.Draw(iOpen)
iFont = ImageFont.truetype(sFont, sSize)
 
# (D) CALCULATE CENTER COORDINATES
iw, ih = iOpen.size # image dimensions
_, _, tw, th = iDraw.textbbox((0, 0), sText, font=iFont) # text dimensions
x = math.floor((iw - tw) / 2)
y = math.floor((ih - th) / 2)
sPos = (x, y)
 
# (E) WRITE TEXT TO IMAGE + SAVE
iDraw.text(sPos, sText, fill=sColor, font=iFont, stroke_width=sStrokeW, stroke_fill=sStrokeC)
iOpen.save(sSave)

Finally, centering the text on the image is sadly… Mathematical. Take note of (D), where we calculate the XY position of the text.

  • Get the dimensions of the image – iw, ih = iOpen.size
  • Get the dimensions of the text box – _, _, tw, th = iDraw.textbbox((0, 0), sText, font=iFont)
  • Then in “plain English”:
    • x = FLOOR((IMAGE WIDTH - TEXT WIDTH) ÷ 2)
    • y = FLOOR((IMAGE HEIGHT - TEXT HEIGHT) ÷ 2)

 

 

EXTRA BITS & LINKS

That’s all for the tutorial, and here is a small section on some extras and links that may be useful to you.

 

LINKS & REFERENCES

 

INFOGRAPHIC CHEAT SHEET

Python Write Text On Image (click to enlarge)

 

THE END

Thank you for reading, and we have come to the end. I hope that it has helped you to better understand, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

Leave a Comment

Your email address will not be published. Required fields are marked *