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

Iterating through all layers extremely slow

Explorer ,
Dec 18, 2016 Dec 18, 2016

I've attached a snipped that changes antialising on all text layers to "Smooth", on both hidden and unhidden layers.

The problem is that this is extreeemely slow, so I'm wondering if there is any way to make this faster? Also, is there an easy way to be able to see a progressbar when running the function?

// FUNCTION: APPLY FONT CHANGES

function fnChangeAntiAlias(target)

{

    // Get the layers of the active document

    var docLayers = target.layers;

    // For each layer in the document

    for (var i = 0; i < docLayers.length; i++)

    {

        // If the current layer is a LayerSet

        if (docLayers.typename == "LayerSet")

        {

            // Recursive: Re-run function with the current LayerSet as target

            fnChangeAntiAlias(docLayers);

        }

        // Else if the current layer is a text layer

        else if (docLayers.kind == LayerKind.TEXT)

        {

              docLayers.textItem.antiAliasMethod = AntiAlias.SMOOTH;

        };

    };

};

// Get the active document

var doc = app.activeDocument;

// Execute the function

fnChangeAntiAlias(doc);

TOPICS
Actions and scripting
3.1K
Translate
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

Guide , Dec 18, 2016 Dec 18, 2016

This should be a bit faster.

#target photoshop;

if(documents.length){

var tLayers = getTextIds();

for(var a in tLayers){

selectLayerByID(Number(tLayers));

activeDocument.activeLayer.textItem.antiAliasMethod = AntiAlias.SMOOTH;

}

alert("All Done");

};

