Suchen
Filter

Photoshop API über Powershell-Skript ansteuern

Photoshop API über Powershell-Skript ansteuern

Mit Powershell auf Photoshop API zugreifen

Powershell ist seit Jahren in aller Munde, aber selbst das aktuelle SDK von Adobe für Photoshop 2019 befasst sich nur mit Beispielen zu JavaScript, VbScript und AppleScript. Seit 2006 wird als Skriptsprache Powershell von Microsft favorisiert und mit sehr viel Herzblut den Administratoren und Programmieren schmackhaft gemacht – aber Adobe ist auf diesem Ohr leider leicht schwerhörig.

Schaut man sich das Adobe Photoshop SDK an, ist die Umsetzung ist mit entsprechendem Hintergrundwissen natürlich möglich. Aber besonders für Neueinsteiger oder Umsteiger von VbScript schwierig.

Geht man über die Suchmaschinen auf Beispieljagd, stellt man schnell fest, dass Powershell eigentlich die Skript-Sprache ist. Besonders seit es Powershell 6.0 gibt und diese Sprache nicht nur unter Windows, sondern auch auf Linux- und Apple-Systemen zum Einsatz kommt. Umso mehr verwundert es einen, dass es so gut wie keine Beispiele hierzu gibt.

Was liegt näher als Photoshop über Powershell anzusteuern. Wir haben es probiert und es funktioniert einfach fantatisch. Aufgrund der vielen modernen Möglichkeiten lasen sich fantastische Szenarien automatisieren.

Wir haben in diesem Blog eine funktionierende Bibliothek zusammengestellt mit der es auch Anfängern möglich ist, einen Prozess nach den eigenen Bedürfnissen anzupassen. Wer gerne etwas fertiges sucht, der findet am Ende eine fertige Lösung, die wir über unsere Website anbieten.

Wir haben das Starten und Schließen von Photoshop in zwei Funktionen gepackt, die jeder für sich sehr einfach anpassen kann.

Die einzelnen Funktionen

COM-Objekte deregistrieren

Die Funktion "Unregister.ComObject" entfernt die Instanzen von Photoshop. Diese Funktion ist für das Freigeben beliebiger Com-Objekte sinnvoll.

Function Unregister-ComObject($Reference, $ObjectName) {
try {
if ($Reference) {
[System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$Reference) | out-null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
Start-Sleep -Milliseconds 500
$Reference = $null
} else { Write-Host "WARNING! Object '$Objectname' was not instantiated before.! $_" -foregroundcolor "magenta" }
} catch {
Write-Host "ERROR! Exception occured, releasing object '$Objectname' failed! $_" -foregroundcolor "red"
}
}

Die Funktion Set-CloseWindow schliesst Windows-Anwendungen, die über einen Fenstertitel erreichbar sind. Hierzu ist eine Windows API notwendig, die in die Powershell-Funktion eingebettet wird.

Windows-Anwendung schließen

$WinApi = @"
using System;
using System.Runtime.InteropServices;
public class WinApi {
[DllImport("user32.dll")]
public static extern int PostMessage(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam);
}
"@
Add-Type $WinApi

function Set-CloseWindow($proc) {
try {
$p = Get-Process | Where-Object {$_.mainWindowTItle } | Where-Object {$_.Name -like "$proc"}
if ($p) {
$h = $p.MainWindowHandle
if ($h) {
[void] [WinApi]::PostMessage($h, 0x10, 0, 0)
} else { Write-Host "WARNING: No valid handle found for '$Proc'" -foregroundcolor "magenta" }
} else { Write-Host "WARNING: No process found for '$Proc'" -foregroundcolor "magenta" }
} catch {
Write-Host "ERROR: Exception occured, the application '$Proc' could not be closed. $_" -foregroundcolor "red"
}
}

Über Open-Photoshop wird Photoshop gestartet, wenn das Programm zuvor schon gestartet wurde, wird automatisch diese Instanz verwendet. Zusätzlich wird das Export-Objekt instanziert. Die Export-Funktion ist auf die Erzeugung von Web-optimierten Bildern optimiert.

Photoshop starten und beenden

Function Open-Photoshop() {
[int] $PsPixels = 1
[int] $PsDisplayNoDialogs = 3

try {
$Script:PsObj = New-Object -ComObject "Photoshop.Application.130"
$Script:ExportObj = New-Object -ComObject "Photoshop.ExportOptionsSaveForWeb.130"

# Save Defaults
$Script:OldRulerUnits = $Script:PsObj.Preferences.RulerUnits
$Script:OldTypeUnits = $Script:PsObj.Preferences.TypeUnits
$Script:OldDisplayDialogs = $Script:PsObj.DisplayDialogs

# Set our Defaults
$Script:PsObj.Preferences.RulerUnits = $PsPixels
$Script:PsObj.Preferences.TypeUnits = $PsPixels
$Script:PsObj.DisplayDialogs = $PsDisplayNoDialogs
Return $True
} catch {
Write-Host "ERROR: Exception occured creating photoshop.application object. $_" -foregroundcolor "red"
Return $false
}
}

