/gimp-pspi

Primary LanguageCMIT LicenseMIT

Introduction
============

This is pspi, a GIMP plug-in that interfaces to Photoshop filter plug-ins.

First, the bad news: Pspi only works on systems that understand i386
Windows executables, more specifically, DLLs. (Photoshop plug-ins are
actually DLLs.) Pspi was developed on (i386) Windows. It is also
possible to build and use it on i386 Linux, using Wine.

To build pspi, you will need the headers from the Adobe Photoshop CC
2015.5 SDK which is available at 

https://www.adobe.com/devnet/photoshop/sdk/eula.html

To build pspi on Linux, from a terminal configure it like this:

export CC=winegcc
export CXX=wineg++
./configure --with-pssdk=/path/to/pluginsdk

Before compiling on Linux, you need to fix a few glitches in the SDK
headers. Copy the adobe patch to /path/to/pluginsdk and do :

patch -p0 < adobe_photoshop_cc_sdk.diff


Debugging pspi
==============

You can set the environment variable PSPI_DEBUG to have pspi print out
various debugging messages at run-time, for instance (in a Windows
command prompt):

set PSPI_DEBUG=resource_suite:debugger

(or in a Linux shell):

export PSPI_DEBUG=ALL

See the source code for other possible values. Obviously, this
environment variable must be set before starting the GIMP (which
eventually runs pspi).

On Windows, as pspi is a Windows GUI application, to actually see the
debugging print-out, you have to start GIMP from a command line with
stdout going somewhere, for instance:

	gimp --verbose | cat

This stdout redirection will be inherited by GIMP's children, like
pspi.

Run-time setup
==============

Pspi has a search path consisting of folders where to search for
Photoshop filter plug-ins, which are files with the extension
.8BF. These folders are searched recursively.

Pspi stores info about the Photoshop plug-ins found in the pspirc file
in the user's personal GIMP directory. The first time a .8BF file is
noticed, pspi loads it and searches for the so-called "PIPL"
resources, which contain some more information about the Photoshop
plug-in, for instance where it should be located in Photoshop's Filter
menu. It gets a identical menu entry in GIMP's <Image>/Filter menu.

Unless the .8BF file changes, it isn't loaded on subsequent GIMP
starts, but only when the filter is invoked.

Also files with the extensions .EFF and .DLL are checked to see if
they are Photoshop plug-ins.

Reverse engineering
===================

The hardest thing in writing this plug-in was figuring out the stuff
in the Photoshop plug-in communication that isn't clearly
documented. To make the reverse engineering easier, I wrote a "proxy"
Photoshop plug-in, piproxy. The Windows resources of a real Photoshop
plug-in (the "target") is copied to piproxy.8bf. The target should be
moved away so that Photoshop won't find it, and instead piproxy.8bf
shouild be put where Photoshop will find it.

Thus, piproxy gets loaded when the menu entry for the original plug-in
is invoked. It then loads the original target plug-in, and starts
passing calls back and forth between Photoshop and the target, while
logging the stuff that passes through. This works fine. If you intend
to run piproxy, set the PIPROXY_LOG and PIPROXY_TARGET environment
variables. See the source code.

The piproxy sources are included, but it does not get built by
default.

After a week of late-evening hacking, the breakthrough came when I
realized that the "Handle" type in the Photoshop API is used by some
plug-ins in an undocumented way. Instead of treating a Handle as an
opaque type, they "know" that a Handle in fact is a pointer to a
pointer, and use it like that without calling the "lock" API which is
the documented way to get the pointer from a Handle.

Tor Lillqvist <tml@iki.fi>, December 2001, March 2006.
Ben Touchette <draekko.software+gimp@gmail.com> July 2016.