@111aaa11 – Here is a new version to automatically process all sub-folders under the selected top-level folder.
EDIT: Original code updated to 1.1 to correct an oversight where %20 characters were output instead of word spaces in saved filenames.
/*
Create GIF89a files from PNG Files in All Sub-folders of Selected Folder.jsx
v1.1 - 24th February 2024, Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/script-to-generate-gif-from-folder-of-images/td-p/14438104
*/
#target photoshop
// Recursive loop over all 1st level sub-folders under the selected parent/root folder by c.pfaffenbichler (2022)
var theFolder = Folder.selectDialog('Please select the input folder:');
var theFolders = theFolder.getFiles(isFolder);
//theFolders.sort().reverse();
theFolders.sort();
for (var m = 0; m < theFolders.length; m++) {
var inputFolder = theFolders[m];
cTID = function (s) {
return app.charIDToTypeID(s);
};
sTID = function (s) {
return app.stringIDToTypeID(s);
};
// Call the main function
gifAnimFromSubfolders();
}
// Functions
function isFolder(theFile) {
if (theFile.constructor.name == "Folder") {
return true;
} else {
return false;
}
}
function gifAnimFromSubfolders() {
// CAPTURE AND SET THE APP PREFS
var savedDisplayDialogs = app.displayDialogs;
app.displayDialogs = DialogModes.NO;
var origUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// STACK THE FILES TO LAYERS
var inputFiles = inputFolder.getFiles(/\.png$/i);
// inputFiles.sort().reverse();
inputFiles.sort();
app.displayDialogs = DialogModes.NO;
var baseDoc = open(inputFiles[0]);
baseDoc = app.activeDocument;
var savePath = baseDoc.path.fsName.replace(/(^.+\/)(.+$)/, '$1');
var saveName = inputFolder.fsName.replace(/(^.+\/)(.+$)/, '$2');
baseDoc.duplicate(saveName, false);
baseDoc.close(SaveOptions.DONOTSAVECHANGES);
for (var i = 0; i < inputFiles.length; i++) {
// true = linked | false = embedded
placeFile(new File(inputFiles[i]), false, 0, 0);
// Remove the filename extension from the layer name
app.activeDocument.activeLayer.name = inputFiles[i].name.replace(/\.[^\.]+$/, '');
}
// Remove the duplicate base layer
app.activeDocument.layers[app.activeDocument.layers.length - 1].remove();
//app.runMenuItem(stringIDToTypeID("selectAllLayers"));
//reverseLayerStack();
// Reset the app prefs
app.displayDialogs = savedDisplayDialogs;
app.preferences.rulerUnits = origUnits;
// MAKE ANIMATION FRAME
var idmakeFrameAnimation = stringIDToTypeID("makeFrameAnimation");
executeAction(idmakeFrameAnimation, undefined, DialogModes.NO);
// MAKE ANIMATION FRAMES FROM LAYERS
var idanimationFramesFromLayers = stringIDToTypeID("animationFramesFromLayers");
var desc203 = new ActionDescriptor();
executeAction(idanimationFramesFromLayers, desc203, DialogModes.NO);
// SELECT ALL ANIMATION FRAMES
var idanimationSelectAll = stringIDToTypeID("animationSelectAll");
var desc208 = new ActionDescriptor();
executeAction(idanimationSelectAll, desc208, DialogModes.NO);
// SET THE ANIMATION FRAME DELAY TO 1 SECOND
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
var reference = new ActionReference();
reference.putEnumerated(s2t("animationFrameClass"), s2t("ordinal"), s2t("targetEnum"));
descriptor.putReference(s2t("null"), reference);
descriptor2.putDouble(s2t("animationFrameDelay"), 1.000000);
descriptor.putObject(s2t("to"), s2t("animationFrameClass"), descriptor2);
executeAction(s2t("set"), descriptor, DialogModes.NO);
// SAVE FOR WEB
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
var descriptor3 = new ActionDescriptor();
var descriptor4 = new ActionDescriptor();
var descriptor5 = new ActionDescriptor();
var descriptor6 = new ActionDescriptor();
var descriptor7 = new ActionDescriptor();
var descriptor8 = new ActionDescriptor();
var descriptor9 = new ActionDescriptor();
var descriptor10 = new ActionDescriptor();
var descriptor11 = new ActionDescriptor();
var descriptor12 = new ActionDescriptor();
var descriptor13 = new ActionDescriptor();
var descriptor14 = new ActionDescriptor();
var descriptor15 = new ActionDescriptor();
var descriptor16 = new ActionDescriptor();
var descriptor17 = new ActionDescriptor();
var list = new ActionList();
var list2 = new ActionList();
descriptor2.putEnumerated(c2t("Op "), c2t("SWOp"), c2t("OpSa"));
descriptor2.putBoolean(c2t("DIDr"), true);
descriptor2.putPath(s2t("in"), new File(savePath)); // thePath
descriptor2.putString(c2t("ovFN"), activeDocument.name + ".gif"); // theName
descriptor2.putEnumerated(s2t("format"), c2t("IRFm"), c2t("GIFf"));
descriptor2.putBoolean(s2t("interfaceIconFrameDimmed"), false);
descriptor2.putEnumerated(c2t("RedA"), c2t("IRRd"), c2t("Sltv"));
descriptor2.putBoolean(c2t("RChT"), false);
descriptor2.putBoolean(c2t("RChV"), false);
descriptor2.putBoolean(c2t("AuRd"), false);
descriptor2.putInteger(c2t("NCol"), 256);
descriptor2.putInteger(c2t("DChS"), 0);
descriptor2.putInteger(c2t("DCUI"), 0);
descriptor2.putBoolean(c2t("DChT"), false);
descriptor2.putBoolean(c2t("DChV"), false);
descriptor2.putInteger(c2t("WebS"), 0);
descriptor2.putEnumerated(c2t("TDth"), c2t("IRDt"), s2t("none"));
descriptor2.putInteger(c2t("TDtA"), 100);
descriptor2.putInteger(c2t("Loss"), 0);
descriptor2.putInteger(c2t("LChS"), 0);
descriptor2.putInteger(c2t("LCUI"), 100);
descriptor2.putBoolean(c2t("LChT"), false);
descriptor2.putBoolean(c2t("LChV"), false);
descriptor2.putBoolean(s2t("transparency"), true);
descriptor2.putBoolean(c2t("Mtt "), true);
descriptor2.putEnumerated(s2t("dither"), c2t("IRDt"), s2t("diffusion"));
descriptor2.putInteger(s2t("ditherAmount"), 100);
descriptor2.putInteger(c2t("MttR"), 255);
descriptor2.putInteger(c2t("MttG"), 255);
descriptor2.putInteger(c2t("MttB"), 255);
descriptor2.putBoolean(c2t("SHTM"), false);
descriptor2.putBoolean(c2t("SImg"), true);
descriptor2.putEnumerated(c2t("SWsl"), c2t("STsl"), c2t("SLAl"));
descriptor2.putEnumerated(c2t("SWch"), c2t("STch"), c2t("CHsR"));
descriptor2.putEnumerated(c2t("SWmd"), c2t("STmd"), c2t("MDNn"));
descriptor2.putBoolean(c2t("ohXH"), false);
descriptor2.putBoolean(c2t("ohIC"), true);
descriptor2.putBoolean(c2t("ohAA"), true);
descriptor2.putBoolean(c2t("ohQA"), true);
descriptor2.putBoolean(c2t("ohCA"), false);
descriptor2.putBoolean(c2t("ohIZ"), true);
descriptor2.putEnumerated(c2t("ohTC"), c2t("SToc"), c2t("OC03"));
descriptor2.putEnumerated(c2t("ohAC"), c2t("SToc"), c2t("OC03"));
descriptor2.putInteger(c2t("ohIn"), -1);
descriptor2.putEnumerated(c2t("ohLE"), c2t("STle"), c2t("LE03"));
descriptor2.putEnumerated(c2t("ohEn"), c2t("STen"), c2t("EN00"));
descriptor2.putBoolean(c2t("olCS"), false);
descriptor2.putEnumerated(c2t("olEC"), c2t("STst"), c2t("ST00"));
descriptor2.putEnumerated(c2t("olWH"), c2t("STwh"), c2t("WH01"));
descriptor2.putEnumerated(c2t("olSV"), c2t("STsp"), c2t("SP04"));
descriptor2.putEnumerated(c2t("olSH"), c2t("STsp"), c2t("SP04"));
descriptor3.putEnumerated(c2t("ncTp"), c2t("STnc"), c2t("NC00"));
list.putObject(c2t("SCnc"), descriptor3);
descriptor4.putEnumerated(c2t("ncTp"), c2t("STnc"), c2t("NC19"));
list.putObject(c2t("SCnc"), descriptor4);
descriptor5.putEnumerated(c2t("ncTp"), c2t("STnc"), c2t("NC28"));
list.putObject(c2t("SCnc"), descriptor5);
descriptor6.putEnumerated(c2t("ncTp"), c2t("STnc"), c2t("NC24"));
list.putObject(c2t("SCnc"), descriptor6);
descriptor7.putEnumerated(c2t("ncTp"), c2t("STnc"), c2t("NC24"));
list.putObject(c2t("SCnc"), descriptor7);
descriptor8.putEnumerated(c2t("ncTp"), c2t("STnc"), c2t("NC24"));
list.putObject(c2t("SCnc"), descriptor8);
descriptor2.putList(c2t("olNC"), list);
descriptor2.putBoolean(c2t("obIA"), true);
descriptor2.putString(c2t("obIP"), "");
descriptor2.putEnumerated(c2t("obCS"), c2t("STcs"), c2t("CS01"));
descriptor9.putEnumerated(c2t("ncTp"), c2t("STnc"), c2t("NC01"));
list2.putObject(c2t("SCnc"), descriptor9);
descriptor10.putEnumerated(c2t("ncTp"), c2t("STnc"), c2t("NC20"));
list2.putObject(c2t("SCnc"), descriptor10);
descriptor11.putEnumerated(c2t("ncTp"), c2t("STnc"), c2t("NC02"));
list2.putObject(c2t("SCnc"), descriptor11);
descriptor12.putEnumerated(c2t("ncTp"), c2t("STnc"), c2t("NC19"));
list2.putObject(c2t("SCnc"), descriptor12);
descriptor13.putEnumerated(c2t("ncTp"), c2t("STnc"), c2t("NC06"));
list2.putObject(c2t("SCnc"), descriptor13);
descriptor14.putEnumerated(c2t("ncTp"), c2t("STnc"), c2t("NC24"));
list2.putObject(c2t("SCnc"), descriptor14);
descriptor15.putEnumerated(c2t("ncTp"), c2t("STnc"), c2t("NC24"));
list2.putObject(c2t("SCnc"), descriptor15);
descriptor16.putEnumerated(c2t("ncTp"), c2t("STnc"), c2t("NC24"));
list2.putObject(c2t("SCnc"), descriptor16);
descriptor17.putEnumerated(c2t("ncTp"), c2t("STnc"), c2t("NC22"));
list2.putObject(c2t("SCnc"), descriptor17);
descriptor2.putList(c2t("ovNC"), list2);
descriptor2.putBoolean(c2t("ovCM"), false);
descriptor2.putBoolean(c2t("ovCW"), false);
descriptor2.putBoolean(c2t("ovCU"), false);
descriptor2.putBoolean(c2t("ovSF"), true);
descriptor2.putBoolean(c2t("ovCB"), true);
descriptor2.putString(c2t("ovSN"), "images");
descriptor.putObject(s2t("using"), s2t("SaveForWeb"), descriptor2);
executeAction(s2t("export"), descriptor, DialogModes.NO);
// CLOSE THE TEMP WORKING DOC
app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
///// FUNCTIONS /////
function placeFile(null2, linked, horizontal, vertical) {
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var AD = new ActionDescriptor();
AD.putInteger(s2t("ID"), 1);
AD.putPath(s2t("null"), null2);
AD.putBoolean(s2t("linked"), linked); // false for embedded
AD.putEnumerated(s2t("freeTransformCenterState"), s2t("quadCenterState"), s2t("QCSAverage"));
AD.putUnitDouble(s2t("horizontal"), s2t("pixelsUnit"), horizontal);
AD.putUnitDouble(s2t("vertical"), s2t("pixelsUnit"), vertical);
AD.putObject(s2t("offset"), s2t("offset"), AD);
executeAction(s2t("placeEvent"), AD, DialogModes.NO);
}
function reverseLayerStack() {
var idreverse = stringIDToTypeID("reverse");
var desc4653 = new ActionDescriptor();
var idnull = stringIDToTypeID("null");
var ref2335 = new ActionReference();
var idlayer = stringIDToTypeID("layer");
var idordinal = stringIDToTypeID("ordinal");
var idtargetEnum = stringIDToTypeID("targetEnum");
ref2335.putEnumerated(idlayer, idordinal, idtargetEnum);
desc4653.putReference(idnull, ref2335);
executeAction(idreverse, desc4653, DialogModes.NO);
}
}