Enhance Image Quality with Cloudinary and Viesus

Ifeoma Imoh

To add to their rich media management capabilities, the Cloudinary platform has taken a step further and partnered with other tech giants, leveraging advanced technology such as AI to develop and provide more specialized tools called add-ons. This further enhances media management concerns such as transformation, security, media conversion, analytics, etc.

We'll look at one of them, the Viesus add-on, in this post. This is an image enhancement solution manufactured by a Swiss company called Image solutions AG. This add-on makes it easy to enhance the visual quality of images for a more crisp and enhanced appearance, automatically detecting and improving its brightness, saturation, and so on while maintaining the image optimized adequately for print or onscreen delivery. We will learn how to use this add-on on our image assets using a simple web application.

Here is a link to the demo CodeSandbox.

Project Setup

Create a Next.js app using the following command:

1npx create-next-app viesus-project

Next, add the project dependencies using the following command:

1npm install cloudinary axios

The Node Cloudinary SDK will provide easy-to-use methods to interact with the Cloudinary APIs, while axios will serve as our HTTP client.

Setting up Cloudinary

To use Cloudinary's provisioned services, you need to first sign up for a free Cloudinary account if you don’t have one already. Displayed on your account’s Management Console (aka Dashboard) are important details: your cloud name, API key, etc.

Next, let’s create environment variables to hold the details of our Cloudinary account. Create a new file called .env at the root of your project and add the following to it:

1CLOUD_NAME = YOUR CLOUD NAME HERE
2API_KEY = YOUR API API KEY
3API_SECRET = YOUR API API SECRET

This will be used as a default when the project is set up on another system. To update your local environment, create a copy of the .env file using the following command:

1cp .env .env.local

By default, this local file resides in the .gitignore folder, mitigating the security risk of inadvertently exposing secret credentials to the public. You can update the .env.local file with your Cloudinary credentials.

Access to the Cloudinary add-ons is not provided out of the box when we create an account. This is a premium Cloudinary offering which means that to access these features, you need to register for the Viesus add-on. Each add-on provides us with several plans and their associated prices. Thankfully, most of them also offer free plans, so click on the free option to register.

Generate Delivery URLs That Include the Viesus Effect as Transformation Parameters

All Cloudinary add-ons meant for image transformation like Viesus by default require that the delivery URLs we generate for assets need to be signed or eagerly generated. A signed delivery URL is simply a URL that contains a base64 encoded hash, usually SHA-1 or SHA-256, as seen below:

The signature in the URL is generated on the server using the identifier of the image to be transformed and the specific transformations to be applied to the asset, all concatenated with the API secret credential.

The other option for generating delivery URLs is by generating transformed versions of the assets eagerly, and this is usually done when the image is being uploaded. When we upload assets using eager transformations, we essentially store the asset unmodified on the cloud. Still, the transformed version of the asset as specified by the transformation parameters will be used to generate another version of the asset, stored on a CDN somewhere. This ensures that the transformed version of our asset is readily available on the CDN to be served on-demand. See here for more on the Cloudinary transformation URL API.

In most use cases, we would apply transformations to images after uploading them, i.e., before we may need to request some transformed version of the image. With this in mind, we'll be focusing on using the signed URL option in this post.

Setup API Endpoint to Generate Signed Delivery URLs for Images with Viesus Effect

We will be using the built-in Next.js API routes that allow us to add serverless functions to help us execute server-side logic in our apps. In the /pages/api folder, create a file named getDeliveryUrl.js and add the following to it:

1const cloudinary = require("cloudinary").v2;
2cloudinary.config({
3 cloud_name: process.env.CLOUD_NAME,
4 api_key: process.env.API_KEY,
5 api_secret: process.env.API_SECRET,
6});
7export default async function handleUpload(req, res) {
8 try {
9 const publicId = req.body.publicId;
10 const image = await cloudinary.image(publicId, {
11 effect: "viesus_correct",
12 sign_url: true,
13 });
14 const URLfromImageTag = await /src='(.+?)'/.exec(image)[1];
15 res.send({ URL: URLfromImageTag });
16 } catch (error) {
17 res.send(error);
18 }
19}

