Skip to main content
August 24, 2011
Answered

Script Request??

  • August 24, 2011
  • 2 replies
  • 2165 views

Wondering if anyone was willing to take the time to write a script for PS CS5 on an iMAC that would allow me to resize the contents of specific folders, by name?  The attached folder hierarchy is representative of two (10-271 and 10-272) of over 100 folders within the root directory of CustomHeadwear.  Each of the 100+ folders has identical four sub-folders, i.e. Additional, Back, Front and Small.


I really need a script that would allow me to resize each of the sub-folders to specific individual width and lengths, based upon name.  For example, if the script could provide an initial interface, similar to below, that would allow me to type in as many as four folder names, and then specific width, height or percentage increase/decrease for each of these folders.  I suppose there would also have to be a Name box for the Root Folder?


I simply don’t have the expertise to create scripts, but I’ve certainly benefited from the expertise of those who have contributed to this Forum!  Thanks for any help!!

This topic has been closed for replies.
Correct answer Michael_L_Hale

Mike - All files are PNG format, and overwriting/saving as PNG is great. Saving them in the same folders is perfect.

Just to make sure I've been clear, the Root folder is Custom Planet, as you have stated. The script will subsequently be applied to CustomHeadwear/10-271/Additional, Front, Back, Small; then 10-272/Additional, Front, Back, Small, et al. I then will use the script on Custom Planet/CustomClothing/363M/Additional, Front, Back, Small, etc. through approximately 60 folders, etc. There are 11 other products, each with about 50 folders. Every product has four folders (Additional, Front, Back and Small). Custom Planet will be the root folder in all cases, then the product description folder (CustomHeadwear, CustomClothing, etc), then the product ID (10-271, 363M, 715, etc.).

BTW, Pinnacle was referring to the video editing software I used back in 2002, and a Mike Hale was a very helpful expert for many people in their Forum at that time.

Thanks again for your time, Mike!

==============


Ok, here is a quick and dirty script that should be close to what you want. The dialog is still ugly and there is limited error checking. Because it overwrites the files I suggest that you do a small test or at least backup you files before you run the script on important files. I did test it using WinXP and CS5 on a small test set and it seems to be working fine. But again use at your own risk.

// get the root folder from the user
var rootFolder = Folder.selectDialog('Please select the root folder');
if( rootFolder != null ){// if the user did not cancel the dialog
     // get all the product folders in rootFolder
     var productFolders = rootFolder.getFiles(isFolder);
     // get all the subFolders in the first product folder
     var subFolders = productFolders[0].getFiles(isFolder);
     // now that we have the needed info create and show the dialog
     var win = createDialog();
     initializeDialog(win);
     var res = runDialog(win);
     if( res == 1){
          // process the files
          for( var p = 0;p<productFolders.length;p++){
               var folders = productFolders

.getFiles(isFolder);
               for( var f = 0; f<folders.length;f++){
                    var folderName = folders.name.toLocaleLowerCase();
                    switch( folderName ){
                         case subFolders[0].name.toLocaleLowerCase():
                              processFolder( folders, Number(win.etWidth1.text), Number(win.etHeight1.text));
                              break;
                         case subFolders[1].name.toLocaleLowerCase():
                              processFolder( folders, Number(win.etWidth2.text), Number(win.etHeight2.text));
                              break;
                         case subFolders[2].name.toLocaleLowerCase():
                              processFolder( folders, Number(win.etWidth3.text), Number(win.etHeight3.text));
                              break;
                         case subFolders[3].name.toLocaleLowerCase():
                              processFolder( folders, Number(win.etWidth4.text), Number(win.etHeight4.text));
                              break;
                         default: break;
                    }
               }
          }
     }
}

