Adobe Photoshop API Developer Shares Experience
Adobe has been developing a new cloud service since 2018 called “Photoshop API” that’s currently in a Public Beta offering. Its aim is to provide image editing features at the level of documents and PSD layers.
Why is a Photoshop API cloud needed?
For quite some time, one method of automating or adding custom features to Photoshop was via ExtendScript, a Javascript-like API and could only run within the Photoshop “host” application. Automating Photoshop has evolved over the years with other methods like CEP and UXP, but they all still require Photoshop software to be running like it normally does.
With these automations it’s often desired to run Photoshop “headless” fashion, where it can execute the automations on a server without any manual intervention. However, Photoshop oddly still has no built-in concept of running in such a manner.
There have been third-party workarounds that would allow Photoshop to operate as such, but random issues could cause a dialog/popup box to open, where Photoshop would remain stuck requiring manual intervention and monitoring, or advanced techniques.
It would be great if Photoshop could run in a headless manner and not get stuck on random dialog boxes. This is where the Adobe Photoshop API attempts to shine.
Brief intro to the Photoshop API
At the time of writing the image editing features are somewhat basic, but can be very useful for certain workflows especially if partly or entirely automated. For example, if having a certain PSD template with a background image, and wanting to easily swap out that background image with several others for faster previewing of each.
The Photoshop API takes a series of operations in JSON format with a document input and a final output specified. At the moment the inputs and outputs have to be an external HTTP URL where the Photoshop API can retrieve the input, and send the final output.
The Photoshop API is not really a direct replacement for what can be done with Photoshop Plugins/Scripts. The API doesn’t have the ability to accept and run programming logic so it’s limited in some regard.
However, most of that could happen on the server-side to build the JSON operation and send that. Maybe in the future Photoshop API will have an option to use Adobe I/O “Runtime” as part of the operations.
Let’s take a look at a simple example of working with the API. Follow the set up steps if you wish to try the API too.
Set up steps to try for yourself
If you’re planning to run these examples too, we’re using the following setup:
Sign up for an Adobe IO developer account and access the Adobe IO Console
Within the console, create a project if one wasn’t already created for you
Add the “Photoshop API” service to your project
Generate and download the public/private key credentials
Generate your API token from the Adobe IO Console, within the Photoshop API service, there’s a field to paste the private key and generate the token
We used the tool Postman for sending the API call and receiving the response, you can also use “curl” if you want to
Configure Postman “Authorization” to use:
Type: OAuth 2.0
Add auth data to: Request Headers
Access Token: Available Tokens, paste the token from before
Header Prefix: Bearer
Add a header for “x-api-key” that holds the client ID from the credentials page
You’ll also need a web server that receive HTTP requests to deliver the inputs and save the HTTP body of the Photoshop API output. We’re using a simple PHP script for the latter.
For example, your dev machine running a web server, and using a service like Ngrok to tunnel from Photoshop API to your dev machine
Sample save.php script (only for experimenting):
<?php $filename = 'output-' . time() . ‘.jpg’; file_put_contents(filename, file_get_contents('php://input'));
First example: Replacing a Smart Object in a PSD
Note: This example uses Photoshop API sample files that are provided under the Apache 2.0 License from here: https://github.com/AdobeDocs/cis-photoshop-api-docs/tree/main/sample_files License: https://github.com/AdobeDocs/cis-photoshop-api-docs/blob/main/LICENSE
In this example we would like to replace a Smart Object image in a PSD with some other image like the sample heroImage.png. Smart Objects are a more advanced way of embedding image data, instead using a pixel layer with a raster image. This example will probably be a common operation, such as wanting to preview different outputs with different images filling in the Smart Object layer.
Referencing the PSD’s smart object layer can be done by the layer’s name or an ID. The ID would come from the “documentManifest” endpoint that returns a JSON object describing the PSD layers. We’ll do that in the second example, but typically using the layer name is sufficient and more descriptive.
Endpoint: https://image.adobe.io/pie/psdService/documentOperations
{ "inputs": [ { "href": "http://abc123.ngrok.io/Example.psd", "storage": "external" }], "options": { "layers": [{ "name": "HeroImage", "input": { "href": "http://abc123.ngrok.io/endertech-logo.png", "storage": "external" } } ] }, "outputs": [ { "storage": "external", "href": "http://abc123.ngrok.io/save.php", "type": "image/jpeg" } ]}'
The API response will be JSON with a link to check on the status of the job, looking like “https://image.adobe.io/pie/psdService/status/dc3afe1f-9134-42c0-b9ad-823072383c0d”.
The status of the job isn’t too important in this case because when the job is complete it’ll send the PSD to the save.php URL where it’s saved to a file. If the file doesn’t arrive, then checking the job status URL should provide an error message of why the job didn’t complete successfully.
From the below images, you can see the PSD that was sent to the Photoshop API. In the API request, we’re specifying to replace the Hero banner Smart Object layer with a different PNG image. The output was received as a PSD, which we opened in Photoshop for the screenshot to demonstrate that it’s operating on layers and can still be edited afterwards.
That’s a pretty simple example and a designer could’ve easily just replaced the image themselves. But when rasterizing the whole document to a format like PNG or JPEG, then it can be used elsewhere in a more automated fashion without having to open Photoshop on a desktop machine.
One example could be a custom marketing platform that lets marketers generate advertising assets themselves without having to wait for a designer, freeing the designer to work on more creative tasks.
Second example: Replacing text in a PSD
Note: This example uses Photoshop API sample files that are provided under the Apache 2.0 License from here: https://github.com/AdobeDocs/cis-photoshop-api-docs/tree/main/sample_files License: https://github.com/AdobeDocs/cis-photoshop-api-docs/blob/main/LICENSE
Using the same Example.psd file from the prior example, we want to change the main text that says “Reset your customers’ expectations” to something else.
One potential issue is that the layer name is the same as the text. So, what we’ll do this time is get the “documentManifest” JSON, and use the ID for the layer instead of the name.
Get the document manifest JSON
Endpoint: https://image.adobe.io/pie/psdService/documentManifest
Request body:
{ "inputs": [ { "href": "http://abc123.ngrok.io/example.psd", "storage": "external" }], ]}
The API response will be a link to the job status. When the job is complete, the job status will include a “layers” value of all the layers in the Example.psd. It’s rather long so we’ll just include the layer we care about in this example.Job status response:
"layers": [ { "blendOptions": { "blendMode": "normal", "opacity": 100 }, "bounds": { "height": 108, "left": 31, "top": 334, "width": 197 }, "id": 412, "index": 6, "locked": false, "name": "Reset your customers’ expectations.", "text": { "characterStyles": [ { "fontAvailable": false, "fontColor": { "rgb": { "blue": 32768, "green": 32768, "red": 32768 } }, "fontName": "AdobeClean-Bold", "fontSize": 36, "orientation": "horizontal" } ], "content": "Reset your customers’ expectations.", "paragraphStyles": [ { "alignment": "left" } ], "type": "area" }, "type": "textLayer", "visible": true }, ]
From the manifest JSON we can see that the layer’s ID is “412”, which we’ll use for the next part of editing the text.
Change the text layer content
Let’s say marketing wanted to try a different headline for this advertising asset, with something like “Surpass your client’s expectations”.
Endpoint: https://image.adobe.io/pie/psdService/documentOperations
Request body (fill in the inputs & outputs with your values from first example):
{ "inputs": [ ... ], "options":{ "layers":[ { "edit":{}, "text": { "content": "Surpass your client’s expectations" }, "id":412 } ], "outputs": [ … ]}'
If all went well, the output image should have the content requested. You’ll notice though that the font looks different and that’s because the Photoshop API doesn’t have the original font file used in the PSD, so it probably defaults to Arial.
That original font in Example.psd is “Adobe Clean” and has its own license, available here: https://spectrum.adobe.com/page/fonts/. If allowed by the license, you can supply a “fonts” key with a URL to the font file, which the API will download and use the correct font.
Your turn: Combine both examples and beyond
Try combining the 1st and 2nd examples so that the API swaps the smart object image and the text content in one API call, or try several other features like changing font family, adding layers, using your own PSDs, and so on.
Use the Photoshop API docs here: https://www.adobe.io/photoshop/photoshop-api-docs/
Additional functionality with Lightroom API and Sensei API
Two other Adobe products available via the Photoshop API service are Lightroom API and Sensei API. They offer some other operations not available in Photoshop API for image editing, such as auto-straightening an image with Lightroom API, or an AI-powered cutout or masking of images. Another possibility is to use the Photoshop API to output a raster image, and use Lightroom API to auto-tone it.
Performance
The Photoshop API seems to run really fast for small operations, such as replacing text, color fill, and smart object image. Without doing any in-depth measurements, the turn around seemed to typically be within 1 to 3 seconds. This could be worthwhile for a web application where users expect quick feedback, assuming pricing is tolerable.
The biggest overhead could be in the network transfer of assets if working with large assets, which isn’t uncommon with very heavy PSDs. You’ll also want to consider any bandwidth costs if doing heavy API call volume.
It seems that Photoshop API is running from the AWS us-east-1 region, so putting assets there could provide the fastest bandwidth and least latency, if that’s important for the use case.
Additionally, to save on bandwidth costs could be to use S3 instead of EC2 in that region for the assets, which the API servers will likely retrieve via AWS’ internal network. One complication of that is having to deal with S3 signed URLs so that the API has permission to retrieve and upload asset objects.
Pricing and usage model
The pricing isn’t yet public and seems to be based on use cases and volume so you’ll need to get in touch with Adobe sales to get some kind of number, although they might also still be trying to figure it out at this point.
At the moment the API has a free trial quota of 5,000 “units”, where a “unit” is simply each successful API call. Perhaps that might change if additional features are added, like the ability to execute ExtendScript which may have a different pricing and usage model.
Every API has some limitations
When working with the Photoshop API we came across a few different things that would be nice to have at some point, or needing to have PSD layers a certain way so the API can work with them.
No ability to reuse existing ExtendScript code
The Photoshop API as it exists now does not have the ability to run ExtendScript code. This means having to port any existing automation scripts into some other code that will instead generate JSON to send to the API. The API’s JSON does not have any computational logic, it’s mainly just document/layer
It would be nice if all that ExtendScript developers have created could continue to be used, as if it were a headless Photoshop, the way users have been wanting for a while. This feature might be in the works already so we’ll just have to wait and see.
There might be some extra abilities by using Photoshop Actions in an Actions file, but these have to be pre-created within Photoshop and exported. There’s no supported tools to edit an Actions file outside of the Photoshop software, such as on-the-fly on a server, so they’re basically a static set of actions.
Unable to use assets from Creative Cloud
At the time of this writing, the API docs appear to support Creative Cloud Libraries via the “cclib” input/output value, but it’s not actually supported yet. This would likely provide the greatest bandwidth and minimal costs when retrieving and storing assets with the Photoshop API if using template type PSDs often.
Creative Cloud Library also has an API to allow querying and storing assets, which could be useful for a custom platform to better integrate with the Adobe ecosystem and put frequently used assets near the Photoshop API.
Pixel layers with images or color fills
The example before used a Smart Object layer to replace an image with another PNG. There could also be a pixel layer with image data. However, handling the auto-sizing of the new image to the layer and maintaining the layer mask wasn’t working too well in some experiments. Using a smart object layer it worked fine including the mask.
Relatedly, there’s no ability to change a pixel layer of color. Changing a color like that can only be done for a color fill layer. After replacing the pixel layer with a color fill layer the API was able to change the color. Color fill layer still worked fine with a layer and clipping mask applied while also having an overlay blending option.
Unable to auto adjust font size to fit a region
One use case for the Photoshop API can be updating text in a PSD, like would be done with an InDesign “data merge” operation. The Photoshop API makes that really easy to do like the 2nd example shows. However, the API doesn’t have the ability to automatically resize the text to best fit in the text region (say like a layer mask used as a bounding box).
There’s a feature in the works to handle that auto-sizing but in the meantime you might just have to experiment and use your own heuristics as to what font size to specify in the API call.
Separate endpoints for text and smart object operations
This one isn’t really an issue but it’s a little odd. The API has endpoints specific for text and smart object operations that seem to have the same functionality as the documentOperations endpoint.
From the pricing section, since each API call has a cost, we’re hoping that some features specific to text or smart objects don’t get locked away behind their specific API endpoint, thus requiring multiple API calls instead of a single documentOperations call.
Unable to monitor usage of quota via an API
At the moment the Photoshop API trial has a quota, but the Adobe I/O Console doesn’t have an API that allows for automated monitoring & alerting of the usage of that quota. There doesn’t seem to be a feature to allow setting manual percentages either to get an email alert.
It would be a good idea to have your software that’s making the API calls keep track of how many calls it’s making and monitor that to alert on any critical values, like reaching 90% of the quota, hourly anomaly detection like excessive API calls, or even forecasting that the quota will be exceeded.
Could the Photoshop API benefit you?
Although still in Public Beta version and not having all the features of Photoshop yet, the new Photoshop API unlocks some new opportunities that are more officially supported by Adobe instead of prior unsupported workarounds or manually running scripts.
If you think the API could be of use to your company or idea please contact us to discuss more and help you incorporate it!