|
PhotoShop
Scripting
by
mlk : Hot Summer Month of 2004
V.
Non-Documented Functions: Using the Script Listener
Using the script listener
to create undocumented functions.
Well, sadly enough you cannot script everything in Photoshop (check out the
scripting limitations in the 7th chapter later
on). However, there are some functions which you can script but are not documented.
For example not all filters are documented in the Adobe documentation. If you
read the documentation, you will have come across the 'Script Listener'. The
script listener is a plug-in that records what you do in Photoshop in a log.
On windows system it will output a JavaScript log and a VBScript log.
To make that plug-in work,
here's what you have to do:
-
When you installed Scripting
(for PS 7 users) there was a folder called 'Utilities' containing the plug-in
'Scriplistener'. You'll need to place that plug-in in the 'Photoshop folder\Plug-Ins\Scripting\'
folder.
-
If you do that while
Photoshop is opened, you'll need to restart Photoshop.
|
|
Note |
The script listener will write text logs to your computer. For
windows users, the files will be placed in C:\ and will be 'ScriptingListenerJS.log'
and 'ScriptingListenerVB.log'. Macintosh will have these files
(but with AppleScript and not VBScript) on their desktops.
You can read
the 'log' files using a simple text editor. |
|
|
 |
Tip |
|
You
should turn 'off' the plug-in when you don't need it. Otherwise
it will output everything you do and end up in enormous text files
slowing down Photoshop. To turn the plug-in off, all you have to
do is change its name or its extension (add an underscore '_' somewhere
in the name for example). |
|
Reading what the script
listener outputs is indeed a real pain, and re-using it even more, most probably
because the Photoshop team decided not to elaborate it, since only a handful
of people would use it. So here I'm not going to go into complicated things
that I myself wouldn't understand.
I will use the script listener
to find out how to create circle selections in Photoshop. You noticed from earlier
scripts that it's quite easy to do a rectangular selection; all you have to
set is the four corners. Well why couldn't I do that with a circle ? Here we
have two possibilities: either finding a function that does it, or creating a
mathematical array of coordinates using cosines and sines (that's how a circle
is defined mathematically). Let's do the first option.
If you haven't done so before,
turn on the script listener (place the plug-in in the 'scripting' folder or
rename it correctly). Start or restart your Photoshop. Because Photoshop will
also record how you open the document, we will:
-
First create a large
enough document to experiment with the circle selection
-
Delete the log file created
(on your desktop for Macs or in 'C:\' for Windows), so that the only output
will be the circle selection
-
Click on the circle selection
tool in the toolbar (double Shift-M for windows users)
-
Create a circle selection
on the canvas. We could draw an ellipse but let's draw a standard circle first,
so during your selection hold 'shift' to constrain the 1:1 ratio.
-
Open up the log file.
-
(eventually close the
document and Photoshop, and rename the Script Listener plug-in so it doesn't
log next time you use Photoshop
Here's what my Photoshop
did output in the JS log file:
var id15 = charIDToTypeID( "setd" );
var desc3 = new ActionDescriptor();
var id16 = charIDToTypeID( "null" );
var ref1 = new ActionReference();
var id17 = charIDToTypeID( "Chnl"
);
var id18 = charIDToTypeID( "fsel"
);
ref1.putProperty( id17, id18 );
desc3.putReference( id16, ref1 );
var id19 = charIDToTypeID( "T " );
var desc4 = new ActionDescriptor();
var id20 = charIDToTypeID( "Top "
);
var id21 = charIDToTypeID( "#Pxl"
);
desc4.putUnitDouble( id20, id21, 15.000000
);
var id22 = charIDToTypeID( "Left"
);
var id23 = charIDToTypeID( "#Pxl"
);
desc4.putUnitDouble( id22, id23, 52.000000
);
var id24 = charIDToTypeID( "Btom"
);
var id25 = charIDToTypeID( "#Pxl"
);
desc4.putUnitDouble( id24, id25, 377.000000
);
var id26 = charIDToTypeID( "Rght"
);
var id27 = charIDToTypeID( "#Pxl"
);
desc4.putUnitDouble( id26, id27, 333.000000
);
var id28 = charIDToTypeID( "Elps" );
desc3.putObject( id19, id28, desc4 );
executeAction( id15, desc3, DialogModes.NO );
We
can see straight away where the coordinates are (here: 52;15 and 333;377)
|
|
Note |
|
Your log file might look different; because a) of your own coordinates
and b) because the id numbers (id15, id28 etc..) and descriptor
numbers (desc3, desc4, etc..) change according to your own Photoshop.
Don't worry about it. |
|
We'll try straight away to use this to see if it works. Open a new text file,
we're going to create a script. This time we will select coordinates (110;110
and 402;402) on a 600x600px canvas:
var
defaultRulerUnits = preferences.rulerUnits;
preferences.rulerUnits = Units.PIXELS;
var newDocumentRef = documents.add(600,600, 72.0, "Circles")
newDocumentRef = null;
var id15 = charIDToTypeID( "setd" );
var desc3 = new ActionDescriptor();
var id16 = charIDToTypeID( "null" );
var ref1 = new ActionReference();
var id17 = charIDToTypeID( "Chnl"
);
var id18 = charIDToTypeID( "fsel"
);
ref1.putProperty( id17, id18 );
desc3.putReference( id16, ref1 );
var id19 = charIDToTypeID( "T " );
var desc4 = new ActionDescriptor();
var id20 = charIDToTypeID( "Top "
);
var id21 = charIDToTypeID( "#Pxl"
);
desc4.putUnitDouble( id20, id21, 110.000000
);
var id22 = charIDToTypeID( "Left"
);
var id23 = charIDToTypeID( "#Pxl"
);
desc4.putUnitDouble( id22, id23, 110.000000
);
var id24 = charIDToTypeID( "Btom"
);
var id25 = charIDToTypeID( "#Pxl"
);
desc4.putUnitDouble( id24, id25, 402.000000
);
var id26 = charIDToTypeID( "Rght"
);
var id27 = charIDToTypeID( "#Pxl"
);
desc4.putUnitDouble( id26, id27, 402.000000
);
var id28 = charIDToTypeID( "Elps" );
desc3.putObject( id19, id28, desc4 );
executeAction( id15, desc3, DialogModes.NO );
preferences.rulerUnits = defaultRulerUnits;

