> ## 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 your task extends beyond this product, fetch the top-level index covering all Cloudinary products and topics at: https://cloudinary.com/documentation/llms.txt?referrer=docpage

# PDF and Photoshop files


With Cloudinary, you can deliver media assets that include multiple pages or layers. This includes PDF and Photoshop files.

## Delivering content from PDF files

You can upload PDF files to Cloudinary as image types. You can deliver them via a CDN, convert them to images, and generate thumbnails. 

> **READING**: :no-icon :title=Important note for free accounts

By default, Free accounts are blocked from delivering files in PDF format for security reasons. For details, see [Media delivery](image_delivery_options#blocked_delivery_formats_for_security).


> **TIP**:
>
> :title=Tips

> * You can use the automatic quality transformation to [optimize PDFs](pdf_optimization) for storage and delivery.

> * You can [create PDF files from images](create_pdf_files_from_images).

### Deliver a PDF or selected pages of a PDF	

To deliver a PDF from Cloudinary, just supply the basic delivery URL: 

![Deliver a PDF](https://res.cloudinary.com/demo/image/upload/long_multi_page_pdf "with_image:false")

```nodejs
cloudinary.image("long_multi_page_pdf")
```

```react
new CloudinaryImage("long_multi_page_pdf");
```

```vue
new CloudinaryImage("long_multi_page_pdf");
```

```angular
new CloudinaryImage("long_multi_page_pdf");
```

```js
new CloudinaryImage("long_multi_page_pdf");
```

```python
CloudinaryImage("long_multi_page_pdf").image()
```

```php
(new ImageTag('long_multi_page_pdf'));
```

```java
cloudinary.url().transformation(new Transformation().imageTag("long_multi_page_pdf");
```

```ruby
cl_image_tag("long_multi_page_pdf")
```

```csharp
cloudinary.Api.UrlImgUp.BuildImageTag("long_multi_page_pdf")
```

```dart
cloudinary.image('long_multi_page_pdf').transformation(Transformation());
```

```swift
imageView.cldSetImage(cloudinary.createUrl().generate("long_multi_page_pdf")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation().generate("long_multi_page_pdf");
```

```flutter
cloudinary.image('long_multi_page_pdf').transformation(Transformation());
```

```kotlin
cloudinary.image {
	publicId("long_multi_page_pdf") 
}.generate()
```

```jquery
$.cloudinary.image("long_multi_page_pdf")
```

```react_native
new CloudinaryImage("long_multi_page_pdf");
```

You can also generate a PDF on the fly that contains only specified pages or page ranges.

* Use semicolons to separate a list of pages: `pg_3;5;7`
* Use hyphens to indicate a page range: `pg_3-5`
* Use a hyphen with no ending page to indicate starting from a specified page until the end: `pg_5-`

> **TIP**:
>
> :title=Tips

> * You can also create PDF files and images from Office documents, using the [Aspose](aspose_document_conversion_addon) add-on.

> * You can extract all text from a PDF when uploading it using the [OCR Text Detection and Extraction](ocr_text_detection_and_extraction_addon).

> * You can apply image transformations, such as adding text layers, to PDF pages when [delivering PDF pages as images](#deliver_a_selected_pdf_page_as_an_image). However, avoid doing this if you're delivering the file as a PDF, as the results can be unpredictable.

### Deliver a selected PDF page as an image

To deliver an image of the first page in a PDF file, just change the file extension from `pdf` to the image format of your choice in the Cloudinary delivery URL. For example, to deliver a JPEG image of the first page in a previously uploaded PDF file called `multi_page_pdf` (scaled down to a width of 300 pixels):

![JPEG image of the first page of a PDF file](https://res.cloudinary.com/demo/image/upload/c_scale,w_300/multi_page_pdf.jpg)

```nodejs
cloudinary.image("multi_page_pdf.jpg", {width: 300, crop: "scale"})
```

```react
import { scale } from "@cloudinary/url-gen/actions/resize";

new CloudinaryImage("multi_page_pdf.jpg").resize(scale().width(300));
```

```vue
import { scale } from "@cloudinary/url-gen/actions/resize";

new CloudinaryImage("multi_page_pdf.jpg").resize(scale().width(300));
```

```angular
import { scale } from "@cloudinary/url-gen/actions/resize";

new CloudinaryImage("multi_page_pdf.jpg").resize(scale().width(300));
```

```js
import { scale } from "@cloudinary/url-gen/actions/resize";

new CloudinaryImage("multi_page_pdf.jpg").resize(scale().width(300));
```

```python
CloudinaryImage("multi_page_pdf.jpg").image(width=300, crop="scale")
```

```php
use Cloudinary\Transformation\Resize;

(new ImageTag('multi_page_pdf.jpg'))
	->resize(Resize::scale()->width(300));
```

```java
cloudinary.url().transformation(new Transformation().width(300).crop("scale")).imageTag("multi_page_pdf.jpg");
```

```ruby
cl_image_tag("multi_page_pdf.jpg", width: 300, crop: "scale")
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(300).Crop("scale")).BuildImageTag("multi_page_pdf.jpg")
```

```dart
cloudinary.image('multi_page_pdf.jpg').transformation(Transformation()
	.resize(Resize.scale().width(300)));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(300).setCrop("scale")).generate("multi_page_pdf.jpg")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation().width(300).crop("scale")).generate("multi_page_pdf.jpg");
```

```flutter
cloudinary.image('multi_page_pdf.jpg').transformation(Transformation()
	.resize(Resize.scale().width(300)));
```

```kotlin
cloudinary.image {
	publicId("multi_page_pdf.jpg")
	 resize(Resize.scale() { width(300) }) 
}.generate()
```

```jquery
$.cloudinary.image("multi_page_pdf.jpg", {width: 300, crop: "scale"})
```

```react_native
import { scale } from "@cloudinary/url-gen/actions/resize";

new CloudinaryImage("multi_page_pdf.jpg").resize(scale().width(300));
```

To deliver an image of a different page, use the `page` parameter (`pg` in URLs):

![PNG image of the second page of a PDF file](https://res.cloudinary.com/demo/image/upload/c_scale,w_300/pg_2/multi_page_pdf.png)

```nodejs
cloudinary.image("multi_page_pdf.png", {transformation: [
  {width: 300, crop: "scale"},
  {page: 2}
  ]})
```

```react
import { scale } from "@cloudinary/url-gen/actions/resize";
import { getPage } from "@cloudinary/url-gen/actions/extract";

new CloudinaryImage("multi_page_pdf.png")
  .resize(scale().width(300))
  .extract(getPage().byNumber(2));
```

```vue
import { scale } from "@cloudinary/url-gen/actions/resize";
import { getPage } from "@cloudinary/url-gen/actions/extract";

new CloudinaryImage("multi_page_pdf.png")
  .resize(scale().width(300))
  .extract(getPage().byNumber(2));
```

```angular
import { scale } from "@cloudinary/url-gen/actions/resize";
import { getPage } from "@cloudinary/url-gen/actions/extract";

new CloudinaryImage("multi_page_pdf.png")
  .resize(scale().width(300))
  .extract(getPage().byNumber(2));
```

```js
import { scale } from "@cloudinary/url-gen/actions/resize";
import { getPage } from "@cloudinary/url-gen/actions/extract";

new CloudinaryImage("multi_page_pdf.png")
  .resize(scale().width(300))
  .extract(getPage().byNumber(2));
```

```python
CloudinaryImage("multi_page_pdf.png").image(transformation=[
  {'width': 300, 'crop': "scale"},
  {'page': 2}
  ])
```

```php
use Cloudinary\Transformation\Resize;
use Cloudinary\Transformation\Extract;

(new ImageTag('multi_page_pdf.png'))
	->resize(Resize::scale()->width(300))
	->extract(Extract::getPage()->byNumber(2));
```

```java
cloudinary.url().transformation(new Transformation()
  .width(300).crop("scale").chain()
  .page(2)).imageTag("multi_page_pdf.png");
```

```ruby
cl_image_tag("multi_page_pdf.png", transformation: [
  {width: 300, crop: "scale"},
  {page: 2}
  ])
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Width(300).Crop("scale").Chain()
  .Page(2)).BuildImageTag("multi_page_pdf.png")
```

```dart
cloudinary.image('multi_page_pdf.png').transformation(Transformation()
	.resize(Resize.scale().width(300))
	.extract(Extract.getPage().byNumber(2)));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setWidth(300).setCrop("scale").chain()
  .setPage(2)).generate("multi_page_pdf.png")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation()
  .width(300).crop("scale").chain()
  .page(2)).generate("multi_page_pdf.png");
```

```flutter
cloudinary.image('multi_page_pdf.png').transformation(Transformation()
	.resize(Resize.scale().width(300))
	.extract(Extract.getPage().byNumber(2)));
```

```kotlin
cloudinary.image {
	publicId("multi_page_pdf.png")
	 resize(Resize.scale() { width(300) })
	 extract(Extract.getPage() { byNumber(2) }) 
}.generate()
```

```jquery
$.cloudinary.image("multi_page_pdf.png", {transformation: [
  {width: 300, crop: "scale"},
  {page: 2}
  ]})
```

```react_native
import { scale } from "@cloudinary/url-gen/actions/resize";
import { getPage } from "@cloudinary/url-gen/actions/extract";

new CloudinaryImage("multi_page_pdf.png")
  .resize(scale().width(300))
  .extract(getPage().byNumber(2));
```

You can control the resolution of the resulting image by changing the default DPI value of 150 with the [density](transformation_reference#dn_density) parameter (`dn` in URLs). For example, to deliver a JPEG image of the PDF file with a density of 20:

![JPEG image of the PDF with 20 density](https://res.cloudinary.com/demo/image/upload/dn_20/multi_page_pdf.jpg)

```nodejs
cloudinary.image("multi_page_pdf.jpg", {density: 20})
```

```react
import { density } from "@cloudinary/url-gen/actions/delivery";

new CloudinaryImage("multi_page_pdf.jpg").delivery(density(20));
```

```vue
import { density } from "@cloudinary/url-gen/actions/delivery";

new CloudinaryImage("multi_page_pdf.jpg").delivery(density(20));
```

```angular
import { density } from "@cloudinary/url-gen/actions/delivery";

new CloudinaryImage("multi_page_pdf.jpg").delivery(density(20));
```

```js
import { density } from "@cloudinary/url-gen/actions/delivery";

new CloudinaryImage("multi_page_pdf.jpg").delivery(density(20));
```

```python
CloudinaryImage("multi_page_pdf.jpg").image(density=20)
```

```php
use Cloudinary\Transformation\Delivery;

(new ImageTag('multi_page_pdf.jpg'))
	->delivery(Delivery::density(20));
```

```java
cloudinary.url().transformation(new Transformation().density(20)).imageTag("multi_page_pdf.jpg");
```

```ruby
cl_image_tag("multi_page_pdf.jpg", density: 20)
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation().Density(20)).BuildImageTag("multi_page_pdf.jpg")
```

```dart
cloudinary.image('multi_page_pdf.jpg').transformation(Transformation()
	.delivery(Delivery.density(20)));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setDensity(20)).generate("multi_page_pdf.jpg")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation().density(20)).generate("multi_page_pdf.jpg");
```

```flutter
cloudinary.image('multi_page_pdf.jpg').transformation(Transformation()
	.delivery(Delivery.density(20)));
```

```kotlin
cloudinary.image {
	publicId("multi_page_pdf.jpg")
	 delivery(Delivery.density(20)) 
}.generate()
```

```jquery
$.cloudinary.image("multi_page_pdf.jpg", {density: 20})
```

```react_native
import { density } from "@cloudinary/url-gen/actions/delivery";

new CloudinaryImage("multi_page_pdf.jpg").delivery(density(20));
```

> **TIP**: You can also use the [explode](image_upload_api_reference#explode_method) method of the Admin API to explicitly generate derived images of all pages of a PDF, including optionally applying any transformation on all the pages before storing them. This method is useful for pre-generating all the pages, so that they do not need to be generated on the fly when first accessed by your users.

## Delivering Photoshop images

If you upload a Photoshop (PSD) file or a TIFF file that was saved with layers and deliver it as a Cloudinary URL, it will enable users to download the original file, including all layers. For example: 	

![Deliver an original Photoshop image](https://res.cloudinary.com/demo/image/upload/docs/cld_record_PSD.psd "with_image:false")

```nodejs
cloudinary.image("docs/cld_record_PSD.psd")
```

```react
new CloudinaryImage("docs/cld_record_PSD.psd");
```

```vue
new CloudinaryImage("docs/cld_record_PSD.psd");
```

```angular
new CloudinaryImage("docs/cld_record_PSD.psd");
```

```js
new CloudinaryImage("docs/cld_record_PSD.psd");
```

```python
CloudinaryImage("docs/cld_record_PSD.psd").image()
```

```php
(new ImageTag('docs/cld_record_PSD.psd'));
```

```java
cloudinary.url().transformation(new Transformation().imageTag("docs/cld_record_PSD.psd");
```

```ruby
cl_image_tag("docs/cld_record_PSD.psd")
```

```csharp
cloudinary.Api.UrlImgUp.BuildImageTag("docs/cld_record_PSD.psd")
```

```dart
cloudinary.image('docs/cld_record_PSD.psd').transformation(Transformation());
```

```swift
imageView.cldSetImage(cloudinary.createUrl().generate("docs/cld_record_PSD.psd")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation().generate("docs/cld_record_PSD.psd");
```

```flutter
cloudinary.image('docs/cld_record_PSD.psd').transformation(Transformation());
```

```kotlin
cloudinary.image {
	publicId("docs/cld_record_PSD.psd") 
}.generate()
```

```jquery
$.cloudinary.image("docs/cld_record_PSD.psd")
```

```react_native
new CloudinaryImage("docs/cld_record_PSD.psd");
```

> **INFO**: To ensure that all file and layer data is completely preserved in your stored image, do not apply any [incoming transformations](eager_and_incoming_transformations#incoming_transformations) when uploading PSD, TIFF or other image formats containing layers.

You can also apply any standard image transformation, and deliver with another image extension (or explicitly set an image format in the transformation) to deliver it in a format that your website or mobile app can display. For example, below, the `cld_record_PSD` image is delivered as a 300 pixel-width JPG with the grayscale effect:

![Deliver a Photoshop image as a JPG with transformations](https://res.cloudinary.com/demo/image/upload/c_scale,w_300/e_grayscale/docs/cld_record_PSD.jpg)

```nodejs
cloudinary.image("docs/cld_record_PSD.jpg", {transformation: [
  {width: 300, crop: "scale"},
  {effect: "grayscale"}
  ]})
```

```react
import { scale } from "@cloudinary/url-gen/actions/resize";
import { grayscale } from "@cloudinary/url-gen/actions/effect";

new CloudinaryImage("docs/cld_record_PSD.jpg")
  .resize(scale().width(300))
  .effect(grayscale());
```

```vue
import { scale } from "@cloudinary/url-gen/actions/resize";
import { grayscale } from "@cloudinary/url-gen/actions/effect";

new CloudinaryImage("docs/cld_record_PSD.jpg")
  .resize(scale().width(300))
  .effect(grayscale());
```

```angular
import { scale } from "@cloudinary/url-gen/actions/resize";
import { grayscale } from "@cloudinary/url-gen/actions/effect";

new CloudinaryImage("docs/cld_record_PSD.jpg")
  .resize(scale().width(300))
  .effect(grayscale());
```

```js
import { scale } from "@cloudinary/url-gen/actions/resize";
import { grayscale } from "@cloudinary/url-gen/actions/effect";

new CloudinaryImage("docs/cld_record_PSD.jpg")
  .resize(scale().width(300))
  .effect(grayscale());
```

```python
CloudinaryImage("docs/cld_record_PSD.jpg").image(transformation=[
  {'width': 300, 'crop': "scale"},
  {'effect': "grayscale"}
  ])
```

```php
use Cloudinary\Transformation\Resize;
use Cloudinary\Transformation\Effect;

(new ImageTag('docs/cld_record_PSD.jpg'))
	->resize(Resize::scale()->width(300))
	->effect(Effect::grayscale());
```

```java
cloudinary.url().transformation(new Transformation()
  .width(300).crop("scale").chain()
  .effect("grayscale")).imageTag("docs/cld_record_PSD.jpg");
```

```ruby
cl_image_tag("docs/cld_record_PSD.jpg", transformation: [
  {width: 300, crop: "scale"},
  {effect: "grayscale"}
  ])
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Width(300).Crop("scale").Chain()
  .Effect("grayscale")).BuildImageTag("docs/cld_record_PSD.jpg")
```

```dart
cloudinary.image('docs/cld_record_PSD.jpg').transformation(Transformation()
	.resize(Resize.scale().width(300))
	.effect(Effect.grayscale()));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setWidth(300).setCrop("scale").chain()
  .setEffect("grayscale")).generate("docs/cld_record_PSD.jpg")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation()
  .width(300).crop("scale").chain()
  .effect("grayscale")).generate("docs/cld_record_PSD.jpg");
```

```flutter
cloudinary.image('docs/cld_record_PSD.jpg').transformation(Transformation()
	.resize(Resize.scale().width(300))
	.effect(Effect.grayscale()));
```

```kotlin
cloudinary.image {
	publicId("docs/cld_record_PSD.jpg")
	 resize(Resize.scale() { width(300) })
	 effect(Effect.grayscale()) 
}.generate()
```

```jquery
$.cloudinary.image("docs/cld_record_PSD.jpg", {transformation: [
  {width: 300, crop: "scale"},
  {effect: "grayscale"}
  ]})
```

```react_native
import { scale } from "@cloudinary/url-gen/actions/resize";
import { grayscale } from "@cloudinary/url-gen/actions/effect";

new CloudinaryImage("docs/cld_record_PSD.jpg")
  .resize(scale().width(300))
  .effect(grayscale());
```

In addition to these basic options, there are a few special options available for working with PSD files.

> **TIP**:
>
> It is recommended to save PSD files in **Maximize Compatibility** mode for the best results when delivering Photoshop images from Cloudinary.

### Deliver selected layers of a PSD image

You can use the `page` (`pg` in URLs) transformation parameter to deliver an image containing only specified layers of a Photoshop image, where `pg_1` represents all layers, and `pg_2` is the bottom layer. The layers are delivered in the order you specify, even if the specified order is different from the original PSD file.

* Use semicolons to separate a list of layers: `pg_3;5;7`
* Use hyphens to indicate a range of layers: `pg_3-5`
* Use a hyphen with no ending page to indicate starting from a specified layer until the end: `pg_5-`

For example, below, `cld_record_PSD` is delivered with all layers except the record cover layer (8), the cover icon layer (9) and the cover's shadow layer (6):

![Delivery Photoshop layers by number](https://res.cloudinary.com/demo/image/upload/pg_2-5;7;10/c_scale,w_300/docs/cld_record_PSD.jpg)

```nodejs
cloudinary.image("docs/cld_record_PSD.jpg", {transformation: [
  {page: "2-5;7;10"},
  {width: 300, crop: "scale"}
  ]})
```

```react
import { getPage } from "@cloudinary/url-gen/actions/extract";
import { scale } from "@cloudinary/url-gen/actions/resize";

new CloudinaryImage("docs/cld_record_PSD.jpg")
  .extract(
    getPage()
      .byRange(2, 5)
      .byNumber(7)
      .byNumber(10)
  )
  .resize(scale().width(300));
```

```vue
import { getPage } from "@cloudinary/url-gen/actions/extract";
import { scale } from "@cloudinary/url-gen/actions/resize";

new CloudinaryImage("docs/cld_record_PSD.jpg")
  .extract(
    getPage()
      .byRange(2, 5)
      .byNumber(7)
      .byNumber(10)
  )
  .resize(scale().width(300));
```

```angular
import { getPage } from "@cloudinary/url-gen/actions/extract";
import { scale } from "@cloudinary/url-gen/actions/resize";

new CloudinaryImage("docs/cld_record_PSD.jpg")
  .extract(
    getPage()
      .byRange(2, 5)
      .byNumber(7)
      .byNumber(10)
  )
  .resize(scale().width(300));
```

```js
import { getPage } from "@cloudinary/url-gen/actions/extract";
import { scale } from "@cloudinary/url-gen/actions/resize";

new CloudinaryImage("docs/cld_record_PSD.jpg")
  .extract(
    getPage()
      .byRange(2, 5)
      .byNumber(7)
      .byNumber(10)
  )
  .resize(scale().width(300));
```

```python
CloudinaryImage("docs/cld_record_PSD.jpg").image(transformation=[
  {'page': "2-5;7;10"},
  {'width': 300, 'crop': "scale"}
  ])
```

```php
use Cloudinary\Transformation\Extract;
use Cloudinary\Transformation\Resize;

(new ImageTag('docs/cld_record_PSD.jpg'))
	->extract(Extract::getPage()
	->byRange(2,5)
->byNumber(7)
->byNumber(10))
	->resize(Resize::scale()->width(300));
```

```java
cloudinary.url().transformation(new Transformation()
  .page("2-5;7;10").chain()
  .width(300).crop("scale")).imageTag("docs/cld_record_PSD.jpg");
```

```ruby
cl_image_tag("docs/cld_record_PSD.jpg", transformation: [
  {page: "2-5;7;10"},
  {width: 300, crop: "scale"}
  ])
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Page("2-5;7;10").Chain()
  .Width(300).Crop("scale")).BuildImageTag("docs/cld_record_PSD.jpg")
```

```dart
cloudinary.image('docs/cld_record_PSD.jpg').transformation(Transformation()
	.extract(Extract.getPage()
	.byRange(2,5)
.byNumber(7)
.byNumber(10))
	.resize(Resize.scale().width(300)));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setPage("2-5;7;10").chain()
  .setWidth(300).setCrop("scale")).generate("docs/cld_record_PSD.jpg")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation()
  .page("2-5;7;10").chain()
  .width(300).crop("scale")).generate("docs/cld_record_PSD.jpg");
```

```flutter
cloudinary.image('docs/cld_record_PSD.jpg').transformation(Transformation()
	.extract(Extract.getPage()
	.byRange(2,5)
.byNumber(7)
.byNumber(10))
	.resize(Resize.scale().width(300)));
```

```kotlin
cloudinary.image {
	publicId("docs/cld_record_PSD.jpg")
	 extract(Extract.getPage() {
	 byRange(2,5)
 byNumber(7)
 byNumber(10) })
	 resize(Resize.scale() { width(300) }) 
}.generate()
```

```jquery
$.cloudinary.image("docs/cld_record_PSD.jpg", {transformation: [
  {page: "2-5;7;10"},
  {width: 300, crop: "scale"}
  ]})
```

```react_native
import { getPage } from "@cloudinary/url-gen/actions/extract";
import { scale } from "@cloudinary/url-gen/actions/resize";

new CloudinaryImage("docs/cld_record_PSD.jpg")
  .extract(
    getPage()
      .byRange(2, 5)
      .byNumber(7)
      .byNumber(10)
  )
  .resize(scale().width(300));
```

You can also deliver layers by name (case-sensitive) using `pg_name:`. For example, now we'll deliver only the record cover and icon together with the cover's shadow:

![Delivery Photoshop layers by name](https://res.cloudinary.com/demo/image/upload/pg_name:record_cover;Shadow;logo/c_scale,w_300/docs/cld_record_PSD.jpg)

```nodejs
cloudinary.image("docs/cld_record_PSD.jpg", {transformation: [
  {page: "name:record_cover;Shadow;logo"},
  {width: 300, crop: "scale"}
  ]})
```

```react
import { getLayer } from "@cloudinary/url-gen/actions/psdTools";
import { scale } from "@cloudinary/url-gen/actions/resize";

new CloudinaryImage("docs/cld_record_PSD.jpg")
  .psdTools(getLayer().byName("record_cover").byName("Shadow").byName("logo"))
  .resize(scale().width(300));
```

```vue
import { getLayer } from "@cloudinary/url-gen/actions/psdTools";
import { scale } from "@cloudinary/url-gen/actions/resize";

new CloudinaryImage("docs/cld_record_PSD.jpg")
  .psdTools(getLayer().byName("record_cover").byName("Shadow").byName("logo"))
  .resize(scale().width(300));
```

```angular
import { getLayer } from "@cloudinary/url-gen/actions/psdTools";
import { scale } from "@cloudinary/url-gen/actions/resize";

new CloudinaryImage("docs/cld_record_PSD.jpg")
  .psdTools(getLayer().byName("record_cover").byName("Shadow").byName("logo"))
  .resize(scale().width(300));
```

```js
import { getLayer } from "@cloudinary/url-gen/actions/psdTools";
import { scale } from "@cloudinary/url-gen/actions/resize";

new CloudinaryImage("docs/cld_record_PSD.jpg")
  .psdTools(getLayer().byName("record_cover").byName("Shadow").byName("logo"))
  .resize(scale().width(300));
```

```python
CloudinaryImage("docs/cld_record_PSD.jpg").image(transformation=[
  {'page': "name:record_cover;Shadow;logo"},
  {'width': 300, 'crop': "scale"}
  ])
```

```php
use Cloudinary\Transformation\PsdTools;
use Cloudinary\Transformation\Resize;

(new ImageTag('docs/cld_record_PSD.jpg'))
	->psdTools(PSDTools::getLayer()->byName("record_cover")
->byName("Shadow")
->byName("logo"))
	->resize(Resize::scale()->width(300));
```

```java
cloudinary.url().transformation(new Transformation()
  .page("name:record_cover;Shadow;logo").chain()
  .width(300).crop("scale")).imageTag("docs/cld_record_PSD.jpg");
```

```ruby
cl_image_tag("docs/cld_record_PSD.jpg", transformation: [
  {page: "name:record_cover;Shadow;logo"},
  {width: 300, crop: "scale"}
  ])
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Page("name:record_cover;Shadow;logo").Chain()
  .Width(300).Crop("scale")).BuildImageTag("docs/cld_record_PSD.jpg")
```

```dart
cloudinary.image('docs/cld_record_PSD.jpg').transformation(Transformation()
	.psdTools(PSDTools.getLayer().byName("record_cover")
.byName("Shadow")
.byName("logo"))
	.resize(Resize.scale().width(300)));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setPage("name:record_cover;Shadow;logo").chain()
  .setWidth(300).setCrop("scale")).generate("docs/cld_record_PSD.jpg")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation()
  .page("name:record_cover;Shadow;logo").chain()
  .width(300).crop("scale")).generate("docs/cld_record_PSD.jpg");
```

```flutter
cloudinary.image('docs/cld_record_PSD.jpg').transformation(Transformation()
	.psdTools(PSDTools.getLayer().byName("record_cover")
.byName("Shadow")
.byName("logo"))
	.resize(Resize.scale().width(300)));
```

```kotlin
cloudinary.image {
	publicId("docs/cld_record_PSD.jpg")
	 psdTools(PSDTools.getLayer() { byName("record_cover")
 byName("Shadow")
 byName("logo") })
	 resize(Resize.scale() { width(300) }) 
}.generate()
```

```jquery
$.cloudinary.image("docs/cld_record_PSD.jpg", {transformation: [
  {page: "name:record_cover;Shadow;logo"},
  {width: 300, crop: "scale"}
  ]})
```

```react_native
import { getLayer } from "@cloudinary/url-gen/actions/psdTools";
import { scale } from "@cloudinary/url-gen/actions/resize";

new CloudinaryImage("docs/cld_record_PSD.jpg")
  .psdTools(getLayer().byName("record_cover").byName("Shadow").byName("logo"))
  .resize(scale().width(300));
```

> **NOTE**: If the PSD has more than one layer with the same name, you can refer to them using the name plus an index value. The first instance should be referred just by `name`, and the next should be referred to as `name-1`, and so on.

### Extract the original content of an embedded object

A Photoshop image may include layers with embedded objects, such as Photoshop **smart objects** that are scaled down or otherwise modified. As long as the original image's content is fully preserved in the PSD file, you can extract and deliver the original embedded object using the `pg_embedded:<index>` parameter, where the `index` is the layer index number in the PSD file, or you can use the `pg_embedded:name:<layer name>` parameter to specify the layer name of the embedded smart object.

For example, suppose you embed a high resolution city scene as a smart object layer in a PSD alongside other layers. You can use the `pg_embedded:name` option to extract the full resolution city image by specifying the layer name, `skyline-3242040_1920`. Alternatively, you could reference it as the layer at index 8 in the PSD file (`pg_embedded:8`).

![Photoshop image with smart objects](https://res.cloudinary.com/demo/image/upload/pg_embedded:name:skyline-3242040_1920/docs/cld_sample_smart_PSD.jpg "with_image:false")

```nodejs
cloudinary.image("docs/cld_sample_smart_PSD.jpg", {page: "embedded:name:skyline-3242040_1920"})
```

```react
import { smartObject } from "@cloudinary/url-gen/actions/psdTools";

new CloudinaryImage("docs/cld_sample_smart_PSD.jpg").psdTools(
  smartObject().byLayerName("skyline-3242040_1920")
);
```

```vue
import { smartObject } from "@cloudinary/url-gen/actions/psdTools";

new CloudinaryImage("docs/cld_sample_smart_PSD.jpg").psdTools(
  smartObject().byLayerName("skyline-3242040_1920")
);
```

```angular
import { smartObject } from "@cloudinary/url-gen/actions/psdTools";

new CloudinaryImage("docs/cld_sample_smart_PSD.jpg").psdTools(
  smartObject().byLayerName("skyline-3242040_1920")
);
```

```js
import { smartObject } from "@cloudinary/url-gen/actions/psdTools";

new CloudinaryImage("docs/cld_sample_smart_PSD.jpg").psdTools(
  smartObject().byLayerName("skyline-3242040_1920")
);
```

```python
CloudinaryImage("docs/cld_sample_smart_PSD.jpg").image(page="embedded:name:skyline-3242040_1920")
```

```php
use Cloudinary\Transformation\PsdTools;

(new ImageTag('docs/cld_sample_smart_PSD.jpg'))
	->psdTools(PSDTools::smartObject()->byLayerName("skyline-3242040_1920"));
```

```java
cloudinary.url().transformation(new Transformation().page("embedded:name:skyline-3242040_1920")).imageTag("docs/cld_sample_smart_PSD.jpg");
```

```ruby
cl_image_tag("docs/cld_sample_smart_PSD.jpg", page: "embedded:name:skyline-3242040_1920")
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation().Page("embedded:name:skyline-3242040_1920")).BuildImageTag("docs/cld_sample_smart_PSD.jpg")
```

```dart
cloudinary.image('docs/cld_sample_smart_PSD.jpg').transformation(Transformation()
	.psdTools(PSDTools.smartObject().byLayerName("skyline-3242040_1920")));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setPage("embedded:name:skyline-3242040_1920")).generate("docs/cld_sample_smart_PSD.jpg")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation().page("embedded:name:skyline-3242040_1920")).generate("docs/cld_sample_smart_PSD.jpg");
```

```flutter
cloudinary.image('docs/cld_sample_smart_PSD.jpg').transformation(Transformation()
	.psdTools(PSDTools.smartObject().byLayerName("skyline-3242040_1920")));
```

```kotlin
cloudinary.image {
	publicId("docs/cld_sample_smart_PSD.jpg")
	 psdTools(PSDTools.smartObject() { byLayerName("skyline-3242040_1920") }) 
}.generate()
```

```jquery
$.cloudinary.image("docs/cld_sample_smart_PSD.jpg", {page: "embedded:name:skyline-3242040_1920"})
```

```react_native
import { smartObject } from "@cloudinary/url-gen/actions/psdTools";

new CloudinaryImage("docs/cld_sample_smart_PSD.jpg").psdTools(
  smartObject().byLayerName("skyline-3242040_1920")
);
```

	
	
	
	
	
	
Full PSD as a jpg. Click to view full size.	
	
	
	
	
Extracted original object. Click to view full size.	
	
	
	
	

### Transforming PSD layers with self-referencing variable

You can combine PSD layer selection with a self-referencing variable to apply transformations to a specific layer of the same PSD file.

In the following example, the transformation:

* Extracts a specific visible layer from a PSD file
* Uses the same PSD file as an underlay
* Targets a different layer in the underlay and applies a colorization effect
* Outputs the result as a JPG

![strawberries_layer](https://res.cloudinary.com/demo/image/upload/$img_current:public_id/pg_3-3/u_$img,pg_2-2,e_colorize:50,co_red/f_jpg/strawberries.psd "thumb: c_scale,w_300")

```nodejs
cloudinary.image("strawberries.psd", {transformation: [
  {variables: [["$img", "current:public_id"]]},
  {page: "3-3"},
  {underlay: "%24img", page: "2-2", effect: "colorize:50", color: "red"},
  {fetch_format: "jpg"}
  ]})
```

```react
import { set } from "@cloudinary/url-gen/actions/variable";
import { getPage } from "@cloudinary/url-gen/actions/extract";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { format } from "@cloudinary/url-gen/actions/delivery";
import { colorize } from "@cloudinary/url-gen/actions/effect";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { jpg } from "@cloudinary/url-gen/qualifiers/format";

new CloudinaryImage("strawberries.psd")
  .addVariable(set("img", expression("current:public_id")))
  .extract(getPage().byRange(3, 3))
  .underlay(
    source(
      image("$img").transformation(
        new Transformation()
          .effect(colorize().level(50).color("red"))
          .extract(getPage().byRange(2, 2))
      )
    )
  )
  .delivery(format(jpg()));
```

```vue
import { set } from "@cloudinary/url-gen/actions/variable";
import { getPage } from "@cloudinary/url-gen/actions/extract";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { format } from "@cloudinary/url-gen/actions/delivery";
import { colorize } from "@cloudinary/url-gen/actions/effect";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { jpg } from "@cloudinary/url-gen/qualifiers/format";

new CloudinaryImage("strawberries.psd")
  .addVariable(set("img", expression("current:public_id")))
  .extract(getPage().byRange(3, 3))
  .underlay(
    source(
      image("$img").transformation(
        new Transformation()
          .effect(colorize().level(50).color("red"))
          .extract(getPage().byRange(2, 2))
      )
    )
  )
  .delivery(format(jpg()));
```

```angular
import { set } from "@cloudinary/url-gen/actions/variable";
import { getPage } from "@cloudinary/url-gen/actions/extract";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { format } from "@cloudinary/url-gen/actions/delivery";
import { colorize } from "@cloudinary/url-gen/actions/effect";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { jpg } from "@cloudinary/url-gen/qualifiers/format";

new CloudinaryImage("strawberries.psd")
  .addVariable(set("img", expression("current:public_id")))
  .extract(getPage().byRange(3, 3))
  .underlay(
    source(
      image("$img").transformation(
        new Transformation()
          .effect(colorize().level(50).color("red"))
          .extract(getPage().byRange(2, 2))
      )
    )
  )
  .delivery(format(jpg()));
```

```js
import { set } from "@cloudinary/url-gen/actions/variable";
import { getPage } from "@cloudinary/url-gen/actions/extract";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { format } from "@cloudinary/url-gen/actions/delivery";
import { colorize } from "@cloudinary/url-gen/actions/effect";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { jpg } from "@cloudinary/url-gen/qualifiers/format";

new CloudinaryImage("strawberries.psd")
  .addVariable(set("img", expression("current:public_id")))
  .extract(getPage().byRange(3, 3))
  .underlay(
    source(
      image("$img").transformation(
        new Transformation()
          .effect(colorize().level(50).color("red"))
          .extract(getPage().byRange(2, 2))
      )
    )
  )
  .delivery(format(jpg()));
```

```python
CloudinaryImage("strawberries.psd").image(transformation=[
  {'variables': [["$img", "current:public_id"]]},
  {'page': "3-3"},
  {'underlay': "%24img", 'page': "2-2", 'effect': "colorize:50", 'color': "red"},
  {'fetch_format': "jpg"}
  ])
```

```php
use Cloudinary\Transformation\Variable;
use Cloudinary\Transformation\Extract;
use Cloudinary\Transformation\Underlay;
use Cloudinary\Transformation\Delivery;
use Cloudinary\Transformation\Effect;
use Cloudinary\Transformation\Expression;
use Cloudinary\Transformation\Source;
use Cloudinary\Transformation\Format;

(new ImageTag('strawberries.psd'))
	->addVariable(Variable::set("img",
	Expression::expression("current:public_id")))
	->extract(Extract::getPage()
	->byRange(3,3)
	)
	->underlay(Underlay::source(
	Source::image("$img")
	->transformation((new Transformation())
	->effect(Effect::colorize()->level(50)
	->color(Color::RED)
	)
	->extract(Extract::getPage()
	->byRange(2,2)
	))
	))
	->delivery(Delivery::format(
	Format::jpg()));
```

```java
cloudinary.url().transformation(new Transformation()
  .variables(variable("$img","current:public_id")).chain()
  .page("3-3").chain()
  .underlay(new Layer().publicId("%24img")).page("2-2").effect("colorize:50").color("red").chain()
  .fetchFormat("jpg")).imageTag("strawberries.psd");
```

```ruby
cl_image_tag("strawberries.psd", transformation: [
  {variables: [["$img", "current:public_id"]]},
  {page: "3-3"},
  {underlay: "%24img", page: "2-2", effect: "colorize:50", color: "red"},
  {fetch_format: "jpg"}
  ])
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Variables("$img", current:public_id).Chain()
  .Page("3-3").Chain()
  .Underlay(new Layer().PublicId("%24img")).Page("2-2").Effect("colorize:50").Color("red").Chain()
  .FetchFormat("jpg")).BuildImageTag("strawberries.psd")
```

```dart
cloudinary.image('strawberries.psd').transformation(Transformation()
	.addVariable(Variable.set("img",
	Expression.expression("current:public_id")))
	.extract(Extract.getPage()
	.byRange(3,3)
	)
	.underlay(Underlay.source(
	Source.image("$img")
	.transformation(new Transformation()
	.effect(Effect.colorize().level(50)
	.color(Color.RED)
	)
	.extract(Extract.getPage()
	.byRange(2,2)
	))
	))
	.delivery(Delivery.format(
	Format.jpg())));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .chain()
  .setPage("3-3").chain()
  .setUnderlay("%24img").setPage("2-2").setEffect("colorize:50").setColor("red").chain()
  .setFetchFormat("jpg")).generate("strawberries.psd")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation()
  .variables(variable("$img","current:public_id")).chain()
  .page("3-3").chain()
  .underlay(new Layer().publicId("%24img")).page("2-2").effect("colorize:50").color("red").chain()
  .fetchFormat("jpg")).generate("strawberries.psd");
```

```flutter
cloudinary.image('strawberries.psd').transformation(Transformation()
	.addVariable(Variable.set("img",
	Expression.expression("current:public_id")))
	.extract(Extract.getPage()
	.byRange(3,3)
	)
	.underlay(Underlay.source(
	Source.image("$img")
	.transformation(new Transformation()
	.effect(Effect.colorize().level(50)
	.color(Color.RED)
	)
	.extract(Extract.getPage()
	.byRange(2,2)
	))
	))
	.delivery(Delivery.format(
	Format.jpg())));
```

```kotlin
cloudinary.image {
	publicId("strawberries.psd")
	 addVariable(Variable.set("img",
	Expression.expression("current:public_id")))
	 extract(Extract.getPage() {
	 byRange(3,3)
	 })
	 underlay(Underlay.source(
	Source.image("\$img") {
	 transformation(Transformation {
	 effect(Effect.colorize() { level(50)
	 color(Color.RED)
	 })
	 extract(Extract.getPage() {
	 byRange(2,2)
	 }) })
	 }))
	 delivery(Delivery.format(
	Format.jpg())) 
}.generate()
```

```jquery
$.cloudinary.image("strawberries.psd", {transformation: [
  {variables: [["$img", "current:public_id"]]},
  {page: "3-3"},
  {underlay: new cloudinary.Layer().publicId("%24img"), page: "2-2", effect: "colorize:50", color: "red"},
  {fetch_format: "jpg"}
  ]})
```

```react_native
import { set } from "@cloudinary/url-gen/actions/variable";
import { getPage } from "@cloudinary/url-gen/actions/extract";
import { source } from "@cloudinary/url-gen/actions/underlay";
import { format } from "@cloudinary/url-gen/actions/delivery";
import { colorize } from "@cloudinary/url-gen/actions/effect";
import { expression } from "@cloudinary/url-gen/qualifiers/expression";
import { image } from "@cloudinary/url-gen/qualifiers/source";
import { jpg } from "@cloudinary/url-gen/qualifiers/format";

new CloudinaryImage("strawberries.psd")
  .addVariable(set("img", expression("current:public_id")))
  .extract(getPage().byRange(3, 3))
  .underlay(
    source(
      image("$img").transformation(
        new Transformation()
          .effect(colorize().level(50).color("red"))
          .extract(getPage().byRange(2, 2))
      )
    )
  )
  .delivery(format(jpg()));
```

How this transformation works:

* `$img_current:public_id`: Stores the public ID of the current PSD file in the $img variable for reuse later in the transformation chain.
* `pg_3-3`: Extracts only layer 3 from the PSD (for example, the main subject layer).
* `w_500`: Resizes the extracted layer to a width of 500 pixels while preserving the aspect ratio.
* `u_$img`: Uses the original PSD (stored in $img) as an underlay.
* `pg_2-2`: From the underlay PSD, selects layer 2 (for example, a shadow layer).
* `e_colorize:50,co_red`: Applies a red colorization effect to the selected underlay layer.
* `f_jpg`: Delivers the final image in JPG format.

#### Reusing the transformation with a named transformation

You can save this chained transformation as a [named transformation](named_transformations) and reuse it when delivering PSD files. 

```multi
|ruby
result = Cloudinary::Api
.create_transformation('shadow_color',
  '$img_current:public_id/pg_3-3,w_500/u_$img,pg_2-2,e_colorize:50,co_red,w_500/f_jpg')

|php_2
$result = $api
->createTransformation("shadow_color", "$img_current:public_id/pg_3-3,w_500/u_$img,pg_2-2,e_colorize:50,co_red,w_500/f_jpg");

|python
result = cloudinary.api\
.create_transformation("shadow_color",
  "$img_current:public_id/pg_3-3,w_500/u_$img,pg_2-2,e_colorize:50,co_red,w_500/f_jpg")

|nodejs
cloudinary.v2.api
.create_transformation('shadow_color',
  '$img_current:public_id/pg_3-3,w_500/u_$img,pg_2-2,e_colorize:50,co_red,w_500/f_jpg')
.then(result=>console.log(result)); 

|java
result = api
.createTransformation("shadow_color", "$img_current:public_id/pg_3-3,w_500/u_$img,pg_2-2,e_colorize:50,co_red,w_500/f_jpg",
  ObjectUtils.emptyMap());

|csharp
var createTransformParams = new CreateTransformParams(){
  Name = "shadow_color",
  Transformation = new Transformation()
  .Variables("$img", current:public_id).Chain()
  .Page("3-3").Chain()
  .Underlay(new Layer().PublicId("%24img")).Page("2-2").Effect("colorize:50").Color("red").Chain()
  .FetchFormat("jpg")
};
cloudinary.CreateTransform(createTransformParams);

|go
resp, err := cld.Admin.CreateTransformation(ctx, admin.CreateTransformationParams{
      Name:           "shadow_color", 
      Transformation: "$img_current:public_id/pg_3-3,w_500/u_$img,pg_2-2,e_colorize:50,co_red,w_500/f_jpg"})

|curl
curl \
  -d 'transformation=$img_current:public_id/pg_3-3,w_500/u_$img,pg_2-2,e_colorize:50,co_red,w_500/f_jpg' \
  -X POST \
  https://<API_KEY>:<API_SECRET>@api.cloudinary.com/v1_1/<CLOUD_NAME>/transformations/shadow_color

|cli
cld admin create_transformation "shadow_color" "$img_current:public_id/pg_3-3,w_500/u_$img,pg_2-2,e_colorize:50,co_red,w_500/f_jpg"
```

Once saved, you can deliver the PSD using the named transformation:

![strawberries_layer_named_transformation](https://res.cloudinary.com/demo/image/upload/t_shadow_color/strawberries.psd "thumb: c_scale,w_300")

```nodejs
cloudinary.image("strawberries.psd", {transformation: ["shadow_color"]})
```

```react
import { name } from "@cloudinary/url-gen/actions/namedTransformation";

new CloudinaryImage("strawberries.psd").namedTransformation(
  name("shadow_color")
);
```

```vue
import { name } from "@cloudinary/url-gen/actions/namedTransformation";

new CloudinaryImage("strawberries.psd").namedTransformation(
  name("shadow_color")
);
```

```angular
import { name } from "@cloudinary/url-gen/actions/namedTransformation";

new CloudinaryImage("strawberries.psd").namedTransformation(
  name("shadow_color")
);
```

```js
import { name } from "@cloudinary/url-gen/actions/namedTransformation";

new CloudinaryImage("strawberries.psd").namedTransformation(
  name("shadow_color")
);
```

```python
CloudinaryImage("strawberries.psd").image(transformation=["shadow_color"])
```

```php
use Cloudinary\Transformation\NamedTransformation;

(new ImageTag('strawberries.psd'))
	->namedTransformation(NamedTransformation::name("shadow_color"));
```

```java
cloudinary.url().transformation(new Transformation().named("shadow_color")).imageTag("strawberries.psd");
```

```ruby
cl_image_tag("strawberries.psd", transformation: ["shadow_color"])
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation().Named("shadow_color")).BuildImageTag("strawberries.psd")
```

```dart
cloudinary.image('strawberries.psd').transformation(Transformation()
	.namedTransformation(NamedTransformation.name("shadow_color")));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setNamed("shadow_color")).generate("strawberries.psd")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation().named("shadow_color")).generate("strawberries.psd");
```

```flutter
cloudinary.image('strawberries.psd').transformation(Transformation()
	.namedTransformation(NamedTransformation.name("shadow_color")));
```

```kotlin
cloudinary.image {
	publicId("strawberries.psd")
	 namedTransformation(NamedTransformation.name("shadow_color")) 
}.generate()
```

```jquery
$.cloudinary.image("strawberries.psd", {transformation: ["shadow_color"]})
```

```react_native
import { name } from "@cloudinary/url-gen/actions/namedTransformation";

new CloudinaryImage("strawberries.psd").namedTransformation(
  name("shadow_color")
);
```

This approach is useful when you need to consistently apply layer-specific effects to layered design files while keeping delivery URLs concise.

> **NOTE**:
>
> * The `pg` parameter supports layer indexes, ranges, and layer names.

> * For predictable layer behavior, upload PSD files without incoming transformations.

> * Self-referencing variables `$img_current` are evaluated per transformation request, making them suitable for dynamic and reusable workflows.
	
### Embed a clipping path in image metadata

You can embed a clipping path into the metadata of a delivered image using the `e_embed_clipping_path` effect. The clipping path is derived from a mask image that you supply as a [user-defined reference variable](user_defined_variables#image_buffer_references). This is intended for formats that preserve clipping-path metadata in the delivered file, in particular JPEG and TIFF.

To define the mask, set a reference variable pointing to the mask image's public ID, then pass the variable to `e_embed_clipping_path:mask_$<variable>`. For example, to embed a clipping path derived from `butterflywomanmask` into the delivered JPEG:

`$mask_ref:!butterflywomanmask!/e_embed_clipping_path:mask_$mask/q_90`

![Butterfly woman image with embedded clipping path](https://res.cloudinary.com/demo/image/upload/$mask_ref:!butterflywomanmask!/e_embed_clipping_path:mask_$mask/q_90/butterfly.jpg "thumb: h_150")

```nodejs
cloudinary.image("butterfly.jpg", {transformation: [
  {variables: [["$mask", "ref:!butterflywomanmask!"]]},
  {effect: "embed_clipping_path:mask_$mask"},
  {quality: 90}
  ]})
```

```react
new CloudinaryImage("butterfly.jpg").addTransformation(
  "$mask_ref:!butterflywomanmask!/e_embed_clipping_path:mask_$mask/q_90"
);
```

```vue
new CloudinaryImage("butterfly.jpg").addTransformation(
  "$mask_ref:!butterflywomanmask!/e_embed_clipping_path:mask_$mask/q_90"
);
```

```angular
new CloudinaryImage("butterfly.jpg").addTransformation(
  "$mask_ref:!butterflywomanmask!/e_embed_clipping_path:mask_$mask/q_90"
);
```

```js
new CloudinaryImage("butterfly.jpg").addTransformation(
  "$mask_ref:!butterflywomanmask!/e_embed_clipping_path:mask_$mask/q_90"
);
```

```python
CloudinaryImage("butterfly.jpg").image(transformation=[
  {'variables': [["$mask", "ref:!butterflywomanmask!"]]},
  {'effect': "embed_clipping_path:mask_$mask"},
  {'quality': 90}
  ])
```

```php
(new ImageTag('butterfly.jpg'))
	->addTransformation("$mask_ref:!butterflywomanmask!/e_embed_clipping_path:mask_$mask/q_90");
```

```java
cloudinary.url().transformation(new Transformation()
  .variables(variable("$mask","ref:!butterflywomanmask!")).chain()
  .effect("embed_clipping_path:mask_$mask").chain()
  .quality(90)).imageTag("butterfly.jpg");
```

```ruby
cl_image_tag("butterfly.jpg", transformation: [
  {variables: [["$mask", "ref:!butterflywomanmask!"]]},
  {effect: "embed_clipping_path:mask_$mask"},
  {quality: 90}
  ])
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Variables("$mask", ref:!butterflywomanmask!).Chain()
  .Effect("embed_clipping_path:mask_$mask").Chain()
  .Quality(90)).BuildImageTag("butterfly.jpg")
```

```dart
cloudinary.image('butterfly.jpg').transformation(Transformation()
	.addTransformation("$mask_ref:!butterflywomanmask!/e_embed_clipping_path:mask_$mask/q_90"));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .chain()
  .setEffect("embed_clipping_path:mask_$mask").chain()
  .setQuality(90)).generate("butterfly.jpg")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation()
  .variables(variable("$mask","ref:!butterflywomanmask!")).chain()
  .effect("embed_clipping_path:mask_$mask").chain()
  .quality(90)).generate("butterfly.jpg");
```

```flutter
cloudinary.image('butterfly.jpg').transformation(Transformation()
	.addTransformation("$mask_ref:!butterflywomanmask!/e_embed_clipping_path:mask_$mask/q_90"));
```

```kotlin
cloudinary.image {
	publicId("butterfly.jpg")
	 addTransformation("\$mask_ref:!butterflywomanmask!/e_embed_clipping_path:mask_\$mask/q_90") 
}.generate()
```

```jquery
$.cloudinary.image("butterfly.jpg", {transformation: [
  {variables: [["$mask", "ref:!butterflywomanmask!"]]},
  {effect: "embed_clipping_path:mask_$mask"},
  {quality: 90}
  ]})
```

```react_native
new CloudinaryImage("butterfly.jpg").addTransformation(
  "$mask_ref:!butterflywomanmask!/e_embed_clipping_path:mask_$mask/q_90"
);
```
> **NOTE**: `q_90` is specified explicitly because the default auto quality optimization strips embedded metadata from the delivered image. To preserve the clipping path in the output, you must set a fixed quality value. See [Metadata stripping](image_optimization#metadata_stripping) for details.

In Photoshop, for example, you can see the embedded clipping mask:

![Butterfly woman image with embedded clipping path in Photoshop](https://cloudinary-res.cloudinary.com/image/upload/f_auto/q_auto/docs/photoshop_embedded_clipping_mask.png "thumb:c_scale,w_600/dpr_2.0, width:600")

For more details, see the [embed_clipping_path](transformation_reference#e_embed_clipping_path) parameter in the _Transformation URL API Reference_.

### Additional Photoshop image transformation options	
	
When working with Photoshop images, you may also want to take advantage of the following:	
	
* You can trim the pixels of a PSD image according to a Photoshop clipping path that is stored in the image's metadata, using the `fl_clip` transformation flag followed by `e_trim`. `fl_clip` makes everything outside the clipping path transparent, but maintains the dimensions of the original image. `e_trim` trims down the dimensions of the image to the non-transparent part.
	

	* If there are multiple paths stored in the PSD, you can specify which path to use by path number or name using the `page` parameter (`pg` or `pg_name` in URLs). 
  
      
        For example, `/fl_clip,pg_2/e_trim/my_image.jpg` will deliver your Photoshop image as a .jpg file, trimmed to the second clipping path in the file. Alternatively, `fl_clip,pg_name:mypath/e_trim` will trim to the clipping path named `mypath` in your PSD file. 
* You can use a clipping path as a gravity option when cropping or overlaying images. Use `g_clipping_path_!<clipping path name>!` to specify the clipping path to gravitate to. By using `c_crop,g_clipping_path_!<clipping path name>!`, you can trim the image to the bounding box of the clipping path. For details, see the [g_clipping_path](transformation_reference#g_clipping_path) parameter in the _Transformation URL API Reference_.
* You can force all semi-transparent pixels in an image to be either fully transparent or fully opaque using the `e_opacity_threshold` transformation effect. This can be a useful solution when Photoshop PSD files are delivered in a format that supports partial transparency, such as PNG, and the default results are not as expected. For details, see the [e\_opacity\_threshold](transformation_reference#e_opacity_threshold) parameter in the _Transformation URL API Reference_.
* You can get the original x (`page_x`) and y (`page_y`) co-ordinates of a layer (`px` and `py` in URLs), and use them to set [user defined variables](user_defined_variables), or within arithmetic or [conditional transformations](conditional_transformations). See this [article](https://support.cloudinary.com/hc/en-us/articles/115001217949-Does-Cloudinary-support-working-with-PSD-layers-) for an example.

### Limitations with Photoshop images

There are some known limitations when working with Photoshop images:

* If a clipping mask is used in a PSD file, the mask only works if delivering the image as a whole. It does not work when delivering selected layers. Layer masks do work when delivering selected layers, so consider using layer masks instead if you intend to be selective about the layers you want to deliver.
* PSD files using custom color spaces, such as duotone and palette mode, or those using spot colors from a non-default color book, do not always render correctly when delivered with an image extension. Try to stick to RGB, Grayscale and CMYK.
* Layers that apply certain effects or blend modes cannot be accessed using the `pg` transformation parameter. For example, in the PSD file shown in the screenshot below, the effect on the third layer is applied to the second layer, but accessing `pg_4` returns an error: "Image only has 3 pages and page 4 requested" (`pg_1` delivers the whole image, including the effect). Accessing `pg_3` returns only the second layer without the effect. 
  ![PSD layers with blend effect](https://cloudinary-res.cloudinary.com/image/upload/bo_1px_solid_gray/f_auto,q_auto/v1619684756/docs/misc/psd_layers_with_effect.png "thumb: w_300,dpr_2, width: 300")