function processFolder( folder, w, h ){
    var files = folder.getFiles(/png$/i);
     for(var f = 0; f<files.length;f++){
          app.open(files);
          fitImage(w,h);
          app.activeDocument.close(SaveOptions.SAVECHANGES);
     }
};
function createDialog( ) {
   var dlg = new Window( 'dialog', 'Your script name here' );
   dlg.alignChildren = 'left';
   dlg.RootPnl = dlg.add( 'panel', undefined, 'Root Folder' );
   dlg.RootPnl.stPath = dlg.RootPnl.add('statictext', undefined, decodeURI(rootFolder));
   dlg.RootPnl.stPath.preferredSize.width = 300;
   dlg.subPnl = dlg.add('panel',undefined,'SubFolders');
   dlg.subPnl.alignChildren = 'right';
   dlg.subPnl.stHeader = dlg.subPnl.add('statictext',undefined,'folder             width(px)      height(px)');
     dlg.subPnl.grp1 = dlg.subPnl.add('group');
     dlg.subPnl.grp1.stFolder = dlg.subPnl.grp1.add('statictext',undefined,subFolders[0].name);
     dlg.etWidth1 = dlg.subPnl.grp1.add('edittext');
      dlg.etWidth1.addEventListener ('keydown', NumericEditKeyboardHandler );
     dlg.etWidth1.preferredSize.width = 40;
     dlg.subPnl.grp1.spacer = dlg.subPnl.grp1.add('statictext');
     dlg.subPnl.grp1.spacer.preferredSize.width = 10;
     dlg.etHeight1 = dlg.subPnl.grp1.add('edittext');
      dlg.etHeight1.addEventListener ('keydown', NumericEditKeyboardHandler );
     dlg.etHeight1.preferredSize.width = 40;
    
     dlg.subPnl.grp2 = dlg.subPnl.add('group');
     dlg.subPnl.grp2.stFolder = dlg.subPnl.grp2.add('statictext',undefined,subFolders[1].name);
     dlg.etWidth2 = dlg.subPnl.grp2.add('edittext');
      dlg.etWidth2.addEventListener ('keydown', NumericEditKeyboardHandler );
     dlg.etWidth2.preferredSize.width = 40;
     dlg.subPnl.grp2.spacer = dlg.subPnl.grp2.add('statictext');
     dlg.subPnl.grp2.spacer.preferredSize.width = 10;
     dlg.etHeight2 = dlg.subPnl.grp2.add('edittext');
      dlg.etHeight2.addEventListener ('keydown', NumericEditKeyboardHandler );
     dlg.etHeight2.preferredSize.width = 40;
    
     dlg.subPnl.grp3 = dlg.subPnl.add('group');
     dlg.subPnl.grp3.stFolder = dlg.subPnl.grp3.add('statictext',undefined,subFolders[2].name);
     dlg.etWidth3 = dlg.subPnl.grp3.add('edittext');
      dlg.etWidth3.addEventListener ('keydown', NumericEditKeyboardHandler );
     dlg.etWidth3.preferredSize.width = 40;
     dlg.subPnl.grp3.spacer = dlg.subPnl.grp3.add('statictext');
     dlg.subPnl.grp3.spacer.preferredSize.width = 10;
     dlg.etHeight3 = dlg.subPnl.grp3.add('edittext');
      dlg.etHeight3.addEventListener ('keydown', NumericEditKeyboardHandler );
     dlg.etHeight3.preferredSize.width = 40;
    
      dlg.subPnl.grp4 = dlg.subPnl.add('group');
     dlg.subPnl.grp4.stFolder = dlg.subPnl.grp4.add('statictext',undefined,subFolders[3].name);
     dlg.etWidth4 = dlg.subPnl.grp4.add('edittext');
      dlg.etWidth4.addEventListener ('keydown', NumericEditKeyboardHandler );
     dlg.etWidth4.preferredSize.width = 40;
     dlg.subPnl.grp4.spacer = dlg.subPnl.grp4.add('statictext');
     dlg.subPnl.grp4.spacer.preferredSize.width = 10;
     dlg.etHeight4 = dlg.subPnl.grp4.add('edittext');
      dlg.etHeight4.addEventListener ('keydown', NumericEditKeyboardHandler );
     dlg.etHeight4.preferredSize.width = 40;
    
       
   dlg.btnPnl = dlg.add( 'panel');
   dlg.btnPnl.orientation = "row";
   dlg.btnPnl.alignment = "right";
   dlg.btnPnl.preferredSize [ 80, 80 ]
   dlg.btnPnl.okBtn = dlg.btnPnl.add( 'button', undefined, 'Ok', { name:'ok' });
   dlg.btnPnl.cancelBtn = dlg.btnPnl.add( 'button', undefined, 'Cancel', { name:'cancel' });
   return dlg;
};
function initializeDialog( w ) {

};
function runDialog( w ) {
   return w.show( );
};
function isFolder(f) {
    return f instanceof Folder;
};
function fitImage(w,h){
     var fitImage = stringIDToTypeID( "3caa3434-cb67-11d1-bc43-0060b0a13dc4" );
          var size = new ActionDescriptor();
          size.putUnitDouble( charIDToTypeID( "Wdth" ), charIDToTypeID( "#Pxl" ), w );
          size.putUnitDouble( charIDToTypeID( "Hght" ), charIDToTypeID( "#Pxl" ), h );
     executeAction( fitImage, size, DialogModes.NO );
};
///////////////////////////////////////////////////////////////////////////////
// Function: NumericEditKeyboardHandler
// Usage: Do not allow anything except for numbers 0-9
// Input: ScriptUI keydown event
// Return: <nothing> key is rejected and beep is sounded if invalid
// From the script 'Fit Image.jsx' by Adobe
///////////////////////////////////////////////////////////////////////////////
function NumericEditKeyboardHandler (event) {
    try {
        var keyIsOK = KeyIsNumeric (event) ||
                        KeyIsDelete (event) ||
                           KeyIsLRArrow (event) ||
                           KeyIsTabEnterEscape (event);
                          
        if (! keyIsOK) {
            //    Bad input: tell ScriptUI not to accept the keydown event
            event.preventDefault();
            /*    Notify user of invalid input: make sure NOT
                to put up an alert dialog or do anything which
                requires user interaction, because that
                interferes with preventing the 'default'
                action for the keydown event */
            app.beep();
        }
    }
    catch (e) {
        ; // alert ("Ack! bug in NumericEditKeyboardHandler: " + e);
    }
};
//    key identifier functions
function KeyIsNumeric ( event ) {
    return  ( event.keyName >= '0' ) && ( event.keyName <= '9' ) && ! KeyHasModifier ( event );
};
function KeyHasModifier ( event ) {
    return event.shiftKey || event.ctrlKey || event.altKey || event.metaKey;
};
function KeyIsDelete (event) {
    //    Shift-delete is ok
    return (event.keyName == 'Backspace') && ! (event.ctrlKey);
};
function KeyIsLRArrow (event) {
    return ((event.keyName == 'Left') || (event.keyName == 'Right')) && ! (event.altKey || event.metaKey);
};
function KeyIsTabEnterEscape (event) {
     return event.keyName == 'Tab' || event.keyName == 'Enter' || event.keyName == 'Escape';
};

