Cloudinary Blog

How to Use Displacement Maps to Transform Images

Use a Displacement Map to Manipulate your Images

Cloudinary offers a wide variety of transformations that enable you to to manipulate images on the fly by using dynamic URLs. Web and mobile developers use these transformations on their images to achieve everything from optimization and responsive delivery to a variety of image improvement manipulations, with a huge collection of cool effects to choose between. One of the more robust transformations applies another image as a displacement map to manipulate your base image in a variety of ways. The displacement mapping algorithm evaluates every pixel in the image map and then displaces the pixels in the base image based on the intensity of the corresponding image map pixels.

The algorithm evaluates both the red and green color channels of the map image: the higher the intensity of the color red in the displacement map the more the corresponding pixel in the base image is displaced horizontally, and the higher the intensity of the green color in the image map, the larger the vertical displacement of the corresponding pixel in the base image.

The following example demonstrates a base image displaced by an image map, creating a zoom effect:

Sample image

Ruby:
cl_image_tag("sample", :overlay=>"docs:zoom_map", :effect=>"displace", :x=>50, :y=>50, :use_root_path=>true)
PHP:
cl_image_tag("sample", array("overlay"=>"docs:zoom_map", "effect"=>"displace", "x"=>50, "y"=>50, "use_root_path"=>true))
Python:
CloudinaryImage("sample").image(overlay="docs:zoom_map", effect="displace", x=50, y=50, use_root_path=True)
Node.js:
cloudinary.image("sample", {overlay: "docs:zoom_map", effect: "displace", x: 50, y: 50, use_root_path: true})
Java:
cloudinary.url().transformation(new Transformation().overlay(new Layer().publicId("docs:zoom_map")).effect("displace").x(50).y(50)).useRootPath(true).imageTag("sample");
JS:
cloudinary.imageTag('sample', {overlay: new cloudinary.Layer().publicId("docs:zoom_map"), effect: "displace", x: 50, y: 50, useRootPath: true}).toHtml();
jQuery:
$.cloudinary.image("sample", {overlay: new cloudinary.Layer().publicId("docs:zoom_map"), effect: "displace", x: 50, y: 50, use_root_path: true})
React:
<Image publicId="sample" useRootPath="true">
  <Transformation overlay="docs:zoom_map" effect="displace" x="50" y="50" />
</Image>
Angular:
<cl-image public-id="sample" use-root-path="true">
  <cl-transformation overlay="docs:zoom_map" effect="displace" x="50" y="50">
  </cl-transformation>
</cl-image>
.Net:
cloudinary.Api.UrlImgUp.Transform(new Transformation().Overlay(new Layer().PublicId("docs:zoom_map")).Effect("displace").X(50).Y(50)).UseRootPath(true).BuildImageTag("sample")
Android:
MediaManager.get().url().transformation(new Transformation().overlay(new Layer().publicId("docs:zoom_map")).effect("displace").x(50).y(50)).useRootPath(true).generate("sample");
iOS:
imageView.cldSetImage(cloudinary.createUrl().setUseRootPath( true).setTransformation(CLDTransformation().setOverlay("docs:zoom_map").setEffect("displace").setX(50).setY(50)).generate("sample")!, cloudinary: cloudinary)

The next example uses a displacement map to warp the perspective of an overlay image for final placement as an overlay on another image:

Sample image

Ruby:
cl_image_tag("sample", :overlay=>"docs:radialize", :effect=>"displace", :x=>50, :y=>50, :use_root_path=>true)
PHP:
cl_image_tag("sample", array("overlay"=>"docs:radialize", "effect"=>"displace", "x"=>50, "y"=>50, "use_root_path"=>true))
Python:
CloudinaryImage("sample").image(overlay="docs:radialize", effect="displace", x=50, y=50, use_root_path=True)
Node.js:
cloudinary.image("sample", {overlay: "docs:radialize", effect: "displace", x: 50, y: 50, use_root_path: true})
Java:
cloudinary.url().transformation(new Transformation().overlay(new Layer().publicId("docs:radialize")).effect("displace").x(50).y(50)).useRootPath(true).imageTag("sample");
JS:
cloudinary.imageTag('sample', {overlay: new cloudinary.Layer().publicId("docs:radialize"), effect: "displace", x: 50, y: 50, useRootPath: true}).toHtml();
jQuery:
$.cloudinary.image("sample", {overlay: new cloudinary.Layer().publicId("docs:radialize"), effect: "displace", x: 50, y: 50, use_root_path: true})
React:
<Image publicId="sample" useRootPath="true">
  <Transformation overlay="docs:radialize" effect="displace" x="50" y="50" />
