DEV Community

Bearveloper 🐻
Bearveloper 🐻

Posted on • Originally published at bearveloper.dev on

Overlay text on images with PHP

Some time ago, someone asked me how to create a list of diplomas using a static background image and a list of names. The problem was simple enough to be implemented in less than 30 mins, so I decided to give a try and here is what I ended up with.

This is a simple PHP script with some assumptions that can be run directly in the command line. It can easily be tweaked to fulfill other more complex requirements, like water marking images, mobile optimized images, reading data from Google Spreadsheets or Airtable, etc., so feel free to fork the repo or download the source and hack it as you need it.

With the code below I go:

From this… …to this
Empty Diploma Filled in Diploma

To the code.

<?php

Enter fullscreen mode Exit fullscreen mode

First, some variables so we can tweak the script behavior without having to figure out where in the code are this things setup

$csv_file = 'names.csv';
$background = 'background.jpg';
$signature = 'sig.png';
$font = 'ConeriaScript.ttf';

Enter fullscreen mode Exit fullscreen mode

Then, we read the CSV file and parse so it is easier to read later by converting it to an associative array with the column names as the keys.

// CSV code from https://www.php.net/manual/en/function.str-getcsv.php
$csv = array_map('str_getcsv', file($csv_file));
array_walk($csv, function (&$a) use ($csv) {
    $a = array_combine($csv[0], $a);
});
array_shift($csv);

Enter fullscreen mode Exit fullscreen mode

For this specific background we will need the current date as three strings to be placed in three different places.

$day = date('j');
$month = date('F');
$year = date('Y');

Enter fullscreen mode Exit fullscreen mode

Now we start having fun with PHP’s image functions. First, we need to read our background image to get some basic info and do some preparation, like setting the text color, the image width (for centering the text), and reading the signature image and its sizes.

$image = imagecreatefromjpeg($background);
$color = imagecolorallocate($image, 0, 0, 0);
$width = imagesx($image);
$signature = imagecreatefrompng($signature);
$signature_width = imagesx($signature);
$signature_height = imagesy($signature);

Enter fullscreen mode Exit fullscreen mode

Now that we have the image data ready, we will start reading each name in our list so we can generate individual images with all the overlaid text. For easier reading, I am saving the name and reason in their own variables.

  foreach ($csv as $row) {
    $name = $row['Name'];
    $reason = $row['Reason'];

Enter fullscreen mode Exit fullscreen mode

Here, I am reading the background image again. For the first item in the loop this does not make sense because I already read it above, but since all the image* functions alter their input, if I do not do this I will end every image in the list will end up all the previous text from all the previous images overlapped; not good. I am also getting the text “bound boxes” which are basically the positions of the four corners of my text; I do this to be able to center the text in the image.

    $image = imagecreatefromjpeg($background);
    $name_box = imagettfbbox(40, 0, $font, $name);
    $reason_box = imagettfbbox(40, 0, $font, $reason);

Enter fullscreen mode Exit fullscreen mode

Now it is time to actually render the text on the image. This is done by providing some information to PHP, including the destination image, text size, angle, x and y position, color, font (yes you can use your fonts!), and last but not least, the actual text.

    imagettftext($image, 40, 0, ($width - $name_box[2]) / 2, 635, $color, $font, $name);
    imagettftext($image, 40, 0, ($width - $reason_box[2]) / 2, 790, $color, $font, $reason);
    imagettftext($image, 32, 0, 400, 895, $color, $font, $day);
    imagettftext($image, 32, 0, 600, 895, $color, $font, $month);
    imagettftext($image, 32, 0, 600, 975, $color, $font, $year);

Enter fullscreen mode Exit fullscreen mode

Once the text is overlaid correctly, I need to add the “signature” image on top of the text so it looks nicer, so I tell PHP to copy the signature image (a transparent PNG file) on top, as you can see, I had to not only provide position, but also size.

    imagecopy($image, $signature, 400, 980, 0, 0, $signature_width, $signature_height);

Enter fullscreen mode Exit fullscreen mode

Almost there! Here I am saving the resulting image to disk by providing a name. I I did not provide the name, PHP would just output the content, which could be used instead as a download link by also providing the correct header.

    imagejpeg($image, "diplomas/$name.jpg");

Enter fullscreen mode Exit fullscreen mode

I do not want to clutter my memory, so once I am done with the image, it is destroyed.

    imagedestroy($image);

Enter fullscreen mode Exit fullscreen mode

And done, to the next item on the list!

}

Enter fullscreen mode Exit fullscreen mode

As you can see this is a fairly simple yet powerful script that can be used for many different purposes. Feel free to see or fork the full project and these are the links to the image functions used in this example:


I hope you enjoy this post and find it useful!

php

Top comments (0)