{"id":23759,"date":"2022-05-04T07:30:00","date_gmt":"2022-05-04T14:30:00","guid":{"rendered":"https:\/\/cloudinary.com\/blog\/?p=23759"},"modified":"2025-03-02T09:31:55","modified_gmt":"2025-03-02T17:31:55","slug":"placing-images-on-curved-surfaces-through-displacement-mapping","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping","title":{"rendered":"Placing Images on Curved Surfaces Through Displacement Mapping and Cloudinary"},"content":{"rendered":"\n<p>Say, you want to place a two-dimensional image on a curved surface, such as a mug or bottle, to create a product mockup or highlight printing capabilities. Thanks to Cloudinary\u2019s displacement-mapping feature, that\u2019s easy to do.<\/p>\n\n\n\n<p>Here\u2019s how displacement mapping works. By means of a map image, the algorithm displaces parts of the image based on the base image\u2019s texture. A lighter red channel in the base causes more horizontal displacement; a darker green channel, more vertical displacement. Also, you can edit image angles for a natural look. Along with the transformation is a detailed map that combines the texture on both surfaces into one.<\/p>\n\n\n\n<p>This tutorial shows displacement mapping in action. You\u2019ll integrate Cloudinary into an application, upload images to Cloudinary, and then create displacement maps on various curved surfaces, such as coffee cups and T-shirts, with <a href=\"https:\/\/cloudinary.com\/documentation\/transformation_reference\">Cloudinary\u2019s Transformation URL API<\/a>. As for prerequisites, you must know the basics of JavaScript and have a working knowledge of Node.js and APIs.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Getting Started<\/h2>\n\n\n\n<p>First, <a href=\"https:\/\/cloudinary.com\/users\/register\/free\">sign up<\/a> for a free Cloudinary account for an ample quota of thousands of transformations, storage, and bandwidth. Note the cloud name, API key, and API secret in your account\u2019s dashboard&nbsp; for connecting your server to Cloudinary later on.<\/p>\n\n\n\n<p>Next, install <a href=\"https:\/\/nodejs.org\/en\/\">Node.js<\/a>. Afterwards, clone the starting code from <a href=\"https:\/\/github.com\/dillionmegida\/cloudinary-snippet\">this GitHub repo<\/a> and check out the<strong> <\/strong>initial branch with two command lines:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">git <span class=\"hljs-keyword\">clone<\/span> git@github.com:dillionmegida\/cloudinary-snippet.git\ngit checkout initial<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The application in this tutorial comprises a front end, which uploads images to the back-end server; and a back-end server, which uploads images to Cloudinary. The server fetches from Cloudinary the images along with the related transformation configurations, ultimately delivering the transformed media to the front end for display.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Building the Front End<\/h2>\n\n\n\n<p>The front-end code will reside in a directory with two pages: the first one for image uploads, the second one for image display.<\/p>\n\n\n\n<p>Build the front end, as follows:<\/p>\n\n\n\n<p> 1. Create an <code>index.html<\/code> file that contains the code below.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-meta\">&lt;!DOCTYPE <span class=\"hljs-meta-keyword\">html<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">html<\/span> <span class=\"hljs-attr\">lang<\/span>=<span class=\"hljs-string\">\"en\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">charset<\/span>=<span class=\"hljs-string\">\"UTF-8\"<\/span> \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"viewport\"<\/span> <span class=\"hljs-attr\">content<\/span>=<span class=\"hljs-string\">\"width=device-width, initial-scale=1.0\"<\/span> \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title<\/span>&gt;<\/span>File Upload<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">title<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\".\/style.css\"<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"stylesheet\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"container\"<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Image Upload<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"form\"<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"input-group\"<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">label<\/span> <span class=\"hljs-attr\">for<\/span>=<span class=\"hljs-string\">\"image\"<\/span>&gt;<\/span>Select image<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">label<\/span>&gt;<\/span>\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"image\"<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"file\"<\/span> \/&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"submit-btn\"<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"submit\"<\/span>&gt;<\/span>Upload<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\".\/script.js\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">html<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p> 2. Create a <code>style.css<\/code> file with the code below.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-tag\">body<\/span> {\n    <span class=\"hljs-attribute\">background-color<\/span>: <span class=\"hljs-built_in\">rgb<\/span>(<span class=\"hljs-number\">6<\/span>, <span class=\"hljs-number\">26<\/span>, <span class=\"hljs-number\">27<\/span>);\n}\n* {\n    <span class=\"hljs-attribute\">box-sizing<\/span>: border-box;\n}\n<span class=\"hljs-selector-class\">.container<\/span> {\n    <span class=\"hljs-attribute\">max-width<\/span>: <span class=\"hljs-number\">1200px<\/span>;\n    <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">60px<\/span> auto;\n}\n<span class=\"hljs-selector-class\">.container<\/span> <span class=\"hljs-selector-tag\">h1<\/span> {\n    <span class=\"hljs-attribute\">text-align<\/span>: center;\n    <span class=\"hljs-attribute\">color<\/span>: white;\n}\n<span class=\"hljs-selector-tag\">form<\/span> {\n    <span class=\"hljs-attribute\">background-color<\/span>: white;\n    <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">30px<\/span>;\n    <span class=\"hljs-attribute\">max-width<\/span>: <span class=\"hljs-number\">500px<\/span>;\n    <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">0<\/span> auto;\n}\n<span class=\"hljs-selector-tag\">form<\/span> <span class=\"hljs-selector-class\">.input-group<\/span> {\n    <span class=\"hljs-attribute\">margin-bottom<\/span>: <span class=\"hljs-number\">15px<\/span>;\n}\n<span class=\"hljs-selector-tag\">form<\/span> <span class=\"hljs-selector-tag\">label<\/span> {\n    <span class=\"hljs-attribute\">display<\/span>: block;\n    <span class=\"hljs-attribute\">margin-bottom<\/span>: <span class=\"hljs-number\">10px<\/span>;\n}\n<span class=\"hljs-selector-tag\">form<\/span> <span class=\"hljs-selector-tag\">input<\/span> {\n    <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">12px<\/span> <span class=\"hljs-number\">20px<\/span>;\n    <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">100%<\/span>;\n    <span class=\"hljs-attribute\">border<\/span>: <span class=\"hljs-number\">1px<\/span> solid <span class=\"hljs-number\">#ccc<\/span>;\n}\n<span class=\"hljs-selector-class\">.submit-btn<\/span> {\n    <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">100%<\/span>;\n    <span class=\"hljs-attribute\">border<\/span>: none;\n    <span class=\"hljs-attribute\">background<\/span>: <span class=\"hljs-built_in\">rgb<\/span>(<span class=\"hljs-number\">37<\/span>, <span class=\"hljs-number\">83<\/span>, <span class=\"hljs-number\">3<\/span>);\n    <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">18px<\/span>;\n    <span class=\"hljs-attribute\">color<\/span>: white;\n    <span class=\"hljs-attribute\">border-radius<\/span>: <span class=\"hljs-number\">3px<\/span>;\n    <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">20px<\/span>;\n    <span class=\"hljs-attribute\">text-align<\/span>: center;\n    <span class=\"hljs-attribute\">cursor<\/span>: pointer;\n}\n<span class=\"hljs-selector-class\">.images<\/span> {\n    <span class=\"hljs-attribute\">background-color<\/span>: white;\n    <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">20px<\/span>;\n    <span class=\"hljs-attribute\">display<\/span>: grid;\n    <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">100%<\/span>;\n    <span class=\"hljs-attribute\">grid-template-columns<\/span>: <span class=\"hljs-built_in\">repeat<\/span>(<span class=\"hljs-number\">4<\/span>, <span class=\"hljs-number\">1<\/span>fr);\n    <span class=\"hljs-attribute\">grid-gap<\/span>: <span class=\"hljs-number\">20px<\/span>;\n}\n<span class=\"hljs-selector-class\">.images<\/span> <span class=\"hljs-selector-class\">.image<\/span> {\n    <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">100%<\/span>;\n}\n<span class=\"hljs-selector-class\">.images<\/span> <span class=\"hljs-selector-tag\">img<\/span> {\n    <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">100%<\/span>;\n}\n<span class=\"hljs-selector-class\">.get-images-btn<\/span> {\n    <span class=\"hljs-attribute\">background-color<\/span>: <span class=\"hljs-built_in\">rgb<\/span>(<span class=\"hljs-number\">37<\/span>, <span class=\"hljs-number\">83<\/span>, <span class=\"hljs-number\">3<\/span>);\n    <span class=\"hljs-attribute\">color<\/span>: white;\n    <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">20px<\/span>;\n    <span class=\"hljs-attribute\">border-radius<\/span>: <span class=\"hljs-number\">3px<\/span>;\n    <span class=\"hljs-attribute\">text-align<\/span>: center;\n    <span class=\"hljs-attribute\">cursor<\/span>: pointer;\n    <span class=\"hljs-attribute\">border<\/span>: none;\n    <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">0<\/span> auto <span class=\"hljs-number\">20px<\/span>;\n    <span class=\"hljs-attribute\">display<\/span>: block;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The above code generates this dialog box:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"512\" height=\"337\" data-public-id=\"dialog_box\/dialog_box.png\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_512,h_337,c_scale\/f_auto,q_auto\/v1648770133\/dialog_box\/dialog_box.png?_i=AA\" alt=\"Dialog box\" class=\"wp-post-23759 wp-image-23762\" loading=\"lazy\" data-format=\"png\" data-transformations=\"f_auto,q_auto\" data-version=\"1648770133\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648770133\/dialog_box\/dialog_box.png?_i=AA 512w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648770133\/dialog_box\/dialog_box.png?_i=AA 300w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/figure>\n\n\n\n<p> 3. Create a <code>script.js<\/code> file with the code below for image uploads.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">const<\/span> form = <span class=\"hljs-built_in\">document<\/span>.getElementById(<span class=\"hljs-string\">\"form\"<\/span>);\n\n<span class=\"hljs-keyword\">if<\/span> (form) form.addEventListener(<span class=\"hljs-string\">\"submit\"<\/span>, submitForm);\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">submitForm<\/span>(<span class=\"hljs-params\">e<\/span>) <\/span>{\n    e.preventDefault();\n    <span class=\"hljs-keyword\">const<\/span> image = <span class=\"hljs-built_in\">document<\/span>.getElementById(<span class=\"hljs-string\">\"image\"<\/span>);\n    <span class=\"hljs-keyword\">const<\/span> formData = <span class=\"hljs-keyword\">new<\/span> FormData();\n    formData.append(<span class=\"hljs-string\">\"image\"<\/span>, image.files&#91;<span class=\"hljs-number\">0<\/span>]);\n    fetch(<span class=\"hljs-string\">\"http:\/\/localhost:5000\/upload_image\"<\/span>, {\n        <span class=\"hljs-attr\">method<\/span>: <span class=\"hljs-string\">\"post\"<\/span>,\n        <span class=\"hljs-attr\">body<\/span>: formData,\n    })\n        .then(<span class=\"hljs-function\">(<span class=\"hljs-params\">res<\/span>) =&gt;<\/span> {\n            alert(<span class=\"hljs-string\">\"successful upload\"<\/span>);\n            image.value = <span class=\"hljs-string\">\"\"<\/span>;\n        })\n        .catch(<span class=\"hljs-function\">(<span class=\"hljs-params\">err<\/span>) =&gt;<\/span> (<span class=\"hljs-string\">\"Error occurred\"<\/span>, err));\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The above code adds a <code>submit event<\/code> listener to the form and attaches the <code>submitForm<\/code> callback function to the listener. On a form submission, you append the selected file to the form data and make a <code>POST<\/code> request to <code>localhost:5000\/upload_files<\/code>. The server will run on <code>localhost:5000<\/code>, and the <code>\/upload_files<\/code> API will upload files.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Building the Back End<\/h2>\n\n\n\n<p>Before building the back end, install the following software:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.npmjs.com\/package\/express\">Express<\/a>: a Node framework for creating APIs<\/li><li><a href=\"https:\/\/www.npmjs.com\/package\/cloudinary\"><code>cloudinary<\/code><\/a>: Cloudinary\u2019s Node.js SDK for uploading and retrieving images<\/li><li><a href=\"https:\/\/www.npmjs.com\/package\/multer\"><code>multer<\/code><\/a>: Node.js middleware for handling multipart form-data (images in forms)<\/li><li><a href=\"https:\/\/www.npmjs.com\/package\/nodemon\"><code>nodemon<\/code><\/a>: a tool that restarts Node.js applications in case of file changes<\/li><li><a href=\"https:\/\/www.npmjs.com\/package\/cors\">CORS<\/a>: Express middleware for sharing of cross-origin resources<\/li><li><a href=\"https:\/\/www.npmjs.com\/package\/dotenv\"><code>dotenv<\/code><\/a>: a module for loading environment variables from an .<code>env<\/code> file<\/li><\/ul>\n\n\n\n<p>Now build the back end, as follows:<\/p>\n\n\n\n<p> 1. Run this command line to incorporate the above packages into the <code>package.json<\/code> file:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-wrap-lines\">npm install express cloudinary multer nodemon cors<\/code><\/span><\/pre>\n\n\n<p> 2. Update the <code>scripts<\/code> property:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-string\">\"scripts\"<\/span>: {\n  <span class=\"hljs-string\">\"dev\"<\/span>: <span class=\"hljs-string\">\"nodemon server.js\"<\/span>\n},<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This script starts the server and, in case of file changes, automatically triggers a restart.<\/p>\n\n\n\n<p> 3. Create a <code>.env<\/code> file and replace the asterisks below with the values from your account\u2019s dashboard.<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-wrap-lines\">CLOUD_NAME=***\nAPI_KEY=***\nAPI_SECRET=***<\/code><\/span><\/pre>\n\n\n<p> 4. Paste this starter code into the <code>server.js<\/code> file:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\"><span class=\"hljs-keyword\">require<\/span>(<span class=\"hljs-string\">\"dotenv\"<\/span>).config();\n<span class=\"hljs-keyword\">const<\/span> multer = <span class=\"hljs-keyword\">require<\/span>(<span class=\"hljs-string\">\"multer\"<\/span>);\n<span class=\"hljs-keyword\">const<\/span> express = <span class=\"hljs-keyword\">require<\/span>(<span class=\"hljs-string\">\"express\"<\/span>);\n<span class=\"hljs-keyword\">const<\/span> cors = <span class=\"hljs-keyword\">require<\/span>(<span class=\"hljs-string\">\"cors\"<\/span>);\n<span class=\"hljs-keyword\">const<\/span> cloudinary = <span class=\"hljs-keyword\">require<\/span>(<span class=\"hljs-string\">\"cloudinary\"<\/span>).v2;\n<span class=\"hljs-keyword\">const<\/span> upload = multer({ dest: <span class=\"hljs-string\">\"uploads\/\"<\/span> });\n\ncloudinary.config({\n    cloud_name: process.env.CLOUD_NAME,\n    api_key: process.env.API_KEY,\n    api_secret: process.env.API_SECRET,\n});\n\n<span class=\"hljs-keyword\">const<\/span> app = express();\napp.<span class=\"hljs-keyword\">use<\/span>(<span class=\"hljs-title\">cors<\/span>());\napp.<span class=\"hljs-keyword\">use<\/span>(<span class=\"hljs-title\">express<\/span>.<span class=\"hljs-title\">json<\/span>());\n\napp.post(<span class=\"hljs-string\">\"\/upload_image\"<\/span>, upload.single(<span class=\"hljs-string\">\"image\"<\/span>), uploadImage);\n\napp.get(<span class=\"hljs-string\">\"\/images\"<\/span>, listImages);\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">uploadImage<\/span><span class=\"hljs-params\">(req, res)<\/span> <\/span>{\n    cloudinary.uploader.upload(\n        req.file.path,\n        {\n            public_id: req.file.filename,\n            folder: <span class=\"hljs-string\">\"cloudinary-test\"<\/span>,\n        },\n        () =&gt; {\n            res.json({ message: <span class=\"hljs-string\">\"Successfully uploaded image\"<\/span> });\n        }\n    );\n}\n\napp.listen(<span class=\"hljs-number\">5000<\/span>, () =&gt; {\n    console.log(`Server started...`);\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Here, you have specified an upload directory for <code>multer<\/code> and created a <code>POST<\/code> API called <code>upload_image<\/code>. The <code>uploadImage<\/code> callback function uploads images to Cloudinary, placing them in the <code>cloudinary-test<\/code> folder. The <code>file<\/code> object on the <code>request<\/code> object is populated with <code>multer middleware (upload.single('image'))<\/code>.<\/p>\n\n\n\n<p> 5. Run npm run dev in the terminal. When the&nbsp; \u201cServer started \u2026\u201d message is displayed, go back to the front end and upload an image.<\/p>\n\n\n\n<p> 6. Go to your Cloudinary account\u2019s dashboard, click <strong>Browse Media Library<\/strong>, and open the <code>cloudinary-test<\/code> folder.<\/p>\n\n\n\n<p>The image you uploaded is displayed, for example, this one:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"512\" height=\"238\" data-public-id=\"cloudinary-test-upload\/cloudinary-test-upload.png\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_512,h_238,c_scale\/f_auto,q_auto\/v1648771207\/cloudinary-test-upload\/cloudinary-test-upload.png?_i=AA\" alt=\"Test upload\" class=\"wp-post-23759 wp-image-23764\" loading=\"lazy\" data-format=\"png\" data-transformations=\"f_auto,q_auto\" data-version=\"1648771207\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648771207\/cloudinary-test-upload\/cloudinary-test-upload.png?_i=AA 512w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648771207\/cloudinary-test-upload\/cloudinary-test-upload.png?_i=AA 300w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/figure>\n\n\n\n<p>The front end calls an API in the back end, which then retrieves the uploaded images from Cloudinary.<\/p>\n\n\n\n<p>Do the following:<\/p>\n\n\n\n<p> 1. Build the API by editing the code below the `listImages` function in the <code>server.js<\/code> file, like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">app.get(<span class=\"hljs-string\">\"\/images\"<\/span>, listImages);\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">listImages<\/span><span class=\"hljs-params\">(req, res)<\/span> <\/span>{\n    cloudinary.api.resources(\n        {\n            type: <span class=\"hljs-string\">\"upload\"<\/span>,\n            prefix: <span class=\"hljs-string\">\"cloudinary-test\"<\/span>,\n        },\n        (err, result) =&gt; {\n            <span class=\"hljs-keyword\">if<\/span> (err) {\n                res.status(<span class=\"hljs-number\">500<\/span>).send(err);\n            } <span class=\"hljs-keyword\">else<\/span> {\n              res.json(result.resources);\n            }\n        }\n    )\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This code retrieves all the images in the <code>cloudinary-test<\/code> folder.<\/p>\n\n\n\n<p> 2. Update the front end by editing the `images.html` file with the code below:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-meta\">&lt;!DOCTYPE <span class=\"hljs-meta-keyword\">html<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">html<\/span> <span class=\"hljs-attr\">lang<\/span>=<span class=\"hljs-string\">\"en\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">charset<\/span>=<span class=\"hljs-string\">\"UTF-8\"<\/span> \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"viewport\"<\/span> <span class=\"hljs-attr\">content<\/span>=<span class=\"hljs-string\">\"width=device-width, initial-scale=1.0\"<\/span> \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title<\/span>&gt;<\/span>Cloudinary images<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">title<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\".\/style.css\"<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"stylesheet\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"container\"<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Images<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"get-images-btn\"<\/span> <span class=\"hljs-attr\">onclick<\/span>=<span class=\"hljs-string\">\"getImages()\"<\/span>&gt;<\/span>Get Images<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"image-container\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"images\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\".\/script.js\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">html<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p> 3. Edit the <code>script.js<\/code> file with the following code so that the<strong> <\/strong><code>image-container<\/code> element will be populated by JavaScript.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">getImages<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n    fetch(<span class=\"hljs-string\">\"http:\/\/localhost:5000\/images\"<\/span>)\n        .then(<span class=\"hljs-function\">(<span class=\"hljs-params\">res<\/span>) =&gt;<\/span> {\n            <span class=\"hljs-keyword\">return<\/span> res.json();\n        })\n        .then(<span class=\"hljs-function\">(<span class=\"hljs-params\">json<\/span>) =&gt;<\/span> {\n            <span class=\"hljs-keyword\">const<\/span> images = json.map(<span class=\"hljs-function\">(<span class=\"hljs-params\">image<\/span>) =&gt;<\/span> {\n                <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">`&lt;div class=\"image\"&gt;\n                    &lt;img src=\"<span class=\"hljs-subst\">${image.url}<\/span>\" alt=\"<span class=\"hljs-subst\">${image.name}<\/span>\" \/&gt;\n                &lt;\/div&gt;`<\/span>;\n            });\n            <span class=\"hljs-built_in\">document<\/span>.getElementById(<span class=\"hljs-string\">\"image-container\"<\/span>).innerHTML = images.join(<span class=\"hljs-string\">\"\"<\/span>);\n        })\n        .catch(<span class=\"hljs-function\">(<span class=\"hljs-params\">err<\/span>) =&gt;<\/span> (<span class=\"hljs-string\">\"Error occurred\"<\/span>, err));\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>When the API returns the images in an array, the code above creates a modified array of those images containing a <code>div<\/code> and an <code>img<\/code> element, then appends the modified array to the DOM.<\/p>\n\n\n\n<p><br>Now load the <code>\/images<\/code> page and click <strong>Get Images<\/strong>. The uploaded image is displayed:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"512\" height=\"293\" data-public-id=\"get-images-dialog-box\/get-images-dialog-box.png\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_512,h_293,c_scale\/f_auto,q_auto\/v1648771733\/get-images-dialog-box\/get-images-dialog-box.png?_i=AA\" alt=\"get images dialog box\" class=\"wp-post-23759 wp-image-23765\" loading=\"lazy\" data-format=\"png\" data-transformations=\"f_auto,q_auto\" data-version=\"1648771733\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648771733\/get-images-dialog-box\/get-images-dialog-box.png?_i=AA 512w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648771733\/get-images-dialog-box\/get-images-dialog-box.png?_i=AA 300w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Transforming Images With Displacement Maps<\/h2>\n\n\n\n<p>You can apply <a href=\"https:\/\/cloudinary.com\/documentation\/transformation_reference\">various transformations<\/a> with Cloudinary. The procedure below steps you through the process of applying displacement maps.<\/p>\n\n\n\n<p> 1. Download the image below, go to your Cloudinary account\u2019s dashboard, create a folder called \u201cgradients\u201d at the <strong>root<\/strong> of the media library. Then, upload the image with the name `<code>gradient<\/code>` to that folder:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"512\" height=\"512\" data-public-id=\"gradient_texture\/gradient_texture.jpg\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_512,h_512,c_fill,g_auto\/f_auto,q_auto\/v1648771989\/gradient_texture\/gradient_texture.jpg?_i=AA\" alt=\"Gradient image\" class=\"wp-post-23759 wp-image-23768\" loading=\"lazy\" data-format=\"jpg\" data-transformations=\"f_auto,q_auto\" data-version=\"1648771989\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648771989\/gradient_texture\/gradient_texture.jpg?_i=AA 512w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648771989\/gradient_texture\/gradient_texture.jpg?_i=AA 150w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648771989\/gradient_texture\/gradient_texture.jpg?_i=AA 300w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"512\" height=\"341\" data-public-id=\"bond_street_image\/bond_street_image.jpg\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_512,h_341,c_scale\/f_auto,q_auto\/v1648772112\/bond_street_image\/bond_street_image.jpg?_i=AA\" alt=\"Bond Street\" class=\"wp-post-23759 wp-image-23769\" loading=\"lazy\" data-format=\"jpg\" data-transformations=\"f_auto,q_auto\" data-version=\"1648772112\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648772112\/bond_street_image\/bond_street_image.jpg?_i=AA 512w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648772112\/bond_street_image\/bond_street_image.jpg?_i=AA 300w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/figure>\n\n\n\n<p> 2. Upload the image above to the root of your media library and rename the image to <code>logo<\/code>.<\/p>\n\n\n\n<p> 3. Update the <code>listImages<\/code> function in the <code>server.js<\/code> file, as follows:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">listImages<\/span>(<span class=\"hljs-params\">req, res<\/span>) <\/span>{\n\t<span class=\"hljs-keyword\">const<\/span> imageUrl = cloudinary\n\t\t.image(<span class=\"hljs-string\">\"logo\"<\/span>, {\n\t\t\t<span class=\"hljs-attr\">overlay<\/span>: <span class=\"hljs-string\">\"gradients:gradient\"<\/span>,\n\t\t\t<span class=\"hljs-attr\">effect<\/span>: <span class=\"hljs-string\">\"displace\"<\/span>,\n\t\t\t<span class=\"hljs-attr\">x<\/span>: <span class=\"hljs-number\">20<\/span>,\n\t\t\t<span class=\"hljs-attr\">y<\/span>: <span class=\"hljs-number\">20<\/span>,\n\t\t\t<span class=\"hljs-attr\">use_root_path<\/span>: <span class=\"hljs-literal\">true<\/span>,\n\t\t})\n\t\t.replace(<span class=\"hljs-string\">\"&lt;img src='\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>)\n\t\t.replace(<span class=\"hljs-string\">\"' \/&gt;\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>);\n\n\tres.json({ imageUrl });\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The colon in <code>gradients:gradient<\/code> is a replacement for <code>\/<\/code>, which specifies paths. So, <code>gradients:gradient<\/code> means the <code>gradient<\/code> file in the <code>gradients<\/code> directory.<\/p>\n\n\n\n<p>The <code>x<\/code> and <code>y<\/code> values denote the amount of displacement on the horizontal and vertical axes, respectively. The higher the value, the greater the displacement.<br>With the <a href=\"https:\/\/cloudinary.com\/documentation\/advanced_url_delivery_options#:~:text=The%20Root%20Path%20URL%20feature,example%2C%20%2Fimage%2Fupload%20.&amp;text=Both%20the%20URLs%20above%20deliver%20the%20same%20uploaded%20image.\"><code>use_root_path<\/code><\/a> option, you can create shorter URLs for uploaded images. <code>replace<\/code> ensures that the output of <code>cloudinary.image<\/code> is in this format:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"...\"<\/span> \/&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>You just need the URL, hence the replacements.<\/p>\n\n\n\n<p> 4. Edit the <code>script.js<\/code> file as follows so that the API responds with an array:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">getImages<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n    fetch(<span class=\"hljs-string\">\"http:\/\/localhost:5000\/images\"<\/span>)\n        .then(<span class=\"hljs-function\">(<span class=\"hljs-params\">res<\/span>) =&gt;<\/span> {\n            <span class=\"hljs-keyword\">return<\/span> res.json();\n        })\n        .then(<span class=\"hljs-function\">(<span class=\"hljs-params\">json<\/span>) =&gt;<\/span> {\n            <span class=\"hljs-keyword\">const<\/span> imageElem = <span class=\"hljs-string\">`\n                &lt;div class=\"image\"&gt;\n                    &lt;img src=\"<span class=\"hljs-subst\">${json.imageUrl}<\/span>\" \/&gt;\n                &lt;\/div&gt;\n            `<\/span>;\n            <span class=\"hljs-built_in\">document<\/span>.getElementById(<span class=\"hljs-string\">\"image-container\"<\/span>).innerHTML = imageElem;\n        })\n        .catch(<span class=\"hljs-function\">(<span class=\"hljs-params\">err<\/span>) =&gt;<\/span> (<span class=\"hljs-string\">\"Error occurred\"<\/span>, err));\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Clicking <strong>Get Images<\/strong> now results in the display of this image:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"512\" height=\"249\" data-public-id=\"upload-image-with-gradient\/upload-image-with-gradient.png\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_512,h_249,c_scale\/f_auto,q_auto\/v1648772581\/upload-image-with-gradient\/upload-image-with-gradient.png?_i=AA\" alt=\"upload image with gradient\" class=\"wp-post-23759 wp-image-23772\" loading=\"lazy\" data-format=\"png\" data-transformations=\"f_auto,q_auto\" data-version=\"1648772581\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648772581\/upload-image-with-gradient\/upload-image-with-gradient.png?_i=AA 512w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648772581\/upload-image-with-gradient\/upload-image-with-gradient.png?_i=AA 300w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/figure>\n\n\n\n<p>The procedure above displaces certain parts of the logo with a template map (gradient). The black regions distort the image upwards; the white regions, downwards. You can create various displacements with different gradient patterns.<\/p>\n\n\n\n<p>Next, attach a modified image like the one you just created to another image\u2014a curved surface generated by a gradient. Follow these steps:<\/p>\n\n\n\n<p> 1. Upload the first image below to the <strong>root<\/strong> of the media library and the second to the gradients folder in your account\u2019s dashboard:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"512\" height=\"341\" data-public-id=\"graffiti\/graffiti.jpg\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_512,h_341,c_scale\/f_auto,q_auto\/v1648772761\/graffiti\/graffiti.jpg?_i=AA\" alt=\"graffiti\" class=\"wp-post-23759 wp-image-23773\" loading=\"lazy\" data-format=\"jpg\" data-transformations=\"f_auto,q_auto\" data-version=\"1648772761\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648772761\/graffiti\/graffiti.jpg?_i=AA 512w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648772761\/graffiti\/graffiti.jpg?_i=AA 300w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"512\" height=\"337\" data-public-id=\"displacement-gradient\/displacement-gradient.png\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_512,h_337,c_scale\/f_auto,q_auto\/v1648828612\/displacement-gradient\/displacement-gradient.png?_i=AA\" alt=\"Gradient image\" class=\"wp-post-23759 wp-image-23778\" loading=\"lazy\" data-format=\"png\" data-transformations=\"f_auto,q_auto\" data-version=\"1648828612\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648828612\/displacement-gradient\/displacement-gradient.png?_i=AA 512w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648828612\/displacement-gradient\/displacement-gradient.png?_i=AA 300w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/figure>\n\n\n\n<p> 2. Rename the top image `sticker` and the bottom image <code>gradient2<\/code>.<\/p>\n\n\n\n<p> 3. Update the <code>server.js<\/code> file to read like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">listImages<\/span>(<span class=\"hljs-params\">req, res<\/span>) <\/span>{\n\t<span class=\"hljs-keyword\">const<\/span> imageUrl = cloudinary\n\t\t.image(<span class=\"hljs-string\">\"sticker\"<\/span>, {\n\t\t\t<span class=\"hljs-attr\">overlay<\/span>: <span class=\"hljs-string\">\"gradients:gradient2\"<\/span>,\n\t\t\t<span class=\"hljs-attr\">effect<\/span>: <span class=\"hljs-string\">\"displace\"<\/span>,\n\t\t\t<span class=\"hljs-attr\">x<\/span>: <span class=\"hljs-number\">30<\/span>,\n\t\t\t<span class=\"hljs-attr\">y<\/span>: <span class=\"hljs-number\">30<\/span>,\n\t\t\t<span class=\"hljs-attr\">use_root_path<\/span>: <span class=\"hljs-literal\">true<\/span>,\n\t\t})\n\t\t.replace(<span class=\"hljs-string\">\"&lt;img src='\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>)\n\t\t.replace(<span class=\"hljs-string\">\"' \/&gt;\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>);\n\n\tres.json({ imageUrl });\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Clicking <strong>Get Images<\/strong> results in the display of this curved image:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"512\" height=\"242\" data-public-id=\"upload-graffiti\/upload-graffiti.png\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_512,h_242,c_scale\/f_auto,q_auto\/v1648848949\/upload-graffiti\/upload-graffiti.png?_i=AA\" alt=\"upload graffiti image\" class=\"wp-post-23759 wp-image-23783\" loading=\"lazy\" data-format=\"png\" data-transformations=\"f_auto,q_auto\" data-version=\"1648848949\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648848949\/upload-graffiti\/upload-graffiti.png?_i=AA 512w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648848949\/upload-graffiti\/upload-graffiti.png?_i=AA 300w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/figure>\n\n\n\n<p>You can now apply the new image as an overlay to a surface, e.g., a cup. Follow the steps below.<\/p>\n\n\n\n<p> 1. Upload an image of a plain paper cup, such as this one from <a href=\"https:\/\/unsplash.com\/s\/photos\/empty-product-images\">Unsplash<\/a>, to the <code>cloudinary-test<\/code> folder. Rename the image <code>cup<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"512\" height=\"512\" data-public-id=\"coffee_cup\/coffee_cup.png\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_512,h_512,c_fill,g_auto\/f_auto,q_auto\/v1648849164\/coffee_cup\/coffee_cup.png?_i=AA\" alt=\"Empty product\" class=\"wp-post-23759 wp-image-23784\" loading=\"lazy\" data-format=\"png\" data-transformations=\"f_auto,q_auto\" data-version=\"1648849164\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648849164\/coffee_cup\/coffee_cup.png?_i=AA 512w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648849164\/coffee_cup\/coffee_cup.png?_i=AA 150w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648849164\/coffee_cup\/coffee_cup.png?_i=AA 300w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/figure>\n\n\n\n<p> 2. Update the <code>server.js<\/code> file to read like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">listImages<\/span>(<span class=\"hljs-params\">req, res<\/span>) <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> imageUrl = cloudinary\n        .image(<span class=\"hljs-string\">\"cloudinary-test\/cup\"<\/span>, {\n            <span class=\"hljs-attr\">use_root_path<\/span>: <span class=\"hljs-literal\">true<\/span>,\n            <span class=\"hljs-attr\">transformation<\/span>: &#91;\n                { <span class=\"hljs-attr\">width<\/span>: <span class=\"hljs-number\">500<\/span>, <span class=\"hljs-attr\">crop<\/span>: <span class=\"hljs-string\">\"scale\"<\/span> },\n                {\n                    <span class=\"hljs-attr\">overlay<\/span>: <span class=\"hljs-string\">\"sticker\"<\/span>,\n                    <span class=\"hljs-attr\">width<\/span>: <span class=\"hljs-number\">100<\/span>,\n                    <span class=\"hljs-attr\">height<\/span>: <span class=\"hljs-number\">100<\/span>,\n                    <span class=\"hljs-attr\">crop<\/span>: <span class=\"hljs-string\">\"pad\"<\/span>,\n                    <span class=\"hljs-attr\">y<\/span>: <span class=\"hljs-number\">10<\/span>,\n                },\n                { <span class=\"hljs-attr\">overlay<\/span>: <span class=\"hljs-string\">\"gradients:gradient2\"<\/span> },\n                { <span class=\"hljs-attr\">flags<\/span>: <span class=\"hljs-string\">\"layer_apply\"<\/span>, <span class=\"hljs-attr\">effect<\/span>: <span class=\"hljs-string\">\"displace\"<\/span>, <span class=\"hljs-attr\">y<\/span>: <span class=\"hljs-number\">2<\/span> },\n            ],\n        })\n        .replace(<span class=\"hljs-string\">\"&lt;img src='\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>)\n        .replace(<span class=\"hljs-string\">\"' \/&gt;\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>);\n    res.json({ imageUrl });\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The above code groups the transformations appropriately with the <code>transformation<\/code> array property. Additionally, the code adds the image as an overlay; also the gradient, but with the displacement effect.<\/p>\n\n\n\n<p>Clicking <strong>Get image<\/strong> results in this display:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"512\" height=\"258\" data-public-id=\"graffiti_on_cup\/graffiti_on_cup.png\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_512,h_258,c_scale\/f_auto,q_auto\/v1648849403\/graffiti_on_cup\/graffiti_on_cup.png?_i=AA\" alt=\"Adding a graffiti image on a coffee cup\" class=\"wp-post-23759 wp-image-23785\" loading=\"lazy\" data-format=\"png\" data-transformations=\"f_auto,q_auto\" data-version=\"1648849403\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648849403\/graffiti_on_cup\/graffiti_on_cup.png?_i=AA 512w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648849403\/graffiti_on_cup\/graffiti_on_cup.png?_i=AA 300w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/figure>\n\n\n\n<p>Neat, right? To enhance the aesthetics, move the image slightly to the left and to the top by adding the following object to the <code>transformation<\/code> array:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\">{ <span class=\"hljs-attribute\">flags<\/span>: <span class=\"hljs-string\">\"layer_apply\"<\/span>, x: -<span class=\"hljs-number\">7<\/span>, y: -<span class=\"hljs-number\">40<\/span>, background: <span class=\"hljs-string\">\"transparent\"<\/span> }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The image now looks like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img width=\"512\" height=\"224\" data-public-id=\"top-left-image-cup\/top-left-image-cup.png\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_512,h_224,c_scale\/f_auto,q_auto\/v1648849797\/top-left-image-cup\/top-left-image-cup.png?_i=AA\" alt=\"Adjusted graffiti image on coffee cup\" class=\"wp-post-23759 wp-image-23786\" loading=\"lazy\" data-format=\"png\" data-transformations=\"f_auto,q_auto\" data-version=\"1648849797\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648849797\/top-left-image-cup\/top-left-image-cup.png?_i=AA 512w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648849797\/top-left-image-cup\/top-left-image-cup.png?_i=AA 300w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/figure>\n\n\n\n<p>To place the image called <code>logo<\/code> on the surface of other products, do the following:<\/p>\n\n\n\n<p> 1. Download from <a href=\"https:\/\/unsplash.com\/s\/photos\/empty-product-images\">Unsplash<\/a> a few plain product images with a curved surface. For example:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img width=\"1024\" height=\"864\" data-public-id=\"blog-upload-to-cloudinary-grid\/blog-upload-to-cloudinary-grid.png\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_1024,h_864,c_scale\/f_auto,q_auto\/v1648852320\/blog-upload-to-cloudinary-grid\/blog-upload-to-cloudinary-grid.png?_i=AA\" alt=\"image collage\" class=\"wp-post-23759 wp-image-23788\" loading=\"lazy\" data-format=\"png\" data-transformations=\"f_auto,q_auto\" data-version=\"1648852320\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648852320\/blog-upload-to-cloudinary-grid\/blog-upload-to-cloudinary-grid.png?_i=AA 1280w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648852320\/blog-upload-to-cloudinary-grid\/blog-upload-to-cloudinary-grid.png?_i=AA 300w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648852320\/blog-upload-to-cloudinary-grid\/blog-upload-to-cloudinary-grid.png?_i=AA 768w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648852320\/blog-upload-to-cloudinary-grid\/blog-upload-to-cloudinary-grid.png?_i=AA 1024w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p> 2. Upload the images to Cloudinary from the front end of the application.<\/p>\n\n\n\n<p> 3. Apply the logo to all five images by editing the <code>listImages<\/code> function in the <code>server.js<\/code> file to read like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">listImages<\/span>(<span class=\"hljs-params\">req, res<\/span>) <\/span>{\n\tcloudinary.api.resources(\n\t\t{\n\t\t\t<span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-string\">\"upload\"<\/span>,\n\t\t\t<span class=\"hljs-attr\">prefix<\/span>: <span class=\"hljs-string\">\"cloudinary-test\"<\/span>,\n\t\t},\n\t\t(err, result) =&gt; {\n\t\t\t<span class=\"hljs-keyword\">if<\/span> (err) {\n\t\t\t\tres.status(<span class=\"hljs-number\">500<\/span>).send(err);\n\t\t\t} <span class=\"hljs-keyword\">else<\/span> {\n\t\t\t\t<span class=\"hljs-keyword\">const<\/span> transformed = result.resources.map(<span class=\"hljs-function\">(<span class=\"hljs-params\">r<\/span>) =&gt;<\/span> {\n\t\t\t\t\t<span class=\"hljs-keyword\">const<\/span> transformedUrl = cloudinary\n\t\t\t\t\t\t.image(r.public_id, {\n\t\t\t\t\t\t\t<span class=\"hljs-attr\">use_root_path<\/span>: <span class=\"hljs-literal\">true<\/span>,\n\t\t\t\t\t\t\t<span class=\"hljs-attr\">transformation<\/span>: &#91;\n\t\t\t\t\t\t\t\t{ <span class=\"hljs-attr\">width<\/span>: <span class=\"hljs-number\">500<\/span>, <span class=\"hljs-attr\">crop<\/span>: <span class=\"hljs-string\">\"scale\"<\/span> },\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t<span class=\"hljs-attr\">overlay<\/span>: <span class=\"hljs-string\">\"sticker\"<\/span>,\n\t\t\t\t\t\t\t\t\t<span class=\"hljs-attr\">width<\/span>: <span class=\"hljs-number\">100<\/span>,\n\t\t\t\t\t\t\t\t\t<span class=\"hljs-attr\">height<\/span>: <span class=\"hljs-number\">100<\/span>,\n\t\t\t\t\t\t\t\t\t<span class=\"hljs-attr\">crop<\/span>: <span class=\"hljs-string\">\"pad\"<\/span>,\n\t\t\t\t\t\t\t\t\t<span class=\"hljs-attr\">y<\/span>: <span class=\"hljs-number\">10<\/span>,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{ <span class=\"hljs-attr\">overlay<\/span>: <span class=\"hljs-string\">\"gradients:gradient2\"<\/span> },\n\t\t\t\t\t\t\t\t{ <span class=\"hljs-attr\">flags<\/span>: <span class=\"hljs-string\">\"layer_apply\"<\/span>, <span class=\"hljs-attr\">effect<\/span>: <span class=\"hljs-string\">\"displace\"<\/span>, <span class=\"hljs-attr\">y<\/span>: <span class=\"hljs-number\">2<\/span> },\n\t\t\t\t\t\t\t\t{ <span class=\"hljs-attr\">flags<\/span>: <span class=\"hljs-string\">\"layer_apply\"<\/span>, <span class=\"hljs-attr\">x<\/span>: <span class=\"hljs-number\">2<\/span>, <span class=\"hljs-attr\">background<\/span>: <span class=\"hljs-string\">\"transparent\"<\/span> },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.replace(<span class=\"hljs-string\">\"&lt;img src='\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>)\n\t\t\t\t\t\t.replace(<span class=\"hljs-string\">\"' \/&gt;\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>);\n\n\t\t\t\t\t<span class=\"hljs-keyword\">return<\/span> { transformedUrl, ...r };\n\t\t\t\t});\n\t\t\t\tres.json(transformed);\n\t\t\t}\n\t\t}\n\t);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p> 4. Update the <code>script.js<\/code> file to receive an array:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">getImages<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n    fetch(<span class=\"hljs-string\">\"http:\/\/localhost:5000\/images\"<\/span>)\n        .then(<span class=\"hljs-function\">(<span class=\"hljs-params\">res<\/span>) =&gt;<\/span> {\n            <span class=\"hljs-keyword\">return<\/span> res.json();\n        })\n        .then(<span class=\"hljs-function\">(<span class=\"hljs-params\">json<\/span>) =&gt;<\/span> {\n            <span class=\"hljs-keyword\">const<\/span> images = json.map(<span class=\"hljs-function\">(<span class=\"hljs-params\">image<\/span>) =&gt;<\/span> {\n                <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">`&lt;div class=\"image\"&gt;\n                    &lt;img src=\"<span class=\"hljs-subst\">${image.transformedUrl}<\/span>\" alt=\"<span class=\"hljs-subst\">${image.name}<\/span>\" \/&gt;\n                &lt;\/div&gt;`<\/span>;\n            });\n            <span class=\"hljs-built_in\">document<\/span>.getElementById(<span class=\"hljs-string\">\"image-container\"<\/span>).innerHTML = images.join(<span class=\"hljs-string\">\"\"<\/span>);\n\n   })\n        .catch(<span class=\"hljs-function\">(<span class=\"hljs-params\">err<\/span>) =&gt;<\/span> (<span class=\"hljs-string\">\"Error occurred\"<\/span>, err));\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Clicking <strong>Get Images<\/strong> results in this display:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"512\" height=\"385\" data-public-id=\"get-images-collage\/get-images-collage.png\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_512,h_385,c_scale\/f_auto,q_auto\/v1648852147\/get-images-collage\/get-images-collage.png?_i=AA\" alt=\"get images collage\" class=\"wp-post-23759 wp-image-23787\" loading=\"lazy\" data-format=\"png\" data-transformations=\"f_auto,q_auto\" data-version=\"1648852147\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648852147\/get-images-collage\/get-images-collage.png?_i=AA 512w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1648852147\/get-images-collage\/get-images-collage.png?_i=AA 300w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/figure>\n\n\n\n<p>The logo looks fine on some objects but not on others. Why? Because, to simultaneously apply the logo to multiple product images, you must ensure that the displacement pattern is a fit for the latter. Otherwise, apply the displacement separately, one product image at a time.<\/p>\n\n\n\n<p>The <a href=\"https:\/\/github.com\/dillionmegida\/cloudinary-snippet\/tree\/implementation\">code<\/a> for this tutorial is on GitHub.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Forging On<\/h2>\n\n\n\n<p>With Cloudinary, you can transform images by leveraging just URL parameters\u2014in this case, displacement maps, which enable texture objects to capitalize on the base image\u2019s displacement strength. Hence the ease with which you can map displaced images to other pictures, rendering the final version lifelike.<\/p>\n\n\n\n<p>To place images on curved surfaces, you\u2019d usually need to merge images with photo-editing software. No need with Cloudinary. By following the simple procedures above, you can showcase how your products look on various objects, and vice versa.<\/p>\n\n\n\n<p>Other image transformations you can perform with Cloudinary\u2019s URL parameters include changing file extensions, editing backgrounds, as well as improving and optimizing quality. For details, see the related <a href=\"https:\/\/cloudinary.com\/documentation\/transformation_reference\">documentation<\/a>. Let your creativity fly!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Say, you want to place a two-dimensional image on a curved surface, such as a mug or bottle, to create a product mockup or highlight printing capabilities. Thanks to Cloudinary\u2019s displacement-mapping feature, that\u2019s easy to do. Here\u2019s how displacement mapping works. By means of a map image, the algorithm displaces parts of the image based [&hellip;]<\/p>\n","protected":false},"author":18,"featured_media":23760,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[362,98,165],"class_list":["post-23759","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-displacement-mapping","tag-e-commerce","tag-image-transformation"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Images on Curved Surfaces: Displacement Mapping on Cloudinary<\/title>\n<meta name=\"description\" content=\"How to place images on a curved surface with Cloudinary&#039;s displacement-mapping feature, showcasing how products look on various objects.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Placing Images on Curved Surfaces Through Displacement Mapping and Cloudinary\" \/>\n<meta property=\"og:description\" content=\"How to place images on a curved surface with Cloudinary&#039;s displacement-mapping feature, showcasing how products look on various objects.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-05-04T14:30:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-03-02T17:31:55+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1631639375\/Web_Assets\/blog\/Images-on-curved-surfaces\/Images-on-curved-surfaces-png?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"2000\" \/>\n\t<meta property=\"og:image:height\" content=\"1100\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Placing Images on Curved Surfaces Through Displacement Mapping and Cloudinary\",\"datePublished\":\"2022-05-04T14:30:00+00:00\",\"dateModified\":\"2025-03-02T17:31:55+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping\"},\"wordCount\":1382,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1631639375\/Web_Assets\/blog\/Images-on-curved-surfaces\/Images-on-curved-surfaces.png?_i=AA\",\"keywords\":[\"Displacement Mapping\",\"E-commerce\",\"Image Transformation\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2022\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping\",\"url\":\"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping\",\"name\":\"Images on Curved Surfaces: Displacement Mapping on Cloudinary\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1631639375\/Web_Assets\/blog\/Images-on-curved-surfaces\/Images-on-curved-surfaces.png?_i=AA\",\"datePublished\":\"2022-05-04T14:30:00+00:00\",\"dateModified\":\"2025-03-02T17:31:55+00:00\",\"description\":\"How to place images on a curved surface with Cloudinary's displacement-mapping feature, showcasing how products look on various objects.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1631639375\/Web_Assets\/blog\/Images-on-curved-surfaces\/Images-on-curved-surfaces.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1631639375\/Web_Assets\/blog\/Images-on-curved-surfaces\/Images-on-curved-surfaces.png?_i=AA\",\"width\":2000,\"height\":1100},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Placing Images on Curved Surfaces Through Displacement Mapping and Cloudinary\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Images on Curved Surfaces: Displacement Mapping on Cloudinary","description":"How to place images on a curved surface with Cloudinary's displacement-mapping feature, showcasing how products look on various objects.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping","og_locale":"en_US","og_type":"article","og_title":"Placing Images on Curved Surfaces Through Displacement Mapping and Cloudinary","og_description":"How to place images on a curved surface with Cloudinary's displacement-mapping feature, showcasing how products look on various objects.","og_url":"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping","og_site_name":"Cloudinary Blog","article_published_time":"2022-05-04T14:30:00+00:00","article_modified_time":"2025-03-02T17:31:55+00:00","og_image":[{"width":2000,"height":1100,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1631639375\/Web_Assets\/blog\/Images-on-curved-surfaces\/Images-on-curved-surfaces-png?_i=AA","type":"image\/png"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping"},"author":{"name":"","@id":""},"headline":"Placing Images on Curved Surfaces Through Displacement Mapping and Cloudinary","datePublished":"2022-05-04T14:30:00+00:00","dateModified":"2025-03-02T17:31:55+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping"},"wordCount":1382,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1631639375\/Web_Assets\/blog\/Images-on-curved-surfaces\/Images-on-curved-surfaces.png?_i=AA","keywords":["Displacement Mapping","E-commerce","Image Transformation"],"inLanguage":"en-US","copyrightYear":"2022","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping","url":"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping","name":"Images on Curved Surfaces: Displacement Mapping on Cloudinary","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1631639375\/Web_Assets\/blog\/Images-on-curved-surfaces\/Images-on-curved-surfaces.png?_i=AA","datePublished":"2022-05-04T14:30:00+00:00","dateModified":"2025-03-02T17:31:55+00:00","description":"How to place images on a curved surface with Cloudinary's displacement-mapping feature, showcasing how products look on various objects.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1631639375\/Web_Assets\/blog\/Images-on-curved-surfaces\/Images-on-curved-surfaces.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1631639375\/Web_Assets\/blog\/Images-on-curved-surfaces\/Images-on-curved-surfaces.png?_i=AA","width":2000,"height":1100},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/placing-images-on-curved-surfaces-through-displacement-mapping#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Placing Images on Curved Surfaces Through Displacement Mapping and Cloudinary"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1631639375\/Web_Assets\/blog\/Images-on-curved-surfaces\/Images-on-curved-surfaces.png?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/23759","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/18"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=23759"}],"version-history":[{"count":15,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/23759\/revisions"}],"predecessor-version":[{"id":37078,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/23759\/revisions\/37078"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/23760"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=23759"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=23759"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=23759"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}