</Image>
Angular:
<cl-image public-id="sample" use-root-path="true">
  <cl-transformation overlay="docs:radialize" effect="displace" x="50" y="50">
  </cl-transformation>
</cl-image>
.Net:
cloudinary.Api.UrlImgUp.Transform(new Transformation().Overlay(new Layer().PublicId("docs:radialize")).Effect("displace").X(50).Y(50)).UseRootPath(true).BuildImageTag("sample")
Android:
MediaManager.get().url().transformation(new Transformation().overlay(new Layer().publicId("docs:radialize")).effect("displace").x(50).y(50)).useRootPath(true).generate("sample");
iOS:
imageView.cldSetImage(cloudinary.createUrl().setUseRootPath( true).setTransformation(CLDTransformation().setOverlay("docs:radialize").setEffect("displace").setX(50).setY(50)).generate("sample")!, cloudinary: cloudinary)

Using this overlay transformation for placement on a mug:

Zoom displacement map

Ruby:
cl_image_tag("left_mug", :use_root_path=>true, :transformation=>[
  {:width=>500, :crop=>"scale"},
  {:overlay=>"sample.png", :width=>250, :height=>250, :crop=>"pad"},
  {:overlay=>"radialize"},
  {:flags=>"layer_apply", :effect=>"displace", :y=>-8},
  {:flags=>"layer_apply", :x=>10, :background=>"transparent"}
  ])
PHP:
cl_image_tag("left_mug", array("use_root_path"=>true, "transformation"=>array(
  array("width"=>500, "crop"=>"scale"),
  array("overlay"=>"sample.png", "width"=>250, "height"=>250, "crop"=>"pad"),
  array("overlay"=>"radialize"),
  array("flags"=>"layer_apply", "effect"=>"displace", "y"=>-8),
  array("flags"=>"layer_apply", "x"=>10, "background"=>"transparent")
  )))
Python:
CloudinaryImage("left_mug").image(use_root_path=True, transformation=[
  {'width': 500, 'crop': "scale"},
  {'overlay': "sample.png", 'width': 250, 'height': 250, 'crop': "pad"},
  {'overlay': "radialize"},
  {'flags': "layer_apply", 'effect': "displace", 'y': -8},
  {'flags': "layer_apply", 'x': 10, 'background': "transparent"}
  ])
Node.js:
cloudinary.image("left_mug", {use_root_path: true, transformation: [
  {width: 500, crop: "scale"},
  {overlay: "sample.png", width: 250, height: 250, crop: "pad"},
  {overlay: "radialize"},
  {flags: "layer_apply", effect: "displace", y: -8},
  {flags: "layer_apply", x: 10, background: "transparent"}
  ]})
Java:
cloudinary.url().transformation(new Transformation()
  .width(500).crop("scale").chain()
  .overlay(new Layer().publicId("sample.png")).width(250).height(250).crop("pad").chain()
  .overlay(new Layer().publicId("radialize")).chain()
  .flags("layer_apply").effect("displace").y(-8).chain()
  .flags("layer_apply").x(10).background("transparent")).useRootPath(true).imageTag("left_mug");
JS:
cloudinary.imageTag('left_mug', {useRootPath: true, transformation: [
  {width: 500, crop: "scale"},
  {overlay: new cloudinary.Layer().publicId("sample.png"), width: 250, height: 250, crop: "pad"},
  {overlay: new cloudinary.Layer().publicId("radialize")},
  {flags: "layer_apply", effect: "displace", y: -8},
  {flags: "layer_apply", x: 10, background: "transparent"}
  ]}).toHtml();
