Add an interactive crop before processing folder

Anyone, especially newbies, asking for help with Photoshop Scripting and Photoshop Automation - as opposed to those contributing to discussion about an aspect of Photoshop Scripting

Moderators: Tom, Kukurykus

craezer

Add an interactive crop before processing folder

Post by craezer »

I have three scripts that reduce flicker in time-lapse sequences by averaging the luminosity of a folder of images. I'm happy with what they do and how they do it, but now I'd like to add the ability to also crop the images. The first script sets a sample area to find the histogram level. I'm thinking it would be best to crop before the sample area is set so that doesn't get cropped off. So my thought was to have a dialog pop up asking if to crop or not before running the rest of the script. If yes, the crop selection bounds could be set. If no, the main dialog would open.

I've managed to add a dialog that does open a bounds selection, but now I'm stuck. If I set the crop area and double click the image, nothing happens. The same thing happens if I click No on the dialog. If I hit Esc, it goes to the crop selection instead of bypassing it. I'm also not sure how to loop the crop so the rest of the images are automatically cropped. Obviously it would be easier to just batch crop the images first, but I'm trying to automate this as much as possible for end users not familiar with PS. My goal is to have the dialog open after cropping is complete. I wonder if it would be easier to add another script to crop and then have that call the next script when finished. I'm a bit rummy after looking at this for a few days, so I apologize if I'm not making sense! I posted the script both before and after to show what I've attempted. I also attached a zip file with all three scripts to give the whole context of the process.

I was hoping I'd be able to figure this out myself, but I'm at a dead end.

Thanks,
Chris


Original code:
Code: Select all/**
* @@@BUILDINFO@@@ 1FindSampleArea.jsx Ver.0.2Thu Nov 11 2010 12:14:23 GMT-0800
*/

//Created by Chris Raezer Photography with scripting assistance from Mike Hale at PS-Scripts.com
//User interface derived from code written by Paul Riggott
// Histogram functions written by Xbytor xbytor@gmail.com

/*
<javascriptresource>
<name>$$$/JavaScripts/FindLuminositySampleArea/Menu=1. Find Luminosity Sample Area</name>
<category>aaaaPSDeflickeringScripts</category>
</javascriptresource>
*/


//----------------------------- Histogram ---------------------------
    Histogram = function Histogram() {}

    Histogram.range = function(hist, cutoff) {
       var HIST_MAX = hist.length;
       cutoff = cutoff || 0;

       if (Levels.dumpHistogram) { // change this to false to see what
                               // the histogram numbers really are
     // debug stuff...
     var str = '';
     for (var i = 0; i < HIST_MAX; i++) {
       str += hist + ",";
     }
     confirm(cutoff + '\r' + str);
   }

   // find the minimum level
   var min = 0;
   while (min < HIST_MAX && hist[min] <= cutoff) {
     min++;
   }
   // find the maximum level
   var max = HIST_MAX-1;
   while (max >= 0 && hist[max] <= cutoff) {
     max--;
   }
   var r = {};
   r.min = min;
   r.max = max;
   if (false) {
     alert(r.min + ':' + r.max);
   }

   // we need at least 2 distinct levels
   if (r.min != HIST_MAX && r.max != -1 && r.max != r.min) {
     // we also need to be sure that we're not already auto-leveled
     if (!(r.min == 0 && r.max == (HIST_MAX-1))) {
       return r;
     }
   }

   return null;
}

