> ## Documentation Index
> Fetch the complete documentation index at: https://cloudinary.com/documentation/llms.txt
> Use this file to discover all available pages before exploring further.

# Underlays, watermarking, and special effects


[remote_image_overlays]: layers#remote_image_overlays

This page covers image underlays, watermarking, and special layer applications for images. For the layer syntax itself, see [Layer syntax](layers). For applying transformations to layers, see [Transforming layers](image_layer_transformations). For text layer options, see [Text layer options](image_text_layers).

## Image underlays
Add an underlay image under a partially transparent base image with the `underlay` parameter (`u` in URLs) and the public ID of a previously uploaded image (e.g., `u_background` for an image with the public ID of `background`), with the following general syntax.

```
u_<public_id of layer>/<optional layer transformations>/fl_layer_apply,<optional placement qualifiers>
```

You can determine the dimension of the underlay using width and height, and adjust the location of the base image over the underlay using the gravity parameter and the x and y parameters. The underlay can also be [further transformed](transformation_reference) like any other image uploaded to Cloudinary, and the underlay parameter supports the same features as for overlays as described above.

For example, add an underlay of an image called `site_bg` to the base image. The underlay and base image are both resized to the same width and height, and the brightness is increased to 100 using the brightness effect (`c_fill,h_200,w_200/u_site_bg/c_scale,h_200,w_200/e_brightness:100/fl_layer_apply`):