jQuery:
$.cloudinary.image("left_mug", {use_root_path: true, transformation: [
  {width: 500, crop: "scale"},
  {overlay: new cloudinary.Layer().publicId("sample.png"), width: 250, height: 250, crop: "pad"},
  {overlay: new cloudinary.Layer().publicId("radialize")},
  {flags: "layer_apply", effect: "displace", y: -8},
  {flags: "layer_apply", x: 10, background: "transparent"}
  ]})
React:
<Image publicId="left_mug" useRootPath="true">
  <Transformation width="500" crop="scale" />
  <Transformation overlay="sample.png" width="250" height="250" crop="pad" />
  <Transformation overlay="radialize" />
  <Transformation flags="layer_apply" effect="displace" y="-8" />
  <Transformation flags="layer_apply" x="10" background="transparent" />
</Image>
Angular:
<cl-image public-id="left_mug" use-root-path="true">
  <cl-transformation width="500" crop="scale">
  </cl-transformation>
  <cl-transformation overlay="sample.png" width="250" height="250" crop="pad">
  </cl-transformation>
  <cl-transformation overlay="radialize">
  </cl-transformation>
  <cl-transformation flags="layer_apply" effect="displace" y="-8">
  </cl-transformation>
  <cl-transformation flags="layer_apply" x="10" background="transparent">
  </cl-transformation>
</cl-image>
.Net:
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Width(500).Crop("scale").Chain()
  .Overlay(new Layer().PublicId("sample.png")).Width(250).Height(250).Crop("pad").Chain()
  .Overlay(new Layer().PublicId("radialize")).Chain()
  .Flags("layer_apply").Effect("displace").Y(-8).Chain()
  .Flags("layer_apply").X(10).Background("transparent")).UseRootPath(true).BuildImageTag("left_mug")
Android:
MediaManager.get().url().transformation(new Transformation()
  .width(500).crop("scale").chain()
  .overlay(new Layer().publicId("sample.png")).width(250).height(250).crop("pad").chain()
  .overlay(new Layer().publicId("radialize")).chain()
  .flags("layer_apply").effect("displace").y(-8).chain()
  .flags("layer_apply").x(10).background("transparent")).useRootPath(true).generate("left_mug");
iOS:
imageView.cldSetImage(cloudinary.createUrl().setUseRootPath( true).setTransformation(CLDTransformation()
  .setWidth(500).setCrop("scale").chain()
  .setOverlay("sample.png").setWidth(250).setHeight(250).setCrop("pad").chain()
  .setOverlay("radialize").chain()
  .setFlags("layer_apply").setEffect("displace").setY(-8).chain()
  .setFlags("layer_apply").setX(10).setBackground("transparent")).generate("left_mug")!, cloudinary: cloudinary)

The Displacement Effect

The displacement effect is controlled by a few configurable parameters that allow you to fine tune the desired result. The dynamic URL for the final image includes:

  • The public_id of the base image.
  • The public_id of the image map to use as a displacement template, added using the overlay parameter (l in URLs).
  • The effect parameter set to displace (e_displace in URLs), which tells Cloudinary to use the image map as a displacement effect rather than adding it as an overlay.
  • The x and y parameters to configure the maximum allowed displacement in the horizontal and vertical directions (negative values for left and up respectively, 0 for no displacement).

The final displacement of each pixel in the base image is determined by a combination of the red and green color channels, together with the configured x and y parameters. For example, for a given x value of 20 and a pixel with a red value of 255 (highest), the corresponding base image pixel would be displaced by 20 pixels horizontally, while a red value of 25 (10%) would only displace the base image pixel by 2 pixels horizontally.

The following example demonstrates the zoom displacement map shown above (along with an overlay of a magnifying glass) to "magnify" the base image.