Histogram.mean = function(hist) {
   var acc = 0;
   var cnt = 0;
   for (var i = 0; i < hist.length; i++) {
     acc += i*hist;
     cnt += hist;
   }
   return acc/cnt;
}
Histogram.median = function(hist) {
   var cnt = 0;
   for (var i = 0; i < hist.length; i++) {
     cnt += hist;
   }
   cnt = cnt/2;
   var acc = 0;
   for (var i = 0; i < hist.length; i++) {
     acc += hist;
     if (acc > cnt) return i-1;
   }
   return -1;
}
    function curveAdjsLayer(input,output) {
       cTID = function(s) { return app.charIDToTypeID(s); };
        var desc = new ActionDescriptor();
            var classRef = new ActionReference();
            classRef.putClass( cTID('AdjL') );
        desc.putReference( cTID('null'), classRef );
          var adjsDesc = new ActionDescriptor();
            var curveDesc = new ActionDescriptor();
                var adjsList = new ActionList();
                    var curveAdesc = new ActionDescriptor();
                        var tragetRef = new ActionReference();
                        tragetRef.putEnumerated( cTID('Chnl'), cTID('Chnl'), cTID('Cmps') );
                    curveAdesc.putReference( cTID('Chnl'), tragetRef );
                        var pointsList = new ActionList();
                            var blackPtDesc = new ActionDescriptor();
                            blackPtDesc.putDouble( cTID('Hrzn'), 0.000000 );
                            blackPtDesc.putDouble( cTID('Vrtc'), 0.000000 );
                        pointsList.putObject( cTID('Pnt '), blackPtDesc );
                            var midPtDesc = new ActionDescriptor();
                            midPtDesc.putDouble( cTID('Hrzn'), input );
                            midPtDesc.putDouble( cTID('Vrtc'), output );
                        pointsList.putObject( cTID('Pnt '), midPtDesc );
                            var whitePtDesc = new ActionDescriptor();
                            whitePtDesc.putDouble( cTID('Hrzn'), 255.000000 );
                            whitePtDesc.putDouble( cTID('Vrtc'), 255.000000 );
                        pointsList.putObject( cTID('Pnt '), whitePtDesc );
                    curveAdesc.putList( cTID('Crv '), pointsList );
                adjsList.putObject( cTID('CrvA'), curveAdesc );
            curveDesc.putList( cTID('Adjs'), adjsList );
        adjsDesc.putObject( cTID('Type'), cTID('Crvs'), curveDesc );
    desc.putObject( cTID('Usng'), cTID('AdjL'), adjsDesc );
    executeAction( cTID('Mk  '), desc, DialogModes.NO );
  };
