HDTR images with
PhotoShop
Javascript
Dr Jeckyll & Mr Hide
Haciendo Fotos
desde los 16 años
Exposiciones
Colectivas e indivudales
Ing. técnico en
Informática de sistemas
Sw Engineer & Trainer
@dgomezg@d_v_g
The HDTR technique
Term coined by Martin Krzywinski
HDTR
High Dynamic
Time Range
The HDTR Technique
Term coined by Martin KrzywinskiHDTR | High Dynamic
Time Range
http://mkweb.bcgsc.ca/fun/hdtr/
Steps
SHOT
Process
Plan
The Planning
Spot the place
(Find out if its going to
be crowded at sunset)
Find out
when and where
the sun sets
Check the
weather forecast
(A rainy sunset looks
quite different)
When and Where
the sun sets
Photographic Shot
Keep the camera steady
for several hours
(a TRIPOD will help)
Set a
NEUTRAL White Balace
Keep a const Depth of
Field (Aperture Priority)
Better if you can shot
Tethered to a Computer
Pick some BEERS & FRIENDS
(but pay attention to the camera)
TOOLS and Setup
Tethered Shooting
Set Aperture Priority
Set timered shooting
(TIMELAPSE SHOOTING)
RESULTSRESULTS
Construction of a
HDTR image
The Photoshop Process
Described at
http://mkweb.bcgsc.ca/fun/hdtr/?tutorial
Automate the
process
Available AT
http://mkweb.bcgsc.ca/fun/hdtr/?CODE
Martin Krzywinski
Implementation
• Perl BASED
• PROS
• Easy setup &
RUN
• FREE
• No dependencies
(but Perl & libs)
• CONS
• Verbose
blending
config
• No tuning
posibility of
result image
PS Scripting
alternative
• PROS
• Final image un
PSD format with
layers
• You could
further adjust
the result
• Easy config & run
• CONS
• PS License
required
• Harder to code
PS scripting languages
Photoshop JS
• Since PHOTOSHOP CS 1
(experimental support in PS 7.0 via an optional
plugin)
• Cross platform
• New DOM To access most of Photoshop
features and properties
Photoshop’s DOM
• BUT Still some operations not
available: Gradients, Adjustment
Layers, Layer Effects, polygonal
selections....
Access to the “Hidden”
functionality
• JS Classes from original PS SDK
interface
• ActionDescriptor,
• ActionList
• ActionReference
• Use codes as parameters
Access to the “Hidden” functionality
ScriptListener plugin
//-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐
var	
  V1	
  =	
  new	
  ActionDescriptor();
var	
  V2	
  =	
  new	
  ActionDescriptor();
V2.putUnitDouble(charIDToTypeID("Hrzn"),charIDToTypeID("#Pxl"),	
  345);	
  
V2.putUnitDouble(charIDToTypeID("Vrtc"),charIDToTypeID("#Pxl"),	
  667);