[ Here's what the script outputs for me]
You should have something
quite similar; the 'marching ant army' selection on your canvas.
So now we're going to clean up that code a bit to see if we can use it for another
script. Javascript allows us to create functions; so why not do one for the
circle; for example 'makeCircle(left,top,right,bottom,antiAlias)'
?
function
makeCircle(left,top,right,bottom,antiAlias){
var circleSelection = charIDToTypeID( "setd" );
var descriptor = new ActionDescriptor();
var id71 = charIDToTypeID( "null"
);
var ref5 = new ActionReference();
var id72 = charIDToTypeID( "Chnl"
);
var id73 = charIDToTypeID( "fsel"
);
ref5.putProperty( id72, id73 );
descriptor.putReference( id71, ref5 );
var id74 = charIDToTypeID( "T " );
var desc12 = new ActionDescriptor();
var top1 = charIDToTypeID( "Top " );
var top2 = charIDToTypeID( "#Pxl" );
desc12.putUnitDouble( top1, top2, top );
var left1 = charIDToTypeID( "Left" );
var left2 = charIDToTypeID( "#Pxl" );
desc12.putUnitDouble( left1, left2, left );
var bottom1 = charIDToTypeID( "Btom" );
var bottom2 = charIDToTypeID( "#Pxl" );
desc12.putUnitDouble( bottom1, bottom2, bottom );
var right1 = charIDToTypeID( "Rght" );
var right2 = charIDToTypeID( "#Pxl" );
desc12.putUnitDouble( right1, right2, right );
var id83 = charIDToTypeID( "Elps" );
descriptor.putObject( id74, id83, desc12 );
var id84 = charIDToTypeID( "AntA" );
descriptor.putBoolean( id84, antiAlias );
executeAction( circleSelection, descriptor, DialogModes.NO );
}
var defaultRulerUnits = preferences.rulerUnits;
preferences.rulerUnits = Units.PIXELS;
var newDocumentRef = documents.add(600,600, 72.0, "Circle Function");
newDocumentRef = null;
for(a=10;a<=40;a++){
var randomColor = new SolidColor;
randomColor.rgb.red = Math.round(Math.random()*255);
randomColor.rgb.green = Math.round(Math.random()*255);
randomColor.rgb.blue = Math.round(Math.random()*255);
makeCircle(a*3,a*3,a*5*3,a*5*3,true);
activeDocument.selection.fill(randomColor);
}
preferences.rulerUnits = defaultRulerUnits;

[ You should have something like that]
Now keep in
mind that you won't always be able to obtain what you want with the script listener
(for instance you cannot record coordinates from the mouse, you cannot use the
eye drop color picker etc... but the script listener will come in handy at times,
you have to experiment with it).
Don't try understanding everything, as it's a real pain, but modify parameters
and see how they modify your image. For example here I could have done an 'intersect'
selection or 'expend' selection to look at the code.
|
 |
Download .js code file of that last script
PS7 /
CS
(not tested on CS yet)
(right click and 'save as') |
|
Now
you can adapt the code you found to do whatever you want. In the following example,
I have used Math.sin(x) and Math.cos(x) to draw a series of circle around bigger
ones. The code might look a bit messy but look at it closely and it's actually
quite simple to understand.

[ Here's what a modified version of the script
can do. Check it out !]
|
 |
Download .js code file of the modified script
PS7 / CS
(right click and 'save as') |
|
Next sections will be sample codes,
without full explanation. First:
Retrieving
and displaying EXIF data from a photo
|
 |
page 5 of
11 |
 |
|