Contents

Batch Convert Bulk Text to Jpg Image

Problem Description

I have a list, for example, a txt file, each line is a person’s name, and I need to convert each person’s name to one image.

Problem Refinement

  1. Data input, here is relatively simple, is to read the names.txt file. Each line in the file is a person’s name, with no extra information, like this:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Linda Wilson
Karl Walker
Ezekiel Brown
Chelsea Resnick
Bryan Dijkhuizen
Jessey Anthony
Suzanne Berger
Joseph Mavericks
Matthew Coast
Bill Petro
Lipika Sahu
Mona Lazar
  1. Picture format requirements. Here is an A4 paper size picture for subsequent printing (the standard size of A4 paper is: 210*297 mm). The name of the person must be enlarged to fill the A4 paper.

  2. Save the image to the output subdirectory of the directory where the names.txt file is located.

Program Implementation

The problem is relatively simple and there are many solutions. I use Python program to solve it here.

Read File Data

The first step is to read the file content. This step is relatively simple yet:

1
2
with open(filename, "r") as f:
    data = f.readlines()

Directly read the content of each line and save it to an array.

Pay attention to the data read in this way. The last one has a newline character, which needs to be removed.

Generate image content

Then you can use Python’s Pillow library to implement the text drawing function. First install the Pillow library, you can use pip install pillow to install it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
    # Create an A4 size white picture
    image = Image.new('RGB', (2100, 2970), 'white')
    draw = ImageDraw.Draw(image)
    
    # Load your favorite fonts
    font = ImageFont.truetype('/System/Library/Fonts/Supplemental/Arial.ttf', 36)
    
    # Calculate text width and height
    text_width, text_height = draw.textsize(name, font=font)
    
    # Calculate where to place text
    x = (2100 - text_width) / 2
    y = (2970 - text_height) / 2
    
    # Write people's names into picture
    draw.text((x, y), name, font=font, fill='black')

But there is a problem. The font size here is set manually to 36, and the characters in the picture are very small.

Of course, you can keep trying and adjust it to a suitable size, but names can be long or short.

If you want the effect of filling the picture with the person’s name just right, you need to dynamically adjust the font size here.

You can increase the font size until the text fills the entire image. The core processing logic is as follows:

1
2
3
4
5
6
7
8
9
    # Keep increasing the font size until the text fills the entire image
    font_size = 16
    while True:
        # Load your favorite fonts
        font = ImageFont.truetype(font_name, font_size)
        text_width, text_height = font.getsize(name)
        if text_width > image_width or text_height > image_height:
            break
        font_size += 1

The effect obtained this time is OK. Each person’s name can completely cover the entire width of the image, as shown in the figure:

text-to-image-1.en.webp
Batch text generation image renderings

Final Complete Code

Finally, the complete Python code is attached:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import os
from PIL import Image, ImageDraw, ImageFont


def generate_name_image(name, number, output_path):
    # Modify it to the font file on your own computer (your favorite)
    font_name = '/System/Library/Fonts/Supplemental/Arial.ttf'
    image_width = 2100
    image_height = 2970
    font_size = 16

    # Keep increasing the font size until the text fills the entire image
    while True:
        # Load your favorite fonts
        font = ImageFont.truetype(font_name, font_size)
        text_width, text_height = font.getsize(name)
        if text_width > (image_width - 20) or text_height > (image_height - 20):
            break
        font_size += 1

    # Recalculate placement
    x = (image_width - text_width) / 2
    y = (image_height - text_height) / 2

    # Create a picture and write the person's name
    image = Image.new('RGB', (image_width, image_height), 'white')
    draw = ImageDraw.Draw(image)
    draw.text((x, y), name, font=font, fill='black')

    # Save picture
    image.save(f'{output_path}/{number}.jpg')


def load_data(filename):
    output_path = "output"
    if not os.path.exists(output_path):  # whether the folder exists
        os.makedirs(output_path)  # not exist, create it

    with open(filename, "r") as f:
        data = f.readlines()
        for i in range(len(data)):
            text = data[i].strip('\r\n ')  # Remove newline characters
            print(text)
            generate_name_image(text, i + 1, output_path)


load_data('names.txt')