//------------------------------End Histogram Functions--------------------------------
  function  main(){
           if(!documents.length){
        alert("There are no open images");
        return;
        }
    var Prefs ={};
    try{
      var desc1 = app.getCustomOptions('efe30920-ef50-11df-98cf-0800200c9a66');
      Prefs = eval(desc1.getString(0));
        }catch(e){}
   // Create a dialog window near the upper left of the screen
      var dlg = new Window('dialog', 'Find Histogram Sample Area');
      dlg.frameLocation = [100, 100];
         dlg.alignChildren = "left";
         dlg.seqPnl = dlg.add('group');
         dlg.seqPnl.st = dlg.seqPnl.add('statictext', undefined,'Script 1 of 3');
         
         
         //add help
         dlg.infoPnl = dlg.add('panel',undefined,'How To Use');
         dlg.infoPnl.alignChildren = "left";
         dlg.infoPnl.st = dlg.infoPnl.add('statictext',undefined,'The purpose of this series of scripts is to help reduce unwanted flicker in time-lapse sequences by reducing luminance fluctuation from image to image. This initial script is used to help determine the sample area that will be used in subsequent scripts. \r\rImages to be processed must be in one folder and file names must be sequentially numbered. Do not place other images in this folder. \r\r1. For this script an image from the sequence must be open.\r\r2. An easy way to find a starting point is to open the Info panel and hover near the area you wish to sample. The X and Y coordinates will be displayed in the Info panel. When selecting your sample area, keep in mind this is for your entire sequence. Best results will come from areas that are clear from transient obstructions, i.e., clouds, vehicles or moving shadows.\r\r3. Enter the X, Y and Sample Area Size values. All values are in pixels. X and Y are measured from the top left corner of the image; sample area is the box created at the the X, Y point.\r\r4. Clicking OK will open an alert with the brightness level along with the values you entered. You may need to adjust the values to fine-tune the sample area. \r\r5. When you are satisfied with the selected sample area, make note of the X, Y and Sample Area values to be used in the next script.',{multiline:true});
         dlg.infoPnl.st.preferredSize = [600,320];
         dlg.infoPnl.margins = [15,15,15,15];
      // Add a container panel for the title and 'message text' strings
      dlg.msgPnl = dlg.add('panel', undefined, 'Enter Values in Pixels');
         
      dlg.msgPnl.alignChildren = "right";
         dlg.msgPnl.margins = [15,15,15,15];
      // add the panel's child components
         
      dlg.msgPnl.xVal = dlg.msgPnl.add('group');
         dlg.msgPnl.yVal = dlg.msgPnl.add('group');
         dlg.msgPnl.szVal = dlg.msgPnl.add('group');

      with (dlg.msgPnl) {
             xVal.st = xVal.add('statictext', undefined, 'Enter X Coordinate:');
             xVal.et = xVal.add('edittext', undefined, '');
             xVal.st.preferredSize = [155,20];
         xVal.et.preferredSize = [80,20];
            if(Prefs.x != undefined){
            xVal.et.text = Number(Prefs.x);
            }
           
             yVal.st = yVal.add('statictext', undefined, 'Enter Y Coordinate:');
             yVal.et = yVal.add('edittext', undefined, '');
             yVal.st.preferredSize = [155,20];
          yVal.et.preferredSize = [80,20];
            if(Prefs.y != undefined){
                    yVal.et.text = Number(Prefs.y);
                    }
           
              szVal.st = szVal.add('statictext', undefined, 'Set Sample Area Size:');
              szVal.et = szVal.add('edittext', undefined, '');
              szVal.st.preferredSize = [155,20];
         szVal.et.preferredSize = [80,20];
              if(Prefs.size != undefined){
                   szVal.et.text = Number(Prefs.size);
                   }
            //Add static text with folder path
                dlg.g15 =dlg.add('group');
                dlg.g15.spacing=10;
                dlg.g15.orientation = 'row';
                dlg.g15.alignment="left";
                dlg.g15.et1 = dlg.g15.add('edittext',undefined,'');
                dlg.g15.et1.preferredSize=[280,20];
                dlg.g15.et1.enabled=false;
                dlg.g15.et1.text = decodeURI(activeDocument.path + "/" +activeDocument.name);
           
           
         dlg.btnPnl = dlg.add('panel', undefined, 'Find Histogram Sample Area');
      dlg.btnPnl.orientation = "row";
         dlg.btnPnl.margins = [10,15,10,10];
         dlg.btnPnl.cancelBtn = dlg.btnPnl.add('button', undefined, 'Cancel', {name:'cancel'});
      dlg.btnPnl.rstBtn = dlg.btnPnl.add('button', undefined, 'Reset');
      dlg.btnPnl.okBtn = dlg.btnPnl.add('button', undefined, 'OK', {name:'ok'});
      }
   
    dlg.center();
dlg.msgPnl.xVal.et.active = true;

dlg.btnPnl.rstBtn.onClick = function(){
      dlg.msgPnl.xVal.et.text = '';
      dlg.msgPnl.yVal.et.text = '';
      dlg.msgPnl.szVal.et.text = '';
     try{
    var desc2 = new ActionDescriptor();
    desc2.putString(0, Prefs.toSource());
    app.eraseCustomOptions('efe30920-ef50-11df-98cf-0800200c9a66', desc2, true );
    }catch(e){alert (e.line["Error"])}
    dlg.msgPnl.xVal.et.active = true;
  }

dlg.btnPnl.okBtn.onClick = function(){
   
                    if(!documents.length){
                alert("There are no open images");
                return;
    }
                    //Test for illegal character in number input
  dlg.msgPnl.xVal.et.onChanging = function () {
       var testCharacter = dlg.msgPnl.xVal.et.text.charAt(dlg.msgPnl.xVal.et.text.length -1);
        if((testCharacter.charCodeAt(0) <48 ) || (testCharacter.charCodeAt(0) >57 )){
             alert("You entered a character that is not a number  => " + testCharacter + " <=") ;           
             };                                 
        };

  dlg.msgPnl.yVal.et.onChanging = function () {
       var testCharacter = dlg.msgPnl.yVal.et.text.charAt(dlg.msgPnl.yVal.et.text.length -1);
        if((testCharacter.charCodeAt(0) <48 ) || (testCharacter.charCodeAt(0) >57 )){
             alert("You entered a character that is not a number  => " + testCharacter + " <=") ;           
             };                                 
        };
   
      dlg.msgPnl.szVal.et.onChanging = function () {
       var testCharacter = dlg.msgPnl.szVal.et.text.charAt(dlg.msgPnl.szVal.et.text.length -1);
        if((testCharacter.charCodeAt(0) <48 ) || (testCharacter.charCodeAt(0) >57 )){
             alert("You entered a character that is not a number  => " + testCharacter + " <=") ;           
             };                                 
        };
      //A replacement for the JavaScript isInteger function that really doesn't work
    //The JavaScript isInteger function will return 12 for a string "12rtt".
    //This function will return NaN for the same string input
    isInteger = function( str) {
                  var bolValidInteger = true;
                  for (var i=0,len=str.length;i<len;i++){
                        if((str.charCodeAt(i) <48 ) || (str.charCodeAt(i) >57 )){
                            bolValidInteger = false;
                           }
                  };
                  if (bolValidInteger) {
                               return parseInt(str);
                     }
                  else {
                     return parseInt("NaN");
                     };               
                  };
       //check values are entered
    if(dlg.msgPnl.xVal.et.text == ''){
        alert("You need to enter the X Coordinate");
        dlg.msgPnl.xVal.et.active = true;
        return;
        }
    var returnedValue = isInteger(dlg.msgPnl.xVal.et.text);
            if(isNaN(returnedValue )){
              alert("ERROR -  "+dlg.msgPnl.xVal.et.text+ " is not a valid number")
                          } else {
               if(returnedValue >=0 && returnedValue <=activeDocument.width.value){
                var xValue = Number(dlg.msgPnl.xVal.et.text);                 
               } else {
                   alert("ERROR -  "+ returnedValue + " is too large for X Coordinate");
                   dlg.msgPnl.xVal.et.active = true;
                    return;
                }           
              }
       
           
    if(dlg.msgPnl.yVal.et.text == ''){
        alert("You need to enter the Y Coordinate");
         dlg.msgPnl.yVal.et.active = true;
         return;
        }
       var returnedValue = isInteger(dlg.msgPnl.yVal.et.text);
            if(isNaN(returnedValue )){
              alert("ERROR -  "+dlg.msgPnl.yVal.et.text+ " is not a valid number")
                          } else {
               if(returnedValue >=0 && returnedValue <=activeDocument.height.value){
                var yValue = Number(dlg.msgPnl.yVal.et.text);                 
               } else {
                   alert("ERROR -  "+ returnedValue + " is too large for Y Coordinate");
                   dlg.msgPnl.yVal.et.active = true;
                return;
                }           
              }
    if(dlg.msgPnl.szVal.et.text == ''){
        alert("You need to enter the Sample Area Size");
         dlg.msgPnl.szVal.et.active = true;
         return;
        }
       var returnedValue = isInteger(dlg.msgPnl.szVal.et.text);
            if(isNaN(returnedValue )){
              alert("ERROR -  "+dlg.msgPnl.szVal.et.text+ " is not a valid number")
                          } else {
               if(returnedValue <=activeDocument.height.value && returnedValue <=activeDocument.width.value){
                var sizeValue = Number(dlg.msgPnl.szVal.et.text);                 
               } else {
                   alert("ERROR -   "+ returnedValue + " is too large for sample area size");
                    dlg.msgPnl.szVal.et.active = true;
                return;
                }           
              }
              try{
    Prefs.x = Number(dlg.msgPnl.xVal.et.text);
    Prefs.y = Number(dlg.msgPnl.yVal.et.text);
    Prefs.size =Number(dlg.msgPnl.szVal.et.text);
    Prefs.folder2 = decodeURI(activeDocument.path);
    var desc2 = new ActionDescriptor();
    desc2.putString(0, Prefs.toSource());
    app.putCustomOptions('efe30920-ef50-11df-98cf-0800200c9a66', desc2, true );
    }catch(e){alert (e.line["Error"])}
          dlg.close(1);
          process();
          }
      dlg.show();
          function process(){
    var x = Number(dlg.msgPnl.xVal.et.text);//X, Y coordinates of sample area
    var y = Number(dlg.msgPnl.yVal.et.text);
    var size =Number(dlg.msgPnl.szVal.et.text);// size of sample area in pixels ie 10x10px
        //select sample area
    activeDocument.selection.select([[x,y],[x+size,y],[x+size,y+size],[x,y+size]]);
    //get the histogram of sample
    var area = activeDocument.histogram;
    alert("Brightness = " + Histogram.median(area) + "\rX = " + x + "\rY = " + y + "\rSize = " + size,['Histogram Level']);
    }

     dlg.btnPnl.cancelBtn.onClick = function(){
     dlg.close();
   }
}