![Image with underlay](https://res.cloudinary.com/demo/image/upload/c_fill,h_200,w_200/u_site_bg/c_scale,h_200,w_200/e_brightness:100/fl_layer_apply/smartphone.png)

```nodejs
cloudinary.image("smartphone.png", {transformation: [
  {height: 200, width: 200, crop: "fill"},
  {underlay: "site_bg"},
  {height: 200, width: 200, crop: "scale"},
  {effect: "brightness:100"},
  {flags: "layer_apply"}
  ]})
```

```react
import { fill, scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { brightness } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryImage("smartphone.png")
  .resize(fill().width(200).height(200))
  .underlay(
    source(
      image("site_bg").transformation(
        new Transformation()
          .resize(scale().width(200).height(200))
          .adjust(brightness().level(100))
      )
    )
  );
```

```vue
import { fill, scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { brightness } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryImage("smartphone.png")
  .resize(fill().width(200).height(200))
  .underlay(
    source(
      image("site_bg").transformation(
        new Transformation()
          .resize(scale().width(200).height(200))
          .adjust(brightness().level(100))
      )
    )
  );
```

```angular
import { fill, scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { brightness } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryImage("smartphone.png")
  .resize(fill().width(200).height(200))
  .underlay(
    source(
      image("site_bg").transformation(
        new Transformation()
          .resize(scale().width(200).height(200))
          .adjust(brightness().level(100))
      )
    )
  );
```

```js
import { fill, scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { brightness } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryImage("smartphone.png")
  .resize(fill().width(200).height(200))
  .underlay(
    source(
      image("site_bg").transformation(
        new Transformation()
          .resize(scale().width(200).height(200))
          .adjust(brightness().level(100))
      )
    )
  );
```

```python
CloudinaryImage("smartphone.png").image(transformation=[
  {'height': 200, 'width': 200, 'crop': "fill"},
  {'underlay': "site_bg"},
  {'height': 200, 'width': 200, 'crop': "scale"},
  {'effect': "brightness:100"},
  {'flags': "layer_apply"}
  ])
```

```php
use Cloudinary\Transformation\Resize;
use Cloudinary\Transformation\Underlay;
use Cloudinary\Transformation\Adjust;
use Cloudinary\Transformation\Source;

(new ImageTag('smartphone.png'))
	->resize(Resize::fill()->width(200)
->height(200))
	->underlay(Underlay::source(
	Source::image("site_bg")
	->transformation((new Transformation())
	->resize(Resize::scale()->width(200)
->height(200))
	->adjust(Adjust::brightness()->level(100)))
	));
```

```java
cloudinary.url().transformation(new Transformation()
  .height(200).width(200).crop("fill").chain()
  .underlay(new Layer().publicId("site_bg")).chain()
  .height(200).width(200).crop("scale").chain()
  .effect("brightness:100").chain()
  .flags("layer_apply")).imageTag("smartphone.png");
```

```ruby
cl_image_tag("smartphone.png", transformation: [
  {height: 200, width: 200, crop: "fill"},
  {underlay: "site_bg"},
  {height: 200, width: 200, crop: "scale"},
  {effect: "brightness:100"},
  {flags: "layer_apply"}
  ])
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Height(200).Width(200).Crop("fill").Chain()
  .Underlay(new Layer().PublicId("site_bg")).Chain()
  .Height(200).Width(200).Crop("scale").Chain()
  .Effect("brightness:100").Chain()
  .Flags("layer_apply")).BuildImageTag("smartphone.png")
```

```dart
cloudinary.image('smartphone.png').transformation(Transformation()
	.resize(Resize.fill().width(200)
.height(200))
	.underlay(Underlay.source(
	Source.image("site_bg")
	.transformation(new Transformation()
	.resize(Resize.scale().width(200)
.height(200))
	.adjust(Adjust.brightness().level(100)))
	)));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setHeight(200).setWidth(200).setCrop("fill").chain()
  .setUnderlay("site_bg").chain()
  .setHeight(200).setWidth(200).setCrop("scale").chain()
  .setEffect("brightness:100").chain()
  .setFlags("layer_apply")).generate("smartphone.png")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation()
  .height(200).width(200).crop("fill").chain()
  .underlay(new Layer().publicId("site_bg")).chain()
  .height(200).width(200).crop("scale").chain()
  .effect("brightness:100").chain()
  .flags("layer_apply")).generate("smartphone.png");
```

```flutter
cloudinary.image('smartphone.png').transformation(Transformation()
	.resize(Resize.fill().width(200)
.height(200))
	.underlay(Underlay.source(
	Source.image("site_bg")
	.transformation(new Transformation()
	.resize(Resize.scale().width(200)
.height(200))
	.adjust(Adjust.brightness().level(100)))
	)));
```

```kotlin
cloudinary.image {
	publicId("smartphone.png")
	 resize(Resize.fill() { width(200)
 height(200) })
	 underlay(Underlay.source(
	Source.image("site_bg") {
	 transformation(Transformation {
	 resize(Resize.scale() { width(200)
 height(200) })
	 adjust(Adjust.brightness() { level(100) }) })
	 })) 
}.generate()
```

```jquery
$.cloudinary.image("smartphone.png", {transformation: [
  {height: 200, width: 200, crop: "fill"},
  {underlay: new cloudinary.Layer().publicId("site_bg")},
  {height: 200, width: 200, crop: "scale"},
  {effect: "brightness:100"},
  {flags: "layer_apply"}
  ]})
```

```react_native
import { fill, scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { brightness } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryImage("smartphone.png")
  .resize(fill().width(200).height(200))
  .underlay(
    source(
      image("site_bg").transformation(
        new Transformation()
          .resize(scale().width(200).height(200))
          .adjust(brightness().level(100))
      )
    )
  );
```

![Video with underlay](https://res.cloudinary.com/demo/video/upload/c_fill,h_200,w_200/u_site_bg/c_scale,h_200,w_200/e_brightness:100/fl_layer_apply/docs/transparent_talking.webm)

```nodejs
cloudinary.video("docs/transparent_talking", {transformation: [
  {height: 200, width: 200, crop: "fill"},
  {underlay: "site_bg"},
  {height: 200, width: 200, crop: "scale"},
  {effect: "brightness:100"},
  {flags: "layer_apply"}
  ]})
```

```react
import { fill, scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { brightness } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryVideo("docs/transparent_talking.webm")
  .resize(fill().width(200).height(200))
  .underlay(
    source(
      image("site_bg").transformation(
        new Transformation()
          .resize(scale().width(200).height(200))
          .adjust(brightness().level(100))
      )
    )
  );
```

```vue
import { fill, scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { brightness } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryVideo("docs/transparent_talking.webm")
  .resize(fill().width(200).height(200))
  .underlay(
    source(
      image("site_bg").transformation(
        new Transformation()
          .resize(scale().width(200).height(200))
          .adjust(brightness().level(100))
      )
    )
  );
```

```angular
import { fill, scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { brightness } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryVideo("docs/transparent_talking.webm")
  .resize(fill().width(200).height(200))
  .underlay(
    source(
      image("site_bg").transformation(
        new Transformation()
          .resize(scale().width(200).height(200))
          .adjust(brightness().level(100))
      )
    )
  );
```

```js
import { fill, scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { brightness } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryVideo("docs/transparent_talking.webm")
  .resize(fill().width(200).height(200))
  .underlay(
    source(
      image("site_bg").transformation(
        new Transformation()
          .resize(scale().width(200).height(200))
          .adjust(brightness().level(100))
      )
    )
  );
```

```python
CloudinaryVideo("docs/transparent_talking").video(transformation=[
  {'height': 200, 'width': 200, 'crop': "fill"},
  {'underlay': "site_bg"},
  {'height': 200, 'width': 200, 'crop': "scale"},
  {'effect': "brightness:100"},
  {'flags': "layer_apply"}
  ])
```

```php
use Cloudinary\Transformation\Resize;
use Cloudinary\Transformation\Underlay;
use Cloudinary\Transformation\Adjust;
use Cloudinary\Transformation\Source;

(new VideoTag('docs/transparent_talking.webm'))
	->resize(Resize::fill()->width(200)
->height(200))
	->underlay(Underlay::source(
	Source::image("site_bg")
	->transformation((new Transformation())
	->resize(Resize::scale()->width(200)
->height(200))
	->adjust(Adjust::brightness()->level(100)))
	));
```

```java
cloudinary.url().transformation(new Transformation()
  .height(200).width(200).crop("fill").chain()
  .underlay(new Layer().publicId("site_bg")).chain()
  .height(200).width(200).crop("scale").chain()
  .effect("brightness:100").chain()
  .flags("layer_apply")).videoTag("docs/transparent_talking");
```

```ruby
cl_video_tag("docs/transparent_talking", transformation: [
  {height: 200, width: 200, crop: "fill"},
  {underlay: "site_bg"},
  {height: 200, width: 200, crop: "scale"},
  {effect: "brightness:100"},
  {flags: "layer_apply"}
  ])
```

```csharp
cloudinary.Api.UrlVideoUp.Transform(new Transformation()
  .Height(200).Width(200).Crop("fill").Chain()
  .Underlay(new Layer().PublicId("site_bg")).Chain()
  .Height(200).Width(200).Crop("scale").Chain()
  .Effect("brightness:100").Chain()
  .Flags("layer_apply")).BuildVideoTag("docs/transparent_talking")
```

```dart
cloudinary.video('docs/transparent_talking.webm').transformation(Transformation()
	.resize(Resize.fill().width(200)
.height(200))
	.underlay(Underlay.source(
	Source.image("site_bg")
	.transformation(new Transformation()
	.resize(Resize.scale().width(200)
.height(200))
	.adjust(Adjust.brightness().level(100)))
	)));
```

```swift
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation()
  .setHeight(200).setWidth(200).setCrop("fill").chain()
  .setUnderlay("site_bg").chain()
  .setHeight(200).setWidth(200).setCrop("scale").chain()
  .setEffect("brightness:100").chain()
  .setFlags("layer_apply")).generate("docs/transparent_talking.webm")
```

```android
MediaManager.get().url().transformation(new Transformation()
  .height(200).width(200).crop("fill").chain()
  .underlay(new Layer().publicId("site_bg")).chain()
  .height(200).width(200).crop("scale").chain()
  .effect("brightness:100").chain()
  .flags("layer_apply")).resourceType("video").generate("docs/transparent_talking.webm");
```

```flutter
cloudinary.video('docs/transparent_talking.webm').transformation(Transformation()
	.resize(Resize.fill().width(200)
.height(200))
	.underlay(Underlay.source(
	Source.image("site_bg")
	.transformation(new Transformation()
	.resize(Resize.scale().width(200)
.height(200))
	.adjust(Adjust.brightness().level(100)))
	)));
```

```kotlin
cloudinary.video {
	publicId("docs/transparent_talking.webm")
	 resize(Resize.fill() { width(200)
 height(200) })
	 underlay(Underlay.source(
	Source.image("site_bg") {
	 transformation(Transformation {
	 resize(Resize.scale() { width(200)
 height(200) })
	 adjust(Adjust.brightness() { level(100) }) })
	 })) 
}.generate()
```

```jquery
$.cloudinary.video("docs/transparent_talking", {transformation: [
  {height: 200, width: 200, crop: "fill"},
  {underlay: new cloudinary.Layer().publicId("site_bg")},
  {height: 200, width: 200, crop: "scale"},
  {effect: "brightness:100"},
  {flags: "layer_apply"}
  ]})
```

```react_native
import { fill, scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { brightness } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryVideo("docs/transparent_talking.webm")
  .resize(fill().width(200).height(200))
  .underlay(
    source(
      image("site_bg").transformation(
        new Transformation()
          .resize(scale().width(200).height(200))
          .adjust(brightness().level(100))
      )
    )
  );
```

> **NOTE**: If the public ID of an image includes slashes (e.g., the public ID of an image is `layers/blue`), replace the slashes with colons when using the image as an underlay (e.g., the public ID of the image becomes `layers:blue` when used as an underlay).

**See full syntax**: [u_\<image id\>](transformation_reference#u_image_id) in the _Transformation Reference_.

### Remote image underlays

Similar to [overlaying a remote image][remote_image_overlays], you can underlay a remote image using `u_fetch:<base64 encoded URL>`.

> **NOTE**:
>
> You can only fetch remote **images** for underlays. Fetching remote videos or audio files for use as underlays isn't supported.

For example, add the background image, `https://res.cloudinary.com/demo/image/upload/site_bg` (base64 encoded: `aHR0cHM6Ly9yZXMuY2xvdWRpbmFyeS5jb20vZGVtby9pbWFnZS91cGxvYWQvc2l0ZV9iZw==`), as an underlay, resized to match the size of the base image (`u_fetch:aHR0cHM6Ly9yZXMuY2xvdWRpbmFyeS5jb20vZGVtby9pbWFnZS91cGxvYWQvc2l0ZV9iZw==/c_fill,fl_layer_apply,fl_relative,h_1.0,w_1.0`):

![Fetched image underlay resized to match base image](https://res.cloudinary.com/demo/image/upload/u_fetch:aHR0cHM6Ly9yZXMuY2xvdWRpbmFyeS5jb20vZGVtby9pbWFnZS91cGxvYWQvc2l0ZV9iZw==/c_fill,fl_layer_apply,fl_relative,h_1.0,w_1.0/smartphone.png "thumb: h_150")

```nodejs
cloudinary.image("smartphone.png", {transformation: [
  {underlay: {url: "https://res.cloudinary.com/demo/image/upload/site_bg"}},
  {flags: ["layer_apply", "relative"], height: "1.0", width: "1.0", crop: "fill"}
  ]})
```

```react
import { source } from "@cloudinary/url-gen/actions/underlay";
import { fill } from "@cloudinary/url-gen/actions/resize";
import { fetch } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryImage("smartphone.png").underlay(
  source(
    fetch(
      "https://res.cloudinary.com/demo/image/upload/site_bg"
    ).transformation(
      new Transformation().resize(fill().width("1.0").height("1.0").relative())
    )
  )
);
```

```vue
import { source } from "@cloudinary/url-gen/actions/underlay";
import { fill } from "@cloudinary/url-gen/actions/resize";
import { fetch } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryImage("smartphone.png").underlay(
  source(
    fetch(
      "https://res.cloudinary.com/demo/image/upload/site_bg"
    ).transformation(
      new Transformation().resize(fill().width("1.0").height("1.0").relative())
    )
  )
);
```

```angular
import { source } from "@cloudinary/url-gen/actions/underlay";
import { fill } from "@cloudinary/url-gen/actions/resize";
import { fetch } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryImage("smartphone.png").underlay(
  source(
    fetch(
      "https://res.cloudinary.com/demo/image/upload/site_bg"
    ).transformation(
      new Transformation().resize(fill().width("1.0").height("1.0").relative())
    )
  )
);
```

```js
import { source } from "@cloudinary/url-gen/actions/underlay";
import { fill } from "@cloudinary/url-gen/actions/resize";
import { fetch } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryImage("smartphone.png").underlay(
  source(
    fetch(
      "https://res.cloudinary.com/demo/image/upload/site_bg"
    ).transformation(
      new Transformation().resize(fill().width("1.0").height("1.0").relative())
    )
  )
);
```

```python
CloudinaryImage("smartphone.png").image(transformation=[
  {'underlay': {'url': "https://res.cloudinary.com/demo/image/upload/site_bg"}},
  {'flags': ["layer_apply", "relative"], 'height': "1.0", 'width': "1.0", 'crop': "fill"}
  ])
```

```php
use Cloudinary\Transformation\Underlay;
use Cloudinary\Transformation\Resize;
use Cloudinary\Transformation\Source;

(new ImageTag('smartphone.png'))
	->underlay(Underlay::source(
	Source::fetch("https://res.cloudinary.com/demo/image/upload/site_bg")
	->transformation((new Transformation())
	->resize(Resize::fill()->width(1.0)
->height(1.0)
	->relative()
	))
	));
```

```java
cloudinary.url().transformation(new Transformation()
  .underlay(new FetchLayer().url("https://res.cloudinary.com/demo/image/upload/site_bg")).chain()
  .flags("layer_apply", "relative").height(1.0).width(1.0).crop("fill")).imageTag("smartphone.png");
```

```ruby
cl_image_tag("smartphone.png", transformation: [
  {underlay: {url: "https://res.cloudinary.com/demo/image/upload/site_bg"}},
  {flags: ["layer_apply", "relative"], height: 1.0, width: 1.0, crop: "fill"}
  ])
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Underlay(new FetchLayer("https://res.cloudinary.com/demo/image/upload/site_bg")).Chain()
  .Flags("layer_apply", "relative").Height(1.0).Width(1.0).Crop("fill")).BuildImageTag("smartphone.png")
```

```dart
cloudinary.image('smartphone.png').transformation(Transformation()
	.underlay(Underlay.source(
	Source.fetch("https://res.cloudinary.com/demo/image/upload/site_bg")
	.transformation(new Transformation()
	.resize(Resize.fill().width('1.0')
.height('1.0')
	.relative()
	))
	)));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setUnderlay("fetch:aHR0cHM6Ly9yZXMuY2xvdWRpbmFyeS5jb20vZGVtby9pbWFnZS91cGxvYWQvc2l0ZV9iZw==").chain()
  .setFlags("layer_apply", "relative").setHeight(1.0).setWidth(1.0).setCrop("fill")).generate("smartphone.png")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation()
  .underlay(new FetchLayer().url("https://res.cloudinary.com/demo/image/upload/site_bg")).chain()
  .flags("layer_apply", "relative").height(1.0).width(1.0).crop("fill")).generate("smartphone.png");
```

```flutter
cloudinary.image('smartphone.png').transformation(Transformation()
	.underlay(Underlay.source(
	Source.fetch("https://res.cloudinary.com/demo/image/upload/site_bg")
	.transformation(new Transformation()
	.resize(Resize.fill().width('1.0')
.height('1.0')
	.relative()
	))
	)));
```

```kotlin
cloudinary.image {
	publicId("smartphone.png")
	 underlay(Underlay.source(
	Source.fetch("https://res.cloudinary.com/demo/image/upload/site_bg") {
	 transformation(Transformation {
	 resize(Resize.fill() { width(1.0F)
 height(1.0F)
	 relative()
	 }) })
	 })) 
}.generate()
```

```jquery
$.cloudinary.image("smartphone.png", {transformation: [
  {underlay: new cloudinary.FetchLayer().url("https://res.cloudinary.com/demo/image/upload/site_bg")},
  {flags: ["layer_apply", "relative"], height: "1.0", width: "1.0", crop: "fill"}
  ]})
```

```react_native
import { source } from "@cloudinary/url-gen/actions/underlay";
import { fill } from "@cloudinary/url-gen/actions/resize";
import { fetch } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryImage("smartphone.png").underlay(
  source(
    fetch(
      "https://res.cloudinary.com/demo/image/upload/site_bg"
    ).transformation(
      new Transformation().resize(fill().width("1.0").height("1.0").relative())
    )
  )
);
```

![Fetched image underlay resized to match base video](https://res.cloudinary.com/demo/video/upload/u_fetch:aHR0cHM6Ly9yZXMuY2xvdWRpbmFyeS5jb20vZGVtby9pbWFnZS91cGxvYWQvc2l0ZV9iZw==/c_fill,fl_layer_apply,fl_relative,h_1.0,w_1.0/docs/transparent_talking.webm "thumb: h_150")

```nodejs
cloudinary.video("docs/transparent_talking", {transformation: [
  {underlay: {url: "https://res.cloudinary.com/demo/image/upload/site_bg"}},
  {flags: ["layer_apply", "relative"], height: "1.0", width: "1.0", crop: "fill"}
  ]})
```

```react
import { source } from "@cloudinary/url-gen/actions/underlay";
import { fill } from "@cloudinary/url-gen/actions/resize";
import { fetch } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryVideo("docs/transparent_talking.webm").underlay(
  source(
    fetch(
      "https://res.cloudinary.com/demo/image/upload/site_bg"
    ).transformation(
      new Transformation().resize(fill().width("1.0").height("1.0").relative())
    )
  )
);
```

```vue
import { source } from "@cloudinary/url-gen/actions/underlay";
import { fill } from "@cloudinary/url-gen/actions/resize";
import { fetch } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryVideo("docs/transparent_talking.webm").underlay(
  source(
    fetch(
      "https://res.cloudinary.com/demo/image/upload/site_bg"
    ).transformation(
      new Transformation().resize(fill().width("1.0").height("1.0").relative())
    )
  )
);
```

```angular
import { source } from "@cloudinary/url-gen/actions/underlay";
import { fill } from "@cloudinary/url-gen/actions/resize";
import { fetch } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryVideo("docs/transparent_talking.webm").underlay(
  source(
    fetch(
      "https://res.cloudinary.com/demo/image/upload/site_bg"
    ).transformation(
      new Transformation().resize(fill().width("1.0").height("1.0").relative())
    )
  )
);
```

```js
import { source } from "@cloudinary/url-gen/actions/underlay";
import { fill } from "@cloudinary/url-gen/actions/resize";
import { fetch } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryVideo("docs/transparent_talking.webm").underlay(
  source(
    fetch(
      "https://res.cloudinary.com/demo/image/upload/site_bg"
    ).transformation(
      new Transformation().resize(fill().width("1.0").height("1.0").relative())
    )
  )
);
```

```python
CloudinaryVideo("docs/transparent_talking").video(transformation=[
  {'underlay': {'url': "https://res.cloudinary.com/demo/image/upload/site_bg"}},
  {'flags': ["layer_apply", "relative"], 'height': "1.0", 'width': "1.0", 'crop': "fill"}
  ])
```

```php
use Cloudinary\Transformation\Underlay;
use Cloudinary\Transformation\Resize;
use Cloudinary\Transformation\Source;

(new VideoTag('docs/transparent_talking.webm'))
	->underlay(Underlay::source(
	Source::fetch("https://res.cloudinary.com/demo/image/upload/site_bg")
	->transformation((new Transformation())
	->resize(Resize::fill()->width(1.0)
->height(1.0)
	->relative()
	))
	));
```

```java
cloudinary.url().transformation(new Transformation()
  .underlay(new FetchLayer().url("https://res.cloudinary.com/demo/image/upload/site_bg")).chain()
  .flags("layer_apply", "relative").height(1.0).width(1.0).crop("fill")).videoTag("docs/transparent_talking");
```

```ruby
cl_video_tag("docs/transparent_talking", transformation: [
  {underlay: {url: "https://res.cloudinary.com/demo/image/upload/site_bg"}},
  {flags: ["layer_apply", "relative"], height: 1.0, width: 1.0, crop: "fill"}
  ])
```

```csharp
cloudinary.Api.UrlVideoUp.Transform(new Transformation()
  .Underlay(new FetchLayer("https://res.cloudinary.com/demo/image/upload/site_bg")).Chain()
  .Flags("layer_apply", "relative").Height(1.0).Width(1.0).Crop("fill")).BuildVideoTag("docs/transparent_talking")
```

```dart
cloudinary.video('docs/transparent_talking.webm').transformation(Transformation()
	.underlay(Underlay.source(
	Source.fetch("https://res.cloudinary.com/demo/image/upload/site_bg")
	.transformation(new Transformation()
	.resize(Resize.fill().width('1.0')
.height('1.0')
	.relative()
	))
	)));
```

```swift
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation()
  .setUnderlay("fetch:aHR0cHM6Ly9yZXMuY2xvdWRpbmFyeS5jb20vZGVtby9pbWFnZS91cGxvYWQvc2l0ZV9iZw==").chain()
  .setFlags("layer_apply", "relative").setHeight(1.0).setWidth(1.0).setCrop("fill")).generate("docs/transparent_talking.webm")
```

```android
MediaManager.get().url().transformation(new Transformation()
  .underlay(new FetchLayer().url("https://res.cloudinary.com/demo/image/upload/site_bg")).chain()
  .flags("layer_apply", "relative").height(1.0).width(1.0).crop("fill")).resourceType("video").generate("docs/transparent_talking.webm");
```

```flutter
cloudinary.video('docs/transparent_talking.webm').transformation(Transformation()
	.underlay(Underlay.source(
	Source.fetch("https://res.cloudinary.com/demo/image/upload/site_bg")
	.transformation(new Transformation()
	.resize(Resize.fill().width('1.0')
.height('1.0')
	.relative()
	))
	)));
```

```kotlin
cloudinary.video {
	publicId("docs/transparent_talking.webm")
	 underlay(Underlay.source(
	Source.fetch("https://res.cloudinary.com/demo/image/upload/site_bg") {
	 transformation(Transformation {
	 resize(Resize.fill() { width(1.0F)
 height(1.0F)
	 relative()
	 }) })
	 })) 
}.generate()
```

```jquery
$.cloudinary.video("docs/transparent_talking", {transformation: [
  {underlay: new cloudinary.FetchLayer().url("https://res.cloudinary.com/demo/image/upload/site_bg")},
  {flags: ["layer_apply", "relative"], height: "1.0", width: "1.0", crop: "fill"}
  ]})
```

```react_native
import { source } from "@cloudinary/url-gen/actions/underlay";
import { fill } from "@cloudinary/url-gen/actions/resize";
import { fetch } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryVideo("docs/transparent_talking.webm").underlay(
  source(
    fetch(
      "https://res.cloudinary.com/demo/image/upload/site_bg"
    ).transformation(
      new Transformation().resize(fill().width("1.0").height("1.0").relative())
    )
  )
);
```

> **NOTE**: The Cloudinary SDKs automatically generate a base64 encoded URL for a given HTTP/S URL, but if you generate the delivery URL in your own code, then you'll need to supply the fetch URL in base64 encoding with padding.

**See full syntax**: [u_fetch](transformation_reference#u_fetch) in the _Transformation Reference_.

## Watermarking

You can use a standard image layer for the purpose of applying a watermark to any delivered image. [Opacity](transformation_reference#o_opacity) and/or [brightness](transformation_reference#e_brightness) transformations are often applied to image layers when they are used as a watermark.

You can also use automatic tiling and/or the smart anti-removal effect with your layer transformation in order to achieve your watermark requirements.


### Add watermarks with JavaScript video tutorial

Watch this video tutorial to learn how to protect your visual content by adding image and text watermarks using Cloudinary's JavaScript SDK.

  This video is brought to you by Cloudinary's video player - embed your own!Use the controls to set the playback speed, navigate to chapters of interest and select subtitles in your preferred language.
{videoTranscript:publicId=training/Add_a_Watermark_to_a_Photo_in_JavaScript}

#### Tutorial contents This tutorial presents the following topics. Click a timestamp to jump to that part of the video.### Introduction: Why watermarks matter
{table:class=tutorial-bullets}|  | 
| --- | --- |
|{videotime:id=media :min=0 :sec=00 :player=cld} | Watermarks are an essential tool for safeguarding your visual content from unauthorized use. Learn how to protect your images or videos so others can't use them without your consent, and explore how Cloudinary's JavaScript SDK simplifies this process. |

### Real-world example: Watermarks in action
{table:class=tutorial-bullets}|  | 
| --- | --- |
|{videotime:id=media :min=0 :sec=27 :player=cld} | See how platforms like Unsplash use watermarks to protect premium content. In today's digital age, where sharing and accessing visual content has become effortless, ensuring the protection of your creative work is of paramount importance. Watermarks step in as a reliable solution, establishing content authenticity while discouraging unauthorized distribution. |

### Getting started with Cloudinary's JavaScript SDK
{table:class=tutorial-bullets}|  | 
| --- | --- |
|{videotime:id=media :min=0 :sec=58 :player=cld} | Dive into the functionality of Cloudinary's [JavaScript SDK](javascript_integration). This tutorial works with two distinct images: applying an image overlay to the first and a text overlay to the second, demonstrating the flexibility of the overlay method. |

### Implementing an image overlay watermark
{table:class=tutorial-bullets}|  | 
| --- | --- |
|{videotime:id=media :min=1 :sec=07 :player=cld} | Start by focusing on the image overlay approach. Learn how to use Cloudinary's `overlay()` method to add an image source from your Cloudinary account. The image is initially set at 300 pixels by 300 pixels for better visibility. See how to attach a source to the overlay method, which can be either an image or text. |

### Resizing the watermark icon
{table:class=tutorial-bullets}|  | 
| --- | --- |
|{videotime:id=media :min=1 :sec=35 :player=cld} | The Cloudinary icon is a bit large for a watermark, so learn how to resize it to fit snugly. Initiate a new transformation and use the scale option to resize the watermark, setting the height to 55 pixels for optimal visibility without overwhelming the image. |

### Positioning the watermark
{table:class=tutorial-bullets}|  | 
| --- | --- |
|{videotime:id=media :min=1 :sec=54 :player=cld} | Position the watermark by creating a new position object that determines its location through compass direction gravity. Choose `south_east` to place the watermark in the lower right corner of the image, a common position for watermarks that doesn't obstruct the main content. |

**Example code for adding an image overlay watermark:**

```javascript
myImage
  .resize(fill(300, 300))
  .format('auto')
  .overlay(
    source(
      image('samples/cloudinary-icon')
        .transformation(new Transformation()
          .resize(scale().height(55))
        )
    )
    .position(new Position().gravity(compass('south_east')))
  )
```

### Adding a text overlay watermark
{table:class=tutorial-bullets}|  | 
| --- | --- |
|{videotime:id=media :min=2 :sec=07 :player=cld} | Explore adding text as an overlay. Use the overlay method and designate text as the source, then input your preferred text. For this example, the word "Preview" is used, but you can use any text like copyright notices or branding. |

### Styling the text watermark
{table:class=tutorial-bullets}|  | 
| --- | --- |
|{videotime:id=media :min=2 :sec=21 :player=cld} | Refine the text watermark's appearance by selecting a font and text size (Arial 60). For a more stylized look reminiscent of a stock image watermark, bold the text using font weight and adjust the text color to a subdued gray tone for a professional appearance. |

### Adding opacity for subtle watermarks
{table:class=tutorial-bullets}|  | 
| --- | --- |
|{videotime:id=media :min=2 :sec=40 :player=cld} | Introduce the opacity attribute by creating a new transformation to control transparency. Adjust the opacity and set it to 70% to create a subtle watermark that protects content without being too obtrusive. This transparency effect is perfect for maintaining image aesthetics while ensuring protection. |

**Example code for adding a text overlay watermark with styling:**

```javascript
mySecondImage
  .resize(fill(300, 300))
  .format('auto')
  .overlay(
    source(
      text('PREVIEW', new TextStyle('arial', 60)
        .fontWeight('bold'))
        .textColor('gray')
        .transformation(new Transformation().adjust(opacity(70)))
    )
  )
```

### Summary: Watermarking made easy
{table:class=tutorial-bullets}|  | 
| --- | --- |
|{videotime:id=media :min=3 :sec=03 :player=cld} | Incorporating watermarks into your images is a breeze using the overlay method from Cloudinary's JavaScript SDK. Use either text or image as the source. For images, provide the path to a chosen Cloudinary asset, resize it, and position it. For text, customize with font weight, color, and add transparency effects. Just like that, you've successfully applied watermarks to protect your visual content. |


### Automatic tiling

Instead of adding your watermark layer to a single, specific location, you can tile layer image over the entire base image by adding the `tiled` qualifier (`fl_tiled` in URLs). The `tiled` flag is added in the same component as the `layer_apply` flag. For example, tiling an overlay of the image called `cloudinary_icon_white` on to the base image (`l_cloudinary_icon_white/fl_layer_apply,fl_tiled`):

![Image with tiled overlay](https://res.cloudinary.com/demo/image/upload/l_cloudinary_icon_white/fl_layer_apply,fl_tiled/leather_bag.jpg "thumb: w_400")

```nodejs
cloudinary.image("leather_bag.jpg", {transformation: [
  {overlay: "cloudinary_icon_white"},
  {flags: ["layer_apply", "tiled"]}
  ]})
```

```react
import { source } from "@cloudinary/url-gen/actions/overlay";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";

new CloudinaryImage("leather_bag.jpg").overlay(
  source(image("cloudinary_icon_white")).position(new Position().tiled())
);
```

```vue
import { source } from "@cloudinary/url-gen/actions/overlay";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";

new CloudinaryImage("leather_bag.jpg").overlay(
  source(image("cloudinary_icon_white")).position(new Position().tiled())
);
```

```angular
import { source } from "@cloudinary/url-gen/actions/overlay";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";

new CloudinaryImage("leather_bag.jpg").overlay(
  source(image("cloudinary_icon_white")).position(new Position().tiled())
);
```

```js
import { source } from "@cloudinary/url-gen/actions/overlay";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";

new CloudinaryImage("leather_bag.jpg").overlay(
  source(image("cloudinary_icon_white")).position(new Position().tiled())
);
```

```python
CloudinaryImage("leather_bag.jpg").image(transformation=[
  {'overlay': "cloudinary_icon_white"},
  {'flags': ["layer_apply", "tiled"]}
  ])
```

```php
use Cloudinary\Transformation\Overlay;
use Cloudinary\Transformation\Source;
use Cloudinary\Transformation\Position;

(new ImageTag('leather_bag.jpg'))
	->overlay(Overlay::source(
	Source::image("cloudinary_icon_white"))
	->position((new Position())
	->tiled()
	)
	);
```

```java
cloudinary.url().transformation(new Transformation()
  .overlay(new Layer().publicId("cloudinary_icon_white")).chain()
  .flags("layer_apply", "tiled")).imageTag("leather_bag.jpg");
```

```ruby
cl_image_tag("leather_bag.jpg", transformation: [
  {overlay: "cloudinary_icon_white"},
  {flags: ["layer_apply", "tiled"]}
  ])
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Overlay(new Layer().PublicId("cloudinary_icon_white")).Chain()
  .Flags("layer_apply", "tiled")).BuildImageTag("leather_bag.jpg")
```

```dart
cloudinary.image('leather_bag.jpg').transformation(Transformation()
	.overlay(Overlay.source(
	Source.image("cloudinary_icon_white"))
	.position(Position()
	.tiled()
	)
	));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setOverlay("cloudinary_icon_white").chain()
  .setFlags("layer_apply", "tiled")).generate("leather_bag.jpg")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation()
  .overlay(new Layer().publicId("cloudinary_icon_white")).chain()
  .flags("layer_apply", "tiled")).generate("leather_bag.jpg");
```

```flutter
cloudinary.image('leather_bag.jpg').transformation(Transformation()
	.overlay(Overlay.source(
	Source.image("cloudinary_icon_white"))
	.position(Position()
	.tiled()
	)
	));
```

```kotlin
cloudinary.image {
	publicId("leather_bag.jpg")
	 overlay(Overlay.source(
	Source.image("cloudinary_icon_white")) {
	 position(Position() {
	 tiled()
	 })
	 }) 
}.generate()
```

```jquery
$.cloudinary.image("leather_bag.jpg", {transformation: [
  {overlay: new cloudinary.Layer().publicId("cloudinary_icon_white")},
  {flags: ["layer_apply", "tiled"]}
  ]})
```

```react_native
import { source } from "@cloudinary/url-gen/actions/overlay";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";

new CloudinaryImage("leather_bag.jpg").overlay(
  source(image("cloudinary_icon_white")).position(new Position().tiled())
);
```

To increase the spacing between repeated tiles, add padding to the overlay **before** tiling it. One way to do this is to apply a padding-based resize mode (for example, `c_lpad`) to the overlay, optionally adjust opacity/brightness, and then tile the result with `fl_layer_apply,fl_tiled`.

For example:

![Image with tiled overlay and spacing](https://res.cloudinary.com/demo/image/upload/l_cloudinary_icon,c_lpad,e_brightness:200,o_50,w_1.5/fl_relative,w_0.3/fl_layer_apply,fl_tiled/leather_bag.jpg "thumb: w_400")

```nodejs
cloudinary.image("leather_bag.jpg", {transformation: [
  {overlay: "cloudinary_icon", effect: "brightness:200", opacity: 50, width: "1.5", crop: "lpad"},
  {flags: "relative", width: "0.3", crop: "scale"},
  {flags: ["layer_apply", "tiled"]}
  ]})
```

```react
import { source } from "@cloudinary/url-gen/actions/overlay";
import { limitPad, scale } from "@cloudinary/url-gen/actions/resize";
import { opacity, brightness } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";

new CloudinaryImage("leather_bag.jpg").overlay(
  source(
    image("cloudinary_icon").transformation(
      new Transformation()
        .resize(limitPad().width(1.5))
        .adjust(opacity(50))
        .adjust(brightness().level(200))
        .resize(scale().width(0.3).relative())
    )
  ).position(new Position().tiled())
);
```

```vue
import { source } from "@cloudinary/url-gen/actions/overlay";
import { limitPad, scale } from "@cloudinary/url-gen/actions/resize";
import { opacity, brightness } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";

new CloudinaryImage("leather_bag.jpg").overlay(
  source(
    image("cloudinary_icon").transformation(
      new Transformation()
        .resize(limitPad().width(1.5))
        .adjust(opacity(50))
        .adjust(brightness().level(200))
        .resize(scale().width(0.3).relative())
    )
  ).position(new Position().tiled())
);
```

```angular
import { source } from "@cloudinary/url-gen/actions/overlay";
import { limitPad, scale } from "@cloudinary/url-gen/actions/resize";
import { opacity, brightness } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";

new CloudinaryImage("leather_bag.jpg").overlay(
  source(
    image("cloudinary_icon").transformation(
      new Transformation()
        .resize(limitPad().width(1.5))
        .adjust(opacity(50))
        .adjust(brightness().level(200))
        .resize(scale().width(0.3).relative())
    )
  ).position(new Position().tiled())
);
```

```js
import { source } from "@cloudinary/url-gen/actions/overlay";
import { limitPad, scale } from "@cloudinary/url-gen/actions/resize";
import { opacity, brightness } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";

new CloudinaryImage("leather_bag.jpg").overlay(
  source(
    image("cloudinary_icon").transformation(
      new Transformation()
        .resize(limitPad().width(1.5))
        .adjust(opacity(50))
        .adjust(brightness().level(200))
        .resize(scale().width(0.3).relative())
    )
  ).position(new Position().tiled())
);
```

```python
CloudinaryImage("leather_bag.jpg").image(transformation=[
  {'overlay': "cloudinary_icon", 'effect': "brightness:200", 'opacity': 50, 'width': "1.5", 'crop': "lpad"},
  {'flags': "relative", 'width': "0.3", 'crop': "scale"},
  {'flags': ["layer_apply", "tiled"]}
  ])
```

```php
use Cloudinary\Transformation\Overlay;
use Cloudinary\Transformation\Resize;
use Cloudinary\Transformation\Adjust;
use Cloudinary\Transformation\Source;
use Cloudinary\Transformation\Position;

(new ImageTag('leather_bag.jpg'))
	->overlay(Overlay::source(
	Source::image("cloudinary_icon")
	->transformation((new Transformation())
	->resize(Resize::limitPad()->width(1.5))
	->adjust(Adjust::opacity(50))
	->adjust(Adjust::brightness()->level(200))
	->resize(Resize::scale()->width(0.3)
	->relative()
	))
	)
	->position((new Position())
	->tiled()
	)
	);
```

```java
cloudinary.url().transformation(new Transformation()
  .overlay(new Layer().publicId("cloudinary_icon")).effect("brightness:200").opacity(50).width(1.5).crop("lpad").chain()
  .flags("relative").width(0.3).crop("scale").chain()
  .flags("layer_apply", "tiled")).imageTag("leather_bag.jpg");
```

```ruby
cl_image_tag("leather_bag.jpg", transformation: [
  {overlay: "cloudinary_icon", effect: "brightness:200", opacity: 50, width: 1.5, crop: "lpad"},
  {flags: "relative", width: 0.3, crop: "scale"},
  {flags: ["layer_apply", "tiled"]}
  ])
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Overlay(new Layer().PublicId("cloudinary_icon")).Effect("brightness:200").Opacity(50).Width(1.5).Crop("lpad").Chain()
  .Flags("relative").Width(0.3).Crop("scale").Chain()
  .Flags("layer_apply", "tiled")).BuildImageTag("leather_bag.jpg")
```

```dart
cloudinary.image('leather_bag.jpg').transformation(Transformation()
	.overlay(Overlay.source(
	Source.image("cloudinary_icon")
	.transformation(new Transformation()
	.resize(Resize.limitPad().width(1.5))
	.adjust(Adjust.opacity(50))
	.adjust(Adjust.brightness().level(200))
	.resize(Resize.scale().width(0.3)
	.relative()
	))
	)
	.position(Position()
	.tiled()
	)
	));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setOverlay("cloudinary_icon").setEffect("brightness:200").setOpacity(50).setWidth(1.5).setCrop("lpad").chain()
  .setFlags("relative").setWidth(0.3).setCrop("scale").chain()
  .setFlags("layer_apply", "tiled")).generate("leather_bag.jpg")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation()
  .overlay(new Layer().publicId("cloudinary_icon")).effect("brightness:200").opacity(50).width(1.5).crop("lpad").chain()
  .flags("relative").width(0.3).crop("scale").chain()
  .flags("layer_apply", "tiled")).generate("leather_bag.jpg");
```

```flutter
cloudinary.image('leather_bag.jpg').transformation(Transformation()
	.overlay(Overlay.source(
	Source.image("cloudinary_icon")
	.transformation(new Transformation()
	.resize(Resize.limitPad().width(1.5))
	.adjust(Adjust.opacity(50))
	.adjust(Adjust.brightness().level(200))
	.resize(Resize.scale().width(0.3)
	.relative()
	))
	)
	.position(Position()
	.tiled()
	)
	));
```

```kotlin
cloudinary.image {
	publicId("leather_bag.jpg")
	 overlay(Overlay.source(
	Source.image("cloudinary_icon") {
	 transformation(Transformation {
	 resize(Resize.limitPad() { width(1.5F) })
	 adjust(Adjust.opacity(50))
	 adjust(Adjust.brightness() { level(200) })
	 resize(Resize.scale() { width(0.3F)
	 relative()
	 }) })
	 }) {
	 position(Position() {
	 tiled()
	 })
	 }) 
}.generate()
```

```jquery
$.cloudinary.image("leather_bag.jpg", {transformation: [
  {overlay: new cloudinary.Layer().publicId("cloudinary_icon"), effect: "brightness:200", opacity: 50, width: "1.5", crop: "lpad"},
  {flags: "relative", width: "0.3", crop: "scale"},
  {flags: ["layer_apply", "tiled"]}
  ]})
```

```react_native
import { source } from "@cloudinary/url-gen/actions/overlay";
import { limitPad, scale } from "@cloudinary/url-gen/actions/resize";
import { opacity, brightness } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";

new CloudinaryImage("leather_bag.jpg").overlay(
  source(
    image("cloudinary_icon").transformation(
      new Transformation()
        .resize(limitPad().width(1.5))
        .adjust(opacity(50))
        .adjust(brightness().level(200))
        .resize(scale().width(0.3).relative())
    )
  ).position(new Position().tiled())
);
```

> **NOTE**: Because the overlay is padded before tiling, each repeated tile includes extra transparent area, creating visible "room" between tiles. Adjust the overlay's padding and size to control the spacing and density of the tiled watermark.

### Smart anti-removal 
You can use the anti-removal effect (`e_anti_removal` in URLs) to slightly modify image overlays in a random manner, thus making them much harder to remove (e.g., adding your logo as a watermark to assets). In most cases, the default level of modification is designed to be visually hard to notice, but still difficult to remove cleanly. If needed, you can optionally control the level of distortion that this transformation applies by adding a colon followed by an integer (the higher the number, the more the image is distorted). The `anti_removal` effect is added in the same component as the `layer_apply` flag.

For example, adding the anti-removal effect (with a high level of 90 for demonstration purposes) to an overlay of the image called `cloudinary_icon_blue` added to the north-east corner of the base asset, with the overlay's opacity set to 50% and scaled to a width of 150 pixels (`c_scale,w_500/l_cloudinary_icon_blue/c_scale,w_150/o_50/e_anti_removal:90,fl_layer_apply,g_north_east`):

![Image with anti-removal overlay](https://res.cloudinary.com/demo/image/upload/c_scale,w_500/l_cloudinary_icon_blue/c_scale,w_150/o_50/e_anti_removal:90,fl_layer_apply,g_north_east/leather_bag_gray.jpg)

```nodejs
cloudinary.image("leather_bag_gray.jpg", {transformation: [
  {width: 500, crop: "scale"},
  {overlay: "cloudinary_icon_blue"},
  {width: 150, crop: "scale"},
  {opacity: 50},
  {effect: "anti_removal:90", flags: "layer_apply", gravity: "north_east"}
  ]})
```

```react
import { scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/overlay";
import { opacity } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";
import { antiRemoval } from "@cloudinary/url-gen/qualifiers/blendMode";
import { compass } from "@cloudinary/url-gen/qualifiers/gravity";

new CloudinaryImage("leather_bag_gray.jpg").resize(scale().width(500)).overlay(
  source(
    image("cloudinary_icon_blue").transformation(
      new Transformation().resize(scale().width(150)).adjust(opacity(50))
    )
  )
    .position(new Position().gravity(compass("north_east")))
    .blendMode(antiRemoval(90))
);
```

```vue
import { scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/overlay";
import { opacity } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";
import { antiRemoval } from "@cloudinary/url-gen/qualifiers/blendMode";
import { compass } from "@cloudinary/url-gen/qualifiers/gravity";

new CloudinaryImage("leather_bag_gray.jpg").resize(scale().width(500)).overlay(
  source(
    image("cloudinary_icon_blue").transformation(
      new Transformation().resize(scale().width(150)).adjust(opacity(50))
    )
  )
    .position(new Position().gravity(compass("north_east")))
    .blendMode(antiRemoval(90))
);
```

```angular
import { scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/overlay";
import { opacity } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";
import { antiRemoval } from "@cloudinary/url-gen/qualifiers/blendMode";
import { compass } from "@cloudinary/url-gen/qualifiers/gravity";

new CloudinaryImage("leather_bag_gray.jpg").resize(scale().width(500)).overlay(
  source(
    image("cloudinary_icon_blue").transformation(
      new Transformation().resize(scale().width(150)).adjust(opacity(50))
    )
  )
    .position(new Position().gravity(compass("north_east")))
    .blendMode(antiRemoval(90))
);
```

```js
import { scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/overlay";
import { opacity } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";
import { antiRemoval } from "@cloudinary/url-gen/qualifiers/blendMode";
import { compass } from "@cloudinary/url-gen/qualifiers/gravity";

new CloudinaryImage("leather_bag_gray.jpg").resize(scale().width(500)).overlay(
  source(
    image("cloudinary_icon_blue").transformation(
      new Transformation().resize(scale().width(150)).adjust(opacity(50))
    )
  )
    .position(new Position().gravity(compass("north_east")))
    .blendMode(antiRemoval(90))
);
```

```python
CloudinaryImage("leather_bag_gray.jpg").image(transformation=[
  {'width': 500, 'crop': "scale"},
  {'overlay': "cloudinary_icon_blue"},
  {'width': 150, 'crop': "scale"},
  {'opacity': 50},
  {'effect': "anti_removal:90", 'flags': "layer_apply", 'gravity': "north_east"}
  ])
```

```php
use Cloudinary\Transformation\Resize;
use Cloudinary\Transformation\Overlay;
use Cloudinary\Transformation\Adjust;
use Cloudinary\Transformation\Source;
use Cloudinary\Transformation\Position;
use Cloudinary\Transformation\BlendMode;
use Cloudinary\Transformation\Gravity;
use Cloudinary\Transformation\Compass;

(new ImageTag('leather_bag_gray.jpg'))
	->resize(Resize::scale()->width(500))
	->overlay(Overlay::source(
	Source::image("cloudinary_icon_blue")
	->transformation((new Transformation())
	->resize(Resize::scale()->width(150))
	->adjust(Adjust::opacity(50)))
	)
	->position((new Position())
	->gravity(
	Gravity::compass(
	Compass::northEast()))
	)
	->blendMode(
	BlendMode::antiRemoval(90))
	);
```

```java
cloudinary.url().transformation(new Transformation()
  .width(500).crop("scale").chain()
  .overlay(new Layer().publicId("cloudinary_icon_blue")).chain()
  .width(150).crop("scale").chain()
  .opacity(50).chain()
  .effect("anti_removal:90").flags("layer_apply").gravity("north_east")).imageTag("leather_bag_gray.jpg");
```

```ruby
cl_image_tag("leather_bag_gray.jpg", transformation: [
  {width: 500, crop: "scale"},
  {overlay: "cloudinary_icon_blue"},
  {width: 150, crop: "scale"},
  {opacity: 50},
  {effect: "anti_removal:90", flags: "layer_apply", gravity: "north_east"}
  ])
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Width(500).Crop("scale").Chain()
  .Overlay(new Layer().PublicId("cloudinary_icon_blue")).Chain()
  .Width(150).Crop("scale").Chain()
  .Opacity(50).Chain()
  .Effect("anti_removal:90").Flags("layer_apply").Gravity("north_east")).BuildImageTag("leather_bag_gray.jpg")
```

```dart
cloudinary.image('leather_bag_gray.jpg').transformation(Transformation()
	.addTransformation("c_scale,w_500/l_cloudinary_icon_blue/c_scale,w_150/o_50/e_anti_removal:90,fl_layer_apply,g_north_east"));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setWidth(500).setCrop("scale").chain()
  .setOverlay("cloudinary_icon_blue").chain()
  .setWidth(150).setCrop("scale").chain()
  .setOpacity(50).chain()
  .setEffect("anti_removal:90").setFlags("layer_apply").setGravity("north_east")).generate("leather_bag_gray.jpg")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation()
  .width(500).crop("scale").chain()
  .overlay(new Layer().publicId("cloudinary_icon_blue")).chain()
  .width(150).crop("scale").chain()
  .opacity(50).chain()
  .effect("anti_removal:90").flags("layer_apply").gravity("north_east")).generate("leather_bag_gray.jpg");
```

```flutter
cloudinary.image('leather_bag_gray.jpg').transformation(Transformation()
	.addTransformation("c_scale,w_500/l_cloudinary_icon_blue/c_scale,w_150/o_50/e_anti_removal:90,fl_layer_apply,g_north_east"));
```

```kotlin
cloudinary.image {
	publicId("leather_bag_gray.jpg")
	 resize(Resize.scale() { width(500) })
	 overlay(Overlay.source(
	Source.image("cloudinary_icon_blue") {
	 transformation(Transformation {
	 resize(Resize.scale() { width(150) })
	 adjust(Adjust.opacity(50)) })
	 }) {
	 position(Position() {
	 gravity(
	Gravity.compass(
	Compass.northEast()))
	 })
	 blendMode(
	BlendMode.antiRemoval(90))
	 }) 
}.generate()
```

```jquery
$.cloudinary.image("leather_bag_gray.jpg", {transformation: [
  {width: 500, crop: "scale"},
  {overlay: new cloudinary.Layer().publicId("cloudinary_icon_blue")},
  {width: 150, crop: "scale"},
  {opacity: 50},
  {effect: "anti_removal:90", flags: "layer_apply", gravity: "north_east"}
  ]})
```

```react_native
import { scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/overlay";
import { opacity } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";
import { antiRemoval } from "@cloudinary/url-gen/qualifiers/blendMode";
import { compass } from "@cloudinary/url-gen/qualifiers/gravity";

new CloudinaryImage("leather_bag_gray.jpg").resize(scale().width(500)).overlay(
  source(
    image("cloudinary_icon_blue").transformation(
      new Transformation().resize(scale().width(150)).adjust(opacity(50))
    )
  )
    .position(new Position().gravity(compass("north_east")))
    .blendMode(antiRemoval(90))
);
```

![Video with anti-removal overlay](https://res.cloudinary.com/demo/video/upload/c_scale,w_500/l_cloudinary_icon_blue/c_scale,w_150/o_50/e_anti_removal:90,fl_layer_apply,g_north_east/old_camera.mp4)

```nodejs
cloudinary.video("old_camera", {transformation: [
  {width: 500, crop: "scale"},
  {overlay: "cloudinary_icon_blue"},
  {width: 150, crop: "scale"},
  {opacity: 50},
  {effect: "anti_removal:90", flags: "layer_apply", gravity: "north_east"}
  ]})
```

```react
import { scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/overlay";
import { opacity } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";
import { antiRemoval } from "@cloudinary/url-gen/qualifiers/blendMode";
import { compass } from "@cloudinary/url-gen/qualifiers/gravity";

new CloudinaryVideo("old_camera.mp4").resize(scale().width(500)).overlay(
  source(
    image("cloudinary_icon_blue").transformation(
      new Transformation().resize(scale().width(150)).adjust(opacity(50))
    )
  )
    .position(new Position().gravity(compass("north_east")))
    .blendMode(antiRemoval(90))
);
```

```vue
import { scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/overlay";
import { opacity } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";
import { antiRemoval } from "@cloudinary/url-gen/qualifiers/blendMode";
import { compass } from "@cloudinary/url-gen/qualifiers/gravity";

new CloudinaryVideo("old_camera.mp4").resize(scale().width(500)).overlay(
  source(
    image("cloudinary_icon_blue").transformation(
      new Transformation().resize(scale().width(150)).adjust(opacity(50))
    )
  )
    .position(new Position().gravity(compass("north_east")))
    .blendMode(antiRemoval(90))
);
```

```angular
import { scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/overlay";
import { opacity } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";
import { antiRemoval } from "@cloudinary/url-gen/qualifiers/blendMode";
import { compass } from "@cloudinary/url-gen/qualifiers/gravity";

new CloudinaryVideo("old_camera.mp4").resize(scale().width(500)).overlay(
  source(
    image("cloudinary_icon_blue").transformation(
      new Transformation().resize(scale().width(150)).adjust(opacity(50))
    )
  )
    .position(new Position().gravity(compass("north_east")))
    .blendMode(antiRemoval(90))
);
```

```js
import { scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/overlay";
import { opacity } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";
import { antiRemoval } from "@cloudinary/url-gen/qualifiers/blendMode";
import { compass } from "@cloudinary/url-gen/qualifiers/gravity";

new CloudinaryVideo("old_camera.mp4").resize(scale().width(500)).overlay(
  source(
    image("cloudinary_icon_blue").transformation(
      new Transformation().resize(scale().width(150)).adjust(opacity(50))
    )
  )
    .position(new Position().gravity(compass("north_east")))
    .blendMode(antiRemoval(90))
);
```

```python
CloudinaryVideo("old_camera").video(transformation=[
  {'width': 500, 'crop': "scale"},
  {'overlay': "cloudinary_icon_blue"},
  {'width': 150, 'crop': "scale"},
  {'opacity': 50},
  {'effect': "anti_removal:90", 'flags': "layer_apply", 'gravity': "north_east"}
  ])
```

```php
use Cloudinary\Transformation\Resize;
use Cloudinary\Transformation\Overlay;
use Cloudinary\Transformation\Adjust;
use Cloudinary\Transformation\Source;
use Cloudinary\Transformation\Position;
use Cloudinary\Transformation\BlendMode;
use Cloudinary\Transformation\Gravity;
use Cloudinary\Transformation\Compass;

(new VideoTag('old_camera.mp4'))
	->resize(Resize::scale()->width(500))
	->overlay(Overlay::source(
	Source::image("cloudinary_icon_blue")
	->transformation((new Transformation())
	->resize(Resize::scale()->width(150))
	->adjust(Adjust::opacity(50)))
	)
	->position((new Position())
	->gravity(
	Gravity::compass(
	Compass::northEast()))
	)
	->blendMode(
	BlendMode::antiRemoval(90))
	);
```

```java
cloudinary.url().transformation(new Transformation()
  .width(500).crop("scale").chain()
  .overlay(new Layer().publicId("cloudinary_icon_blue")).chain()
  .width(150).crop("scale").chain()
  .opacity(50).chain()
  .effect("anti_removal:90").flags("layer_apply").gravity("north_east")).videoTag("old_camera");
```

```ruby
cl_video_tag("old_camera", transformation: [
  {width: 500, crop: "scale"},
  {overlay: "cloudinary_icon_blue"},
  {width: 150, crop: "scale"},
  {opacity: 50},
  {effect: "anti_removal:90", flags: "layer_apply", gravity: "north_east"}
  ])
```

```csharp
cloudinary.Api.UrlVideoUp.Transform(new Transformation()
  .Width(500).Crop("scale").Chain()
  .Overlay(new Layer().PublicId("cloudinary_icon_blue")).Chain()
  .Width(150).Crop("scale").Chain()
  .Opacity(50).Chain()
  .Effect("anti_removal:90").Flags("layer_apply").Gravity("north_east")).BuildVideoTag("old_camera")
```

```dart
cloudinary.video('old_camera.mp4').transformation(Transformation()
	.addTransformation("c_scale,w_500/l_cloudinary_icon_blue/c_scale,w_150/o_50/e_anti_removal:90,fl_layer_apply,g_north_east"));
```

```swift
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation()
  .setWidth(500).setCrop("scale").chain()
  .setOverlay("cloudinary_icon_blue").chain()
  .setWidth(150).setCrop("scale").chain()
  .setOpacity(50).chain()
  .setEffect("anti_removal:90").setFlags("layer_apply").setGravity("north_east")).generate("old_camera.mp4")
```

```android
MediaManager.get().url().transformation(new Transformation()
  .width(500).crop("scale").chain()
  .overlay(new Layer().publicId("cloudinary_icon_blue")).chain()
  .width(150).crop("scale").chain()
  .opacity(50).chain()
  .effect("anti_removal:90").flags("layer_apply").gravity("north_east")).resourceType("video").generate("old_camera.mp4");
```

```flutter
cloudinary.video('old_camera.mp4').transformation(Transformation()
	.addTransformation("c_scale,w_500/l_cloudinary_icon_blue/c_scale,w_150/o_50/e_anti_removal:90,fl_layer_apply,g_north_east"));
```

```kotlin
cloudinary.video {
	publicId("old_camera.mp4")
	 resize(Resize.scale() { width(500) })
	 overlay(Overlay.source(
	Source.image("cloudinary_icon_blue") {
	 transformation(Transformation {
	 resize(Resize.scale() { width(150) })
	 adjust(Adjust.opacity(50)) })
	 }) {
	 position(Position() {
	 gravity(
	Gravity.compass(
	Compass.northEast()))
	 })
	 blendMode(
	BlendMode.antiRemoval(90))
	 }) 
}.generate()
```

```jquery
$.cloudinary.video("old_camera", {transformation: [
  {width: 500, crop: "scale"},
  {overlay: new cloudinary.Layer().publicId("cloudinary_icon_blue")},
  {width: 150, crop: "scale"},
  {opacity: 50},
  {effect: "anti_removal:90", flags: "layer_apply", gravity: "north_east"}
  ]})
```

```react_native
import { scale } from "@cloudinary/url-gen/actions/resize";
import { source } from "@cloudinary/url-gen/actions/overlay";
import { opacity } from "@cloudinary/url-gen/actions/adjust";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { Position } from "@cloudinary/url-gen/qualifiers/position";
import { antiRemoval } from "@cloudinary/url-gen/qualifiers/blendMode";
import { compass } from "@cloudinary/url-gen/qualifiers/gravity";

new CloudinaryVideo("old_camera.mp4").resize(scale().width(500)).overlay(
  source(
    image("cloudinary_icon_blue").transformation(
      new Transformation().resize(scale().width(150)).adjust(opacity(50))
    )
  )
    .position(new Position().gravity(compass("north_east")))
    .blendMode(antiRemoval(90))
);
```

> **NOTE**: Adding this effect generates a different result for each derived image, even if the transformation is the same. For example, every transformation URL including an overlay and the anti-removal effect, where only the public_id of the base image is changed, will result in a slightly different overlay.

**See full syntax**: [e_anti_removal](transformation_reference#e_anti_removal) in the _Transformation Reference_.

## Special layer applications
In addition to the primary use of layers for placing other assets or text on the base image, some transformation features make use of the layer option to specify a public ID that will be applied to the base image in order to achieve a desired effect. The following features make use of the layer transformation parameter in a special way:

Feature | Description
---|---
[3D LUTs](effects_and_artistic_enhancements#3_color_dimension_luts_3d_luts) | 3-color-dimension lookup tables (3D LUTs) map the color space in a LUT layer to the color space in a base image.
[Displacement maps](effects_and_artistic_enhancements#displacement_maps) | Displace pixels in a base image based on the intensity of pixels in a displacement map layer image.
[Blending and masking layers](effects_and_artistic_enhancements#blending_and_masking_layers) | Effects that blend or mask a base image based on the pixels in a layer image.
[Shape cutouts](effects_and_artistic_enhancements#shape_cutouts) | Remove or keep areas of a base image based on the opaque shape in a layer image.

> **READING**:
>
> * [Layer syntax](layers): Learn the layer URL syntax and overlay types for images.

> * [Layer placement](image_layer_placement): Position layers using gravity, offsets, and overflow behavior.

> * [Text layer options](image_text_layers): Text styling, color, multi-line text, and special characters.

> * [Transforming layers](image_layer_transformations): Apply transformations, multiple overlays, and relative sizing to layers.