function selectLayerByID(ID, add) {

    add = (add == undefined)  ? add = false : add;

    var ref = new ActionReference();

    ref.putIdentifier(charIDToTypeID('Lyr '), ID);

    var desc = new ActionDescriptor();

    desc.putReference(charIDToTypeID('null'), ref)

...
Translate
Adobe
Guide ,
Dec 18, 2016 Dec 18, 2016

This should be a bit faster.

#target photoshop;

if(documents.length){

var tLayers = getTextIds();

for(var a in tLayers){

selectLayerByID(Number(tLayers));

activeDocument.activeLayer.textItem.antiAliasMethod = AntiAlias.SMOOTH;

}

alert("All Done");

};

function selectLayerByID(ID, add) {

    add = (add == undefined)  ? add = false : add;

    var ref = new ActionReference();

    ref.putIdentifier(charIDToTypeID('Lyr '), ID);

    var desc = new ActionDescriptor();

    desc.putReference(charIDToTypeID('null'), ref);

    if (add) {

        desc.putEnumerated(stringIDToTypeID('selectionModifier'), stringIDToTypeID('selectionModifierType'), stringIDToTypeID('addToSelection'));

    }

    desc.putBoolean(charIDToTypeID('MkVs'), false);

    executeAction(charIDToTypeID('slct'), desc, DialogModes.NO);

};

function getTextIds(){

   var ref = new ActionReference();

   ref.putProperty( charIDToTypeID( "Prpr" ), charIDToTypeID( 'NmbL' ));

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

   var count = executeActionGet(ref).getInteger(charIDToTypeID('NmbL')) +1;

   var TextIDs=[];

try{

    activeDocument.backgroundLayer;

var i = 0; }catch(e){ var i = 1; };

   for(i;i<count;i++){

       if(i == 0) continue;

        ref = new ActionReference();

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

        var desc = executeActionGet(ref);

        if( desc.hasKey( stringIDToTypeID( 'textKey' ) ) ){

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

    TextIDs.push(ID);

}

   };

return TextIDs;

};

Translate
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
Explorer ,
Dec 18, 2016 Dec 18, 2016

Haha, a bit? It went 100x faster now, thank you sir!

I gotta say though, ActionScripts looks cryptic to me, could you point me in a direction to learn about it?

Thanks again man, much appreciated

Translate
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
Participant ,
Dec 18, 2016 Dec 18, 2016
This should be a bit faster.

That should be a lot faster! The only downside I see is that it has to select the layer and set the "smooth" property using Photoshop's API, which can be a little slow.

SuperMerlin​, I made some adjustments to your code to set the smooth property through Descriptors without selecting layers, and using the layerIds you gathered. it should be a bit faster

#target photoshop

if(documents.length) { 

    var tLayers = getTextIds();

   

    for(var a = 0; a < tLayers.length; a++) { 

        setTextLayerToSmooth(tLayers);

    }

   

    alert("All Done"); 

}; 

function getTextIds() {

    var ref = new ActionReference();

    ref.putProperty( charIDToTypeID( "Prpr" ), charIDToTypeID( 'NmbL' ));

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

    var count = executeActionGet(ref).getInteger(charIDToTypeID('NmbL')) +1;

    var TextIDs = [];

    try {

        activeDocument.backgroundLayer; 

        var i = 0;

    } catch(e) { var i = 1; };

   

    for(i; i < count; i++) {

        if(i == 0) continue;

        ref = new ActionReference();

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

        var desc = executeActionGet(ref);

        if( desc.hasKey( stringIDToTypeID( 'textKey' ) ) ) {

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

            TextIDs.push(ID);

        }

    }

    return TextIDs;

}

function setTextLayerToSmooth(layerId) {

    var antiAliasDesc = new ActionDescriptor();

    var antiAliasRef = new ActionReference();

    antiAliasRef.putProperty( charIDToTypeID( "Prpr" ), charIDToTypeID( "AntA" ) );

    antiAliasRef.putIdentifier( charIDToTypeID( "TxLr" ), layerId );

    antiAliasDesc.putReference( charIDToTypeID( "null" ), antiAliasRef );

    antiAliasDesc.putEnumerated( charIDToTypeID( "T   " ), charIDToTypeID( "Annt" ), charIDToTypeID( "AnSm" ) );

    executeAction( charIDToTypeID( "setd" ), antiAliasDesc, DialogModes.NO );

}

Translate
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
Guide ,
Dec 19, 2016 Dec 19, 2016

Yes you are right! But one thing I hate doing is woking with text in action manager since CS5, CS6 was a nightmare when it was first released and still has problems. As for the latest versions I do not know as my last version is CS6.

So anything action manager with text needs to be tested on the version it is to be used on.

Translate
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
Guide ,
Dec 19, 2016 Dec 19, 2016

There is no easy way of learing Action Manager code, you need to delve into thr descriptors

Christoph wrote some hany code for looking at a layers descriptor.

It should give you a start.

  1. //Written by Christoph Pfaffenbichler 
  2. // based on code by michael l hale; 
  3. // 2012, use it at your own risk; 
  4. #target photoshop 
  5. var ref = new ActionReference(); 
  6. ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );  
  7. var applicationDesc = executeActionGet(ref); 
  8. checkDesc2(applicationDesc); 
  9.  
  10. function checkDesc2 (aDesc) { 
  11. var c = aDesc.count; 
  12. var str = ''
  13. for(var i=0;i<c;i++){ //enumerate descriptor's keys 
  14.           str = str + 'Key '+i+' = '+typeIDToStringID(aDesc.getKey(i))+': '+aDesc.getType(aDesc.getKey(i))+'\n'+getValues (aDesc, i)+'\n'; 
  15.           }; 
  16. $.writeln("desc\n\n"+str); 
  17. }; 
  18. ////// check ////// 
  19. function getValues (aDesc, aNumber) { 
  20. switch (aDesc.getType(aDesc.getKey(aNumber))) { 
  21. case DescValueType.BOOLEANTYPE: 
  22. return aDesc.getBoolean(aDesc.getKey(aNumber)); 
  23. break; 
  24. case DescValueType.CLASSTYPE: 
  25. return aDesc.getClass(aDesc.getKey(aNumber)); 
  26. break; 
  27. case DescValueType.DOUBLETYPE: 
  28. return aDesc.getDouble(aDesc.getKey(aNumber)); 
  29. break; 
  30. case DescValueType.ENUMERATEDTYPE: 
  31. return (typeIDToStringID(aDesc.getEnumerationValue(aDesc.getKey(aNumber)))+"_"+typeIDToStringID(aDesc.getEnumerationType(aDesc.getKey(aNumber)))); 
  32. break; 
  33. case DescValueType.INTEGERTYPE: 
  34. return aDesc.getInteger(aDesc.getKey(aNumber)); 
  35. break; 
  36. case DescValueType.LISTTYPE: 
  37. return aDesc.getList(aDesc.getKey(aNumber)); 
  38. break; 
  39. case DescValueType.OBJECTTYPE: 
  40. return (aDesc.getObjectValue(aDesc.getKey(aNumber))+"_"+typeIDToStringID(aDesc.getObjectType(aDesc.getKey(aNumber)))); 
  41. break; 
  42. case DescValueType.REFERENCETYPE: 
  43. return aDesc.getReference(aDesc.getKey(aNumber)); 
  44. break; 
  45. case DescValueType.STRINGTYPE: 
  46. return aDesc.getString(aDesc.getKey(aNumber)); 
  47. break; 
  48. case DescValueType.UNITDOUBLE: 
  49. return (aDesc.getUnitDoubleValue(aDesc.getKey(aNumber))+"_"+typeIDToStringID(aDesc.getUnitDoubleType(aDesc.getKey(aNumber)))); 
  50. break; 
  51. default:  
  52. break; 
  53. }; 
  54. }; 
Translate
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
Explorer ,
Dec 19, 2016 Dec 19, 2016

So the way people are learning this is by using the Script Listener, then trying to remove parts from the code, re-run etc? Is there no good documentation on this? Is there at least some reference for the shortnames, like "Prpr" = Property, "NmbL" = Number of layers?

Another thing I'm wondering about, how is scripting in Photoshop between different versions? Will you normally have to make changes on both Javascripts and ActionManagerScripts when a new Photoshop version comes out? Or is Javascript "safer" to use in that regard?

Translate
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
LEGEND ,
Dec 24, 2016 Dec 24, 2016
LATEST
Translate
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
Explorer ,
Dec 19, 2016 Dec 19, 2016

I didn't quite understand the purpose of Christoph Pfaffenbichler's script though, nothing happens when I run it?

Translate
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
Guide ,
Dec 19, 2016 Dec 19, 2016

The code should be copied and pasted into ExtendScript Toolkit.

You should have a document open with a layer selected, then run the code from within ExtendScript Toolkit (ESTK) in the console window it will show you the results.

There is a huge amount of information to be found at:-

Tonton Pixel | Blog of Michel MARIANI aka “Mikaeru”

Code needs to be tested on the version(s) it is intended to be run on, there are some major changes between versions.

Good luck.

Translate
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
Explorer ,
Dec 19, 2016 Dec 19, 2016

Thank you for all your help SuperMerlin, it's very enlightening, it doesn't seem there's a vast amount of people knowing much about this topic. I'll try to put two more questions in if you haven't lost your patience with me yet

I'm wondering about these three commands:

actionRef.putProperty( charIDToTypeID( "Prpr" ), charIDToTypeID( 'NmbL' ));

actionRef.putEnumerated( charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );

var count = executeActionGet(actionRef).getInteger(charIDToTypeID('NmbL')) +1;

Could you explain what they do? From what I understand the putProperty assigns the value "NumberOfLayers" to the class "Property". I have no idea what putEnumerated do. The executeActionGet will return the number of layers because of the putProperty, right? I'm sorry if these are stupid questions, I'm just struggling to wrap my mind around how this works just my looking at the code I've looked around on several scripts on github, but it seems noone make comments in their ActionManager code?

Thanks man, I really appreciate the help you have given me

Translate
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
Guide ,
Dec 20, 2016 Dec 20, 2016

Yes, the putProperty is the only property we want from the Document descriptor.

'Dcmn' = Document

The number of layers returned includes TWO entries for each layerset, one for the start and one for the end of the layerset.

Translate
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
Explorer ,
Dec 22, 2016 Dec 22, 2016

I'm sorry, I'm still confused So I tried removing the putProperty, and the script still worked, do I even need this? It doesn't seem to do anything?

Also, putEnumerated, could you explain what this actually does? I pass in the argument for document, ordinal and target, when I've done that I can get the number of layers by using executeActionGet(actionRef).getInteger(charIDToTypeID('NmbL')), but as I don't need putProperty to add the 'NmbL' property, why can I still get the number of layers?

If I just knew exactly what putEnumerated did it would be a lot easier to understand how this hangs together

Translate
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
Guide ,
Dec 22, 2016 Dec 22, 2016

Ok, the putProperty is there to select ONLY this property from the action descriptor, and with this line included it can/does speed the process of getting the infomation.

The putEnumerated is the setup to get the descriptor inforation.

executeActionGet goes and fetchs the information.

Experiment with Chistoph's code abobe.

change

//layer information

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

to

//document information

ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 

also

//Current app

ref.putEnumerated( charIDToTypeID("capp"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 

These will show what is available, if you add the putProperty line in Christoph's code you will see it only retrieves that property.

actionRef.putProperty( charIDToTypeID( "Prpr" ), charIDToTypeID( 'NmbL' ));

actionRef.putEnumerated( charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );

Keep trying

Translate
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
Explorer ,
Dec 22, 2016 Dec 22, 2016

Awesome, exactly what I was hoping for! Thank you for that detailed explanation, I think I get it now

Translate
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