V1.putObject(charIDToTypeID("From"),charIDToTypeID("Pnt	
  "),	
  V2);
var	
  V3	
  =	
  new	
  ActionDescriptor();
[...]
Records User’s interaction to JS script
var fillWithGradient = function(startX, startY, endX, endY) {
var V1 = new ActionDescriptor();
var V2 = new ActionDescriptor();
V2.putUnitDouble(
charIDToTypeID("Hrzn"),
charIDToTypeID("#Pxl"),
startX); // start point X
V2.putUnitDouble(
charIDToTypeID("Vrtc"),
charIDToTypeID("#Pxl"),
startY); // start point Y
V1.putObject(
charIDToTypeID("From"),
charIDToTypeID("Pnt "), V2);
var V3 = new ActionDescriptor();
Access to the “Hidden” functionality
Code translation
//-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐
var	
  V1	
  =	
  new	
  ActionDescriptor();
var	
  V2	
  =	
  new	
  ActionDescriptor();
V2.putUnitDouble(charIDToTypeID("Hrzn"),charIDToTypeID("#Pxl"),	
  345);	
  
V2.putUnitDouble(charIDToTypeID("Vrtc"),charIDToTypeID("#Pxl"),	
  667);
V1.putObject(charIDToTypeID("From"),charIDToTypeID("Pnt	
  "),	
  V2);
var	
  V3	
  =	
  new	
  ActionDescriptor();
[...]
Translating codes
/*
lMID.maskHides = 1214529900;//"HdAl"
lMID.maskRevealsAll = 1383492673;//"RvlA"
lMID.maskReveals = 1383492691;//"Rvls"
lMID.mask = 1299409696;//"Msk "
lMID.at = 1098129440;//"At "
lMID.using = 1433628263;//"Usng"
lMID.userMask = 1433629261;//"UsrM"
lMID.make = 1298866208;//"Mk "
lMID.property = 1349677170;//"Prpr"
...
*/
cTID = function(s) { return app.charIDToTypeID(s); };
sTID = function(s) { return app.stringIDToTypeID(s); };
Photoshop Extended
Script
• SOME Photoshop classes are defined in
an extended an particular way
alert(app.activeDocument.height);
#include	
  "modules/json/json.js"
alert(JSON.stringify(app.activeDocument.height));
Photoshop
ExtendScript
.JSX .JS
Convention
ExtendScript files Regular files
not using special Adobe
classes and functions
DEVELOPMENT TOOLS
ExtendScript Toolkit
DEVELOPMENT TOOLS
ExtendScript Toolkit
• Delivered with every Creative Suite
product
• Need to set the target application
• Combo
• #target
• Benefits
• run on application
• Debug tools
• Inspector
DEVELOPMENT TOOLS
Any other JS editor
Launch script via File > Scripts > Browse ...
the Photoshop
HDTR.jsx script
Process config
var	
  hdtrConfig	
  =	
  {
	
  	
  	
  	
  direction	
  :	
  Direction.VERTICAL
	
  	
  	
  	
  ,	
  maskOffset	
  :	
  25
	
  	
  	
  	
  ,	
  guideSpacing	
  :	
  function	
  ()	
  {
	
  	
  	
  	
  	
  	
  	
  	
  if	
  (this.direction	
  ==	
  Direction.VERTICAL)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  this.docDimensions.width	
  /	
  this.shots;
	
  	
  	
  	
  	
  	
  	
  	
  }	
  else	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  this.docDimensions.height	
  /	
  this.shots;
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  }
};
Added later:
- Image (document) dimensions
- Number of original shots
- Blending Offset (in Pixels)
Source file selection
& further config
var files = app.openDialog();
hdtrConfig.shots = files.length;
hdtrConfig.docDimensions = getImageFileDimensions(files[0]);
hdtrConfig.offset =
hdtrConfig.maskOffset * hdtrConfig.guideSpacing();
var getImageFileDimensions = function(file) {
	 var imageDocument = app.open(file);
	 var documentDimensions = { "height" : document.height,
	 	 	 "width" : document.width,
	 	 	 "resolution" : document.resolution};
	 imageDocument.close();
	 return documentDimensions;
}
HDTR document
var	
  hdtrDocument	
  =	
  app.documents.add(
hdtrConfig.docDimensions.width,	
  
hdtrConfig.docDimensions.height,
hdtrConfig.docDimensions.resolution);
drawGuides(hdtrDocument,	
  hdtrConfig.direction,	
  hdtrConfig.shots);
var	
  drawGuides	
  =	
  function(document,	
  direction,	
  number)	
  {
	
   var	
  distance	
  =	
  (direction	
  ==	
  Direction.HORIZONTAL)?
document.height	
  /	
  number	
  :
document.width	
  /	
  number	
  ;
	
   for	
  (var	
  i	
  =	
  0;	
  i	
  <	
  number	
  +	
  1;	
  i++)	
  {
	
   	
   var	
  position;
	
   	
   position	
  =	
  i	
  *	
  distance;
	
   	
   document.guides.add(direction,	
  
new	
  UnitValue(position,	
  position));
	
   }
}
Main Loop
var	
  refGuide;
var	
  from;
var	
  to;
for	
  (index	
  =	
  0;	
  index	
  <	
  files.length;	
  index++)	
  {
	
  	
  	
  	
  addLayerFromFile(hdtrDocument,	
  files[index]);
	
  	
  	
  	
  if	
  (index	
  >	
  0)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  refGuide	
  =	
  hdtrDocument.guides[index];
	
  	
  	
  	
  	
  	
  	
  	
  from	
  =	
  refGuide.coordinate	
  -­‐	
  hdtrConfig.offset;
	
  	
  	
  	
  	
  	
  	
  	
  to	
  =	
  refGuide.coordinate	
  +	
  hdtrConfig.offset;
	
  	
  	
  	
  	
  	
  	
  	
  createLayerMask(hdtrDocument,	
  hdtrDocument.activeLayer,	
  false);
	
  	
  	
  	
  	
  	
  	
  	
  fillWithGradient(from,	
  hdtrConfig.docDimensions.height	
  /2,
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  to,	
  hdtrConfig.docDimensions.height	
  /2);
	
  	
  	
  	
  }
}
Add Layer from File
var	
  addLayerFromFile	
  =	
  function(hdtrDocument,	
  file)	
  {
	
  	
  	
  	
  var	
  sourceDocument	
  =	
  app.open(file);
	
  	
  	
  	
  app.activeDocument	
  =	
  sourceDocument;
	
  	
  	
  	
  app.activeDocument.activeLayer.copy();
	
  	
  	
  	
  app.activeDocument	
  =	
  hdtrDocument;
	
  	
  	
  	
  hdtrDocument.paste();
	
  	
  	
  	
  hdtrDocument.activeLayer.name	
  =	
  
(hdtrDocument.artLayers.length	
  -­‐1)	
  +	
  "-­‐"	
  +	
  sourceDocument.name;
	
  	
  	
  	
  sourceDocument.close();
}
Create Layer Mask
var	
  createLayerMask	
  =	
  function(doc,	
  layer,	
  fromSelection)	
  {
	
  	
  	
  	
  var	
  desc	
  =	
  new	
  ActionDescriptor();
	
  	
  	
  	
  desc.putClass(cTID("Nw	
  	
  "),	
  cTID("Chnl"));
	
  	
  	
  	
  
	
  	
  	
  	
  var	
  ref	
  =	
  new	
  ActionReference();
	
  	
  	
  	
  ref.putEnumerated(cTID("Chnl"),	
  cTID("Chnl"),	
  cTID("Msk	
  "));
	
  	
  	
  	
  desc.putReference(cTID("At	
  	
  "),	
  ref);
	
  	
  	
  	
  
	
  	
  	
  	
  if	
  (fromSelection	
  ==	
  true)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  desc.putEnumerated(cTID("Usng"),	
  cTID("UsrM"),	
  cTID("RvlS"));
	
  	
  	
  	
  }	
  else	
  {
	
  	
  	
  	
  	
  	
  	
  	
  desc.putEnumerated(cTID("Usng"),	
  cTID("UsrM"),	
  cTID("RvlA"));
	
  	
  	
  	
  }
	
  	
  	
  	
  executeAction(cTID("Mk	
  	
  "),	
  desc,	
  DialogModes.NO);
}
Fill with Gradient
var fillWithGradient = function(startX, startY, endX, endY) {
var V1 = new ActionDescriptor();
var V2 = new ActionDescriptor();
V2.putUnitDouble(
charIDToTypeID("Hrzn"),
charIDToTypeID("#Pxl"),
startX); // start point X
V2.putUnitDouble(
charIDToTypeID("Vrtc"),
charIDToTypeID("#Pxl"),
startY); // start point Y
V1.putObject(
charIDToTypeID("From"),
charIDToTypeID("Pnt "), V2);
var V3 = new ActionDescriptor();
....
Better to see the source code
DEMO TIME!
Next Steps
Heterogeneous slice
distribution
Easier configuration
Using Photoshop UI
Photoshop CS1
User Interaction via Alerts
Photoshop CS2
Added ScriptUI
(page 187 of PS CS2 JS Reference)
Photoshop CS3+
ScriptUI moved to PS JS TOOLS GUIDE
Script UI
var	
  dlg	
  =	
  new	
  Window("dialog{text:'Script	
  Interface',bounds:
[100,100,561,269],
iwtfkhamhc:EditText{bounds:[16,16,444.95,94]	
  ,	
  text:'Your	
  text	
  goes	
  
here'	
  ,properties:{multiline:false,noecho:false,readonly:false}},
button0:Button{bounds:[17,102,117,122]	
  ,	
  text:'Save'	
  },
button1:Button{bounds:[236,101,336,121]	
  ,	
  text:'Cancel'	
  },
button2:Button{bounds:[345,101,445,121]	
  ,	
  text:'Whatever'	
  },
slider0:Slider{bounds:[18,138,173,148]	
  ,	
  minvalue:0,maxvalue:100,value:
0},
checkbox0:Checkbox{bounds:[190,133,261,154]	
  ,	
  text:'Checkbox	
  Text'	
  },
dropdown0:DropDownList{bounds:[299,134,443,149],properties:{items:
['Select	
  One']}}
};");
dlg.show();
Further Reference
http://kcy.me/l7uohttp://kcy.me/l7ur
Q & A
Thanks
@d_v_g
@dgomezg
https://github.com/dgomezg/hdtr-photoshop-js

HDTR images with Photoshop Javascript Scripting

  • 1.
  • 2.
    Dr Jeckyll &Mr Hide Haciendo Fotos desde los 16 años Exposiciones Colectivas e indivudales Ing. técnico en Informática de sistemas Sw Engineer & Trainer @dgomezg@d_v_g
  • 3.
    The HDTR technique Termcoined by Martin Krzywinski HDTR High Dynamic Time Range
  • 4.
    The HDTR Technique Termcoined by Martin KrzywinskiHDTR | High Dynamic Time Range http://mkweb.bcgsc.ca/fun/hdtr/
  • 5.
  • 6.
    The Planning Spot theplace (Find out if its going to be crowded at sunset) Find out when and where the sun sets Check the weather forecast (A rainy sunset looks quite different)
  • 7.
  • 8.
    Photographic Shot Keep thecamera steady for several hours (a TRIPOD will help) Set a NEUTRAL White Balace Keep a const Depth of Field (Aperture Priority) Better if you can shot Tethered to a Computer Pick some BEERS & FRIENDS (but pay attention to the camera)
  • 9.
    TOOLS and Setup TetheredShooting Set Aperture Priority Set timered shooting (TIMELAPSE SHOOTING)
  • 10.
  • 11.
  • 12.
    The Photoshop Process Describedat http://mkweb.bcgsc.ca/fun/hdtr/?tutorial
  • 13.
  • 14.
    Available AT http://mkweb.bcgsc.ca/fun/hdtr/?CODE Martin Krzywinski Implementation •Perl BASED • PROS • Easy setup & RUN • FREE • No dependencies (but Perl & libs) • CONS • Verbose blending config • No tuning posibility of result image
  • 15.
    PS Scripting alternative • PROS •Final image un PSD format with layers • You could further adjust the result • Easy config & run • CONS • PS License required • Harder to code
  • 16.
  • 17.
    Photoshop JS • SincePHOTOSHOP CS 1 (experimental support in PS 7.0 via an optional plugin) • Cross platform • New DOM To access most of Photoshop features and properties
  • 18.
    Photoshop’s DOM • BUTStill some operations not available: Gradients, Adjustment Layers, Layer Effects, polygonal selections....
  • 19.
    Access to the“Hidden” functionality • JS Classes from original PS SDK interface • ActionDescriptor, • ActionList • ActionReference • Use codes as parameters
  • 20.
    Access to the“Hidden” functionality ScriptListener plugin //-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ var  V1  =  new  ActionDescriptor(); var  V2  =  new  ActionDescriptor(); V2.putUnitDouble(charIDToTypeID("Hrzn"),charIDToTypeID("#Pxl"),  345);   V2.putUnitDouble(charIDToTypeID("Vrtc"),charIDToTypeID("#Pxl"),  667); V1.putObject(charIDToTypeID("From"),charIDToTypeID("Pnt  "),  V2); var  V3  =  new  ActionDescriptor(); [...] Records User’s interaction to JS script var fillWithGradient = function(startX, startY, endX, endY) { var V1 = new ActionDescriptor(); var V2 = new ActionDescriptor(); V2.putUnitDouble( charIDToTypeID("Hrzn"), charIDToTypeID("#Pxl"), startX); // start point X V2.putUnitDouble( charIDToTypeID("Vrtc"), charIDToTypeID("#Pxl"), startY); // start point Y V1.putObject( charIDToTypeID("From"), charIDToTypeID("Pnt "), V2); var V3 = new ActionDescriptor();
  • 21.
    Access to the“Hidden” functionality Code translation //-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ var  V1  =  new  ActionDescriptor(); var  V2  =  new  ActionDescriptor(); V2.putUnitDouble(charIDToTypeID("Hrzn"),charIDToTypeID("#Pxl"),  345);   V2.putUnitDouble(charIDToTypeID("Vrtc"),charIDToTypeID("#Pxl"),  667); V1.putObject(charIDToTypeID("From"),charIDToTypeID("Pnt  "),  V2); var  V3  =  new  ActionDescriptor(); [...] Translating codes /* lMID.maskHides = 1214529900;//"HdAl" lMID.maskRevealsAll = 1383492673;//"RvlA" lMID.maskReveals = 1383492691;//"Rvls" lMID.mask = 1299409696;//"Msk " lMID.at = 1098129440;//"At " lMID.using = 1433628263;//"Usng" lMID.userMask = 1433629261;//"UsrM" lMID.make = 1298866208;//"Mk " lMID.property = 1349677170;//"Prpr" ... */ cTID = function(s) { return app.charIDToTypeID(s); }; sTID = function(s) { return app.stringIDToTypeID(s); };
  • 22.
    Photoshop Extended Script • SOMEPhotoshop classes are defined in an extended an particular way alert(app.activeDocument.height); #include  "modules/json/json.js" alert(JSON.stringify(app.activeDocument.height));
  • 23.
    Photoshop ExtendScript .JSX .JS Convention ExtendScript filesRegular files not using special Adobe classes and functions
  • 24.
  • 25.
    DEVELOPMENT TOOLS ExtendScript Toolkit •Delivered with every Creative Suite product • Need to set the target application • Combo • #target • Benefits • run on application • Debug tools • Inspector
  • 26.
    DEVELOPMENT TOOLS Any otherJS editor Launch script via File > Scripts > Browse ...
  • 27.
  • 28.
    Process config var  hdtrConfig  =  {        direction  :  Direction.VERTICAL        ,  maskOffset  :  25        ,  guideSpacing  :  function  ()  {                if  (this.direction  ==  Direction.VERTICAL)  {                        return  this.docDimensions.width  /  this.shots;                }  else  {                        return  this.docDimensions.height  /  this.shots;                }        } }; Added later: - Image (document) dimensions - Number of original shots - Blending Offset (in Pixels)
  • 29.
    Source file selection &further config var files = app.openDialog(); hdtrConfig.shots = files.length; hdtrConfig.docDimensions = getImageFileDimensions(files[0]); hdtrConfig.offset = hdtrConfig.maskOffset * hdtrConfig.guideSpacing(); var getImageFileDimensions = function(file) { var imageDocument = app.open(file); var documentDimensions = { "height" : document.height, "width" : document.width, "resolution" : document.resolution}; imageDocument.close(); return documentDimensions; }
  • 30.
    HDTR document var  hdtrDocument  =  app.documents.add( hdtrConfig.docDimensions.width,   hdtrConfig.docDimensions.height, hdtrConfig.docDimensions.resolution); drawGuides(hdtrDocument,  hdtrConfig.direction,  hdtrConfig.shots); var  drawGuides  =  function(document,  direction,  number)  {   var  distance  =  (direction  ==  Direction.HORIZONTAL)? document.height  /  number  : document.width  /  number  ;   for  (var  i  =  0;  i  <  number  +  1;  i++)  {     var  position;     position  =  i  *  distance;     document.guides.add(direction,   new  UnitValue(position,  position));   } }
  • 31.
    Main Loop var  refGuide; var  from; var  to; for  (index  =  0;  index  <  files.length;  index++)  {        addLayerFromFile(hdtrDocument,  files[index]);        if  (index  >  0)  {                refGuide  =  hdtrDocument.guides[index];                from  =  refGuide.coordinate  -­‐  hdtrConfig.offset;                to  =  refGuide.coordinate  +  hdtrConfig.offset;                createLayerMask(hdtrDocument,  hdtrDocument.activeLayer,  false);                fillWithGradient(from,  hdtrConfig.docDimensions.height  /2,                                to,  hdtrConfig.docDimensions.height  /2);        } }
  • 32.
    Add Layer fromFile var  addLayerFromFile  =  function(hdtrDocument,  file)  {        var  sourceDocument  =  app.open(file);        app.activeDocument  =  sourceDocument;        app.activeDocument.activeLayer.copy();        app.activeDocument  =  hdtrDocument;        hdtrDocument.paste();        hdtrDocument.activeLayer.name  =   (hdtrDocument.artLayers.length  -­‐1)  +  "-­‐"  +  sourceDocument.name;        sourceDocument.close(); }
  • 33.
    Create Layer Mask var  createLayerMask  =  function(doc,  layer,  fromSelection)  {        var  desc  =  new  ActionDescriptor();        desc.putClass(cTID("Nw    "),  cTID("Chnl"));                var  ref  =  new  ActionReference();        ref.putEnumerated(cTID("Chnl"),  cTID("Chnl"),  cTID("Msk  "));        desc.putReference(cTID("At    "),  ref);                if  (fromSelection  ==  true)  {                desc.putEnumerated(cTID("Usng"),  cTID("UsrM"),  cTID("RvlS"));        }  else  {                desc.putEnumerated(cTID("Usng"),  cTID("UsrM"),  cTID("RvlA"));        }        executeAction(cTID("Mk    "),  desc,  DialogModes.NO); }
  • 34.
    Fill with Gradient varfillWithGradient = function(startX, startY, endX, endY) { var V1 = new ActionDescriptor(); var V2 = new ActionDescriptor(); V2.putUnitDouble( charIDToTypeID("Hrzn"), charIDToTypeID("#Pxl"), startX); // start point X V2.putUnitDouble( charIDToTypeID("Vrtc"), charIDToTypeID("#Pxl"), startY); // start point Y V1.putObject( charIDToTypeID("From"), charIDToTypeID("Pnt "), V2); var V3 = new ActionDescriptor(); .... Better to see the source code
  • 35.
  • 36.
  • 37.
  • 38.
    Easier configuration Using PhotoshopUI Photoshop CS1 User Interaction via Alerts Photoshop CS2 Added ScriptUI (page 187 of PS CS2 JS Reference) Photoshop CS3+ ScriptUI moved to PS JS TOOLS GUIDE
  • 39.
    Script UI var  dlg  =  new  Window("dialog{text:'Script  Interface',bounds: [100,100,561,269], iwtfkhamhc:EditText{bounds:[16,16,444.95,94]  ,  text:'Your  text  goes   here'  ,properties:{multiline:false,noecho:false,readonly:false}}, button0:Button{bounds:[17,102,117,122]  ,  text:'Save'  }, button1:Button{bounds:[236,101,336,121]  ,  text:'Cancel'  }, button2:Button{bounds:[345,101,445,121]  ,  text:'Whatever'  }, slider0:Slider{bounds:[18,138,173,148]  ,  minvalue:0,maxvalue:100,value: 0}, checkbox0:Checkbox{bounds:[190,133,261,154]  ,  text:'Checkbox  Text'  }, dropdown0:DropDownList{bounds:[299,134,443,149],properties:{items: ['Select  One']}} };"); dlg.show();
  • 40.
  • 41.
  • 42.