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.


Sign up for Cloudinary free today!


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

On-Demand Viewing of Live Video Presents New Opportunities

In early 2020, Cloudinary was planning its fourth annual ImageCon conference, a two-day event in the heart of San Francisco, where we’d congregate with curious digital-media minds to brainstorm best practices for media management. Instead, the COVID-19 pandemic forced the entirety of ImageCon 2020 online. As with all other events being planned, we had to overhaul the content to be communicated on video. Gratifyingly, we found the right partner—the event platform Bizzabo—to turn that into a reality.

Read more
Why the Future of E-commerce Is Live

In a previous post, I discussed how “going live” is gaining popularity across industries and verticals. What began as a way for gamers to jam together has evolved into a medium for broader entertainment and business purposes. To continue the conversation, this post unpacks the current trends of shoppable live streams to shine a light on how brands are leveraging “lives” to connect with shoppers in new ways.

Read more
An Overview of Live-Streaming Video Trends

“Let’s go live.” For decades, that’s what newscasters say as they cut to real-time footage of a colleague reporting in the field. The live-video feed adds visual interest and perspective to a story beyond what can be communicated by someone sitting behind the news desk. In the same way, live-streaming video nowadays adds context to other consumer environments. From gaming and events to shopping and social media, “going live” enhances everyday experiences, and it’s something anyone can do with relative ease.

Read more
Readying Live Streams for Video on Demand

When planning a live broadcast or stream, companies often overlook the redistribution phase, but live-stream videos are useful well beyond their initial streaming. Why? Because not everyone watches the first run. For a wider audience, it makes sense to repost live content on your website under an “events” tab, on YouTube, and other social sites for video on demand (VOD). However, preparing footage for reposting can be a lot of work.

Read more