if (app.version.match(/\d+/) <10){
    alert("Sorry but this script needs CS3 or better");
    }else{
main();
}

Hacked code:
Code: Select all/**
* @@@BUILDINFO@@@ 1FindSampleAreaBeta3.jsx
*/

//Created by Chris Raezer Photography with scripting assistance from Mike Hale at PS-Scripts.com
//User interface derived from code written by Paul Riggott
// Histogram functions written by Xbytor xbytor@gmail.com

/*
<javascriptresource>
<name>$$$/JavaScripts/FindLuminositySampleArea/Menu=1. Find Luminosity Sample Area</name>
<category>aaaaPSDeflickeringScripts</category>
</javascriptresource>
*/

//----------------------------- Histogram ---------------------------
    Histogram = function Histogram() {}

    Histogram.range = function(hist, cutoff) {
       var HIST_MAX = hist.length;
       cutoff = cutoff || 0;

       if (Levels.dumpHistogram) { // change this to false to see what
                               // the histogram numbers really are
     // debug stuff...
     var str = '';
     for (var i = 0; i < HIST_MAX; i++) {
       str += hist + ",";
     }
     confirm(cutoff + '\r' + str);
   }

   // find the minimum level
   var min = 0;
   while (min < HIST_MAX && hist[min] <= cutoff) {
     min++;
   }
   // find the maximum level
   var max = HIST_MAX-1;
   while (max >= 0 && hist[max] <= cutoff) {
     max--;
   }
   var r = {};
   r.min = min;
   r.max = max;
   if (false) {
     alert(r.min + ':' + r.max);
   }

   // we need at least 2 distinct levels
   if (r.min != HIST_MAX && r.max != -1 && r.max != r.min) {
     // we also need to be sure that we're not already auto-leveled
     if (!(r.min == 0 && r.max == (HIST_MAX-1))) {
       return r;
     }
   }

   return null;
}

