Skip to main content
Participating Frequently
October 20, 2021
Answered

Applying an action to all the layers in a document.

  • October 20, 2021
  • 3 replies
  • 8782 views

Hello all.
Does anyone know if there is a way to apply the same Action to all the layers in the Layers Palette? I imported a video sequence and would like to carry out a semi-rotoscope action on all the layer prior to exporting the video. Batch doesn't seem to do it, it can only work on files in a folder.
Thank you in advance,

Sarah

Birmingham City University

UK

 

 

Ps: I am definitely not a scripter, but willing to learn! I don't even know the scripting language in Photoshop. 😞

This topic has been closed for replies.
Correct answer jazz-y

Copy the code from this page, create a new document in any text editor, paste the code. Save it in plain text (txt) format with any filename. After (or during) saving, change the file extension from ".txt" to ".jsx" (so that Photoshop understands that this is a file with a script inside).

Find the folder where you have installed Photoshop, place the * .jsx file in the \Presets\Scripts\ directory. Restart Photoshop, after that the script will appear in the File-> Scripts menu. After that, you can run it manually, assign a hotkey, or record it into an action. 

3 replies

Legend
October 21, 2021

script runs selected action in actions palette for all selected layers

 

#target photoshop
var s2t = stringIDToTypeID;

(r = new ActionReference()).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var lrs = executeActionGet(r).getList(p);

(r = new ActionReference()).putEnumerated(s2t('action'), s2t('ordinal'), s2t('targetEnum'));
try {
    try {
        var atn = executeActionGet(r).getString(s2t('name')),
            set = executeActionGet(r).getString(s2t('parentName'));
    }
    catch (e) { throw 'Before start select any action from actions palette!' }

    for (var i = 0; i < lrs.count; i++) {
        (r = new ActionReference()).putIdentifier(s2t('layer'), lrs.getReference(i).getIdentifier(s2t('layerID')));
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        try { executeAction(s2t('select'), d, DialogModes.NO); } catch (e) { throw e + '\nCannot select layer!' }
        (r = new ActionReference()).putName(s2t('action'), atn);
        r.putName(s2t('actionSet'), set);
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        try { executeAction(s2t('play'), d) } catch (e) { throw e + '\nCannot play action "' + atn + '" from set "' + set + '"' }
    }
} catch (e) { alert(e) }

 

JJMack
Community Expert
Community Expert
October 21, 2021

That is a much better way  you run the action on the layer you want to process  not have to filter layer types in a custom script before running the action.

 

 

I forget to highlight an action when I did delect an action that action added a nen document frone the layer  the script failed because of the doc switch. 

The script could be improved to test if the docoment has been switched and if it has try to switch back to the document the script was run from.

 

Its a neet script

JJMack
JJMack
Legend
October 21, 2021

I try not to write complex scripts that provide for all possible states of the objects involved in them, when it comes to solving a simple problem. That is, it is better to literally follow the instructions 🙂

Bojan Živković11378569
Community Expert
Community Expert
October 21, 2021

"same Action to all the layers in the Layers Palette? "

Well, difficult thing using action unless your documents always have same amount of layers. You can record action with conditional steps to start from top most layer then to check and stop playing (play None action) when it hits Background layer for example. If every conditional step have that condition then you can insert as many if steps as you want and everything will work fine if you have Background layer what can be also checked and fixed. If you want to process and Background layer then check in the very last if step for Background layer and play action to process Background layer.

Participating Frequently
October 22, 2021

Thankyou so much Bojan.
I'll have a go, thank you for the information. This isn't as easy as I hoped it might be!
All the best,

Cathy

JJMack
Community Expert
Community Expert
October 21, 2021

How would your action know what to do for each layer it processes. It would be easy for a script to  do your Action with each layer in the document being the document active layer.  What would your action do for smart object layers, for adjustment layers, for gradient fills for pattern fills etc.  Your action can test just a few layer conditions and would need to play other actions to handle layer conditions. The list of condition an Action can test is very limited. It can not even test if the active layer is a smart object layer?????

You need to learn scripting to Process all layer in a document.

 

if (documents.length) {
	// declare Global variables
	var layerList = new Array;
	var setList = new Array;
	var allList = new Array;
	var allLayers = ""; 

	main();
	for( var i = 0; i < layerList.length; i++) {processLayer(layerList[i]);}

	//alert("Layerset: " + setList.length + " Layers: "  + layerList.length + " Total: " + allList.length + "\n\n" +allLayers);
	logInfo("Layerset: " + setList.length + " Layers: "  + layerList.length + " Total: " + allList.length + "\n\n" +allLayers);
}
//////////////////////////////////////////////////////////////////////////////////////////////
function main() {
	processLayers(activeDocument) 
}
function processLayers(obj) {  
    for( var i = obj.layers.length-1; 0 <= i; i--) {
		if (obj.layers[i].kind!=undefined) {
			layerList.push(obj.layers[i]);
			allList.push(obj.layers[i]);			
		}
		else {
			setList.push(obj.layers[i]);
			allList.push(obj.layers[i]);			
			processLayers(obj.layers[i]);
		}
	} 
} 
function processLayer(layer) { 
	//alert('Layer Name = "' + layer.name + '" Layer Kind ' + layer.kind );
	allLayers = allLayers + layer.name + " , ID " + layer.id + ", " + layer.kind + "\n";
	//allLayers = allLayers + obj_to_str(layer) + "\n";
}
function obj_to_str(obj){
    var str = ""; 
    for (var p in obj) {	
        if(obj.hasOwnProperty(p)) {
            try{str+=p+"::"+obj[p]+"\n";}
            catch(e){};
        }
    }		
    return str;
}   
function logInfo(Txt){
    try {	
       var file = new File(Folder.desktop + "/LayersBotToTop.txt"); 
       file.open("w", "TEXT", "????"); 
       //alert(file.encoding);
       file.encoding = "UTF8";
       file.seek(0,2);   
       $.os.search(/windows/i)  != -1 ? file.lineFeed = 'windows'  : file.lineFeed = 'macintosh';
       file.writeln(Txt); 
       if (file.error) alert(file.error);
       file.close();
       file.execute(); 
    }
    catch(e) { alert(e + ': on line ' + e.line, 'Script Error', true); }
};

 

 

 

 

You could modify this script. Modify the processLayer make normal Layer the Active layer and use the doaction method  to run your action ignore all other layer kinds.

JJMack
Participating Frequently
October 22, 2021

Thank you JJMack. This is clearly not a trivial thing and as you say I would need to learn Javascript (?) to get this to work. I did have a clunky workaround which was to save all the layers as documents into a folder and then run a batch procedure on them.