Copy link to clipboard
Copied
Could someone help me with a script that will merge all layers with the same name, but only for certain hard coded names?
For example a file might contain 20 layers named "layerA", 30 layers named "layerB" and 40 layers named "layerC" > but only "layerA" and "layerB" should be merged, not "layerC". Its fine if this is hard coded into the script.
The big issue is that the script should iterate through all layers in the document only once, since my document has 10k layers iterating through all layers for each different name is too slow.
Is there a way to iterate only once through the document and use that iteration to create a dictionary that contains all groups of layers with the same name? This would then establish O(1) access for a given name, and I could then hard code a bunch of names that I want to merge.
Could someone help me code this? I am at a loss with the adobe script language, thanks in advance!
1 Correct answer
because I have 10k layers and it takes too long to do that
By jack284003085p35
How did you manage to create 10k layers?
When the number of layers is more than 8000, problems begin with the file, not to mention the fact that adding new layers manually will not work.
Try this script. I would like to see your timings.
It won't be possible to do it faster.
var layers = get_layers();
merge_layers(layers, "Layer 1");
merge_layers(layers, "Layer 1 copy");
function get_layers()
{
try {
...
Explore related tutorials & articles
Copy link to clipboard
Copied
Please provide a clear description of the process and a sample file (feel free to downsample it drastically).
How many groups of identically named Layers should be merged, what are the actual target-names, …?
Copy link to clipboard
Copied
i think I have it pretty well described in the post.
i want a script that I can hardcode something like:
var string = "layerA"
//code to merge all layers with name of string
result after running the script, all the layers that were named "layerA" are now merged into a single layer named "layerA".
BUT THERE CAN BE NO ITERATION, no for loop going over every single layer in the file to check if its named "layerA" ( because I have 10k layers and it takes too long to do that)
Maybe one iteration once to gather IDs of all layers, and then save that to a file that can be accessed to directly get the layers as if they were in an array, a surgical search instead of a brute force iteration everytime i want to merge a different name.
maybe its not possible
Copy link to clipboard
Copied
BUT THERE CAN BE NO ITERATION, no for loop going over every single layer in the file to check if its named "layerA" ( because I have 10k layers and it takes too long to do that)
What is that supposed to mean?
How could you check the Layers’ names other than by checking the Layers’ names?
Have you tested the AM code from your thread about selecting identically named layers yet?
Copy link to clipboard
Copied
are you by chance familiar with c# and dictionaries?
for example in c# if you can create a dictionary of hashset and doing something like dictionary[layerA] would instantly give a hashset that contains all the layers named "layerA" without iterating anything.
Of course I would have to first iterate once over the whole document to create such a dictionary that neatly groups layers like this for fast access, but after that dictionary is compiled I would never have to iterate again unless the document is changed
Copy link to clipboard
Copied
I am not familiar with c#.
But the image would be changed when you merge Layers so the dictionary would need amending because it would otherwise contain invalid entries, would it not?
And again:
Have you tested the AM code from your thread about selecting identically named layers yet?
Likes
Copy link to clipboard
Copied
because I have 10k layers and it takes too long to do that
By jack284003085p35
How did you manage to create 10k layers?
When the number of layers is more than 8000, problems begin with the file, not to mention the fact that adding new layers manually will not work.
Try this script. I would like to see your timings.
It won't be possible to do it faster.
var layers = get_layers();
merge_layers(layers, "Layer 1");
merge_layers(layers, "Layer 1 copy");
function get_layers()
{
try {
$.hiresTimer;
var layers = new Array();
var r = new ActionReference();
r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("count"));
r.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
var count = executeActionGet(r).getInteger(stringIDToTypeID("count"));
var n = 0;
if (!app.activeDocument.layers[app.activeDocument.layers.length-1].isBackgroundLayer) { n = 1; ++count; }
for (var i = count-1; i >= n; i--)
{
var r = new ActionReference();
r.putIndex(stringIDToTypeID("layer"), i);
var d = executeActionGet(r);
layers.push({id:d.getInteger(stringIDToTypeID("layerID")), name:d.getString(stringIDToTypeID("name"))});
}
alert("Scanned " + count + " layers in " + ($.hiresTimer/1000000).toFixed(2) + " seconds", "Timer");
return layers;
}
catch (e) { alert(e); throw(e); }
}
function merge_layers(layers, name)
{
try {
$.hiresTimer;
var len = layers.length;
var cnt = 0;
var r = new ActionReference();
for (var i = 0; i < len; i++)
{
if (layers[i].name == name) { r.putIdentifier(stringIDToTypeID("layer"), layers[i].id); ++cnt; }
}
var d = new ActionDescriptor();
d.putReference(stringIDToTypeID("null"), r);
d.putBoolean(stringIDToTypeID("makeVisible"), false);
executeAction(stringIDToTypeID("select"), d, DialogModes.NO);
alert("Selected " + cnt + " \"" + name + "\" in " + ($.hiresTimer/1000000).toFixed(2) + " seconds", "Timer");
$.hiresTimer;
executeAction(stringIDToTypeID("mergeLayersNew"), undefined, DialogModes.NO);
alert("Merged " + cnt + " \"" + name + "\" in " + ($.hiresTimer/1000000).toFixed(2) + " seconds", "Timer");
}
catch (e) { alert(e); throw(e); }
}
Copy link to clipboard
Copied
if (!app.activeDocument.layers[app.activeDocument.layers.length-1].isBackgroundLayer) { n = 1; ++count; }
try { app.activeDocument.backgroundLayer; } catch(e) { n = 1; ++count; }
Copy link to clipboard
Copied
The layer name filter is often useful, which is the manual equivalent of scripting and the manual steps are not that taxing.
Copy link to clipboard
Copied
thanks, this of course solves the problem if i wanted to do it manually, but i want to automate it
Copy link to clipboard
Copied
thanks, this of course solves the problem if i wanted to do it manually, but i want to automate it
By jack284003085p35
You only mentioned the need to do this for 2 sets of named layers.
I understand, however, there is a cost/benefit to this.
It would take approx. 1 minute to do this manually. The manual steps are not onerous. Multiply this however many documents need to be processed.
Compared to the time spent by a volunteer developing the script.
Copy link to clipboard
Copied
This works for LayerA and LayerB, but fails for LayerA and LayerAB.
Copy link to clipboard
Copied
This works for LayerA and LayerB, but fails for LayerA and LayerAB.
By r-bin
Just as well, the OP only has LayerA, LayerB and LayerC then! :]
All joking aside, there are indeed limitations to the native feature as you describe.
Don't get me wrong, I'm all for a script if somebody has the time and knowledge to make it.