There isn't a lot happening here. We simply bring in the Cloudinary module we installed earlier and configure it using our Cloudinary credentials.

Next, we define and export the serverless function, which expects the HTTP request and response objects. Internally we simply request and send a signed delivery URL for an image with the viesus effect applied to it, and we go about this by doing the following:

  • First, we extract the image’s public identifier from the request body and store it in a variable called publicId.
  • Next, we construct the delivery URL for the image by a call to the cloudinary.image method. This method expects two parameters, the first being the image identifier, and the second is an options object that defines specific configurations for the various parts of the URL. Here we included a signature in the URL by setting the signed key to true. Next, in the transformation section of the delivery URL, using the effect transformation parameter, we specify viesus_correct as the value. This string is what will instruct the Cloudinary servers to use Viesus to enhance all aspects of the image for a more crisp and enhanced look. The Cloudinary.image method returns a string that holds an HTML img tag with the delivery URL bound to its src attribute.
  • Next, we extract the contents of the src attribute from the img tag using a regular expression and finally send it as the response.

It is important to note that the generated URL for an image with the viesus effect applied will only be created when the user makes a request using the URL to get the transformed image. After the first time the image is requested, it is cached on a CDN to ensure that the asset is made available quickly to other consumers.

Upload Images to Your Cloudinary Account

To hit our previously defined serverless function, we need to have some images on our Cloudinary account. There are several ways to upload images to your account, but the one that we will be using is the easiest option which is to use the upload widget via the GUI on your dashboard. Once the upload is successful, the asset will be available for view on your dashboard; taking a closer look at the asset, you will see the public id of the image as seen below:

Build the Frontend to Request for and Display the Transformed Image

Add the following to your page/index.js file:

1import { useState } from "react";
2import axios from "axios";
3const image = {
4 publicId: "vz4xzvqpdxvelgbbaa2f",
5 URL: "https://res.cloudinary.com/ifeomaimoh/image/upload/v1639114080/vz4xzvqpdxvelgbbaa2f.jpg",
6};
7export default function IndexPage() {
8 const [transformedImageURL, setTransformedImageURL] = useState("");
9 const getSignedDeliveryURL = async () => {
10 try {
11 const res = await axios.post("/api/getDeliveryUrl", {
12 publicId: image.publicId,
13 });
14 setTransformedImageURL(res.data.URL);
15 } catch (error) {
16 console.log(error);
17 }
18 };
19 return (
20 <section className="main_con">
21 <article className="image_toog">images</article>
22 <article>
23 <h2> default image</h2>
24 <div className="img_con">
25 <img src={image.URL} alt={"test"} />
26 </div>
27 </article>
28 <button onClick={getSignedDeliveryURL}> apply viscus effect </button>
29 <article>
30 <div className="img_con">
31 {transformedImageURL && (
32 <>
33 <h2> Image with viscus effect</h2>
34 <img src={transformedImageURL} alt={"test"} />
35 </>
36 )}
37 </div>
38 </article>
39 </section>
40 );
41}

In the code above, we define an object that holds the public id and delivery URL of the image we uploaded. In the IndexPage component, we create a state variable that would be used to set and get the delivery URL of the transformed image; this is followed by the getSignedDeliveryURL async function. This function first makes an HTTP request to the Serverless function we defined earlier and passes the image’s public id as the payload. If the request is successful, we get the signed delivery URL from the response body and store it in the state.

This component returns some JSX, including image tags used to display the original image and the transformed image and a button to invoke the getSignedDeliveryURL function.

Run this command to preview the running application:

1npm run dev

Find the complete project here on GitHub.

Conclusion

The importance of high, quality and visually appealing images in various domains in our world today cannot be overstated. With great platforms like Cloudinary, the potential for how effectively and efficiently we can manage, manipulate, and deliver media assets as needed are limitless.

Resources you may find helpful:

Ifeoma Imoh

Software Developer

Ifeoma is a software developer and technical content creator in love with all things JavaScript.