Flash Components      Flash Menu      Flash Gallery      Flash Slideshow      FLV Player      Flash Form      MP3 Player      PhotoFlow      Flash CMS      3D Wall      Flash Scroller

 

 

 

 

 
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;

Click Me for Larger Image !

[ 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;


Click Me for Larger Image !

[ 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 !

[ 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


 




SUPPORTERS:

kirupa.com's fast and reliable hosting provided by Media Temple.