Cloudinary Blog

How to Build an Enhanced Gravatar Service, Part 2

By
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

Our $2B Valuation

By
Blackstone Growth Invests in Cloudinary

When we started our journey in 2012, we were looking to improve our lives as developers by making it easier for us to handle the arduous tasks of handling images and videos in our code. That initial line of developer code has evolved into a full suite of media experience solutions driven by a mission that gradually revealed itself over the course of the past 10 years: help companies unleash the full potential of their media to create the most engaging visual experiences.

Read more
Direct-to-Consumer E-Commerce Requires Compelling Visual Experiences

When brands like you adopt a direct–to-consumer (DTC) e-commerce approach with no involvement of retailers or marketplaces, you gain direct and timely insight into evolving shopping behaviors. Accordingly, you can accommodate shoppers’ preferences by continually adjusting your product offering and interspersing the shopping journey with moments of excitement and intrigue. Opportunities abound for you to cultivate engaging customer relationships.

Read more
Automatically Translating Videos for an International Audience

No matter your business focus—public service, B2B integration, recruitment—multimedia, in particular video, is remarkably effective in communicating with the audience. Before, making video accessible to diverse viewers involved tasks galore, such as eliciting the service of production studios to manually dub, transcribe, and add subtitles. Those operations were costly and slow, especially for globally destined content.

Read more
Cloudinary Helps Minted Manage Its Image-Generation Pipeline at Scale

Shoppers return time and again to Minted’s global online community of independent artists and designers because they know they can count on unique, statement-making products of the highest quality there. Concurrently, the visual imagery on Minted.com must do justice to the designs into which the creators have poured their hearts and souls. For Minted’s VP of Engineering David Lien, “Because we are a premium brand, we need to ensure that every single one of our product images matches the selected configuration exactly. For example, if you pick an 18x24 art print on blue canvas, we will show that exact combination on the hero images in the PDF.”

Read more
Highlights on ImageCon 2021 and a Preview of ImageCon 2022

New year, same trend! Visual media will continue to play a monumental role in driving online conversions. To keep up with visual-experience trends and best practices, Cloudinary holds an annual conference called ImageCon, a one-of-a-kind event that helps attendees create the most engaging visual experiences possible.

Read more