Cloudinary Blog

How to Build an Enhanced Gravatar Service, Part 2

How to Build an Enhanced Gravatar Service, Part 2

Part 1 of this post defines the capabilities of an enhanced Gravatar service, which I named Clavatar, and describes the following initial steps for building it:

  1. Set up the database.
  2. Establish the user-registration process.
  3. Install the Cloudinary PHP Library, version 2.0.0-Beta.
  4. Implement the image-upload operation.
  5. Associate images with user accounts.

This post, part 2 of the series, explains how to make Clavatar work like Gravatar and to develop Clavatar’s capabilities of enabling requests for various versions of the images related to user accounts.

Image Retrieval Through User Hashes

Recall that Gravatar retrieves user images through their hash in a URL, as in this example:

https://www.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50

To enable Clavatar to do the same, set up the API endpoint, as follows:

1. Add the following to the routes/web.php file:

Copy to clipboard
$router->get('avatar/{hash}', 'AvatarController@retrieveAvatar');

2. Add the following retrieveAvatar function to the app/Http/Controllers/AvatarController.php file:

Copy to clipboard
public function retrieveAvatar(Request $request, $hash)
    {
        $defaultImageTag = $this->cloudinary->imageTag('default')->serialize();
        $defaultImageUrl = $this->cloudinary->image('default')->toUrl();

        $user = User::where('hash', $hash)->first();

        if(is_null($user)) {
            return $defaultImageTag;
        }

        $publicId = $user->avatar_id;

        $imageUrl = $this->cloudinary->image($publicId);
        $imageTag = $this->cloudinary->imageTag($publicId);

        return $imageTag->serialize();
    }

The code above does the following:

  • $this->cloudinary->imageTag('default')->serialize(); returns an <image> tag that displays an image with the public ID (public_id) default.
  • $this->cloudinary->image('default')->toUrl(); returns a link to the default image.
  • User::where('hash', $hash)->first(); checks if this hash is in the database and, if so, returns the image associated with the user account. Otherwise, the code returns the default image.

Note
A default image is already in the database. Be sure to upload another default image to your Cloudinary account’s Media Library and name it default.

3. Verify that everything works by running the API endpoint in a browser:

  • With a random hash, e.g.:

    avatar

  • With a valid hash, e.g.:

    Prosper Avatar

Now Clavatar works exactly like Gravatar.

Implementation of Other Features

Feature: Enablement of the ability to request for an image of any size by adding the size parameter, e.g., s=400 or size=400, to the URL.

Implementation Step: Update the retrieveAvatar function, as follows:

Copy to clipboard
public function retrieveAvatar(Request $request, $hash)
    {
        $defaultImageTag = $this->cloudinary->imageTag('default')->serialize();
        $defaultImageUrl = $this->cloudinary->image('default')->toUrl();

        $user = User::where('hash', $hash)->first();

        if(is_null($user)) {
            return $defaultImageTag;
        }

        $publicId = $user->avatar_id;

        $imageUrl = $this->cloudinary->image($publicId);
        $imageTag = $this->cloudinary->imageTag($publicId);

        if($request->has('s') || $request->has('size')) {
            $size = $request->query('s') ?: $request->query('size');

            $imageUrl->resize(Resize::fill($size, $size));
            $imageTag->resize(Resize::fill($size, $size));
        } else {
            $imageUrl->resize(Resize::fill(100,100));
            $imageTag->resize(Resize::fill(100,100));
        }

        return $imageTag->serialize();
    }

Result (Example):

Avatar results

Feature: Enablement of the ability to return a cartoonized version of an image by adding the d=cp parameter to the URL.

Implementation Step: Add the following to the retrieveAvatar function:

Copy to clipboard
public function retrieveAvatar(Request $request, $hash)
    {
        ….
        ….
        if($request->has('d')) {
            $defaultOption = $request->query('d');

            if($defaultOption == 'cp') {
                $imageUrl->effect(Effect::cartoonify());
                $imageTag->effect(Effect::cartoonify());
            }
        }

        return $imageTag->serialize();
    }

Result (Example):

Avatar

Feature: Enablement of the ability to request for the black-and white version of an image by adding the d=bw parameter to the URL.

Implementation Step: Update the retrieveAvatar function, as follows:

Copy to clipboard
public function retrieveAvatar(Request $request, $hash)
    {
        ….
        ….
        if($request->has('d')) {
            $defaultOption = $request->query('d');

            if($defaultOption == 'cp') {
                $imageUrl->effect(Effect::cartoonify());
                $imageTag->effect(Effect::cartoonify());
            }

           if($defaultOption == 'bw') {
                $imageUrl->effect(Effect::blackWhite(30));
                $imageTag->effect(Effect::blackWhite(30));
            }

        }

        return $imageTag->serialize();
    }

Result (Example):

BW Avatar

Feature: Enablement of the ability to request for an artistic version of an image by adding the d=hk parameter to the URL.

Implementation Step: Update the retrieveAvatar function, as follows:

Copy to clipboard
public function retrieveAvatar(Request $request, $hash)
    {
        ….
        ….
        if($request->has('d')) {
            $defaultOption = $request->query('d');

            if($defaultOption == 'cp') {
                $imageUrl->effect(Effect::cartoonify());
                $imageTag->effect(Effect::cartoonify());
            }

           if($defaultOption == 'bw') {
                $imageUrl->effect(Effect::blackWhite(30));
                $imageTag->effect(Effect::blackWhite(30));
            }

           if($defaultOption == 'hk') {
                $imageUrl->effect(Effect::artisticFilter(ArtisticFilter::HOKUSAI));
                $imageTag->effect(Effect::artisticFilter(ArtisticFilter::HOKUSAI));
            }
        }

        return $imageTag->serialize();
    }

