Photoshop Plugin mit HTML5/CSS/JavaScript
Photoshop Plugin mit HTML5/CSS/JavaScript
Nebst der Programmierung von eigenen Tools mit der breiten Anzahl an Sprachen und GUI Frameworks von Null auf, hat mich die Programmierung von Plugins für bestehende Software schon jeher interessiert. Das Potenzial, ein Werkzeug, das man in seinem Alltag benutzt, zu erweitern, um den eigenen Bedürfnissen anzupassen, erweckt in mir das Gefühl als sässe ich nicht vor einem Rechner, mehr als fände ich mich in einer Werkstatt wieder.Und weil ich mich in diesen letzten Wochen mit Photoshop Plugins beschäftigt habe, will ich euch in diesem Blog zeigen, wie man ein Plugin für Photoshop mit HTML5 und JavaScript entwickelt. Vielleicht, falls dies euer erster Plugin ist, wird dieses “Tutorial” ein Anstoss für euch, das oben beschriebene Gefühl selbst durchzuleben. Oder vielleicht bin ich einfach übertrieben enthusiastisch darüber, dass ich endlich die Gelegenheit dazu gefunden habe, ein Plugin für eines meiner Lieblingsprogramme zu entwickeln. Wie dem auch sei, legen wir los:
Vorab, ein paar allgemeine Informationen, wie das HTML5 Plugin in Photoshop funktioniert:
- Ihr entwickelt ein ganz übliches, normales UI als würdet Ihr für das Web HTML schreiben. Da Photoshop seit CS5(? oder CS6?) HTML5 Plugins unterstütz, könnt Ihr euer Tool mit allen gängigen Frameworks schreiben. Angular, Vue, React etc., macht keinen Unterschied, das Tool das als Panel in Photoshop erscheint könnt Ihr euch wie eine Webseite in Photoshop vorstellen. Auch Layout Frameworks wie Bootstrap könnt hier verwenden. In diesem Fenster könnt Ihr zusätzlich auch modernes JavaScript schreiben, sprich ES6+.
- Um bestimmte Routinen in Photoshop aufzurufen, delegiert Ihr mit einem speziellen Interface (CSInterface.js) eure Aufrufe von eurer “Webseite”-Panel zu Photoshop, der euren Skript dann mit euren vorgegeben Werten in Photoshop ausführt. Es gibt also zwei “Mengen” an Scripts die Ihr schreibt, eine für das HTML5 Plugin selbst, und eine für die Funktionen und Routinen, die Ihr innerhalb von Photoshop per Interface aufruft. Ihr könnt also Routinen und Funktionen innerhalb von Photoshop definieren, und diese per HTML5 Plugin aufrufen.
- Hier ist aber Achtung angesagt, denn: Photoshop Scripting sieht sehr nach JavaScript aus, aber ist es nicht! Oder zumindest nicht modernes JavaScript. Soweit ich urteilen konnte, ist der Funktionsumfang von “JavaScript” (ab nun als PhotoshopScript referenziert) in Photoshop auf Stufe JavaScript 1.2 oder 1.3. Sehr limitierend, wie ich gefunden habe, vor allem wenn man schon ein bisschen mit dem moderneren JavaScript Syntax sich angefreundet hat, realisiert man schnell, dass man vieles in PhotoshopScript selber machen muss. Kein map/reduce, kein .filter(…), nicht mal ein .push(…) für Arrays.
- Zusätzlich erlaubt Photoshop per Scripting nur bestimmte Automatisierungen. Man kann zwar sehr viel in dieser limitierenden Umgebung anstellen, doch sollte man darüber informiert sein. Man kann sich zum Beispiel nicht per PhotoshopScript an die meisten Events (falls überhaupt) von Photoshop binden. Dies mag aber nicht nur eine Limitation für HTML5 Plugins sein. In meiner Recherche nach C++ basierten Photoshop Plugins musste ich leider feststellen, dass Photoshop nur bestimmte Aspekte des Programms ansprechen lässt, sprich es gibt bestimmte Kategorien von Plugins die man entwickeln kann und man sitzt in diesen Kategorien fest. Zwar kann man mit C++ Plugins weitaus mehr in Photoshop anstellen, doch kann man auch mit C++ nicht einfach blind das Programm erweitern. Dazu jedoch werde ich später was schreiben, wenn ich meinen ersten Plugin für Photoshop mit C++ geschrieben habe. Bis dann sollte ein HTML5 Plugin für viele eurer Bedürfnisse reichen. Man bedenke, dass Plugins wie Coolorus auch auf Basis HTML5 Plugins geschrieben wurden. Und wenn ich mir vor Augen führe, was Plugins wie Coolorus einem anbieten, so drückt einem die “Limitation” nicht so stark auf die Hände.
OK, nun da diese allgemeinen Informationen aus dem Weg geräumt sind, wollen wir uns mit dem Setup beschäftigen.
Was braucht Ihr um ein HTML5 Plugin zu entwickeln?
1) Ganz wenig, denn Ihr könnt euer “Plugin” wie eine Webseite schreiben. Was Ihr zusätzlich braucht ist das CSXS Dossier mit dem manifest.xml. Anhand des manifest.xml’s erkennt Photoshop, welche Version von CSXS (Runtime für Photoshop Scripts) benützt wird, für welche Version von Photoshop das Plugin entwickelt wurde und eine Menge anderer Informationen, die für die Integration mit Photoshop gedacht sind. Ihr könnt euch das manifest.xml mit Plugins von anderen Tools automatisch generieren lassen (z.B. Visual Studio Code) oder Ihr könnt mein manifest.xml übernehmen und für eure Applikation anpassen.
https://github.com/Zmote/PhotoshopTestPanel/blob/master/CSXS/manifest.xml
Man kann im manifest.xml weit mehr Informationen einbetten als was in meinem manifest.xml vorzufinden ist. Ich rate hier, einfach manifest.xml’s von anderen Photoshop Plugins auf Github euch anzuschauen, damit Ihr ein Gefühl dafür bekommt, was, wofür gebraucht wird. Die Tag’s sind weitgehend selbsterklärend.
Hier muss ich jedoch einige Tags speziell anpsrechen, bevor wir weiterfahren:
<ScriptPath>…URL_ZU_EUREM_PHOTOSHOP_SCRIPT…</ScriptPath>
Der hier angegeben Script wird beim Starten eures Panels in Photoshop geladen. Fortan sind die Funktionen, die Ihr bereitgestellt habt, innerhalb von Photoshop verfügbar. Doch da man hier nur eine Datei angeben kann, ist dies anfänglich sehr limitierend. Denn entwickelt man eine etwas grössere Applikation, so will man diese für die Übersicht in mehrere Einheiten unterteilen. Ich werde im Laufe dieses Tutorials zeigen, wie Ihr dynamisch weitere PhotoshopScript - Dateien in Photoshop laden könnt.
Im
<MainPath>…URL_ZU_EUREM_EINSTIGES_HTML…</MainPath>
gibt Ihr den Pfad zu eurer Einstiegshtml an. Wenn dieses HTML geladen wird, werden auch automatisch alle eurer Scripts und CSS geladen, wie in einem Browser.
Und zuletzt
<MinSize>…</MinSize> und <MaxSize></MaxSize>
Wie die Namen schon verraten, steuert Ihr hierüber die Grösse eures Panels.
Ist der anfängliche Setup mal erledigt, kopiert Ihr eure Dateistruktur nach
…\AppData\Roaming\Adobe\CEP\extensions
Bild 1: Dateistruktur meines TestPanels
AppData findet Ihr in eurem Benutzerordner, also in dem Ordner wo auch z.B. Dokumente, Downloads etc. platziert sind.
Startet Ihr jetzt Photoshop neu, könnt Ihr über Window > Extensions euer Plugin laden. Erhält Ihr eine Fehler? Dies ist normal. Denn damit euer Plugin im Releasemode von Photoshop aufgerufen werden kann, muss es digital signiert sein. Doch da wir zurzeit nicht daran interessiert sind, unser Plugin im Web zu verteilen, stellen wir Photoshop für die Entwicklung auf den Debugmodus um, dies geht wie folgt:
Ihr müsst in der Registry von Windows, Photoshop auf Debugmode stellen, also:
1) Windows + R
2) “regedit” eintippen und ausführen.
3) Das Registry Fenster öffnet sich.
4) Navigiert nach: HKEY_CURRENT_USER/Software/Adobe/CSXS.8 und fügt hier einen neuen Wert (Zeichenkette) mit Namen “PlayerDebugMode”. Setzt den Wert dieses Schlüssels auf 1.
Startet Ihr Photoshop nun neu, wird dieser im Debugmodus gestartet und euer Panel wird angezeigt. Aber Achtung: Dies macht Photoshop nun auch empfindlich gegenüber anderen Panels die in Photoshop laufen, ie. “gefährliche” Skripts könnten ausgeführt werden. Aber falls Ihr nicht irgendiwe suspekte Plugins am Laufen habt, sollte dies kein Problem sein. Vielleicht werde ich in Zukunft auch etwas zum Signieren von Photoshop Plugins schreiben, aber für den Moment lasse ich dieses Thema hier liegen, den der Fokus hier ist das Entwickeln des Plugins, nicht die Distribution.
Bild 2: Mein gestartetes Panel in Photoshop
OK, nun lädt unser Plugin in Photoshop. Als nächstes müssen wir noch zwei Dinge erledigen, damit das Setup komplett ist:
1) CSInterface.js herunterladen und in unserer Dateistruktur einbetten. Zusätzlich müssen wir CSInterface.js in unserem HTML laden, damit die Interfacefunktionen in unseren anderen JS verfügbar werden.
2) Den Code für das dynamische Laden von PhotoshopScripts schreiben, so dass wir unseren PhotoshopScript Code in übersichtliche Einheiten einteilen können.
Fangen wir mit Nummer 1 an:
Das CSInterface.js findet Ihr hier: https://github.com/Adobe-CEP/CEP-Resources/tree/master/CEP_8.x
Das ist vom Github Repo von Adobe. Falls Ihr für ein anderes Runtime entwickeln wollt, könnt Ihr das entsprechende CSInterface im selben Repo finden (ist in Ordnern unterteilt).
Ihr könnt den Inhalt von Github direkt kopieren und in einen eigenen JS einbetten, ist nicht so wichtig. Die Funktionen, die das CSInterface.js einführt, jedoch schon. Über diese kommunizieren wir mit der Photoshop Umgebung.
Bild 3: Einbetten von CSInterface.js in unserem Einstiegshtml
Gut, nun weiter mit Nummer 2:
Erinnert Ihr euch an den <ScriptPath>…</ScriptPath> Tag im Manifest? Dies ist die jsx die beim Öffnen des Panels in Photoshop geladen und ausgeführt wird. Falls Ihr die Datei noch nicht erstellt habt, einfach in eurer Dateistruktur einen neuen Ordner jsx erstelln und darin einen main.jsx erstellen und diesen im ScriptPath referenzieren. In main.jsx schreiben wir folgenden Code:
Bild 4: PhotoshopScript mit dem Code zum dynamischen Laden von anderen PhotoshopScripts
Und rufen diesen beim Laden unseres Panels mit einem IIFE auf:
Bild 5: IIFE, das beim Laden des Panels ausgeführt wird (ist im main.js)
Was wir hier machen, ist im Prinzip ganz einfach: Im PhotoshopScript, das wir beim Öffnen des Panels in Photoshop laden, definieren wir funktionen, um dynamisch weitere PhotoshopScript - Dateien in einem bestimmten Ordner zu laden. In unserem IIFE, dass wir in einem JS das mit dem HTML geladen wird, ausführen, geben wir einfach an, wo sich unsere JSX PhotoshopScript Dateien befinden und übergeben diese unserem Haupt-PhotoshopScript, damit dieser beim Öffen des Panels alle PhotoshopScripts automatisch für uns ladet. So können wir die PhotoshopScripts( die hier so mal bemerkt, mit .jsx enden müssen) im jsx - Ordner unseres Plugins beliebig in Unterordner aufteilen und unser Haupt-PhotoshopScript wird diese automatisch finden und laden.
Dies funktioniert, weil Photoshop selbst uns die Funktion $._ext.evalFiles(file) zum Evaluieren von Script anbietet. Wir benutzen diese Funktion, laden unsere Dateien und evaluieren deren Inhalt mit dieser Funktion, wonach Sie in unserem Kontext verfügbar werden. Keine Angst, auch wenn dies eine Evaluation ist und man das in JavaScript normalerweise nie tun sollte, führen wir diese Evaluation im Photoshopkontext aus, darum kann man es getrost verwenden.
Im Bild zum IFFE Call sehen wir auch, wie man per HTML5 Panel Funktionen im Photoshopkontext per CSInterface aufruft.
Mit dieser Kombination programmiert man seine Logik und übergibt Sie dem Photoshopkontext zur Ausführung.
OK, nun haben wir alles, um unseren Plugin für Photoshop zu schreiben. Per CSInterface können von unserem HTML5 Panel aus Code im Photoshop-Kontext ausführen - Code, den wir per dynamisches Laden beim Aufruf des Panels in den Kontext von Photoshop laden. Und mit HTML5 können wir das UI und deren Logik wie eine Webseite schreiben.
Nun kommt aber der “schwierigste” Teil bei der Plugin-Entwicklung für Photoshop, auf den ich hier im Blog nicht eingehen werde; ganz einfach aus dem Grund, dass es im Umfang diesen Beiträg sprengen würde. Das, worüber ich hier spreche, ist der Umgang mit dem Photoshop DOM.
Ja, genau, Photoshop DOM, denn Photoshop besitzt für sein Scripting Interface einen DOM und dieser ist, wie der Name erraten lässt, ein Photoshop eigenes DOM. Hierfür rate ich die entsprechende Referenez von hier herunterzuladen: http://www.adobe.com/devnet/photoshop/scripting.html
Leider gibt es zum Photoshop DOM nicht so viele Einträge auf StackOverflow, dass man bestimmte Sachen schnell nachschlagen könnte. Man muss es hier leider “Old School” machen, im PDF suchen und testen. Ihr könnt euch ein bisschen in meinen PhotoshopScript’s umschauen, um euch ein anfängliches Bild zu machen: https://github.com/Zmote/PhotoshopTestPanel/tree/master/jsx
Auch rate ich euch, das ExtendScript Toolkit von Adobe herunterzuladen.
http://www.adobe.com/ch_de/products/extendscript-toolkit.html
Das Toolkit erlaubt euch PhotoshopScript direkt in Photoshop auszuführen und, was noch wichtiger ist, euren PhotoshopScript zu debuggen. Für das Schreiben von Code habe ich es jetzt nicht so besonders gut gefunden, weshalb ich meinen Code, nachdem ich es in meinem bevorzugten Editor geschrieben haben, per Copy&Paste reingeworfen habe, um es zu testen. Was das Toolkit euch auch anbietet, ist eine Übersicht für das Photoshop DOM, vor allem wenn Ihr debuggt, werden die relevanten Objekte im entsprechenden Fenster angezeigt. So könnt Ihr euch experimentell mit dem Photoshop DOM vertraut machen.
Aber auch hier gilt wieder Achtung, denn: Für was für einen Grund auch immer könnt Ihr die Biblitohek für Photoshop nicht laden, ie. Syntaxkontrolle mag an bestimmte Stellen nicht unbedingt stimmen. Ich rate euch hier für die Syntaxkontrolle die von Illustrator zu laden, da diese der von Photoshop am nahesten kommt.
Das Entwickeln von Plugins für Photoshop geht leider mit vielen Hürden einher. Ich hoffe ich konnte hier die wichtigsten auflisten.
Viel Spass mit dem Schreiben eures ersten Plugins!
Github Testpanel:
https://github.com/Zmote/PhotoshopTestPanel
Youtube Video (Vorstellung Tool, hat auch Einblicke in den Code):
https://youtu.be/retbm9ffJTg
Kommentare
Kommentar veröffentlichen