• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Looping through layers is slow.

New Here ,
Jul 16, 2014 Jul 16, 2014

Copy link to clipboard

Copied

Hi, so i am trying to make a script that goes goes through all the layers of an a document, sets the size of the layer to a specified width and height and export it in a separate file. I finished the script but it really really slow. I read that accessing layers from the DOM is slow and that i should use the ActionManager instead, but I can't find any documentation on how to use the ActionManager.

This is what I have so far:

Ok so right now I am creating a document with the size I want. Copy the layer I want from the current doc to the new one and save the document. When I see a group I create a folder on the Directory and call the function recursively.

var refDoc;

var tempDoc;

function main(){

        refDoc = app.activeDocument;

        tempDoc = app.documents.add(500, 500, 72, "tempDoc", NewDocumentMode.RGB, DocumentFill.TRANSPARENT);

        app.activeDocument = refDoc;

        mainFolder = app.activeDocument.path + "/test";

          savetAllLayers(app.activeDocument, mainFolder);

        tempDoc.close (SaveOptions.DONOTSAVECHANGES);

}

function saveAllLayers(group, folderName){

    var groupFolder = new Folder(folderName)

    for (var i = 0; i < group.layers.length; i++){

            if (group.layers.typename.valueOf() === "LayerSet"){

                var groupFolder = new Folder(folderName + "/" + group.layers.name);

                if (!groupFolder.exist){

                    groupFolder.create();

                }

                saveAllLayers(group.layers, groupFolder);

            }

            else if (group.layers.typename.valueOf() === "ArtLayer"){

                try {

                    app.activeDocument = refDoc;

                    group.layers.copy();

                    app.activeDocument = tempDoc;

                    var targetLayer = tempDoc.artLayers.add();

                    tempDoc.paste();

                    tempDoc.activeLayer.resize(500, 500);

                    var options = new ExportOptionsSaveForWeb();

                    options.fomat = SaveDocumentType.PNG;

                    options.PNG8 = false;

                    options.transparency = true;

                    options.optimized = true;

                    //Export Save for Web in the current folder

                    tempDoc.exportDocument(File(folderName +'/' + group.layers.name +'.png'), ExportType.SAVEFORWEB, options);

                    targetLayer.remove();

                } catch (e){

                    alert("Error on layer: " + group.layers.name + "\n\n\n" + e.message);

                }

            }

    }

    return

}}

How can I use the ActionManager to achieve this? Thank you.

TOPICS
Actions and scripting

Views

1.4K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Contributor , Jul 17, 2014 Jul 17, 2014

I don't think that AM will help to much, the time eating operation is the resize and you can't do anything with AM to make it faster,

the only think in where the AM could help is the going through layers, other than that I don't see how you can make it faster...

Here is a code with AM that will do what your function is doing, I've compared the time for both of them and there is a small improvement with AM in terms of time but it's not that much noticeable.