Result (Example):

Avatar hk

Feature: Enablement of the ability to request for the compressed and optimized version of an image by adding the q=auto parameter to the URL.

Implementation Step: Add the following to the retrieveAvatar function:

Copy to clipboard
public function retrieveAvatar(Request $request, $hash)
    {
        ….
        ….
        ….
        ….
        if($request->has('q')) {
            $qualityOption = $request->query('q');

            if($qualityOption == 'auto') {
                $imageUrl->quality(Quality::auto());
                $imageTag->quality(Quality::auto());
            }
        }

        return $imageTag->serialize();
    }

Result (Example):

Avatar Quality

Feature: Enablement of the capability to request for the best format of an image by adding the f=auto parameter to the URL. This version ensures the most suitable format for whichever browser is delivering the image.

Implementation Step: Add the following to the retrieveAvatar function:

Copy to clipboard
public function retrieveAvatar(Request $request, $hash)
    {
        ….
        ….
        ….
        ….
        if($request->has('f')) {
            $formatOption = $request->query('f');

            if($formatOption == 'auto') {
                $imageUrl->format(Format::auto());
                $imageTag->format(Format::auto());
            }
        }

        return $imageTag->serialize();
    }

Result (Example):

Avatar Format

Feature: Enablement of the ability to request for the rounded-corners version of an image by adding the a rc=y parameter to the URL.

Implementation Step: Add the following to the retrieveAvatar function:

Copy to clipboard
public function retrieveAvatar(Request $request, $hash)
    {
        ….
        ….
        ….
        ….
        if($request->has('rc')) {
            $roundedOption = $request->query('rc');

            if($roundedOption == 'y') {
                $imageUrl->roundCorners(RoundCorners::max());
                $imageTag->roundCorners(RoundCorners::max());
            }
        }

        return $imageTag->serialize();
    }

Result (Example):

Rounded corners

Feature: Enablement of the ability to rotate an image by adding the r=<angle> parameter, e.g., r=40, to the URL. The value of the angle must be between 1 and 100.

Implementation Step: Add the following to the retrieveAvatar function:

Copy to clipboard
public function retrieveAvatar(Request $request, $hash)
    {
        ….
        ….
        ….
        ….
        if($request->has('r')) {
            $roundedOption = $request->query('r');

            $imageUrl->rotate($roundedOption);
            $imageTag->rotate($roundedOption);
        }

        return $imageTag->serialize();
    }

Result (Example):

Rotate

Feature: Enablement of the ability to request for a color-bordered version of an image by adding the b=<color> parameter, e.g., b=red, to the URL.

Implementation Step: Add the following to the retrieveAvatar function:

Copy to clipboard
public function retrieveAvatar(Request $request, $hash)
    {
        ….
        ….
        ….
        ….
        if($request->has('b')) {
            $borderOption = $request->query('b');

            $imageUrl->border(Border::solid()->width(3)->color($borderOption));
            $imageTag->border(Border::solid()->width(3)->color($borderOption));
        }

        return $imageTag->serialize();
    }

Result:

Outline

Combination of Parameters

You can combine as many parameters as you desire—in any order—to retrieve the image associated with an account.

Example:

To retrieve a cartoonized, circular avatar of a 500x500 size, optimized and in the best format, add the related parameters to the URL:

http://localhost:8000/avatar/7b71271e3c93106dbc3b68fb867344e9?s=500&d=hk&rc=y&f=auto&q=auto

Cloudinary returns this image:

avatar format and quality

Feel free to clone the Clavatar repository on GitHub and run the helpful service.

More Cloudinary Features

With Cloudinary, you can automate your entire image-management lifecycle, from upload and transformation to optimization and delivery. Notably, Cloudinary’s upload widget offers a superfast way to upload multiple images in bulk. The platform also features numerous capabilities for editing and managing videos.

Do check them out.

Recent Blog Posts

Amplify Your Jamstack With Video

By Alex Patterson
Amplify Your Jamstack With Cloudinary Video

As defined by Amazon Web Services (AWS), Amplify is a set of products and tools with which mobile and front-end web developers can build and deploy AWS-powered, secure, and scalable full-stack apps. Also, you can efficiently configure their back ends, connect them to your app with just a few lines of code, and deploy static web apps in only three steps. Historically, because of their performance issues, managing images and videos is a daunting challenge for developers. Even though you can easily load media to an S3 bucket with AWS Amplify, transforming, compressing, and responsively delivering them is labor intensive and time consuming.

Read more
Cloudinary Helps Move James Hardie’s Experience Online

While COVID has affected most businesses, it has been particularly hard on those that sell products for the physical ‘brick and mortar’ world. One company that literally fits that bill is our Australian customer James Hardie, the largest global manufacturer of fibre cement products used in both domestic and commercial construction. These are materials that its buyers ideally want to see up close, in detail. When customers have questions, they expect personal service.

Read more
How to Build an Enhanced Gravatar Service, Part 1

The advent of web development since 25 years ago has given birth to an abundance of online services that help developers build apps efficiently and smoothly. Gravatar is a shining example of such a service. Built by WordPress, Gravatar generates globally recognized avatars. Fun fact: 80 percent of Gravatar users first came across that service when reading a WordPress blog.

Read more