Ruby:
cl_image_tag("woman.jpg", :use_root_path=>true, :transformation=>[
  {:width=>500, :height=>500, :crop=>"fill"},
  {:overlay=>"woman", :width=>500, :height=>500, :crop=>"fill"},
  {:width=>200, :height=>200, :x=>20, :y=>20, :crop=>"crop"},
  {:width=>200, :height=>200, :overlay=>"docs:zoom_map", :crop=>"fill"},
  {:flags=>"layer_apply", :effect=>"displace", :x=>20, :y=>20},
  {:flags=>"layer_apply", :gravity=>"north_west", :x=>20, :y=>20},
  {:overlay=>"mag-glass.png", :width=>330, :height=>215, :gravity=>"north_west", :x=>38, :y=>38, :flags=>"no_overflow"}
  ])
PHP:
cl_image_tag("woman.jpg", array("use_root_path"=>true, "transformation"=>array(
  array("width"=>500, "height"=>500, "crop"=>"fill"),
  array("overlay"=>"woman", "width"=>500, "height"=>500, "crop"=>"fill"),
  array("width"=>200, "height"=>200, "x"=>20, "y"=>20, "crop"=>"crop"),
  array("width"=>200, "height"=>200, "overlay"=>"docs:zoom_map", "crop"=>"fill"),
  array("flags"=>"layer_apply", "effect"=>"displace", "x"=>20, "y"=>20),
  array("flags"=>"layer_apply", "gravity"=>"north_west", "x"=>20, "y"=>20),
  array("overlay"=>"mag-glass.png", "width"=>330, "height"=>215, "gravity"=>"north_west", "x"=>38, "y"=>38, "flags"=>"no_overflow")
  )))
Python:
CloudinaryImage("woman.jpg").image(use_root_path=True, transformation=[
  {'width': 500, 'height': 500, 'crop': "fill"},
  {'overlay': "woman", 'width': 500, 'height': 500, 'crop': "fill"},
  {'width': 200, 'height': 200, 'x': 20, 'y': 20, 'crop': "crop"},
  {'width': 200, 'height': 200, 'overlay': "docs:zoom_map", 'crop': "fill"},
  {'flags': "layer_apply", 'effect': "displace", 'x': 20, 'y': 20},
  {'flags': "layer_apply", 'gravity': "north_west", 'x': 20, 'y': 20},
  {'overlay': "mag-glass.png", 'width': 330, 'height': 215, 'gravity': "north_west", 'x': 38, 'y': 38, 'flags': "no_overflow"}
  ])
Node.js:
cloudinary.image("woman.jpg", {use_root_path: true, transformation: [
  {width: 500, height: 500, crop: "fill"},
  {overlay: "woman", width: 500, height: 500, crop: "fill"},
  {width: 200, height: 200, x: 20, y: 20, crop: "crop"},
  {width: 200, height: 200, overlay: "docs:zoom_map", crop: "fill"},
  {flags: "layer_apply", effect: "displace", x: 20, y: 20},
  {flags: "layer_apply", gravity: "north_west", x: 20, y: 20},
  {overlay: "mag-glass.png", width: 330, height: 215, gravity: "north_west", x: 38, y: 38, flags: "no_overflow"}
  ]})
Java:
cloudinary.url().transformation(new Transformation()
  .width(500).height(500).crop("fill").chain()
  .overlay(new Layer().publicId("woman")).width(500).height(500).crop("fill").chain()
  .width(200).height(200).x(20).y(20).crop("crop").chain()
  .width(200).height(200).overlay(new Layer().publicId("docs:zoom_map")).crop("fill").chain()
  .flags("layer_apply").effect("displace").x(20).y(20).chain()
  .flags("layer_apply").gravity("north_west").x(20).y(20).chain()
  .overlay(new Layer().publicId("mag-glass.png")).width(330).height(215).gravity("north_west").x(38).y(38).flags("no_overflow")).useRootPath(true).imageTag("woman.jpg");
JS:
cloudinary.imageTag('woman.jpg', {useRootPath: true, transformation: [
  {width: 500, height: 500, crop: "fill"},
  {overlay: new cloudinary.Layer().publicId("woman"), width: 500, height: 500, crop: "fill"},
  {width: 200, height: 200, x: 20, y: 20, crop: "crop"},
  {width: 200, height: 200, overlay: new cloudinary.Layer().publicId("docs:zoom_map"), crop: "fill"},
  {flags: "layer_apply", effect: "displace", x: 20, y: 20},
  {flags: "layer_apply", gravity: "north_west", x: 20, y: 20},
  {overlay: new cloudinary.Layer().publicId("mag-glass.png"), width: 330, height: 215, gravity: "north_west", x: 38, y: 38, flags: "no_overflow"}
  ]}).toHtml();