function BCM_saveAsFolders( pathname ){

 

...

Votes

Translate

Translate
Adobe
Community Expert ,
Jul 16, 2014 Jul 16, 2014

Copy link to clipboard

Copied

The code in that thread is largely based on stuff Mike and Paul have provided (I may have added mistakes of my own, though) but I can’t locate the threads from which I took it.

Calculating width height in script

If you remove the lines

alert ("width: "+theWidth+", height: "+theHeight+", index: "+m+", name: "+theName);

selectLayerByIndex(m,false);

and instead collect the info in an Array for example it should run faster than the corresponding DOM code.

Maybe you should search

PS-Scripts • Photoshop Scripting Community

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jul 17, 2014 Jul 17, 2014

Copy link to clipboard

Copied

I don't think that AM will help to much, the time eating operation is the resize and you can't do anything with AM to make it faster,

the only think in where the AM could help is the going through layers, other than that I don't see how you can make it faster...

Here is a code with AM that will do what your function is doing, I've compared the time for both of them and there is a small improvement with AM in terms of time but it's not that much noticeable.

function BCM_saveAsFolders( pathname ){

  refDoc1 = app.activeDocument;

  var sizes = {w:500, h:500};

    var tempDoc1 = app.documents.add(500,500, 72, "BCM_rrrre_tempDoc1", NewDocumentMode.RGB, DocumentFill.TRANSPARENT); 

  app.activeDocument = refDoc1;

  var ref = new ActionReference();

  ref.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );

    var aa = 0;

    try{app.activeDocument.backgroundLayer}catch(err){aa = 1};

  var count = executeActionGet(ref).getInteger(charIDToTypeID('Cnt ')) - aa;// the number of layers in the document

  var x, y, r = 0;

  var currentFolder = new Folder(pathname);

  if(!currentFolder.exists){currentFolder.create()};

  for(i = count; i >= 0 ; i--){// the recursive loop

  ref = new ActionReference();

      ref.putIndex( charIDToTypeID( 'Lyr ' ), i );

     try{

      var desc = executeActionGet(ref);

     }catch(err){ break; }

     var layerName = desc.getString(charIDToTypeID( 'Nm  ' ));

        var Id = desc.getInteger(stringIDToTypeID( 'layerID' ));

        var ls = desc.getEnumerationValue(stringIDToTypeID("layerSection"));

        ls = typeIDToStringID(ls);

        var vis = desc.getInteger(stringIDToTypeID( 'visible' ));r

            if(ls == 'layerSectionContent'){

            duplicateTotempDoc1umentAndSaveByIDX(i, (currentFolder.fullName +"/"+layerName), sizes, tempDoc1);

            app.activeDocument = refDoc1;

            }

            if(ls == 'layerSectionStart'){// if it's the start of a layer set

            currentFolder = new Folder(currentFolder.fullName +"/"+layerName);

            if( !currentFolder.exists ){

            currentFolder.create();

            }

            }

            if(ls == 'layerSectionEnd'){// if it's the end of a layerSet

            var cPthStr = currentFolder.fullName.toString();

            currentFolder = new Folder(cPthStr.substring(0,cPthStr.lastIndexOf("/")));

            }

  }

    tempDoc1.close (SaveOptions.DONOTSAVECHANGES);

}

function duplicateTotempDoc1umentAndSaveByIDX(idx, pathname, size, tempDoc1){

  // =======================================================duplicate layer to a new document

  var idDplc = charIDToTypeID( "Dplc" );

     var desc57 = new ActionDescriptor();

     var idnull = charIDToTypeID( "null" );

         var ref47 = new ActionReference();

         ref47.putIndex( charIDToTypeID( "Lyr " ), idx );

     desc57.putReference( idnull, ref47 );

     var idT = charIDToTypeID( "T   " );

         var ref48 = new ActionReference();

         var idDcmn = charIDToTypeID( "Dcmn" );

         ref48.putName( idDcmn, "BCM_rrrre_tempDoc1" );

     desc57.putReference( idT, ref48 );

     var idVrsn = charIDToTypeID( "Vrsn" );

     desc57.putInteger( idVrsn, 5 );

  executeAction( idDplc, desc57, DialogModes.NO );

  app.activeDocument = tempDoc1;

    tempDoc1.activeLayer.resize(500, 500);

  var options = new ExportOptionsSaveForWeb(); 

  options.format = SaveDocumentType.PNG; 

  options.PNG8 = false; 

  options.transparency = true; 

  options.optimized = true; 

  //Export Save for Web in the current folder 

  tempDoc1.exportDocument(new File(pathname +'.png'), ExportType.SAVEFORWEB, options);

  tempDoc1.activeLayer.remove(); 

}

// var startTime = new Date().getTime();

BCM_saveAsFolders(Folder.desktop +"/test");

// var endTime = new Date().getTime();

// alert(endTime - startTime);

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jul 17, 2014 Jul 17, 2014

Copy link to clipboard

Copied

Two things you could try:

  • Instead of Copy/Paste use layer.duplicate()
  • When doing lots of operations, maintaining history can be a bottleneck. Try using

    app.activeDocument.suspendHistory("Executing script, please wait...", "savetAllLayers(app.activeDocument, mainFolder)")



Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jul 21, 2014 Jul 21, 2014

Copy link to clipboard

Copied

Thank you. What exactly does suspenHistory do? and should i call it?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Aug 09, 2014 Aug 09, 2014

Copy link to clipboard

Copied

LATEST

Sorry, forgot this. suspendHistory tells Photoshop to run a part of script without saving the undo state for each step. Basically everything is one big undo (which is typically what you'd want in any case). Calling it gives one info text (becomes title or something) and the second parameter is a peace of Javascript you want to run like calling one function. Not 100% sure if passing parameters as references/values works.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines