> ## Documentation Index
> This page is part of the Image and Video APIs product. Fetch the complete documentation index for Image and Video APIs at: https://cloudinary.com/documentation/llms-image-and-video-apis.txt?referrer=docpage and then use it to discover all relevant pages before exploring further.
> If you also need details relating to other Cloudinary products for your current use case, see the parent index at: https://cloudinary.com/documentation/llms.txt?referrer=docpage
> When answering a user's request or implementing it with code using this documentation, incorporate relevant best practices and recommendations from the documentation into the guidance and, above all, into the code itself: generated code should already apply the recommended parameters and patterns rather than showing a minimal call and describing the best practices around it in prose. Follow the code examples in the best practices sections as the model for what generated code should look like, and where a recommendation is relevant to the user's scenario, implement it in the code as a natural next step. Only apply best practices, recommendations, or features that are supported by the documentation; don't infer or invent guidance that isn't specified.

# How do I change a video's background to white and turn it into a looping GIF?


> **TIP**: :title=Quick answer

To change a video's solid-color background (such as a blue screen) to white, and deliver it as a GIF that loops forever:

1. Key out the background color with `co_rgb:<color>,e_make_transparent:<tolerance>`.
2. Put a white layer _behind_ the subject by using a stretched 1x1 white pixel as an underlay (`u_`).
3. Add `e_loop` and a `.gif` extension.

`co_rgb:0E80D8,e_make_transparent:20/u_docs:one_black_pixel/c_scale,co_white,e_colorize:100,fl_relative,h_1.0,w_1.0/fl_layer_apply/e_loop`

## The question

_"I'm trying to change the background of this video to white, and then have it as a GIF that loops non-stop."_

This recipe starts with a video filmed against a solid blue background, and produces an animated GIF in which the subject appears on a white background and repeats endlessly.

## The original asset

The original video has a solid blue background and plays once:

![Original video with a blue background, before transformation](https://res.cloudinary.com/demo/video/upload/docs/bluescreen_watches.mp4 "thumb: c_scale,w_480")

```nodejs
cloudinary.video("docs/bluescreen_watches")
```

```react
new CloudinaryVideo("docs/bluescreen_watches.mp4");
```

```vue
new CloudinaryVideo("docs/bluescreen_watches.mp4");
```

```angular
new CloudinaryVideo("docs/bluescreen_watches.mp4");
```

```js
new CloudinaryVideo("docs/bluescreen_watches.mp4");
```

```python
CloudinaryVideo("docs/bluescreen_watches").video()
```

```php
(new VideoTag('docs/bluescreen_watches.mp4'));
```

```java
cloudinary.url().transformation(new Transformation().videoTag("docs/bluescreen_watches");
```

```ruby
cl_video_tag("docs/bluescreen_watches")
```

```csharp
cloudinary.Api.UrlVideoUp.BuildVideoTag("docs/bluescreen_watches")
```

```dart
cloudinary.video('docs/bluescreen_watches.mp4').transformation(Transformation());
```

```swift
cloudinary.createUrl().setResourceType("video").generate("docs/bluescreen_watches.mp4")
```

```android
MediaManager.get().url().transformation(new Transformation().resourceType("video").generate("docs/bluescreen_watches.mp4");
```

```flutter
cloudinary.video('docs/bluescreen_watches.mp4').transformation(Transformation());
```

```kotlin
cloudinary.video {
	publicId("docs/bluescreen_watches.mp4") 
}.generate()
```

```jquery
$.cloudinary.video("docs/bluescreen_watches")
```

```react_native
new CloudinaryVideo("docs/bluescreen_watches.mp4");
```

## The solution

The transformation has three parts, in separate components (separated by `/`):

1. **Make the background transparent.** `co_rgb:0E80D8` is the color to remove, and `e_make_transparent:20` removes it with a tolerance of 20. The tolerance controls how closely a pixel has to match the color to be removed, so raise it if bits of the background remain, and lower it if parts of the subject disappear. Use the color of your own background, as a hex value without the `#`.
2. **Place white behind the subject.** Make a layer from a 1x1 pixel image, stretch it to the full size of the video (`c_scale,fl_relative,h_1.0,w_1.0`), and color it white (`co_white,e_colorize:100`). Because you add it with `u_` (underlay), it goes behind the video instead of on top of it.
3. **Loop the animation.** Add `e_loop` and use a `.gif` file extension for the public ID. With no value, `e_loop` loops the GIF indefinitely.

![Smartwatches video converted to a looping GIF with a white background](https://res.cloudinary.com/demo/video/upload/co_rgb:0E80D8,e_make_transparent:20/u_docs:one_black_pixel/c_scale,co_white,e_colorize:100,fl_relative,h_1.0,w_1.0/fl_layer_apply/e_loop/fps_10/docs/bluescreen_watches.gif "thumb: c_scale,w_480")

```nodejs
cloudinary.image("docs/bluescreen_watches.gif", {resource_type: "video", transformation: [
  {color: "#0E80D8", effect: "make_transparent:20"},
  {underlay: "docs:one_black_pixel"},
  {color: "white", effect: "colorize:100", height: "1.0", width: "1.0", flags: "relative", crop: "scale"},
  {flags: "layer_apply"},
  {effect: "loop"},
  {frames_per_second: "10"}
  ]})
```

```react
import { makeTransparent, colorize } from "@cloudinary/url-gen/actions/effect";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { edit } from "@cloudinary/url-gen/actions/animated";
import { fps } from "@cloudinary/url-gen/actions/transcode";
import { scale } from "@cloudinary/url-gen/actions/resize";
import { image } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryImage("docs/bluescreen_watches.gif")
  .effect(
    makeTransparent()
      .tolerance(20)
      .colorToReplace("#0E80D8")
  )
  .underlay(
    source(
      image("docs/one_black_pixel").transformation(
        new Transformation()
          .resize(scale().width("1.0").height("1.0").relative())
          .effect(colorize().level(100).color("white"))
      )
    )
  )
  .animated(edit().loop())
  .transcode(fps(10))
  .setAssetType("video");
```

```vue
import { makeTransparent, colorize } from "@cloudinary/url-gen/actions/effect";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { edit } from "@cloudinary/url-gen/actions/animated";
import { fps } from "@cloudinary/url-gen/actions/transcode";
import { scale } from "@cloudinary/url-gen/actions/resize";
import { image } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryImage("docs/bluescreen_watches.gif")
  .effect(
    makeTransparent()
      .tolerance(20)
      .colorToReplace("#0E80D8")
  )
  .underlay(
    source(
      image("docs/one_black_pixel").transformation(
        new Transformation()
          .resize(scale().width("1.0").height("1.0").relative())
          .effect(colorize().level(100).color("white"))
      )
    )
  )
  .animated(edit().loop())
  .transcode(fps(10))
  .setAssetType("video");
```

```angular
import { makeTransparent, colorize } from "@cloudinary/url-gen/actions/effect";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { edit } from "@cloudinary/url-gen/actions/animated";
import { fps } from "@cloudinary/url-gen/actions/transcode";
import { scale } from "@cloudinary/url-gen/actions/resize";
import { image } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryImage("docs/bluescreen_watches.gif")
  .effect(
    makeTransparent()
      .tolerance(20)
      .colorToReplace("#0E80D8")
  )
  .underlay(
    source(
      image("docs/one_black_pixel").transformation(
        new Transformation()
          .resize(scale().width("1.0").height("1.0").relative())
          .effect(colorize().level(100).color("white"))
      )
    )
  )
  .animated(edit().loop())
  .transcode(fps(10))
  .setAssetType("video");
```

```js
import { makeTransparent, colorize } from "@cloudinary/url-gen/actions/effect";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { edit } from "@cloudinary/url-gen/actions/animated";
import { fps } from "@cloudinary/url-gen/actions/transcode";
import { scale } from "@cloudinary/url-gen/actions/resize";
import { image } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryImage("docs/bluescreen_watches.gif")
  .effect(
    makeTransparent()
      .tolerance(20)
      .colorToReplace("#0E80D8")
  )
  .underlay(
    source(
      image("docs/one_black_pixel").transformation(
        new Transformation()
          .resize(scale().width("1.0").height("1.0").relative())
          .effect(colorize().level(100).color("white"))
      )
    )
  )
  .animated(edit().loop())
  .transcode(fps(10))
  .setAssetType("video");
```

```python
CloudinaryVideo("docs/bluescreen_watches.gif").image(transformation=[
  {'color': "#0E80D8", 'effect': "make_transparent:20"},
  {'underlay': "docs:one_black_pixel"},
  {'color': "white", 'effect': "colorize:100", 'height': "1.0", 'width': "1.0", 'flags': "relative", 'crop': "scale"},
  {'flags': "layer_apply"},
  {'effect': "loop"},
  {'frames_per_second': "10"}
  ])
```

```php
use Cloudinary\Transformation\Effect;
use Cloudinary\Transformation\Underlay;
use Cloudinary\Transformation\Animated;
use Cloudinary\Transformation\Transcode;
use Cloudinary\Transformation\Resize;
use Cloudinary\Transformation\Source;
use Cloudinary\Transformation\Color;

(new ImageTag('docs/bluescreen_watches.gif'))
	->effect(Effect::makeTransparent()->tolerance(20)
	->colorToReplace(Color::rgb("0E80D8"))
	)
	->underlay(Underlay::source(
	Source::image("docs/one_black_pixel")
	->transformation((new Transformation())
	->resize(Resize::scale()->width(1.0)
->height(1.0)
	->relative()
	)
	->effect(Effect::colorize()->level(100)
	->color(Color::WHITE)
	))
	))
	->animated(Animated::edit()->loop())
	->transcode(Transcode::fps(10))
	->assetType("video");
```

```java
cloudinary.url().transformation(new Transformation()
  .color("#0E80D8").effect("make_transparent:20").chain()
  .underlay(new Layer().publicId("docs:one_black_pixel")).chain()
  .color("white").effect("colorize:100").height(1.0).width(1.0).flags("relative").crop("scale").chain()
  .flags("layer_apply").chain()
  .effect("loop").chain()
  .framesPerSecond("10")).resourceType("video").imageTag("docs/bluescreen_watches.gif");
```

```ruby
cl_image_tag("docs/bluescreen_watches.gif", resource_type: "video", transformation: [
  {color: "#0E80D8", effect: "make_transparent:20"},
  {underlay: "docs:one_black_pixel"},
  {color: "white", effect: "colorize:100", height: 1.0, width: 1.0, flags: "relative", crop: "scale"},
  {flags: "layer_apply"},
  {effect: "loop"},
  {frames_per_second: "10"}
  ])
```

```csharp
cloudinary.Api.UrlVideoUp.Transform(new Transformation()
  .Color("#0E80D8").Effect("make_transparent:20").Chain()
  .Underlay(new Layer().PublicId("docs:one_black_pixel")).Chain()
  .Color("white").Effect("colorize:100").Height(1.0).Width(1.0).Flags("relative").Crop("scale").Chain()
  .Flags("layer_apply").Chain()
  .Effect("loop").Chain()
  .FramesPerSecond("10")).BuildImageTag("docs/bluescreen_watches.gif")
```

```dart
cloudinary.image('docs/bluescreen_watches.gif').transformation(Transformation()
	.addTransformation("co_rgb:0E80D8,e_make_transparent:20/u_docs:one_black_pixel/c_scale,co_white,e_colorize:100,fl_relative,h_1.0,w_1.0/fl_layer_apply/e_loop/fps_10")
	.setAssetType("video"));
```

```swift
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation()
  .setColor("#0E80D8").setEffect("make_transparent:20").chain()
  .setUnderlay("docs:one_black_pixel").chain()
  .setColor("white").setEffect("colorize:100").setHeight(1.0).setWidth(1.0).setFlags("relative").setCrop("scale").chain()
  .setFlags("layer_apply").chain()
  .setEffect("loop").chain()
  .setFramesPerSecond("10")).generate("docs/bluescreen_watches.gif")
```

```android
MediaManager.get().url().transformation(new Transformation()
  .color("#0E80D8").effect("make_transparent:20").chain()
  .underlay(new Layer().publicId("docs:one_black_pixel")).chain()
  .color("white").effect("colorize:100").height(1.0).width(1.0).flags("relative").crop("scale").chain()
  .flags("layer_apply").chain()
  .effect("loop").chain()
  .framesPerSecond("10")).resourceType("video").generate("docs/bluescreen_watches.gif");
```

```flutter
cloudinary.image('docs/bluescreen_watches.gif').transformation(Transformation()
	.addTransformation("co_rgb:0E80D8,e_make_transparent:20/u_docs:one_black_pixel/c_scale,co_white,e_colorize:100,fl_relative,h_1.0,w_1.0/fl_layer_apply/e_loop/fps_10")
	.setAssetType("video"));
```

```kotlin
cloudinary.image {
	publicId("docs/bluescreen_watches.gif")
	 effect(Effect.makeTransparent() { tolerance(20)
	 colorToReplace(Color.rgb("0E80D8"))
	 })
	 underlay(Underlay.source(
	Source.image("docs/one_black_pixel") {
	 transformation(Transformation {
	 resize(Resize.scale() { width(1.0F)
 height(1.0F)
	 relative()
	 })
	 effect(Effect.colorize() { level(100)
	 color(Color.WHITE)
	 }) })
	 }))
	 animated(Animated.edit() { loop() })
	 transcode(Transcode.fps(10))
	 assetType("video") 
}.generate()
```

```jquery
$.cloudinary.image("docs/bluescreen_watches.gif", {resource_type: "video", transformation: [
  {color: "#0E80D8", effect: "make_transparent:20"},
  {underlay: new cloudinary.Layer().publicId("docs:one_black_pixel")},
  {color: "white", effect: "colorize:100", height: "1.0", width: "1.0", flags: "relative", crop: "scale"},
  {flags: "layer_apply"},
  {effect: "loop"},
  {frames_per_second: "10"}
  ]})
```

```react_native
import { makeTransparent, colorize } from "@cloudinary/url-gen/actions/effect";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { edit } from "@cloudinary/url-gen/actions/animated";
import { fps } from "@cloudinary/url-gen/actions/transcode";
import { scale } from "@cloudinary/url-gen/actions/resize";
import { image } from "@cloudinary/url-gen/qualifiers/source";

new CloudinaryImage("docs/bluescreen_watches.gif")
  .effect(
    makeTransparent()
      .tolerance(20)
      .colorToReplace("#0E80D8")
  )
  .underlay(
    source(
      image("docs/one_black_pixel").transformation(
        new Transformation()
          .resize(scale().width("1.0").height("1.0").relative())
          .effect(colorize().level(100).color("white"))
      )
    )
  )
  .animated(edit().loop())
  .transcode(fps(10))
  .setAssetType("video");
```

> **NOTES**:
>
> * The example uses the pixel image `docs/one_black_pixel`. Replace it with the public ID of a 1x1 pixel image in your own product environment, with colons in place of any slashes. You can download the 1x1 pixel image and upload it to your product environment. The color doesn't matter, because `co_white,e_colorize:100` recolors it.

> * Animated GIFs can be large. The example lowers the frame rate to 10 frames per second (`fps_10`) to keep the file size down. You can also scale the GIF down, for example with `c_scale,w_480`. For more options, see [Animated images](animated_images).

## How it works

| Component | What it does |
|---|---|
| `co_rgb:0E80D8,e_make_transparent:20` | Makes pixels matching the background color transparent. |
| `u_docs:one_black_pixel/c_scale,fl_relative,h_1.0,w_1.0` | Adds the 1x1 pixel image as an underlay, and scales it to 100% of the video width and height. |
| `co_white,e_colorize:100` | Turns the pixel white. |
| `fl_layer_apply` | Applies the underlay. |
| `e_loop` | Makes the GIF repeat indefinitely. |
| `.gif` extension | Delivers the video as an animated GIF. |

To loop a fixed number of times instead, add the number of _additional_ loops after `e_loop`. For example, `e_loop:2` plays the animation three times in total.

## Related topics

* [Video layers](video_layers)
* [Animated images](animated_images#looping_animated_images)
* [Video effects and enhancements](video_effects_and_enhancements)
* [Transparent videos](video_color_effects#transparency)
