Create Feature Image With Python
Share this post

This post is part of the complete Guide on Python for SEO

Creating Images for your blog can be a painful process.

I hate working on images, so I decided to always use the same background image template and create images automatically from a specific text in Python.

Actually, the feature image used for this post was created using the code that I am showing you here.

You can get the full code at the end of this post or on my Github.

Getting Started

To run this code, you will need to:

  • Install Python
  • Find a template background image

You can read how to install Python with Anaconda.

Step 1. Install the Pillow Library

To do this Python image programming tutorial, we will use Pillow. Go to your Terminal and install the package.

$ pip install Pillow

You will load the PIL Image, ImageDraw and ImageFont modules.

from PIL import Image, ImageDraw, ImageFont

Step 2. Add the Features of Your Image

Here we will have two text lines in order to give different styling to each line.

# create Image object
text1 = 'Create Feature Image'
text2 = 'With Python'

We will give the image output file a name.

img_name = 'featured-image-creation-with-python.png'

And choose which color we want to use as a filter of the image.

color = 'dark_blue' #grey,light_blue,blue,orange,purple,yellow,green

Then we will need to download the Roboto font from Github and add it to your work folder.

font = 'Roboto-Bold.ttf'

Step 3. Find Your Background Image

If you want to find free images to use as background you can download one from Unsplash.

In my case, I have used a very simple one that I will always use as a background image.

Since I am frequently blogging about Python, I also found a Python logo to incorporate in my designs.

Add images that you want in your work folder.

In the code, you will see these lines that are my background image and the Python logo.

background = Image.open('background.jpg')
foreground = Image.open('python-logo.png')

Step 4. Create The Color Templates

Here I will create a dictionary to define background and text colour depending of the style that was chosen.

colors = {
    'dark_blue':{'c':(27,53,81),'p_font':'rgb(255,255,255)','s_font':'rgb(255, 212, 55)'},
    'grey':{'c':(70,86,95),'p_font':'rgb(255,255,255)','s_font':'rgb(93,188,210)'},
    'light_blue':{'c':(93,188,210),'p_font':'rgb(27,53,81)','s_font':'rgb(255,255,255)'},
    'blue':{'c':(23,114,237),'p_font':'rgb(255,255,255)','s_font':'rgb(255, 255, 255)'},
    'orange':{'c':(242,174,100),'p_font':'rgb(0,0,0)','s_font':'rgb(0,0,0)'},
    'purple':{'c':(114,88,136),'p_font':'rgb(255,255,255)','s_font':'rgb(255, 212, 55)'},
    'red':{'c':(255,0,0),'p_font':'rgb(0,0,0)','s_font':'rgb(0,0,0)'},
    'yellow':{'c':(255,255,0),'p_font':'rgb(0,0,0)','s_font':'rgb(27,53,81)'},
    'yellow_green':{'c':(232,240,165),'p_font':'rgb(0,0,0)','s_font':'rgb(0,0,0)'},
    'green':{'c':(65, 162, 77),'p_font':'rgb(217, 210, 192)','s_font':'rgb(0, 0, 0)'}
    }

Step 5. Define The Functions

We will define a few functions.

  1. add_color() to add a coloured filter to the background image.
  2. center_text() to center the text in the image if there is no logo in the image.
  3. add_text() to actually add the text where we want it to be.
  4. add_logo() to add the logo when you have one, like in my case.
  5. write_image() to combine all the work and return the new image.

Add Colour to the Image

Here the function lets you define which image to take as the background image, the color (c), and the transparency level from 0 to 255.

def add_color(image,c,transparency):
    color = Image.new('RGB',image.size,c)
    mask = Image.new('RGBA',image.size,(0,0,0,transparency))
    return Image.composite(image,color,mask).convert('RGB')

Center Text

This function will check the background image and the text size, an make calculation to make sure that the text will be center-aligned.

