Introduction
Guest Author
This is a guest post by Daniel Koestler, an Adobe applications developer. This post will explain how to connect your Flash, Flex, and AIR apps to Photoshop using the Photoshop Touch SDK. The author created the Photoshop Touch SDK for AS3 with help from Renaun Erickson, an Adobe developer evangelist. This part of the SDK is a SWC distributed in the freely available download.
This article will tell you how to create a new project, connect to Photoshop, and send simple commands back and forth. There are additional resources at the end of the article, which will guide you through more advanced steps.
What is the Photoshop Touch SDK?
The Photoshop Touch SDK is a collection of APIs that allow virtually any device to connect to and control Photoshop, using any Internet or WiFi connection. For the first time, you can interface with Photoshop directly, and use this to create mobile, desktop, or web applications that are tailored to the needs of creative professionals or casual-creative users.
The Photoshop Touch SDK is available for free from Adobe, and works with Photoshop CS5 12.0.4 and above. It also includes a SWC library, which contain the APIs that this article covers. This SWC library, called the Photoshop Touch SDK for AS3, allows you to write very simple ActionScript 3 code in any Flash, AIR, or Flex application, and saves you from doing tedious socket-level work. As you’ll hopefully discover, these AS3 APIs are flexible and easy-to-use, and will allow you to leverage the portability of Flash, versatility of Flex, and power of ActionScript 3 to help you realize your vision for designing creative apps.
Sample Code
As you follow along, you may want to refer to the sample code, which contains a project that’s been created by following this blog post. See the Additional Resources section for information about an upcoming ADC article, which will also cover more advanced topics.
Table of Contents:
Creating a Project
Connecting to Photoshop
Sending Commands to Photoshop
Summary
Additional Resources
Requirements
Software
- Photoshop CS 5 12.0.4 or later (update CS 5 from within Photoshop)
- Flash Builder 4.5 (or an IDE of your choice) with the Flex 4.5 SDK
Libraries
- Photoshop Touch SDK (http://www.adobe.com/devnet/photoshop.html)
- as3corelib (https://github.com/mikechambers/as3corelib)
- as3crypto (https://code.google.com/p/as3crypto/)
- StructuredLogTestingSDK (for logging) (https://code.google.com/p/structuredlogtesting/)
Creating a Project
Step 1: Create a new Flex Mobile Project in Flash Builder
The first step is to create a new Flex mobile project. Although we’re using Flex, the Flash runtime runs on a variety of platforms and devices, so you could just as easily create an AS3 or AIR project. For this article, though, we’ll focus on creating a mobile Flex app.
- Open Flash Builder and go to
File -> New. SelectFlex Mobile Project. - Enter a project name, and choose a location. Click next.
- Make sure Google Android is your target platform, and select “
View-Based application.” - Name your initial view “
LoginView.” It’s here that you’ll write code to handle the connection to Photoshop. - Click finish to complete the new Flex mobile project.
Step 2: Link to the Photoshop Touch SDK library
The Photoshop Touch SDK includes a file called PhotoshopTouchSDK.swc. This is a pre-compiled library that you can integrate into any Flash or Flex applications, which provides APIs to connect to and control Photoshop. This part of the library is open source, and you are free to modify and learn from the code (in accordance with the accompanying EULA and/or license agreement).
When you downloaded and extracted the Photoshop Touch SDK from the Adobe site (http://www.adobe.com/devnet/photoshop.html), it will have created the PhotoshopTouchSDK.swc file in the following relative location:
(some directory)\samples\air\photoshoptouchsdk\bin\PhotoshopTouchSDK.swc
- Locate the
PhotoshopTouchSDK.swcfile in the extracted files. - Copy
PhotoshopTouchSDK.swcand paste it in the “libs” folder inside your project directory. You can do this from within Flash Builder, or using Explorer/Finder/bash/etc.
Step 3: Link to the other required libraries
The file (some directory)\samples\air\photoshoptouchsdk\README.txt will indicate the complete list of libraries that are necessary to use the APIs. At the time of this writing, there are three additional libraries you have to include:
- as3corelib (https://github.com/mikechambers/as3corelib)
- as3crypto (https://code.google.com/p/as3crypto/)
- StructuredLogTestingSDK (for logging) (https://code.google.com/p/structuredlogtesting/)
Obtaining these libraries is relatively straight-forward. Follow the included links (or use Google). At the time of this writing, you can take the following steps on the libraries’ respective sites:
- Click the grey “
Downloads” button for as3corelib and obtain “as3corelib-.93.zip.” Extract this and open “lib,” and you’ll see theas3corelib.swcfile. - For as3crypto, click the “
Downloads” link and obtain “as3crypto.swc.” - For StructuredLogTestingSDK, click the “
Downloads” link and get “StructuredLogTestingSDK-1.3.swc.”
Take these three SWCs and drop them into the “libs” directory in your project, as you did with the PhotoshopTouchSDK SWC.
Connecting to Photoshop
Overview
The PhotoshopTouchSDK includes a class called PhotoshopConnection, which provides functions and dispatches events for managing the connection state with Photoshop. You’ll need to call functions such as connect(), initEncryption(), and (to save time for future connections) initEncryptionFromKey(). You’ll need to listen for PhotoshopEvents such as PhotoshopEvent.CONNECTED, ENCRYPTION_SUCCESS, and ERROR.
Connecting to Photoshop using this class is a three step process, barring any communication or password problems:
- Create a new
PhotoshopConnectionand listen for events - Call
connect()on your instance of thePhotoshopConnection - After a successful connection, initialize encryption using either
initEncryption()or (if you’ve saved the user’s key withgetKey()),initEncryptionFromKey()
After these steps have been completed, you may send and receive data with Photoshop. As we code these features into the mobile application, we’ll create data structures that will allow you to easily add functionality later in this article.
Step 1: Create a singleton Model, to establish a MVC design
Our application needs to create a PhotoshopConnection, but we want to store it in a location where it can be conveniently accessed by various parts of our UI (the View in the Model-View-Controller design pattern). Thus, we’ll create a Model in which to store Object references, constants, and variables.
- Right click your project in Flash Builder, and choose
New ActionScript Class - Enter the string “
model” as the package - Name the Class “
Model“ - Click Finish
We now need to add a static variable to this class, a function called getInstance() which returns that variable, and, finally, a Bindable, public variable that will store our PhotoshopConnection. Enter the following code inside of public class Model { ... }
private static var _inst:Model; [Bindable] public var photoshopConn:PhotoshopConnection; public function Model() { } public static function getInstance():Model { if ( !_inst ) { _inst = new Model(); } return _inst; }
We can now reference the variable photoshopConn from either AS3 or Flex code, simply by calling Model.getInstance() and referencing photoshopConn. I.e., Model.getInstance().photoshopConn.
Step 2: Instantiate the PhotoshopConnection and listen for events
We’ll instantiate the PhotoshopConnection the first time the user attempts to connect, but it would be a good idea to create initialization code in your own applications, to handle things like reading the hostname and password from disk, managing the user’s key and preferences, etc.
Open your views/LoginView.mxml file. We’ll allow the user to connect to Photoshop using a Spark Button, and they’ll have to enter the hostname and password using s:TextInput components. Type the following into the DisplayList on your LoginView Class:
<fx:Script> <![CDATA[ protected function loginButton_clickHandler(event:MouseEvent):void { // TODO Auto-generated method stub } ]]> </fx:Script> <s:VGroup width="100%" height="100%"> <s:Label text="Hostname"/> <s:TextInput id="hostname" text="192.168.1.10"/> <s:Label text="Password"/> <s:TextInput id="password" displayAsPassword="true" text="photoshop"/> <s:Button id="loginButton" label="Login" click="loginButton_clickHandler(event)"/> </s:VGroup> </fx:Script>
You’ll see that we’ve created two TextInput components and a Button, as well as an fx:Script tag that will contain some click-handler logic. When this button is pressed, we want to create a new PhotoshopConnection, and listen for events. Thus, type the following, so that your fx:Script tag looks like this:
<fx:Script> <![CDATA[ import com.adobe.photoshop.connection.PhotoshopConnection; import model.Model; protected function loginButton_clickHandler(event:MouseEvent):void { if ( !Model.getInstance().photoshopConn ) { createNewConnection(); } } private function createNewConnection():void { var m:Model = Model.getInstance(); m.photoshopConn = new PhotoshopConnection(); } ]]> </fx:Script>
We’ve created a function called createNewConnection(), which is called if the photoshopConn variable is null. We now have to attach event listeners to this new PhotoshopConnection. Add the following to the bottom of your createNewConnection function:
m.photoshopConn.addEventListener(PhotoshopEvent.CONNECTED,onConnected);
m.photoshopConn.addEventListener(PhotoshopEvent.ENCRYPTION_SUCCESS,onEncrypted);
m.photoshopConn.addEventListener(PhotoshopEvent.ERROR,onError);
Of course, we now have to create the functions onConnected, onEncrypted, and onError, in which we’ll put the application logic for handling these eventualities.
private function onConnected(pe:PhotoshopEvent):void { trace("Connected established."); } private function onEncrypted(pe:PhotoshopEvent):void { trace("Encryption was successful"); } private function onError(pe:PhotoshopEvent):void { trace("There was an error while connecting!"); }
With these functions created, we’re ready to try and connect to Photoshop. It’s always a good idea to remove event listeners when you’re not using them, however, so create a function called cleanUp(), and remove each of those three event listeners from the photoshopConn instance. We’ll call this function once we’re ready to switch Views in the application (after successfully encrypting the connection).
Step 3: Call connect()
As you’ll see, connecting to Photoshop is very simple. In your click handler function for the “Login” button, add the following code to the bottom of the function:
Model.getInstance().photoshopConn.connect(this.hostname.text);
As the asdocs for the connect() function note:
Opens a Photoshop data connection to Photoshop.
You may call this function before you call initEncryption(), but you will have to initialize the encryption before you can successfully communicate with Photoshop.Parameters
serverName:String – IP address or resolvable hostname of the serverserverPort:int (default = 49494) – Port to connect to. Default is 49494
After this function has been called, the API will attempt to connect. It will dispatch the necessary events during this process.
Step 4: Initialize encryption, and move on to the next View.
As the docs indicate, a successful connection will cause PhotoshopConnection to dispatch a PhotoshopEvent.CONNECTED event. Since we’re listening for this event, our function onConnected will be called. It’s here that we’ll make the call to initialize encryption. Thus, make your onConnected() function look like the following:
private function onConnected(pe:PhotoshopEvent):void { trace("Connected established. Encrypting connection. This will take a few seconds..."); Model.getInstance().photoshopConn.initEncryption(this.password.text); }
If this is successful, our code will enter the onEncrypted() event handler. At that point, we’re ready to send data to and from Photoshop. To prepare for this step:
- Right click your project and select
New MXML Component - Put it in the package “
views,” and name it “HomeView“ - Click “Finish”
Now, we just have to push a HomeView onto the ViewNavigator:
private function onEncrypted(pe:PhotoshopEvent):void { trace("Encryption was successful. Cleaning up event listeners."); this.cleanUp(); trace("Proceeding to the 'Home' View."); this.navigator.pushView(HomeView); }
We’ve also cleaned up the event listeners, which you should do wherever possible to prevent memory leaks. You should now test your project. In the next section, we’ll send some simple commands to Photoshop.
Sending Commands to Photoshop
At this point in your application, you’ve used the Photoshop Touch SDK to establish an encrypted connection to Photoshop. You’re ready to send and receive data. With a single function call, you can push raw bytes to Photoshop, and—if you wish—you could create your own datagram format that encapsulates these bytes. The Photoshop Touch SDK includes ActionScript APIs to do this for you, however, and provides functions which minimize the amount of low-level code you have to write.
The first of these classes is the MessageDispatcher. As the asdocs state:
The MessageDispatcher is an abstraction layer on top of the PhotoshopConnection, which makes it easy to send properly formatted messages to Photoshop. You can either call some of the helper functions that will create and dispatch the messages for you (createNewDocument, requestThumbnail, etc.), or create your own IMessage and call sendMessage().
Since we’re just beginning, we will indeed use the simplest of these method calls. We’ll create an s:Button in our HomeView that tells Photoshop to create a new document. Photoshop will respond with an id referencing the document.
Step 1: Create a MessageDispatcher instance
Before we can use the MessageDispatcher, we have to create a new instance of it, and give it a reference to our existing PhotoshopConnection (this allows the MessageDispatcher to use the connection that we initialized in the previous section). We’ll store this instance in the Model, just like we do with the photoshopConn variable. Thus, in your Model.mxml file, add the following:
[Bindable] public var messageDisp:MessageDispatcher;
The Bindable property allows us to use this variable in Flex and/or attach our own ChangeWatchers, should the need arise.
We now have to instantiate this variable. Open your HomeView Class and generate an event handler for the initialize event. Type the following:
protected function view1_initializeHandler(event:FlexEvent):void { var m:Model = Model.getInstance(); if ( !m.messageDisp ) { m.messageDisp = new MessageDispatcher(m.photoshopConn); } }
As you can see, this code will only create a MessageDispatcher should it not already exist, and it’ll pass a reference to the existing PhotoshopConnection. You’ll want to handle initialization logic like this in a dedicated initialization controller, should you be creating a more robust application. We’re now ready to use this Object.
Step 2: Listen for Photoshop’s Response(s)
We could send the command at this point, but, should an error occur, our application would never hear about it. Thus, it’s necessary to attach some event listeners to the PhotoshopConnection. There are three events that are particularly useful for handling message-related communication:
ErrorEvent: Dispatched when there’s been an error in either data transfer, encryption, or connection management.ErrorMessageReceivedEvent: Dispatched when an error message is received from Photoshop.MessageReceivedEvent: Dispatched when a message is received from Photoshop.
There are a number of other useful events, such as MessageSentEvent, ProgressEvent, and ImageReceivedEvent, but we won’t be using them for this example.
Inside of your HomeView initialization handler, add the following to attach event listeners to the PhotoshopConnection:
m.photoshopConn.addEventListener(PhotoshopEvent.ERROR,onError); m.photoshopConn.addEventListener(PhotoshopMessageEvent.MESSAGE_RECEIVED,onMessage); m.photoshopConn.addEventListener(PhotoshopMessageEvent.ERROR_MESSAGE_RECEIVED,onErrorMessage);
Of course, you now have to create three functions: onError, onMessage, and onErrorMessage:
private function onError(pe:PhotoshopEvent):void { trace("Error while sending a message!"); } private function onMessage(pme:PhotoshopMessageEvent):void { trace("We received a message from Photoshop"); } private function onErrorMessage(pme:PhotoshopMessageEvent):void { trace("We received an error message from Photoshop"); }
As before, it’s a good idea to clean up event listeners that you no longer need. So create a cleanUp() function that calls removeEventListener for those three events.
Step 3: Send a Message to Photoshop
We’re finally ready to make Photoshop do something! We’ll ask it to do something simple: create a new document. If this is successful, Photoshop will send a message in response that contains the id of the created document.
First, use MXML to create a Spark Button inside of the DisplayList:
<s:Button id="createNewDocument" label="Create a New Document" click="createNewDocument_clickHandler(event)"/>
Inside of the click handler for this Button, we’ll tell the MessageDispatcher to dispatch a Message to Photoshop.
Model.getInstance().messageDisp.createNewDocument();
Pay particular attention to the default parameters in that function call. As the ASDocs say:
Dispatches a message instructing Photoshop to create a new document with the specified parameters.
Parameters
transactionID:int (default = -1) – You can override the default value if you wish to send the message with a custom transactionID.
If you leave it as -1, the message dispatcher will keep track of transactionIDs for you.
It’s recommended that you don’t mix these two systems, as it might lead to conflicts and unpredictable behavior.width:int (default = 640) – The width of the document to create, in pixels
height:int (default = 480) – The height of the document to create, in pixels
ppi:int (default = 72) – The density of the document to create, in pixels per inch
Since we’re creating a relatively simply application, we don’t need the added flexibility that comes with managing our own transaction IDs. We’ve also accepted the default values for the width, height, and PPI of the document that’s to be created.
You should run your application. Once you press the button, you should see the appropriate trace statements, and Photoshop will create the document. In my case, Photoshop responded with a TextMessage. By inspecting the pme.message.message field, I was able to see that Photoshop responded with “[Document Untitled-1]“–the ID of the document.
To finish this step, you should add an event listener for the “removing” event to the View; inside of the handler, call this.cleanUp(), to remove the event listeners that we no longer need.
Summary
At this point you’ve been shown how to: create a project; link to the Photoshop Touch SDK libraries; set up a Model-View architecture for managing the Photoshop objects; connect to Photoshop and manage encryption; and send messages while listening for responses.
There are still a number of tasks that you may want your application to perform, and the SDK can help you with these. For example, you can use the SDK to:
- Listen for foreground and background color changes
- Listen for tool change events
- Be notified when the user modifies a document
- Change the brush size, the currently selected tool, or the document’s properties
- Send other, custom commands
These tasks are made possible by using the SubscriptionManager, TransactionManager and Photoshop’s ScriptListener plug-in. Please see Daniel Koestler’s ADC article and blog to learn about these tasks, and to get tutorials and sample code that’ll help you take your applications further.
Additional Resources
An ADC article covering the content of this blog post (as well as more advanced topics) will be available next week. Please check Daniel Koestler’s blog http://blogs.adobe.com/koestler, where he’ll post the article as soon as it’s available. You may also want to follow him on Twitter: @antiChipotle.
Update 6/16/2011: The ADC Article is now published. That article contains some additional information about using the Photoshop Touch SDK.
You may want to download the sample code, which contains a project that has been created following the above steps. The ADC article contains code that demonstrates the SubscriptionManager, custom messages, and other, more advanced tasks.



Very useful article… Thanks
Question: How can I discover available Photoshop connections? Rather than providing an IP address to connect to that computer, I want to see all the available Photoshop connections to connect with. Like you guys have done with these three apps (Eazel, Color Lava, Nav).
Sounds cool but i got this.
[IOErrorEvent type="ioError" bubbles=false cancelable=false eventPhase=2 text="Error #2031: Socket Error. URL: xxx.xxx.x.xx" errorID=2031]
(i am using the photoshop CS5 12.1 trial)
At what point do you get that event? When you attempt to connect, or when you attempt to send a command?
login attempt
***
private function onError(pe:PhotoshopEvent):void
{
trace( pe.data );
trace(“There was an error while connecting!”);
}
***
[SWF] ADCTutorial.swf – 3 354 931 octets après la décompression
[IOErrorEvent type="ioError" bubbles=false cancelable=false eventPhase=2 text="Error #2031: Socket Error. URL: xxx.xx.x.xx" errorID=2031]
There was an error while connecting!
***
There could be a number of things causing that IOErrorEvent, so we need more information. The Photoshop Touch SDK uses the StructuredLogTestingSDK for its internal logging. We can turn it on and see some information that’ll help you debug.
You first have to set up a trace target, to have the SDK log via trace statements:
var traceTarget:TraceTarget = new TraceTarget();traceTarget.includeCategory = true;
traceTarget.includeDate = true;
traceTarget.includeLevel = true;
traceTarget.includeTime = true;
Then call two static functions on SLog; the first function will add the trace target, and the second will test the logger’s ability to output:
SLog.addTarget(traceTarget);SLog.debug(this,"Logging initialized.");
You may have to link to StructureLogTestingSDK.swc. You can get it here: https://code.google.com/p/structuredlogtesting/downloads/list
If that link stops working, its homepage is: http://structuredlogs.com/
Pingback: John Nack on Adobe : News for Suite developers
I’m always getting error 2031 when trying to connect to any socket from Flex Mobile projects, I tried to serve crossdomain.xml, security policy files – no luck. Sockets are broken in Flex Mobile, I gave up.
Hey John,
Would you be able to provide me with a project where you keep getting #2031? crossdomain.xml and policy files shouldn’t be necessary, though it’s possible you’re trying to connect in a way I didn’t anticipate.
(Did you try the usual things, such as switching networks, disabling firewalls, manually verifying the IP, etc?)
-Dan
The reason for the error #2031 is the lack of enabling Photoshop to accept incoming credentials and failing to set a password. To correct this issue, you must edit your Photoshop settings.
To allow remote connections:
Open Photoshop.
Choose the Edit menu.
Choose the “Remote Connections…” option.
You may leave the Service Name as is, or you can specify a different one.
Enter a password, at least 6 characters in length.
Check the box to “Enable Remote Connections”.
Click OK.
Now when you run the AIR app from this tutorial, your app will be able to connect to Photoshop, properly authenticate, and communicate.
Also, be sure to enter your correct password in the Login window in this app when you run it. Alternatively, you can also edit the source to pre-populate your password by changing the text value of the text input field.
Hello, I want to know how to send a Image to the Photoshop? Because I had send an Image to the Photoshop, but I don’t know how to let the Photoshop to open this Image.I don’t
know Where can I find this Image.
If you can give me an example, it’s best!
Thank you!
If you have Photoshop installed on your system, you can use File > Open from within Photoshop and navigate to your image files to open them.
If you’re on a Mac, then you can also drag an image to the Photoshop icon on your Dock
On Windows 7, you can rightclick an image and choose “Open With > Adobe Photoshop CS6″
Hi. One of my computers is not showing the IPv4 address inside Photoshop (office network). Any reason for that? I can’t connect with a prototype I’m working on.
Another question, there is any way to get a list of a discovered connections? You know, some applications like Acquire do this.
Thanks!
Hi Daniel,
We’d need more info like OS/platform. Does Photoshop connect to the network correctly if you choose Help>Photoshop Support Center… from Photoshop?
If you haven’t already, I’d post more details on the SDK/companion app forum: http://forums.adobe.com/community/photoshop/photoshop_sdk?view=overview
Hi Jeffrey,
Thanks for your reply! Yes, it is connecting correctly with the network. And apps like ‘Live View’ or ‘Acquire’ are connecting correctly with it. That’s why I was asking about ‘discovered connections’.
I’m running PS 13.1.2 on OSX 10.7.5
I will check the forum