Copy link to clipboard
Copied
Hello,
I am looking for a script that can locate and delete all black layers in PS.
I don't know how to write Javascript, and I can't find any thread explaining how to do this.
I am looking for something that is similar to "Delete All Empty Layers" script, but that finds black layers instead.
Thank you for taking your time,
Tsu-tey
sTT = stringIDToTypeID; function tggl() {
(ref = new ActionReference()).putIdentifier(sTT('layer'), idntfr);
(lst = new ActionList()).putReference(ref); (dsc = new ActionDescriptor())
.putList(sTT('null'), lst), dsc.putBoolean(sTT('toggleOptionsPalette'), true)
executeAction(sTT('show'), dsc)
}
lrs = [].slice.call((aD = activeDocument).artLayers)
wh = aD.width * aD.height; while(lrs.length)
idntfr = (shft = lrs.shift()).id, tggl(),
blck = aD.histogram[0] == wh,
tggl(), blck && shft.rem
...
Give an example. Upload your PSD file.
Noticed that scripts (mine and yours) remove the black layer if there is one RGB pixel (0,0,1) in it, which is wrong. Corrected my script
// important, the active layer must not have to be a group.
var inv = false; // depends on channels settings. true = masked areas, false = selected areas. check what you have.
var r = new ActionReference();
r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("count"));
r.putEnumerated(stringIDToTypeID("lay
...
Copy link to clipboard
Copied
Try this script (not CS6 compatible)
// important, the active layer must not have to be a group.
var inv = true; // depends on channels settings. true = masked areas, false = selected areas. check what you have.
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;
try { app.activeDocument.backgroundLayer; } catch(e) { n = 1; ++count; }
var r_idx = new ActionReference();
for (var i = count-1; i >= n; i--)
{
var r = new ActionReference();
r.putIndex(stringIDToTypeID("layer"), i);
if (executeActionGet(r).getInteger(stringIDToTypeID("layerKind")) != 1) continue;
var d = new ActionDescriptor();
var r = new ActionReference();
r.putProperty(stringIDToTypeID("channel"), stringIDToTypeID("selection"));
d.putReference(stringIDToTypeID("null"), r);
var d1 = new ActionDescriptor();
var r1 = new ActionReference();
r1.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("gray"));
r1.putIndex(stringIDToTypeID("layer"), i);
d1.putBoolean(stringIDToTypeID("invert"), inv);
d1.putReference(stringIDToTypeID("to"), r1);
d1.putEnumerated(stringIDToTypeID("calculation"), stringIDToTypeID("calculationType"), stringIDToTypeID("linearDodge"));
var r2 = new ActionReference();
r2.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("gray"));
r2.putIndex(stringIDToTypeID("layer"), i);
d1.putReference(stringIDToTypeID("source2"), r2);
d1.putBoolean(stringIDToTypeID("invertSource2"), inv);
d.putObject(stringIDToTypeID("to"), stringIDToTypeID("calculation"), d1);
executeAction(stringIDToTypeID("set"), d, DialogModes.NO);
var r = new ActionReference();
r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("selection"));
r.putEnumerated(stringIDToTypeID("document"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
if (!executeActionGet(r).hasKey(stringIDToTypeID("selection"))) r_idx.putIndex(stringIDToTypeID("layer"), i);
}
app.activeDocument.selection.deselect();
var d = new ActionDescriptor();
d.putReference(stringIDToTypeID("null"), r_idx);
executeAction(stringIDToTypeID("delete"), d, DialogModes.NO);
alert("done");
Copy link to clipboard
Copied
Copy link to clipboard
Copied
change true to false.
I'll fix the script yet. This also will be an error if there are no black layers.
Copy link to clipboard
Copied
// important, the active layer must not have to be a group.
var inv = false; // depends on channels settings. true = masked areas, false = selected areas. check what you have.
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;
try { app.activeDocument.backgroundLayer; } catch(e) { n = 1; ++count; }
var r_idx = new ActionReference();
var do_it = false;
for (var i = count-1; i >= n; i--)
{
var r = new ActionReference();
r.putIndex(stringIDToTypeID("layer"), i);
if (executeActionGet(r).getInteger(stringIDToTypeID("layerKind")) != 1) continue;
var d = new ActionDescriptor();
var r = new ActionReference();
r.putProperty(stringIDToTypeID("channel"), stringIDToTypeID("selection"));
d.putReference(stringIDToTypeID("null"), r);
var d1 = new ActionDescriptor();
var r1 = new ActionReference();
r1.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("gray"));
r1.putIndex(stringIDToTypeID("layer"), i);
d1.putBoolean(stringIDToTypeID("invert"), inv);
d1.putReference(stringIDToTypeID("to"), r1);
d1.putEnumerated(stringIDToTypeID("calculation"), stringIDToTypeID("calculationType"), stringIDToTypeID("linearDodge"));
var r2 = new ActionReference();
r2.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("gray"));
r2.putIndex(stringIDToTypeID("layer"), i);
d1.putReference(stringIDToTypeID("source2"), r2);
d1.putBoolean(stringIDToTypeID("invertSource2"), inv);
d.putObject(stringIDToTypeID("to"), stringIDToTypeID("calculation"), d1);
executeAction(stringIDToTypeID("set"), d, DialogModes.NO);
var r = new ActionReference();
r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("selection"));
r.putEnumerated(stringIDToTypeID("document"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
if (!executeActionGet(r).hasKey(stringIDToTypeID("selection"))) { r_idx.putIndex(stringIDToTypeID("layer"), i); do_it = true; }
}
app.activeDocument.selection.deselect();
if (do_it)
{
var d = new ActionDescriptor();
d.putReference(stringIDToTypeID("null"), r_idx);
executeAction(stringIDToTypeID("delete"), d, DialogModes.NO);
}
alert("done");
Copy link to clipboard
Copied
Awesome, thank you aswell 🙂
Copy link to clipboard
Copied
Ah, I will test it out.
Copy link to clipboard
Copied
I found your script deletes all layers beside black ones and some layers with black elements 😕
Copy link to clipboard
Copied
Give an example. Upload your PSD file.
Noticed that scripts (mine and yours) remove the black layer if there is one RGB pixel (0,0,1) in it, which is wrong. Corrected my script
// important, the active layer must not have to be a group.
var inv = false; // depends on channels settings. true = masked areas, false = selected areas. check what you have.
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;
try { app.activeDocument.backgroundLayer; } catch(e) { n = 1; ++count; }
var r_idx = new ActionReference();
var do_it = false;
for (var i = count-1; i >= n; i--)
{
var r = new ActionReference();
r.putIndex(stringIDToTypeID("layer"), i);
if (executeActionGet(r).getInteger(stringIDToTypeID("layerKind")) != 1) continue;
var d = new ActionDescriptor();
var r = new ActionReference();
r.putProperty(stringIDToTypeID("channel"), stringIDToTypeID("selection"));
d.putReference(stringIDToTypeID("null"), r);
var d1 = new ActionDescriptor();
var r1 = new ActionReference();
r1.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("gray"));
r1.putIndex(stringIDToTypeID("layer"), i);
d1.putBoolean(stringIDToTypeID("invert"), inv);
d1.putReference(stringIDToTypeID("to"), r1);
d1.putEnumerated(stringIDToTypeID("calculation"), stringIDToTypeID("calculationType"), stringIDToTypeID("normal"));
var r2 = new ActionReference();
r2.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("gray"));
r2.putIndex(stringIDToTypeID("layer"), i);
d1.putReference(stringIDToTypeID("source2"), r2);
d1.putBoolean(stringIDToTypeID("invertSource2"), inv);
d.putObject(stringIDToTypeID("to"), stringIDToTypeID("calculation"), d1);
executeAction(stringIDToTypeID("set"), d, DialogModes.NO);
var r = new ActionReference();
r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("selection"));
r.putEnumerated(stringIDToTypeID("document"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
if (!executeActionGet(r).hasKey(stringIDToTypeID("selection"))) { r_idx.putIndex(stringIDToTypeID("layer"), i); do_it = true; }
}
app.activeDocument.selection.deselect();
if (do_it)
{
var d = new ActionDescriptor();
d.putReference(stringIDToTypeID("null"), r_idx);
executeAction(stringIDToTypeID("delete"), d, DialogModes.NO);
}
alert("done");
Copy link to clipboard
Copied
The script I refered is 1st one you posted, however I'm saying now about probably updated version, but in the same post with that code. Create new document, add normal layer, fill it with black, then add another empty layer. That script will remove empty layer, but not black layer, while it should do the opposite.
The current one seems to work correctly. Why didn't you edit your first post, but created another posts with changed codes? It would be much better to have them in origianl one 😉
Good find about that 0, 0, 1 RGB values. That's probably because LAB is still 0, 0, 0. When you use 1, 0, 0 RGB values, the LAB is not changed again, so histogram must be refered to LAB?
Copy link to clipboard
Copied
It depends on the setting of the "inv" variable. Read the notes. It should match the channel settings (add a new alpha channel and check what settings you have). Either black or white (and blank) layers are removed.
Copy link to clipboard
Copied
I changed inv to false (in first code) and it gives error. Well no matter. Your other code is ok 🙂
Copy link to clipboard
Copied
It does not take into account the lack of removable layers. Your code (and mine) will also give an error if all layers are black.
Copy link to clipboard
Copied
Probably author is not going to use documents with only black layers, he didn't want it 😉
Copy link to clipboard
Copied
Removed my answer as correct. Let the author decide for himself.
Copy link to clipboard
Copied
Mark your last code as correct, I think it's good one.
Copy link to clipboard
Copied
sTT = stringIDToTypeID; function tggl() {
(ref = new ActionReference()).putIdentifier(sTT('layer'), idntfr);
(lst = new ActionList()).putReference(ref); (dsc = new ActionDescriptor())
.putList(sTT('null'), lst), dsc.putBoolean(sTT('toggleOptionsPalette'), true)
executeAction(sTT('show'), dsc)
}
lrs = [].slice.call((aD = activeDocument).artLayers)
wh = aD.width * aD.height; while(lrs.length)
idntfr = (shft = lrs.shift()).id, tggl(),
blck = aD.histogram[0] == wh,
tggl(), blck && shft.remove()
Copy link to clipboard
Copied
Kukurykus, what's this?
Copy link to clipboard
Copied
The solution 🙂
Copy link to clipboard
Copied
What does it do? The black layers are not removed from me.
Copy link to clipboard
Copied
I filled some layers with black colour, and the script I provided deletes only them.
Copy link to clipboard
Copied
Not working for 2020. What is its working principle?
Copy link to clipboard
Copied
It makes visible only one layer at time. Then it checks if 1st cell of hitogram (that is reserved for black) is equal to document dimension. If it is, there are not any other colors, so the layer is fully black. Then it toogles previous visibility of layers, and if layer was black it gets deleted.
Copy link to clipboard
Copied
What is toggleOptionsPalette?
upd. I understood. But for some reason it doesn't work.
upd2. For it to work, you need to put pixels in the ruler. Also does not work for layers in folders. Doesn't ignore adjustment layers.
Copy link to clipboard
Copied
'toggleOptionsPalette' is when you manually click on 'eye' of layer.
1) Like me, create new document. Add some layers, and fill some of them with black paint.
2) Yes that's right, for Pixels only and no layer sets. Original poster did not use Adjustment layers, but it works for them too, so I did it simple according posted image 😉