def center_text(img,font,text1,text2,fill1,fill2):
    draw = ImageDraw.Draw(img) # Initialize drawing on the image
    w,h = img.size # get width and height of image
    t1_width, t1_height = draw.textsize(text1, font) # Get text1 size
    t2_width, t2_height = draw.textsize(text2, font) # Get text2 size
    p1 = ((w-t1_width)/2,h // 3) # H-center align text1
    p2 = ((w-t2_width)/2,h // 3 + h // 5) # H-center align text2
    draw.text(p1, text1, fill=fill1, font=font) # draw text on top of image
    draw.text(p2, text2, fill=fill2, font=font) # draw text on top of image
    return img

Add Text to the Image

This function will add text on the image.

The font and font_size arguments are defined by default. Also, by default, the image will not have any additional images on top of it. It will simply be text over background.

If you define a foreground image in the write_image() function that we will see later, the logo will be set to True, and the layout will change automatically.

This is where the center_text() function comes in. If there is no logo set up, the image will return a centre-aligned text.

def add_text(img,color,text1,text2,logo=False,font='Roboto-Bold.ttf',font_size=75):
    draw = ImageDraw.Draw(img)

    p_font = color['p_font']
    s_font = color['s_font']
    
    # starting position of the message
    img_w, img_h = img.size
    height = img_h // 3
    font = ImageFont.truetype(font,size=font_size)

    if logo == False:
        center_text(img,font,text1,text2,p_font,s_font)
    else:
        text1_offset = (img_w // 4, height)
        text2_offset = (img_w // 4, height + img_h // 5)
        draw.text(text1_offset, text1, fill=p_font, font=font)
        draw.text(text2_offset, text2, fill=s_font, font=font)
    return img

Add a Logo to the Image

You can add the image you want, but this function will simply add the image that you defined in the foreground variable to the layout.

def add_logo(background,foreground):
    bg_w, bg_h = background.size
    img_w, img_h = foreground.size
    img_offset = (20, (bg_h - img_h) // 2)
    background.paste(foreground, img_offset, foreground)
    return background

Combine all Steps to Write the Image

Now it is time to put all that together in a single function.

This functions set’s up the background image and adds it the colour overlay.

If there is a foreground image to add on top of the background, it adds it and modify the text layout.

Otherwise, it will center-align the text on top of the background image.

def write_image(background,color,text1,text2,foreground=''):
    background = add_color(background,color['c'],25)
    if not foreground:
        add_text(background,color,text1,text2)
    else:
        add_text(background,color,text1,text2,logo=True)
        add_logo(background,foreground)
    return background

Step 6. Run the Function

There we will run the write_image() function and save it using the save() function.

The if __name__ == '__main__' simply tells the program to execute the function only when you are executing the script, not when importing the module.

if __name__ == '__main__':
    background = write_image(background,colors[color],text1,text2,foreground=foreground)
    background.save(img_name) 

Full Code

from PIL import Image, ImageDraw, ImageFont
 
# create Image object
text1 = 'Create Feature Image'
text2 = 'With Python'
img_name = 'featured-image-creation-with-python.png'
color = 'dark_blue' #grey,light_blue,blue,orange,purple,yellow,green
font = 'Roboto-Bold.ttf'

background = Image.open('default.jpg')
foreground = Image.open('python-logo.png')

#create the coloured overlays
colors = {
    'dark_blue':{'c':(27,53,81),'p_font':'rgb(255,255,255)','s_font':'rgb(255, 212, 55)'},
    'grey':{'c':(70,86,95),'p_font':'rgb(255,255,255)','s_font':'rgb(93,188,210)'},
    'light_blue':{'c':(93,188,210),'p_font':'rgb(27,53,81)','s_font':'rgb(255,255,255)'},
    'blue':{'c':(23,114,237),'p_font':'rgb(255,255,255)','s_font':'rgb(255, 255, 255)'},
    'orange':{'c':(242,174,100),'p_font':'rgb(0,0,0)','s_font':'rgb(0,0,0)'},
    'purple':{'c':(114,88,136),'p_font':'rgb(255,255,255)','s_font':'rgb(255, 212, 55)'},
    'red':{'c':(255,0,0),'p_font':'rgb(0,0,0)','s_font':'rgb(0,0,0)'},
    'yellow':{'c':(255,255,0),'p_font':'rgb(0,0,0)','s_font':'rgb(27,53,81)'},
    'yellow_green':{'c':(232,240,165),'p_font':'rgb(0,0,0)','s_font':'rgb(0,0,0)'},
    'green':{'c':(65, 162, 77),'p_font':'rgb(217, 210, 192)','s_font':'rgb(0, 0, 0)'}
    }

def add_color(image,c,transparency):
    color = Image.new('RGB',image.size,c)
    mask = Image.new('RGBA',image.size,(0,0,0,transparency))
    return Image.composite(image,color,mask).convert('RGB')

def center_text(img,font,text1,text2,fill1,fill2):
    draw = ImageDraw.Draw(img)
    w,h = img.size
    t1_width, t1_height = draw.textsize(text1, font)
    t2_width, t2_height = draw.textsize(text2, font)
    p1 = ((w-t1_width)/2,h // 3)
    p2 = ((w-t2_width)/2,h // 3 + h // 5)
    draw.text(p1, text1, fill=fill1, font=font)
    draw.text(p2, text2, fill=fill2, font=font)
    return img

def add_text(img,color,text1,text2,logo=False,font='Roboto-Bold.ttf',font_size=75):
    draw = ImageDraw.Draw(img)

    p_font = color['p_font']
    s_font = color['s_font']
    
    # starting position of the message
    img_w, img_h = img.size
    height = img_h // 3
    font = ImageFont.truetype(font,size=font_size)

    if logo == False:
        center_text(img,font,text1,text2,p_font,s_font)
    else:
        text1_offset = (img_w // 4, height)
        text2_offset = (img_w // 4, height + img_h // 5)
        draw.text(text1_offset, text1, fill=p_font, font=font)
        draw.text(text2_offset, text2, fill=s_font, font=font)
    return img

def add_logo(background,foreground):
    bg_w, bg_h = background.size
    img_w, img_h = foreground.size
    img_offset = (20, (bg_h - img_h) // 2)
    background.paste(foreground, img_offset, foreground)
    return background

def write_image(background,color,text1,text2,foreground=''):
    background = add_color(background,color['c'],25)
    if not foreground:
        add_text(background,color,text1,text2)
    else:
        add_text(background,color,text1,text2,logo=True)
        add_logo(background,foreground)
    return background

if __name__ == '__main__':
    background = write_image(background,colors[color],text1,text2,foreground=foreground)
    background.save(img_name) 
    

This is the end of the tutorial on how to create feature images from text using Python.