Automating Image Workflows
with APIs

who am i?

  • Raymond Camden
  • Senior Developer Evangelist for Adobe
  • Husband, father of 8 kids, 5 cats, 1 dog, and no sleep
  • Blog: raymondcamden.com
  • Email: jedimaster@adobe.com

github.com/cfjedimaster/photoshop_api_preso

Adobe Photoshop API

  • Image automation for Photoshop + Lightroom
  • Set of REST APIs
  • Node sample in development
  • Photoshop experience not required! 😀

What's it cost?

  • Free trial (500 API calls, no production use)
  • SMB/Individual: 0.15 per call (subscribe via AWS)
  • Enterprise: Reach out!
  • Latest: Pricing

Current List of Features

  • Photoshop Actions, Smart Object editing, Text layer editing, Smart Crop, Depth Blur, Rendering (PDF to JPG, thumbnails, etc), layer editing, resizing, artboard creation, remove background, and image mask
  • AutoTone, AutoStraighten, Lightroom Presets and edits

Credentials

  • Adobe ID
  • No credit card/payment required
  • Sign up

Checking Access - Part 1

  • Convert client id + secret to Access Token...
  • Using new OAuth Server-to-Server creds
  • All can be done in one API call

CODE

Show generateAccessToken

Checking Access - Part 2

  • Hit the "hello" endpoint
  • This isn't *required*

CODE

Show sayHello

Storage

  • All services work with remote files only!
  • AWS S3
  • Google Drive
  • Azure
  • Dropbox
  • Any readable URL (for input)
  • Any writable URL (for output)

Storage

  • All services work with remote files only!
  • AWS S3
  • Google Drive
  • Azure
  • Dropbox
  • Any readable URL (for input)
  • Any writable URL (for output)

API Flow

  1. Get the input URL (or URLs)
  2. Specify your output URL (or URLs)
  3. Create your JSON body
  4. Hit the endpoint
  5. Poll for response
  6. Repeat. Profit. Etc.
Example 1: Remove Background

{
  "input": {
    "href": "string",
    "storage": "external"
  },
  "options": {
    "optimize": "performance",
  },
  "output": {
    "href": "string",
    "storage": "external",
    "overwrite": true,
    "color": {
      "space": "rgb"
    },
    "mask": {
      "format": "soft"
    }
  }
}				
				

API Ref

CODE

Show removeBg

Polling

  • Take the result from the job creation...
  • Poll at an interval
  • Wait for status 'succeeded' or 'failed'

CODE

Show removeBg_withPoll

ActionJSON

  • New(ish)
  • Takes an Action JSON file and applies to new images
  • Like the Action endpoint, but flexible
  • Enabling:
    • Enable Developer Mode in Photoshop (via Preferences/Plugins)
    • Plugins/Development - select Record Action Commands

DEMO+CODE

Show creating the file in PS,
Show actionJSON example

CODE

Modify actionJSON example

Lightroom APIs

  • AutoStraighten
  • Presets
  • Edit (exposure, contract, sharpness, many more)
  • AutoTone (auto fix exposure, contract, sharpness, saturation, etc)

CODE

Show autoTone

Real Use Case

  • Marketing creates ad, with dummy text
  • Day before sale, finally, folks agree on text
  • You need to generate a final version...
  • Oh, and in multiple languages
  • An hour before they change the text 😀
Our Input:
Example 2: Edit Text Layer

{
		"inputs": [{
			"href": input,
			"storage": "external"
		}],
		"options": {
			"layers":[
				{
					"name":"Ad Copy",
					"text":{
						"content":text
					}
				}
			]
		},
		"outputs": [{
			"href": output,
			"storage": "external",
			"overwrite": true,
			"type":"image/jpeg"
		}]
	};	
				

API Ref

CODE

Results

Automation Examples


// Sample Lambda code, SDK still in development
const awsLib = require('/opt/nodejs/src/lib/awsLib')
const sdk = require('/opt/nodejs/config/config')

exports.handler = async (event) => {
	try {
		const client = await sdk.initSDK()

		const input = {
		// href: await awsLib.getSignedUrl('getObject', 'input/input01.jpg'), //ex: AWS S3 (s3://<awsConfig.bucketName>/input/input01.jpg)
		href: 'https://raw.githubusercontent.com/adobe/adobe-photoshop-api-sdk/main/testfiles/input/input01.jpg',
		storage: sdk.psApiLib.Storage.EXTERNAL,
		}

		const output = {
		href: await awsLib.getSignedUrl('putObject', 'output/test01.png'),
		storage: sdk.psApiLib.Storage.EXTERNAL,
		type: sdk.psApiLib.MimeType.PNG
		}

		const job = await client.createCutout(input, output)
		console.log(`Response: ${JSON.stringify(job,null,2)}\n`)
		console.log(`Output File: ${await awsLib.getSignedUrl('getObject', 'output/test01.png')}\n`)
	} catch (e) {
		console.error(e)
	}
};				
				

Resources