2 replies

c.pfaffenbichler
Community Expert
Community Expert
August 25, 2011
that would allow me to type in as many as four folder names,

Quite frankly that seems odd (and in case of typing-errors problematic).

Is there a reason you don’t want to use a Folder-dialog?

August 25, 2011

Thanks for the reply. I guess I don't know what you mean by "Folder-dialog"?? The issue is, I have 112 folders, and each has four identically named sub-folders. All four of these sub-folders need to be resized, i.e. XXXX1 may contain 25 PNG images that need to be one consistent size; XXXX2 may contain 30 PNG images that need to be another consistent size; XXXX3 may contain 10 PNG images that need to be yet another size, etc., then on to the next folder. I only used the number "four" because that is the number of sub-folders in each of the 112 folders. These 112 folders only cover one root folder - there are eleven more root folders, containing approximately 8,000 images, awaiting the same application.

Perhaps I'm not using the correct verbiage, but the above is what I need to do. If a "Folder-dialog" would accomplish this, without doing a "folder by folder" resizing, that would be great! Thanks again.

=============

August 28, 2011

Ok, here is a quick and dirty script that should be close to what you want. The dialog is still ugly and there is limited error checking. Because it overwrites the files I suggest that you do a small test or at least backup you files before you run the script on important files. I did test it using WinXP and CS5 on a small test set and it seems to be working fine. But again use at your own risk.

// get the root folder from the user
var rootFolder = Folder.selectDialog('Please select the root folder');
if( rootFolder != null ){// if the user did not cancel the dialog
     // get all the product folders in rootFolder
     var productFolders = rootFolder.getFiles(isFolder);
     // get all the subFolders in the first product folder
     var subFolders = productFolders[0].getFiles(isFolder);
     // now that we have the needed info create and show the dialog
     var win = createDialog();
     initializeDialog(win);
     var res = runDialog(win);
     if( res == 1){
          // process the files
          for( var p = 0;p<productFolders.length;p++){
               var folders = productFolders

.getFiles(isFolder);
               for( var f = 0; f<folders.length;f++){
                    var folderName = folders.name.toLocaleLowerCase();
                    switch( folderName ){
                         case subFolders[0].name.toLocaleLowerCase():
                              processFolder( folders, Number(win.etWidth1.text), Number(win.etHeight1.text));
                              break;
                         case subFolders[1].name.toLocaleLowerCase():
                              processFolder( folders, Number(win.etWidth2.text), Number(win.etHeight2.text));
                              break;
                         case subFolders[2].name.toLocaleLowerCase():
                              processFolder( folders, Number(win.etWidth3.text), Number(win.etHeight3.text));
                              break;
                         case subFolders[3].name.toLocaleLowerCase():
                              processFolder( folders, Number(win.etWidth4.text), Number(win.etHeight4.text));
                              break;
                         default: break;
                    }
               }
          }
     }
}

