I've made a script that does almost exactly that (in terms of end result... It doesn't really merge anything). The thing is, it only supports one source folder at a time.
Export document for each layer inside selected group.jsx.
The way it works:
- First it hides all layers in the first level of the selected folder
- Then it loops through each of those layers performing these actions on each layer:
- Shows the current layer (which can also be a group)
- Saves the document
- Hides the current layer
So anything outside of the selected group is visible in every single output image.
// Name: Export document for each layer inside selected group.jsx
// Formerly: Export Layers Inside Selected Group.jsx
// Description: Photoshop script that saves the whole document for each top level layer inside the selected group.
// Image example: https://user-images.githubusercontent.com/1164476/49152494-aef8af00-f31b-11e8-80ff-d774e3103eae.png
// https://gist.github.com/joonaspaakko/013a223e94ba0fb9a2a0
#target photoshop
try {
var doc = app.activeDocument;
var n = 0;
var duplicates = {};
}
catch (e) {
alert( 'Open a document first...' );
}
function processLayers( options) {
var group = doc.activeLayer;
var groupLength = group.layers.length;
var visibleArray = [];
// HIDE ALL LAYERS
for ( var i = 0; i < groupLength; i++ ) {
visibleArray.push( group.layers[i].visible );
group.layers[i].visible = false;
}
// START SAVING
options.docName = doc.name.split('.')[0]; // Assumes filename contains only one period before the extion.
for ( var i = 0; i < groupLength; i++ ) {
var layer = group.layers[ i ];
options.layerName = layer.name;
options.layerIndex = i+1;
layer.visible = true;
save.file( options );
layer.visible = false;
}
// RESTORE VISIBILITY
for ( var i = 0; i < groupLength; i++ ) {
group.layers[i].visible = visibleArray[i];
}
doc.activeLayer = group;
alert('Done!'); // There's no error check so who am I to say if the files were saved, but at least the script is done...
}
var save = {
file: function( options ) {
var saveOptions = {};
for ( var i=0; i < options.fileFormats.length; i++ ) {
var fileformat = options.fileFormats[i];
var destinationFolder = options.destination + "/" + fileformat.toUpperCase();
makeFolder( destinationFolder ); // If it doesn't exist already...
var filename = '';
filename += options.prefix;
filename += options.useLayerName ? options.layerName : options.custonName;
filename += options.suffix;
// IF FILENAME CONTAINS A DOLLAR SIGN
if ( filename.match(/\$/) !== null ) {
filename = filename.replace('$',options.layerIndex);
}
// IF FILENAME DOESN'T HAVE THE DOLLAR SIGN AND A
// DUPLICATE FILENAME IS FOUND, ADD A NUMBER ANYWAYS.
else {
if ( typeof duplicates[ fileformat ] == 'undefined' ) {
duplicates[ fileformat ] = {};
}
var duplicateNumber = '';
if ( typeof duplicates[ fileformat ][ filename ] === 'object' ) {
duplicateNumber = ' ' + duplicates[ fileformat ][ filename ].length;
duplicates[ fileformat ][ filename ].push( filename );
}
else {
duplicates[ fileformat ][ filename ] = [ filename ];
}
filename += duplicateNumber;
}
doc.saveAs( File( destinationFolder + "/" + filename ), save[ fileformat ](), true );
}
},
psd: function() {
var psd_saveOpts = new PhotoshopSaveOptions();
psd_saveOpts.layers = true;
psd_saveOpts.embedColorProfile = true;
psd_saveOpts.annotations = true;
psd_saveOpts.alphaChannels = true;
return psd_saveOpts;
},
pdf: function() {
var presetName = '[High Quality Print]';
var pdf_SaveOpts = new PDFSaveOptions();
pdf_SaveOpts.pDFPreset = presetName;
return pdf_SaveOpts;
},
jpeg: function() {
var jpg_SaveOpts = new JPEGSaveOptions();
jpg_SaveOpts.matte = MatteType.WHITE;
jpg_SaveOpts.quality = 10;
jpg_SaveOpts.formatOptions.STANDARDBASELINE;
return jpg_SaveOpts;
},
png: function() {
var png_SaveOpts = new PNGSaveOptions();
png_SaveOpts.compression = 9;
png_SaveOpts.interlaced = false;
return png_SaveOpts;
},
tiff: function() {
var tiff_SaveOpts = new TiffSaveOptions();
tiff_SaveOpts.alphaChannels = true;
tiff_SaveOpts.annotations = true;
tiff_SaveOpts.imageCompression = TIFFEncoding.JPEG;
tiff_SaveOpts.interleaveChannels = true;
tiff_SaveOpts.jpegQuality = 10;
tiff_SaveOpts.layers = true;
tiff_SaveOpts.layerCompression = LayerCompression.ZIP;
tiff_SaveOpts.transparency = true;
return tiff_SaveOpts;
}
};
function makeFolder( path ) {
var newFolder = Folder( path );
if( !newFolder.exists ) newFolder.create();
}
if ( app.documents.length > 0 ) {
if ( app.activeDocument.activeLayer.layers ) {
init();
}
else {
alert( "Error: \nSelect a parent group of the layers you want to export.")
}
}
function init() {
/*
Code for Import https://scriptui.joonas.me — (Triple click to select):
{"items":{"item-0":{"id":0,"type":"Dialog","parentId":false,"style":{"text":"Export document for each layer inside selected group.jsx","preferredSize":[0,0],"margins":16,"orientation":"column","spacing":10,"alignChildren":["center","top"]}},"item-1":{"id":1,"type":"Checkbox","parentId":6,"style":{"text":"PSD","preferredSize":[0,0],"alignment":null}},"item-2":{"id":2,"type":"Checkbox","parentId":6,"style":{"text":"TIFF","preferredSize":[0,0],"alignment":null}},"item-3":{"id":3,"type":"Checkbox","parentId":6,"style":{"text":"JPEG","preferredSize":[0,0],"alignment":null,"checked":true}},"item-4":{"id":4,"type":"Checkbox","parentId":6,"style":{"text":"PNG","preferredSize":[0,0],"alignment":null}},"item-5":{"id":5,"type":"Checkbox","parentId":6,"style":{"text":"PDF","preferredSize":[0,0],"alignment":null}},"item-6":{"id":6,"type":"Panel","parentId":9,"style":{"text":"","preferredSize":[0,0],"margins":10,"orientation":"row","spacing":10,"alignChildren":["center","top"],"alignment":null}},"item-7":{"id":7,"type":"Panel","parentId":9,"style":{"text":"","preferredSize":[0,0],"margins":10,"orientation":"column","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-8":{"id":8,"type":"EditText","parentId":14,"style":{"text":"","preferredSize":[90,0],"alignment":null}},"item-9":{"id":9,"type":"Group","parentId":0,"style":{"preferredSize":[0,0],"margins":0,"orientation":"column","spacing":10,"alignChildren":["fill","top"],"alignment":null}},"item-10":{"id":10,"type":"Group","parentId":0,"style":{"preferredSize":[0,0],"margins":[15,0,10,0],"orientation":"row","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-11":{"id":11,"type":"Button","parentId":10,"style":{"text":"Save","justify":"center","preferredSize":[0,0],"alignment":null}},"item-12":{"id":12,"type":"Button","parentId":10,"style":{"text":"Cancel","justify":"center","preferredSize":[0,0],"alignment":null}},"item-13":{"id":13,"type":"StaticText","parentId":14,"style":{"text":"Prefix:","justify":"left","preferredSize":[0,0],"alignment":null}},"item-14":{"id":14,"type":"Group","parentId":22,"style":{"preferredSize":[0,0],"margins":0,"orientation":"column","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-15":{"id":15,"type":"Checkbox","parentId":7,"style":{"text":"Use layer name","preferredSize":[0,0],"alignment":null,"checked":false}},"item-16":{"id":16,"type":"Group","parentId":22,"style":{"preferredSize":[0,0],"margins":0,"orientation":"column","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-17":{"id":17,"type":"StaticText","parentId":16,"style":{"text":"Custom name:","justify":"left","preferredSize":[0,0],"alignment":null}},"item-18":{"id":18,"type":"EditText","parentId":16,"style":{"text":"File Name ","preferredSize":[160,0],"alignment":null}},"item-19":{"id":19,"type":"Group","parentId":22,"style":{"preferredSize":[0,0],"margins":0,"orientation":"column","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-20":{"id":20,"type":"StaticText","parentId":19,"style":{"text":"Suffix:","justify":"left","preferredSize":[0,0],"alignment":null}},"item-21":{"id":21,"type":"EditText","parentId":19,"style":{"text":"","preferredSize":[90,0],"alignment":null}},"item-22":{"id":22,"type":"Group","parentId":7,"style":{"preferredSize":[0,0],"margins":0,"orientation":"row","spacing":10,"alignChildren":["left","center"],"alignment":null}},"item-23":{"id":23,"type":"Divider","parentId":7,"style":false},"item-24":{"id":24,"type":"StaticText","parentId":7,"style":{"text":"Dollar symbol ($) is replaced with incremental numbers","justify":"left","preferredSize":[0,0],"alignment":"center"}}},"order":[0,9,7,15,23,22,14,13,8,16,17,18,19,20,21,24,6,3,4,1,5,2,10,12,11],"activeId":10}
*/
// DIALOG
// ======
var dialog = new Window("dialog");
dialog.text = "Export document for each layer inside selected group.jsx";
dialog.orientation = "column";
dialog.alignChildren = ["center","top"];
dialog.spacing = 10;
dialog.margins = 16;
// GROUP1
// ======
var group1 = dialog.add("group");
group1.orientation = "column";
group1.alignChildren = ["fill","top"];
group1.spacing = 10;
group1.margins = 0;
// PANEL1
// ======
var panel1 = group1.add("panel");
panel1.orientation = "column";
panel1.alignChildren = ["left","top"];
panel1.spacing = 10;
panel1.margins = 10;
var checkbox1 = panel1.add("checkbox");
checkbox1.text = "Use layer name";
var divider1 = panel1.add("panel");
divider1.alignment = "fill";
// GROUP2
// ======
var group2 = panel1.add("group");
group2.orientation = "row";
group2.alignChildren = ["left","center"];
group2.spacing = 10;
group2.margins = 0;
// GROUP3
// ======
var group3 = group2.add("group");
group3.orientation = "column";
group3.alignChildren = ["left","top"];
group3.spacing = 10;
group3.margins = 0;
var statictext1 = group3.add("statictext");
statictext1.text = "Prefix:";
var edittext1 = group3.add("edittext");
edittext1.minimumSize.width = 90;
// GROUP4
// ======
var group4 = group2.add("group");
group4.orientation = "column";
group4.alignChildren = ["left","top"];
group4.spacing = 10;
group4.margins = 0;
var statictext2 = group4.add("statictext");
statictext2.text = "Custom name:";
var edittext2 = group4.add("edittext");
edittext2.text = "File Name ";
edittext2.minimumSize.width = 160;
// GROUP5
// ======
var group5 = group2.add("group");
group5.orientation = "column";
group5.alignChildren = ["left","top"];
group5.spacing = 10;
group5.margins = 0;
var statictext3 = group5.add("statictext");
statictext3.text = "Suffix:";
var edittext3 = group5.add("edittext");
edittext3.minimumSize.width = 90;
// PANEL1
// ======
var statictext4 = panel1.add("statictext");
statictext4.text = "Dollar symbol ($) is replaced with incremental numbers";
statictext4.alignment = ["center","top"];
// PANEL2
// ======
var panel2 = group1.add("panel");
panel2.orientation = "row";
panel2.alignChildren = ["center","top"];
panel2.spacing = 10;
panel2.margins = 10;
var checkbox2 = panel2.add("checkbox");
checkbox2.text = "JPEG";
checkbox2.value = true;
var checkbox3 = panel2.add("checkbox");
checkbox3.text = "PNG";
var checkbox4 = panel2.add("checkbox");
checkbox4.text = "PSD";
var checkbox5 = panel2.add("checkbox");
checkbox5.text = "PDF";
var checkbox6 = panel2.add("checkbox");
checkbox6.text = "TIFF";
// GROUP6
// ======
var group6 = dialog.add("group");
group6.orientation = "row";
group6.alignChildren = ["left","top"];
group6.spacing = 10;
group6.margins = [0,15,0,10];
var button1 = group6.add("button", undefined, undefined, {name:"cancel"});
button1.text = "Cancel";
button1.justify = "center";
var button2 = group6.add("button", undefined, undefined, {name:"ok"});
button2.text = "Save";
button2.justify = "center";
// DIALOG CUSTOMIZATION
var filename = edittext2;
filename.text = app.activeDocument.name.split()[0]; // Assumes filename contains only one period before the extion.
filename.active = true;
var useLayerName = checkbox1;
useLayerName.onClick = function() {
var check = this.value;
var customName = edittext2;
if ( check ) customName.enabled = !check;
else customName.enabled = !check;
};
var cancelBtn = button1;
cancelBtn.onClick = function() {
dialog.close();
};
var saveBtn = button2;
saveBtn.onClick = function() {
n = ++n;
if ( n === 1 ) {
var formatsArray = [];
var formats = panel2.children;
for (var i = 0; i < formats.length; i++) {
var format = formats[i];
if ( format.value ) {
formatsArray.push( format.text.toLowerCase() );
}
}
var path = '';
try { path = doc.path; } catch(e) {}
var options = {
useLayerName: useLayerName.value,
fileFormats: formatsArray,
prefix: edittext1.text,
custonName: edittext2.text,
suffix: edittext3.text,
destination: Folder.selectDialog( 'Select destination folder...', path )
};
dialog.close();
if ( options.destination ) {
processLayers( options );
}
}
};
dialog.show();
}
= 12