jQuery:
$.cloudinary.image("woman.jpg", {use_root_path: true, transformation: [
  {width: 500, height: 500, crop: "fill"},
  {overlay: new cloudinary.Layer().publicId("woman"), width: 500, height: 500, crop: "fill"},
  {width: 200, height: 200, x: 20, y: 20, crop: "crop"},
  {width: 200, height: 200, overlay: new cloudinary.Layer().publicId("docs:zoom_map"), crop: "fill"},
  {flags: "layer_apply", effect: "displace", x: 20, y: 20},
  {flags: "layer_apply", gravity: "north_west", x: 20, y: 20},
  {overlay: new cloudinary.Layer().publicId("mag-glass.png"), width: 330, height: 215, gravity: "north_west", x: 38, y: 38, flags: "no_overflow"}
  ]})
React:
<Image publicId="woman.jpg" useRootPath="true">
  <Transformation width="500" height="500" crop="fill" />
  <Transformation overlay="woman" width="500" height="500" crop="fill" />
  <Transformation width="200" height="200" x="20" y="20" crop="crop" />
  <Transformation width="200" height="200" overlay="docs:zoom_map" crop="fill" />
  <Transformation flags="layer_apply" effect="displace" x="20" y="20" />
  <Transformation flags="layer_apply" gravity="north_west" x="20" y="20" />
  <Transformation overlay="mag-glass.png" width="330" height="215" gravity="north_west" x="38" y="38" flags="no_overflow" />
</Image>
Angular:
<cl-image public-id="woman.jpg" use-root-path="true">
  <cl-transformation width="500" height="500" crop="fill">
  </cl-transformation>
  <cl-transformation overlay="woman" width="500" height="500" crop="fill">
  </cl-transformation>
  <cl-transformation width="200" height="200" x="20" y="20" crop="crop">
  </cl-transformation>
  <cl-transformation width="200" height="200" overlay="docs:zoom_map" crop="fill">
  </cl-transformation>
  <cl-transformation flags="layer_apply" effect="displace" x="20" y="20">
  </cl-transformation>
  <cl-transformation flags="layer_apply" gravity="north_west" x="20" y="20">
  </cl-transformation>
  <cl-transformation overlay="mag-glass.png" width="330" height="215" gravity="north_west" x="38" y="38" flags="no_overflow">
  </cl-transformation>
</cl-image>
.Net:
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Width(500).Height(500).Crop("fill").Chain()
  .Overlay(new Layer().PublicId("woman")).Width(500).Height(500).Crop("fill").Chain()
  .Width(200).Height(200).X(20).Y(20).Crop("crop").Chain()
  .Width(200).Height(200).Overlay(new Layer().PublicId("docs:zoom_map")).Crop("fill").Chain()
  .Flags("layer_apply").Effect("displace").X(20).Y(20).Chain()
  .Flags("layer_apply").Gravity("north_west").X(20).Y(20).Chain()
  .Overlay(new Layer().PublicId("mag-glass.png")).Width(330).Height(215).Gravity("north_west").X(38).Y(38).Flags("no_overflow")).UseRootPath(true).BuildImageTag("woman.jpg")
Android:
MediaManager.get().url().transformation(new Transformation()
  .width(500).height(500).crop("fill").chain()
  .overlay(new Layer().publicId("woman")).width(500).height(500).crop("fill").chain()
  .width(200).height(200).x(20).y(20).crop("crop").chain()
  .width(200).height(200).overlay(new Layer().publicId("docs:zoom_map")).crop("fill").chain()
  .flags("layer_apply").effect("displace").x(20).y(20).chain()
  .flags("layer_apply").gravity("north_west").x(20).y(20).chain()
  .overlay(new Layer().publicId("mag-glass.png")).width(330).height(215).gravity("north_west").x(38).y(38).flags("no_overflow")).useRootPath(true).generate("woman.jpg");