Am Ende des Exports werden die ComObjekte wieder freigegeben und eine CloseWindow-Message an das Fenster gesendet - Photoshop wird beendet.

Function Close-Photoshop() {
# Restore Defaults
if ($Script:PsObj) {
$Script:PsObj.Preferences.RulerUnits = $Script:OldRulerUnits
$Script:PsObj.Preferences.TypeUnits = $Script:OldTypeUnits
$Script:PsObj.DisplayDialogs = $Script:OldDisplayDialogs
}

Unregister-ComObject $Script:ExportObj "Photoshop.ExportOptionsSaveForWeb"
Unregister-ComObject $Script:PsObj "Photoshop.Application"
Set-CloseWindow "photoshop"
}

Bild im PSD-Format in PNG exportieren

Die Kernfunktion exportiert das geladene Bild in das PNG-Format.


Function Export-Png([string] $FilePath) {
try {
[int] $PsSavePNG = 13
[int] $PsExportSAVEFORWEB = 2
[int] $PsDoNotSaveChanges = 2

$Doc = $Script:PsObj.Open($FilePath)
$Script:ExportObj.format = $PsSavePNG
$Script:ExportObj.PNG8 = $True
$Script:ExportObj.Transparency = $True
$Script:ExportObj.Interlaced = $True
$Script:ExportObj.Quality = 8
$FName = [io.path]::ChangeExtension($FilePath, "png")
$Doc.Export($FName,$PsExportSAVEFORWEB, $Script:ExportObj)
$Script:PsObj.ActiveDocument.Close($PsDoNotSaveChanges)
} catch {
Write-Host "ERROR: Exception occured on exporting png for the web. $_" -foregroundcolor "red"
Return $false
}
Return $true
}

Hauptroutine

Das vereinfachte Hauptprogramm konvertiert die Datei "test.psd" vom Desktop in das png-Format.

if (Open-Photoshop) {
$DesktopPath = [Environment]::GetFolderPath("Desktop")
Export-Png "$DesktopPath\test.psd" | Out-Null
Close-Photoshop
}

Diese wenigen Funktionen erlauben es, eine Photoshop-Datei im PSD-format zu laden und als PNG optimiert für das Web zu exportieren. Auf der Adobe Webseite findet man die Beschreibung zum SDK unter https://www.adobe.com/devnet/photoshop/scripting.html und kann dieses einfache Beispiel sehr schnell zu einer komplexen Anwendung ausbauen.

Download

Das hier beschriebene Besipiel-Skrip kann über Github kostenfrei geladen werden. GitHub: Eulanda/PsPhotoshopApi

Komplexeres Export-Skript

Wir haben dies gemacht und ein knapp 1000 zeiliges Powershell-Skript erstellt. Es durchsucht ein Verzeichnis nach psd-Dateien - auf Wunsch auch rekursiv mit Unterordnern - und exportiert das Bild wahlweise als png oder jpg-Datei. Über weitere Parameter hat man Einfluss auf die Bildqualität, Transparenz bei png-Bildern oder Interlaced. Letzteres erlaubt es bereits ein Bild während des Ladens anzuzeigen.

Jede psd-Datei wird mit einer Prüfsummer versehen, so dass bei mehrfachem Aufruf des Skripts nur geänderte psd-Dateien erneut konvertiert werden. Durc Löschen der Prüfsummendatei lassen sich natürlich jederzeit wieder alle Bilder erneut exportieren.

Das Skript unterstützt ferner den -verbose Parameter mit erweiterten Bildschirmausgaben sowie den Parameter "-whatif" der einen export simiuliert und am Ende anzeigt wieviele psd-dateien identisch, geändert, neu oder inzwischen vom Datenträger gelöscht wurden.

Das Zielverzeichnis kann auch ein Cloud-Laufwerk wie Onedrive sein. Bevor das Bild geladen wird, testet eine Routine, ob die Bild-Datei beschreibbar ist und damit nicht in diesem Moment in der Synchronisation ist. Die Wartezeit, also der Timeout bis das Programm mit dem nächsten Bild fortfährt kann im Skript eingestellt werden.

Das Skript PsPsdConvert.ps1 kann mehrfach täglich aufgerufen werden und konvertiert die PSD-Dateien, die zuvor noch nicht konvertiert wurden. Diese Lösung eignet sich beispielsweise um eine Shop-Schnittstelle in den Workflow der Grafikabteilung einzubinden.

Preis: 49.- EUR inkl. MwSt.

Zum fertigen Produkt: PSD Convert

Einen Kommentar hinterlassen