Histogram.mean = function(hist) {
   var acc = 0;
   var cnt = 0;
   for (var i = 0; i < hist.length; i++) {
     acc += i*hist;
     cnt += hist;
   }
   return acc/cnt;
}
Histogram.median = function(hist) {
   var cnt = 0;
   for (var i = 0; i < hist.length; i++) {
     cnt += hist;
   }
   cnt = cnt/2;
   var acc = 0;
   for (var i = 0; i < hist.length; i++) {
     acc += hist;
     if (acc > cnt) return i-1;
   }
   return -1;
}
    function curveAdjsLayer(input,output) {
       cTID = function(s) { return app.charIDToTypeID(s); };
        var desc = new ActionDescriptor();
            var classRef = new ActionReference();
            classRef.putClass( cTID('AdjL') );
        desc.putReference( cTID('null'), classRef );
          var adjsDesc = new ActionDescriptor();
            var curveDesc = new ActionDescriptor();
                var adjsList = new ActionList();
                    var curveAdesc = new ActionDescriptor();
                        var tragetRef = new ActionReference();
                        tragetRef.putEnumerated( cTID('Chnl'), cTID('Chnl'), cTID('Cmps') );
                    curveAdesc.putReference( cTID('Chnl'), tragetRef );
                        var pointsList = new ActionList();
                            var blackPtDesc = new ActionDescriptor();
                            blackPtDesc.putDouble( cTID('Hrzn'), 0.000000 );
                            blackPtDesc.putDouble( cTID('Vrtc'), 0.000000 );
                        pointsList.putObject( cTID('Pnt '), blackPtDesc );
                            var midPtDesc = new ActionDescriptor();
                            midPtDesc.putDouble( cTID('Hrzn'), input );
                            midPtDesc.putDouble( cTID('Vrtc'), output );
                        pointsList.putObject( cTID('Pnt '), midPtDesc );
                            var whitePtDesc = new ActionDescriptor();
                            whitePtDesc.putDouble( cTID('Hrzn'), 255.000000 );
                            whitePtDesc.putDouble( cTID('Vrtc'), 255.000000 );
                        pointsList.putObject( cTID('Pnt '), whitePtDesc );
                    curveAdesc.putList( cTID('Crv '), pointsList );
                adjsList.putObject( cTID('CrvA'), curveAdesc );
            curveDesc.putList( cTID('Adjs'), adjsList );
        adjsDesc.putObject( cTID('Type'), cTID('Crvs'), curveDesc );
    desc.putObject( cTID('Usng'), cTID('AdjL'), adjsDesc );
    executeAction( cTID('Mk  '), desc, DialogModes.NO );
  };
//------------------------------End Histogram Functions--------------------------------

//---------Interactive crop before opening main dialog----------------------------- 
  var win = new Window('dialog','Crop');
  win.frameLocation = [100,100];
  win.pnl = win.add('panel',undefined);
  win.pnl.st = win.pnl.add('statictext',undefined,'Do you want to crop your images during this process?');
  win.btnPnl = win.add('group');
  win.btnPnl.orientation = "row";
  win.btnPnl.button0 = win.btnPnl.add('button',undefined,'OK');
  win.btnPnl.button1 = win.btnPnl.add('button',undefined,'No');
//~   "dialog { text:'Crop',"+
//~  "msg: StaticText { text:'Do you want to crop your images during this process?',  preferredSize: [200, 30],"+
//~  "alignment:['center','top'], properties:{multiline:true} },"+
//~  "btnGroup: Group {"+
//~  "alignment:'center',"+
//~  "okBtn: Button { text:'OK', },"+
//~  "noBtn: Button { text:'No', }"+
//~  "cancelBtn: Button{text:'Cancel',}"+
//~  "}\}"

win.center();
win.show();

