DEV Community

Cover image for Creating default user initial avatars in PHP 7 ๐Ÿค˜๐Ÿ˜Ž
Kim Hallberg
Kim Hallberg

Posted on

Creating default user initial avatars in PHP 7 ๐Ÿค˜๐Ÿ˜Ž

๐Ÿค” What are "default" avatars?

When it comes to user-uploaded material, such as avatars, for instance, some users might refrain from uploading one and, in those instances providing a sensible fallback is an appropriate thing to do, generally, you'll find that they're simple, with a plain background, some figure like a silhouette of a person, the applications logo, or an egg. Some will provide a custom fallback with the user's initials, giving their fallbacks some difference between users.

And that is what we're going to be doing right now. ๐Ÿคฏ


๐Ÿ“ƒ The requirements

For this, you'll need to be running PHP 7+ compiled with support for FreeType.

--with-freetype-dir=DIR
Enter fullscreen mode Exit fullscreen mode

You will also need to have a .ttf file handy, for local test use, you can copy one from your systems font storage, where ever that happens to be located. For production use, please grab a legal for commercial use copy.

So let's get started writing some code. โœ๏ธ

๐Ÿ”จ Our foundation

Before we get so the good stuff, we have some housekeeping to get done first, so let's get that out of the way and create our new function, which I will name createDefaultAvatar().

if (!function_exists('createDefaultAvatar')) {
    function createDefaultAvatar()
    {
    }
}
Enter fullscreen mode Exit fullscreen mode

This will house the majority if not all of our image creation work and manipulation, and I'm sorry to my OOP buddies, but this will break SRP. ๐Ÿ˜ฑ


๐ŸŒ„ Let's create our canvas

The next step in our function will be to create the image stream that we will be manipulating, and for that, we'll use the imagecreate function, which takes two arguments, the width and height in pixels and creates a new palette based image, so let's add that to our function, and pass in our width and height as arguments with some default sizes.

function createDefaultAvatar(
    int $width = 600,
    int $height = 600
) {
    $image = @imagecreate($width, $height)
        or die("Cannot Initialize new GD image stream");

    return $image;
}
Enter fullscreen mode Exit fullscreen mode

And yes, you can type-hint the return value with resource but what will create issues, since resource isn't valid return value.

Fatal error: Uncaught TypeError: Return value of createDefaultAvatar() must be an instance of resource, resource returned
Enter fullscreen mode Exit fullscreen mode

๐ŸŽจ Time to add some color

What would an image be without some colors? To add some color to our image, let's allocate a color with the imagecolorallocate function, and thanks to us using the imagecreate function, the first call to imagecolorallocate() will fill our background color.

So let's add that section to our function, we will call this function twice, with some default colors added into our arguments.

function createDefaultAvatar(
    ...,
    array $bgColor = [0, 0, 0],
    array $textColor = [255, 255, 255]
) {
    ...
    imagecolorallocate($image, $bgColor[0], $bgColor[1], $bgColor[2]);

    $fontColor = imagecolorallocate($image, $textColor[0], $textColor[1], $textColor[2]);

    return $image;
}
Enter fullscreen mode Exit fullscreen mode

Here we are setting the default $bgColor to black and our $textColor to white.


๐Ÿ‹๏ธโ€โ™€๏ธ Time for some heavy lifting

Now we'll get into the biggest and most difficult part of this function, getting our text to center both vertically and horizontally, to do that we'll need to grab the bounding box of our TrueType text using imagettfbbox, which will return an array of all four points our text bounding box.

And to do that we will need to pass in our font size, the path to our TrueType file, and our text.

function createDefaultAvatar(
    ...
    string $text = 'DEV',
    int $fontSize = 140,
    string $font = './arial.ttf'
) {
    ...
    $textBoundingBox = imagettfbbox($fontSize, 0, $font, $text);

    return $image;
}
Enter fullscreen mode Exit fullscreen mode