function processFolder( folder, w, h ){
    var files = folder.getFiles(/png$/i);
     for(var f = 0; f<files.length;f++){
          app.open(files);
          fitImage(w,h);
          app.activeDocument.close(SaveOptions.SAVECHANGES);
     }
};
function createDialog( ) {
   var dlg = new Window( 'dialog', 'Your script name here' );
   dlg.alignChildren = 'left';
   dlg.RootPnl = dlg.add( 'panel', undefined, 'Root Folder' );
   dlg.RootPnl.stPath = dlg.RootPnl.add('statictext', undefined, decodeURI(rootFolder));
   dlg.RootPnl.stPath.preferredSize.width = 300;
   dlg.subPnl = dlg.add('panel',undefined,'SubFolders');
   dlg.subPnl.alignChildren = 'right';
   dlg.subPnl.stHeader = dlg.subPnl.add('statictext',undefined,'folder             width(px)      height(px)');
     dlg.subPnl.grp1 = dlg.subPnl.add('group');
     dlg.subPnl.grp1.stFolder = dlg.subPnl.grp1.add('statictext',undefined,subFolders[0].name);
     dlg.etWidth1 = dlg.subPnl.grp1.add('edittext');
      dlg.etWidth1.addEventListener ('keydown', NumericEditKeyboardHandler );
     dlg.etWidth1.preferredSize.width = 40;
     dlg.subPnl.grp1.spacer = dlg.subPnl.grp1.add('statictext');
     dlg.subPnl.grp1.spacer.preferredSize.width = 10;
     dlg.etHeight1 = dlg.subPnl.grp1.add('edittext');
      dlg.etHeight1.addEventListener ('keydown', NumericEditKeyboardHandler );
     dlg.etHeight1.preferredSize.width = 40;
    
     dlg.subPnl.grp2 = dlg.subPnl.add('group');
     dlg.subPnl.grp2.stFolder = dlg.subPnl.grp2.add('statictext',undefined,subFolders[1].name);
     dlg.etWidth2 = dlg.subPnl.grp2.add('edittext');
      dlg.etWidth2.addEventListener ('keydown', NumericEditKeyboardHandler );
     dlg.etWidth2.preferredSize.width = 40;
     dlg.subPnl.grp2.spacer = dlg.subPnl.grp2.add('statictext');
     dlg.subPnl.grp2.spacer.preferredSize.width = 10;
     dlg.etHeight2 = dlg.subPnl.grp2.add('edittext');
      dlg.etHeight2.addEventListener ('keydown', NumericEditKeyboardHandler );
     dlg.etHeight2.preferredSize.width = 40;
    
     dlg.subPnl.grp3 = dlg.subPnl.add('group');
     dlg.subPnl.grp3.stFolder = dlg.subPnl.grp3.add('statictext',undefined,subFolders[2].name);
     dlg.etWidth3 = dlg.subPnl.grp3.add('edittext');
      dlg.etWidth3.addEventListener ('keydown', NumericEditKeyboardHandler );
     dlg.etWidth3.preferredSize.width = 40;
     dlg.subPnl.grp3.spacer = dlg.subPnl.grp3.add('statictext');
     dlg.subPnl.grp3.spacer.preferredSize.width = 10;
     dlg.etHeight3 = dlg.subPnl.grp3.add('edittext');
      dlg.etHeight3.addEventListener ('keydown', NumericEditKeyboardHandler );
     dlg.etHeight3.preferredSize.width = 40;
    
      dlg.subPnl.grp4 = dlg.subPnl.add('group');
     dlg.subPnl.grp4.stFolder = dlg.subPnl.grp4.add('statictext',undefined,subFolders[3].name);
     dlg.etWidth4 = dlg.subPnl.grp4.add('edittext');
      dlg.etWidth4.addEventListener ('keydown', NumericEditKeyboardHandler );
     dlg.etWidth4.preferredSize.width = 40;
     dlg.subPnl.grp4.spacer = dlg.subPnl.grp4.add('statictext');
     dlg.subPnl.grp4.spacer.preferredSize.width = 10;
     dlg.etHeight4 = dlg.subPnl.grp4.add('edittext');
      dlg.etHeight4.addEventListener ('keydown', NumericEditKeyboardHandler );
     dlg.etHeight4.preferredSize.width = 40;
    
       
   dlg.btnPnl = dlg.add( 'panel');
   dlg.btnPnl.orientation = "row";
   dlg.btnPnl.alignment = "right";
   dlg.btnPnl.preferredSize [ 80, 80 ]
   dlg.btnPnl.okBtn = dlg.btnPnl.add( 'button', undefined, 'Ok', { name:'ok' });
   dlg.btnPnl.cancelBtn = dlg.btnPnl.add( 'button', undefined, 'Cancel', { name:'cancel' });
   return dlg;
};
function initializeDialog( w ) {

};
function runDialog( w ) {
   return w.show( );
};
function isFolder(f) {
    return f instanceof Folder;
};
function fitImage(w,h){
     var fitImage = stringIDToTypeID( "3caa3434-cb67-11d1-bc43-0060b0a13dc4" );
          var size = new ActionDescriptor();
          size.putUnitDouble( charIDToTypeID( "Wdth" ), charIDToTypeID( "#Pxl" ), w );
          size.putUnitDouble( charIDToTypeID( "Hght" ), charIDToTypeID( "#Pxl" ), h );
     executeAction( fitImage, size, DialogModes.NO );
};
///////////////////////////////////////////////////////////////////////////////
// Function: NumericEditKeyboardHandler
// Usage: Do not allow anything except for numbers 0-9
// Input: ScriptUI keydown event
// Return: <nothing> key is rejected and beep is sounded if invalid
// From the script 'Fit Image.jsx' by Adobe
///////////////////////////////////////////////////////////////////////////////
function NumericEditKeyboardHandler (event) {
    try {
        var keyIsOK = KeyIsNumeric (event) ||
                        KeyIsDelete (event) ||
                           KeyIsLRArrow (event) ||
                           KeyIsTabEnterEscape (event);
                          
        if (! keyIsOK) {
            //    Bad input: tell ScriptUI not to accept the keydown event
            event.preventDefault();
            /*    Notify user of invalid input: make sure NOT
                to put up an alert dialog or do anything which
                requires user interaction, because that
                interferes with preventing the 'default'
                action for the keydown event */
            app.beep();
        }
    }
    catch (e) {
        ; // alert ("Ack! bug in NumericEditKeyboardHandler: " + e);
    }
};
//    key identifier functions
function KeyIsNumeric ( event ) {
    return  ( event.keyName >= '0' ) && ( event.keyName <= '9' ) && ! KeyHasModifier ( event );
};
function KeyHasModifier ( event ) {
    return event.shiftKey || event.ctrlKey || event.altKey || event.metaKey;
};
function KeyIsDelete (event) {
    //    Shift-delete is ok
    return (event.keyName == 'Backspace') && ! (event.ctrlKey);
};
function KeyIsLRArrow (event) {
    return ((event.keyName == 'Left') || (event.keyName == 'Right')) && ! (event.altKey || event.metaKey);
};
function KeyIsTabEnterEscape (event) {
     return event.keyName == 'Tab' || event.keyName == 'Enter' || event.keyName == 'Escape';
};