win.button.okBtn.onClick = sixteenNineCrop();
function sixteenNineCrop() {
  function cTID(s) { return app.charIDToTypeID(s); };
  function sTID(s) { return app.stringIDToTypeID(s); };
    var myCrop = stringIDToTypeID( "efe30920-ef50-11df-98cf-0800200c9a66" );
    var desc14 = new ActionDescriptor();
        var desc15 = new ActionDescriptor();
        desc15.putUnitDouble( cTID('Top '), cTID('#Rlt'), 0.000000 );
        desc15.putUnitDouble( cTID('Left'), cTID('#Rlt'), 0.000000 );
        desc15.putUnitDouble( cTID('Btom'), cTID('#Rlt'), 43.82462 );
        desc15.putUnitDouble( cTID('Rght'), cTID('#Rlt'), 77.91045 );
    desc14.putObject( cTID('T   '), cTID('Rctn'), desc15 );
    desc14.putUnitDouble( cTID('Angl'), cTID('#Ang'), 0.000000 );
    desc14.putUnitDouble( cTID('Wdth'), cTID('#Rlt'), 216.000000 );
    desc14.putUnitDouble( cTID('Hght'), cTID('#Rlt'), 121.500000 );
    desc14.putUnitDouble( cTID('Rslt'), cTID('#Rsl'), 0.000000 );
      try {
    executeAction( cTID('Crop'), desc14, DialogModes.ALL );
    return true;
    main();
  }catch(e){
    if(!e.message.match(/User cancelled the operation/)) throw e;
    return false;
  };
};
if(sixteenNineCrop == true){
    main();
    }
win.button.noBtn.onClick = main();
win.close();
//----------------------------End interactive crop------------------------