iOS:
imageView.cldSetImage(cloudinary.createUrl().setUseRootPath( true).setTransformation(CLDTransformation()
  .setWidth(500).setHeight(500).setCrop("fill").chain()
  .setOverlay("woman").setWidth(500).setHeight(500).setCrop("fill").chain()
  .setWidth(200).setHeight(200).setX(20).setY(20).setCrop("crop").chain()
  .setWidth(200).setHeight(200).setOverlay("docs:zoom_map").setCrop("fill").chain()
  .setFlags("layer_apply").setEffect("displace").setX(20).setY(20).chain()
  .setFlags("layer_apply").setGravity("north_west").setX(20).setY(20).chain()
  .setOverlay("mag-glass.png").setWidth(330).setHeight(215).setGravity("north_west").setX(38).setY(38).setFlags("no_overflow")).generate("woman.jpg")!, cloudinary: cloudinary)
zoomed in image

Custom Art Effects

Any image can be used as a displacement map, even if it hasn't been specifically created for that purpose. Most of the time, using a photograph as a map will give some surreal effects, but if you use a photograph with a (semi) repeating pattern, you can actually end up with some nice new texture effects. The following interactive example allows you to combine a base picture with various image "textures":

1  Select the strength of the distortion effect:    

2  Pick an image to use as a distortion effect

water pebbles concrete

3  Press the button!

Adapting Overlays to a Non-smooth Surface

Another more practical case for using the displacement effect is to make an overlay appear more realistic when placing it over an object with its own texture, making the overlay seem like its actually part of that object itself. This can be very useful for generating customized eCommerce images.

This can be achieved by using the base image itself as a displacement map for the overlay. For example, below we've added an overlay to a sweater, using the sweater itself as a displacement map for the overlay:

Ruby:
cl_image_tag("docs/bulls.png", :transformation=>[
  {:width=>490, :opacity=>80, :crop=>"scale"},
  {:height=>2.0, :width=>1.0, :crop=>"pad"},
  {:overlay=>"docs:sweater", :effect=>"displace", :y=>-8},
  {:effect=>"trim"},
  {:underlay=>"docs:sweater", :width=>690}
  ])
PHP:
cl_image_tag("docs/bulls.png", array("transformation"=>array(
  array("width"=>490, "opacity"=>80, "crop"=>"scale"),
  array("height"=>2.0, "width"=>1.0, "crop"=>"pad"),
  array("overlay"=>"docs:sweater", "effect"=>"displace", "y"=>-8),
  array("effect"=>"trim"),
  array("underlay"=>"docs:sweater", "width"=>690)
  )))
Python:
CloudinaryImage("docs/bulls.png").image(transformation=[
  {'width': 490, 'opacity': 80, 'crop': "scale"},
  {'height': 2.0, 'width': 1.0, 'crop': "pad"},
  {'overlay': "docs:sweater", 'effect': "displace", 'y': -8},
  {'effect': "trim"},
  {'underlay': "docs:sweater", 'width': 690}
  ])
Node.js:
cloudinary.image("docs/bulls.png", {transformation: [
  {width: 490, opacity: 80, crop: "scale"},
  {height: "2.0", width: "1.0", crop: "pad"},
  {overlay: "docs:sweater", effect: "displace", y: -8},
  {effect: "trim"},
  {underlay: "docs:sweater", width: 690}
  ]})
Java:
cloudinary.url().transformation(new Transformation()
  .width(490).opacity(80).crop("scale").chain()
  .height(2.0).width(1.0).crop("pad").chain()
  .overlay(new Layer().publicId("docs:sweater")).effect("displace").y(-8).chain()
  .effect("trim").chain()
  .underlay(new Layer().publicId("docs:sweater")).width(690)).imageTag("docs/bulls.png");
JS:
cloudinary.imageTag('docs/bulls.png', {transformation: [
  {width: 490, opacity: 80, crop: "scale"},
  {height: "2.0", width: "1.0", crop: "pad"},
  {overlay: new cloudinary.Layer().publicId("docs:sweater"), effect: "displace", y: -8},
  {effect: "trim"},
  {underlay: new cloudinary.Layer().publicId("docs:sweater"), width: 690}
  ]}).toHtml();