Mike - It worked EXACTLY as intended! Will save me much time and I thank you so much for doing this!

+++++++++++++++

JJMack
Community Expert
Community Expert
August 24, 2011

The script you requestion would need to be fully designed the outline you described I'm sure does not include all the details involved.  It would be a complex program to design and program not a quick hack. For example width height  is that a force fit distort or a fit image constrained type resize.

Look at Russell Browns web site for the Image Process Pro script it is a Photoshop Plug-in script you can record it in actions and it will run without a Dialog when the action is played if you keep re-using the input folders.  If the folders names change you can use the Image Process Pro dialog.  The Image Processor Pro is found from menu File>Automate>Image Processor Pro.  This Image Processor besides being a Plug-in script has a Tabed middle section where you can add and remove desired output file type with different resize settings.  Tabs images can be turn on and off.  You can also save the setup you make to this tabed section.  These save setup can also be loaded.  So you could create a library of the setup you needs and just load the setup you need for your different tree types.

JJMack
August 25, 2011

Thanks, JJMack, for the heads up. I've installed the script and viewed the tutorial, and I think it will work for my project. The only thing I'm not sure about yet is whether IPP will, after resizing images in the first named sub-folder, then continue on to the next folder, locating similarly named sub-folders and resizing them as well?? Whatever the result, this will be a beneficial tool to have - thanks again!

===============