function main(){
           if(!documents.length){
        alert("There are no open images");
        return;
        }
    var Prefs ={};
    try{
      var desc1 = app.getCustomOptions('efe30920-ef50-11df-98cf-0800200c9a66');
      Prefs = eval(desc1.getString(0));
        }catch(e){}
   // Create a dialog window near the upper left of the screen
      var dlg = new Window('dialog', 'Find Histogram Sample Area');
      dlg.frameLocation = [100, 100];
         dlg.alignChildren = "left";
         dlg.seqPnl = dlg.add('group');
         dlg.seqPnl.st = dlg.seqPnl.add('statictext', undefined,'Script 1 of 3');
         
         
         //add help
         dlg.infoPnl = dlg.add('panel',undefined,'How To Use');
         dlg.infoPnl.alignChildren = "left";
         dlg.infoPnl.st = dlg.infoPnl.add('statictext',undefined,'The purpose of this series of scripts is to help reduce unwanted flicker in time-lapse sequences by reducing luminance fluctuation from image to image. This initial script is used to help determine the sample area that will be used in subsequent scripts. \r\rImages to be processed must be in one folder and file names must be sequentially numbered. Do not place other images in this folder. \r\r1. For this script an image from the sequence must be open.\r\r2. An easy way to find a starting point is to open the Info panel and hover near the area you wish to sample. The X and Y coordinates will be displayed in the Info panel. When selecting your sample area, keep in mind this is for your entire sequence. Best results will come from areas that are clear from transient obstructions, i.e., clouds, vehicles or moving shadows.\r\r3. Enter the X, Y and Sample Area Size values. All values are in pixels. X and Y are measured from the top left corner of the image; sample area is the box created at the the X, Y point.\r\r4. Clicking OK will open an alert with the brightness level along with the values you entered. You may need to adjust the values to fine-tune the sample area. \r\r5. When you are satisfied with the selected sample area, make note of the X, Y and Sample Area values to be used in the next script.',{multiline:true});
         dlg.infoPnl.st.preferredSize = [600,320];
         dlg.infoPnl.margins = [15,15,15,15];
      // Add a container panel for the title and 'message text' strings
      dlg.msgPnl = dlg.add('panel', undefined, 'Enter Values in Pixels');
         
      dlg.msgPnl.alignChildren = "right";
         dlg.msgPnl.margins = [15,15,15,15];
      // add the panel's child components
         
      dlg.msgPnl.xVal = dlg.msgPnl.add('group');
         dlg.msgPnl.yVal = dlg.msgPnl.add('group');
         dlg.msgPnl.szVal = dlg.msgPnl.add('group');

      with (dlg.msgPnl) {
             xVal.st = xVal.add('statictext', undefined, 'Enter X Coordinate:');
             xVal.et = xVal.add('edittext', undefined, '');
             xVal.st.preferredSize = [155,20];
         xVal.et.preferredSize = [80,20];
            if(Prefs.x != undefined){
            xVal.et.text = Number(Prefs.x);
            }
           
             yVal.st = yVal.add('statictext', undefined, 'Enter Y Coordinate:');
             yVal.et = yVal.add('edittext', undefined, '');
             yVal.st.preferredSize = [155,20];
          yVal.et.preferredSize = [80,20];
            if(Prefs.y != undefined){
                    yVal.et.text = Number(Prefs.y);
                    }
           
              szVal.st = szVal.add('statictext', undefined, 'Set Sample Area Size:');
              szVal.et = szVal.add('edittext', undefined, '');
              szVal.st.preferredSize = [155,20];
         szVal.et.preferredSize = [80,20];
              if(Prefs.size != undefined){
                   szVal.et.text = Number(Prefs.size);
                   }
            //Add static text with folder path
                dlg.g15 =dlg.add('group');
                dlg.g15.spacing=10;
                dlg.g15.orientation = 'row';
                dlg.g15.alignment="left";
                dlg.g15.et1 = dlg.g15.add('edittext',undefined,'');
                dlg.g15.et1.preferredSize=[280,20];
                dlg.g15.et1.enabled=false;
                dlg.g15.et1.text = decodeURI(activeDocument.path + "/" +activeDocument.name);
           
           
         dlg.btnPnl = dlg.add('panel', undefined, 'Find Histogram Sample Area');
      dlg.btnPnl.orientation = "row";
         dlg.btnPnl.margins = [10,15,10,10];
         dlg.btnPnl.cancelBtn = dlg.btnPnl.add('button', undefined, 'Cancel', {name:'cancel'});
      dlg.btnPnl.rstBtn = dlg.btnPnl.add('button', undefined, 'Reset');
      dlg.btnPnl.okBtn = dlg.btnPnl.add('button', undefined, 'OK', {name:'ok'});
      }
   
    dlg.center();
dlg.msgPnl.xVal.et.active = true;

dlg.btnPnl.rstBtn.onClick = function(){
      dlg.msgPnl.xVal.et.text = '';
      dlg.msgPnl.yVal.et.text = '';
      dlg.msgPnl.szVal.et.text = '';
     try{
    var desc2 = new ActionDescriptor();
    desc2.putString(0, Prefs.toSource());
    app.eraseCustomOptions('efe30920-ef50-11df-98cf-0800200c9a66', desc2, true );
    }catch(e){alert (e.line["Error"])}
    dlg.msgPnl.xVal.et.active = true;
  }

dlg.btnPnl.okBtn.onClick = function(){
   
                    if(!documents.length){
                alert("There are no open images");
                return;
    }
                    //Test for illegal character in number input
  dlg.msgPnl.xVal.et.onChanging = function () {
       var testCharacter = dlg.msgPnl.xVal.et.text.charAt(dlg.msgPnl.xVal.et.text.length -1);
        if((testCharacter.charCodeAt(0) <48 ) || (testCharacter.charCodeAt(0) >57 )){
             alert("You entered a character that is not a number  => " + testCharacter + " <=") ;           
             };                                 
        };

  dlg.msgPnl.yVal.et.onChanging = function () {
       var testCharacter = dlg.msgPnl.yVal.et.text.charAt(dlg.msgPnl.yVal.et.text.length -1);
        if((testCharacter.charCodeAt(0) <48 ) || (testCharacter.charCodeAt(0) >57 )){
             alert("You entered a character that is not a number  => " + testCharacter + " <=") ;           
             };                                 
        };
   
      dlg.msgPnl.szVal.et.onChanging = function () {
       var testCharacter = dlg.msgPnl.szVal.et.text.charAt(dlg.msgPnl.szVal.et.text.length -1);
        if((testCharacter.charCodeAt(0) <48 ) || (testCharacter.charCodeAt(0) >57 )){
             alert("You entered a character that is not a number  => " + testCharacter + " <=") ;           
             };                                 
        };
      //A replacement for the JavaScript isInteger function that really doesn't work
    //The JavaScript isInteger function will return 12 for a string "12rtt".
    //This function will return NaN for the same string input
    isInteger = function( str) {
                  var bolValidInteger = true;
                  for (var i=0,len=str.length;i<len;i++){
                        if((str.charCodeAt(i) <48 ) || (str.charCodeAt(i) >57 )){
                            bolValidInteger = false;
                           }
                  };
                  if (bolValidInteger) {
                               return parseInt(str);
                     }
                  else {
                     return parseInt("NaN");
                     };               
                  };
       //check values are entered
    if(dlg.msgPnl.xVal.et.text == ''){
        alert("You need to enter the X Coordinate");
        dlg.msgPnl.xVal.et.active = true;
        return;
        }
    var returnedValue = isInteger(dlg.msgPnl.xVal.et.text);
            if(isNaN(returnedValue )){
              alert("ERROR -  "+dlg.msgPnl.xVal.et.text+ " is not a valid number")
                          } else {
               if(returnedValue >=0 && returnedValue <=activeDocument.width.value){
                var xValue = Number(dlg.msgPnl.xVal.et.text);                 
               } else {
                   alert("ERROR -  "+ returnedValue + " is too large for X Coordinate");
                   dlg.msgPnl.xVal.et.active = true;
                    return;
                }           
              }
       
           
    if(dlg.msgPnl.yVal.et.text == ''){
        alert("You need to enter the Y Coordinate");
         dlg.msgPnl.yVal.et.active = true;
         return;
        }
       var returnedValue = isInteger(dlg.msgPnl.yVal.et.text);
            if(isNaN(returnedValue )){
              alert("ERROR -  "+dlg.msgPnl.yVal.et.text+ " is not a valid number")
                          } else {
               if(returnedValue >=0 && returnedValue <=activeDocument.height.value){
                var yValue = Number(dlg.msgPnl.yVal.et.text);                 
               } else {
                   alert("ERROR -  "+ returnedValue + " is too large for Y Coordinate");
                   dlg.msgPnl.yVal.et.active = true;
                return;
                }           
              }
    if(dlg.msgPnl.szVal.et.text == ''){
        alert("You need to enter the Sample Area Size");
         dlg.msgPnl.szVal.et.active = true;
         return;
        }
       var returnedValue = isInteger(dlg.msgPnl.szVal.et.text);
            if(isNaN(returnedValue )){
              alert("ERROR -  "+dlg.msgPnl.szVal.et.text+ " is not a valid number")
                          } else {
               if(returnedValue <=activeDocument.height.value && returnedValue <=activeDocument.width.value){
                var sizeValue = Number(dlg.msgPnl.szVal.et.text);                 
               } else {
                   alert("ERROR -   "+ returnedValue + " is too large for sample area size");
                    dlg.msgPnl.szVal.et.active = true;
                return;
                }           
              }
              try{
    Prefs.x = Number(dlg.msgPnl.xVal.et.text);
    Prefs.y = Number(dlg.msgPnl.yVal.et.text);
    Prefs.size =Number(dlg.msgPnl.szVal.et.text);
    Prefs.folder2 = decodeURI(activeDocument.path);
    var desc2 = new ActionDescriptor();
    desc2.putString(0, Prefs.toSource());
    app.putCustomOptions('efe30920-ef50-11df-98cf-0800200c9a66', desc2, true );
    }catch(e){alert (e.line["Error"])}
          dlg.close(1);
          process();
          }
      dlg.show();
          function process(){
    var x = Number(dlg.msgPnl.xVal.et.text);//X, Y coordinates of sample area
    var y = Number(dlg.msgPnl.yVal.et.text);
    var size =Number(dlg.msgPnl.szVal.et.text);// size of sample area in pixels ie 10x10px
        //select sample area
    activeDocument.selection.select([[x,y],[x+size,y],[x+size,y+size],[x,y+size]]);
    //get the histogram of sample
    var area = activeDocument.histogram;
    alert("Brightness = " + Histogram.median(area) + "\rX = " + x + "\rY = " + y + "\rSize = " + size,['Histogram Level']);
    }

     dlg.btnPnl.cancelBtn.onClick = function(){
     dlg.close();
   }
}