The second argument is the angle of our text, we don't care about that.

The next part of this step is to calculate the new $x and $y coordinates of our text, so let's add this after our imagettfbbox function call.

$y = abs(ceil(($height - $textBoundingBox[5]) / 2));
$x = abs(ceil(($width - $textBoundingBox[2]) / 2));
Enter fullscreen mode Exit fullscreen mode

This will calculate the position by dividing our bounding box in half to get the middle, and rounding up the division between that and our image height or width, then we get the absolute value of that.

NOTE:

I added the abs function after some experiment, with just ceil the text was sometimes of by a pixel give or take.

You might need to experiment with the bounding box values to get the perfect fit for your font file.


โœ๏ธ Time to write our text

The last step in our function is to write our text to our image, all we've done up till this point is to create our image, set some colors, and calculated where out text should be positioned, now we will use imagettftext to write the text to our image.

So before we return our image, let's write to it, using our new coordinates, our $fontColor, $font, and $text.

function createDefaultAvatar(
    ...
) {
    ...
    imagettftext($image, $fontSize, 0, $x, $y, $fontColor, $font, $text);

    return $image;
}

Enter fullscreen mode Exit fullscreen mode

As above, the 0 in this case is our angle and we don't care about those.


๐ŸŽ‰ Finished function

After switching the arguments around to better fit the usage of the function, the final function will look something like this.

if (!function_exists('createDefaultAvatar')) {
    function createDefaultAvatar(
        string $text = 'DEV',
        array $bgColor = [0, 0, 0],
        array $textColor = [255, 255, 255],
        int $fontSize = 140,
        int $width = 600,
        int $height = 600,
        string $font = './arial.ttf'
    ) {
        $image = @imagecreate($width, $height)
            or die("Cannot Initialize new GD image stream");

        imagecolorallocate($image, $bgColor[0], $bgColor[1], $bgColor[2]);

        $fontColor = imagecolorallocate($image, $textColor[0], $textColor[1], $textColor[2]);

        $textBoundingBox = imagettfbbox($fontSize, 0, $font, $text);

        $y = abs(ceil(($height - $textBoundingBox[5]) / 2));
        $x = abs(ceil(($width - $textBoundingBox[2]) / 2));

        imagettftext($image, $fontSize, 0, $x, $y, $fontColor, $font, $text);

        return $image;
    }
}
Enter fullscreen mode Exit fullscreen mode

Calling our new function createDefaultAvatar(); without any arguments will create an image looking like this.

image with a black background and white text saying dev

Now we can use this function to create user initial avatars by simply passing in new initials into our function.

image with a black background and white text saying k h

createDefaultAvatar("KH")
Enter fullscreen mode Exit fullscreen mode

๐Ÿ˜ฎ More usages.

Why not use this more PHP functions and return the image directly in the browser? We can do that too. ๐Ÿ™Œ

$img = createDefaultAvatar();

header("Content-Type: image/png");

imagepng($img);
imagedestroy($img);
Enter fullscreen mode Exit fullscreen mode

Now when you visit your file in the browser, PHP will render the image in the browser, you can also save the image by providing a path or stream as the second argument to imagepng.


๐Ÿ˜Ž Parting words

So, is this production-ready? Can it be improved? I would say maybe to the first and absolutely to the later.

This is just a tutorial, a proof-of-concept so to speak.

I would break this up into its own class, maybe a service class, that would create, store and give back the location path to be stored in the database for future reference.

But I will leave that up to you, hope you enjoyed it, thanks for reading and goodbye. ๐Ÿ‘‹


TL;DR

Source code:

GitHub logo thinkverse / create-avatar

Creating default user initial avatars in PHP 7

showing rendering default avatar in browser

Latest comments (1)

Collapse
 
rifrocket profile image
Mohammad Arif

really nice peace of code , well document on the post, thanx for sharing knowledge.