jQuery:
$.cloudinary.image("docs/bulls.png", {transformation: [
  {width: 490, opacity: 80, crop: "scale"},
  {height: "2.0", width: "1.0", crop: "pad"},
  {overlay: new cloudinary.Layer().publicId("docs:sweater"), effect: "displace", y: -8},
  {effect: "trim"},
  {underlay: new cloudinary.Layer().publicId("docs:sweater"), width: 690}
  ]})
React:
<Image publicId="docs/bulls.png" >
  <Transformation width="490" opacity="80" crop="scale" />
  <Transformation height="2.0" width="1.0" crop="pad" />
  <Transformation overlay="docs:sweater" effect="displace" y="-8" />
  <Transformation effect="trim" />
  <Transformation underlay="docs:sweater" width="690" />
</Image>
Angular:
<cl-image public-id="docs/bulls.png" >
  <cl-transformation width="490" opacity="80" crop="scale">
  </cl-transformation>
  <cl-transformation height="2.0" width="1.0" crop="pad">
  </cl-transformation>
  <cl-transformation overlay="docs:sweater" effect="displace" y="-8">
  </cl-transformation>
  <cl-transformation effect="trim">
  </cl-transformation>
  <cl-transformation underlay="docs:sweater" width="690">
  </cl-transformation>
</cl-image>
.Net:
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Width(490).Opacity(80).Crop("scale").Chain()
  .Height(2.0).Width(1.0).Crop("pad").Chain()
  .Overlay(new Layer().PublicId("docs:sweater")).Effect("displace").Y(-8).Chain()
  .Effect("trim").Chain()
  .Underlay(new Layer().PublicId("docs:sweater")).Width(690)).BuildImageTag("docs/bulls.png")
Android:
MediaManager.get().url().transformation(new Transformation()
  .width(490).opacity(80).crop("scale").chain()
  .height(2.0).width(1.0).crop("pad").chain()
  .overlay(new Layer().publicId("docs:sweater")).effect("displace").y(-8).chain()
  .effect("trim").chain()
  .underlay(new Layer().publicId("docs:sweater")).width(690)).generate("docs/bulls.png");
iOS:
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setWidth(490).setOpacity(80).setCrop("scale").chain()
  .setHeight(2.0).setWidth(1.0).setCrop("pad").chain()
  .setOverlay("docs:sweater").setEffect("displace").setY(-8).chain()
  .setEffect("trim").chain()
  .setUnderlay("docs:sweater").setWidth(690)).generate("docs/bulls.png")!, cloudinary: cloudinary)
Adapting overlay to a surface

Final Displacements

Displacement maps can be a useful addition to your arsenal of image manipulations. They allow you to customize your images in interesting ways and add realistic effects. This capability is already being used by our customers to displace images overlays, and as shown in this post, can also be used in multiple, perhaps unexpected ways. The feature is available for use with all Cloudinary accounts, including the free tier.

Recent Blog Posts

Converting Videos to GIFs in Kotlin-Based Android Apps

Among the image formats available today, Graphics Interchange Format (GIF) works for both static and animated images. A popular use of GIF images—commonly called GIFs—is to repeatedly loop motions, which you cannot in real life. Many people have turned themselves into online celebrities through effective application of GIFs.

Read more
Simple Steps to Make Your Site Accessible With Cloudinary

Web accessibility (a11y) is about gaining an insight into—

It’s a blurry line between accessibility and usability (or user experience) and one might argue that they are actually the same thing. Nonetheless, if your audience can't use your app with ease and confidence, then it’s not accessible enough and the user experience is not good enough.

Read more
Learn three ways in which to tell appealing stories on video.

Video storytelling is one of the most effective means of conveying messages to your audience. It’s also a popular marketing tool because most people are automatically drawn to video. In eCommerce, if accompanied by attractive images and a compelling narrative, video storytelling uniquely connect with potential customers without fail.

Read more