if (app.version.match(/\d+/) <10){
    alert("Sorry but this script needs CS3 or better");
    }else{
main();
}

Professional AI Audio Generation within Adobe Premiere Pro - Download Free Plugin here

craezer

Add an interactive crop before processing folder

Post by craezer »

After taking a break from this for a bit, I started thinking cropping in an action and then calling a script from that would do the trick. I thought I was on to something when I found this thread- http://ps-scripts.com/bb/viewtopic.php? ... +crop+area. Paul's suggestion was was along the same idea I had, and Mike's example looks like it would work for my first idea. But after poking around a bit more on this, I'm having second thoughts on both ideas. I suspect my limited knowledge is creating hurdles that really aren't there.

First, is it possible to share an action? I use actions a lot, but I thought they weren't portable. Am I wrong on that? If they are portable, are they as simple to install as dropping a script in the scripts folder? Some of the end users pretty much live in Nuke and want this part of their workflow as invisible as possible. Second, is it possible for the user to set a crop area once and then crop a folder of images without further interaction? I batch process actions quite a bit, but my goal is to simplify this as much as possible. Is it possible to script the batch process under File>Automate?

Finally, this might seem counterintuitive, but I'm not sure crop is the best tool for a user to set crop bounds. If I remember correctly, the crop tool can do strange things to the image size and distort it after dragging the bounds. Perhaps marquee or some other tool would be a better choice?

Thanks again,
Chris