Here is the final 1.4 script, there is no longer any need to use an action or batch/image processor/image processor pro as this script is now self-contained. You will be prompted to select the JPG, PNG and Save folders and the script will then create the final combined JPG files with random backgrounds.
/*
Place Random Background Image.jsx
Version 1.4, Stephen Marsh, 3rd April 2022
https://community.adobe.com/t5/photoshop-ecosystem-discussions/place-many-pngs-on-many-different-backgrounds/td-p/12839669
Notes:
* Random background images in JPEG format, 1000 x 1000 px
* Random background image filename must be consistent and have variable digits,
i.e.: bk (5).jpg, bk (20).jpg or Post_4.jpg, Post_11.jpg etc
* Variable foreground images in transparent PNG format, various sizes fitted to 800 x 800px
* Foreground to be centered on background
*/
#target photoshop
(function () {
try {
// JPEG folder selection
var jpgFolder = Folder.selectDialog("Select the random JPG background image folder:");
if (jpgFolder === null) {
alert('Script cancelled!');
return;
}
// PNG folder selection
var pngFolder = Folder.selectDialog("Select the transparent PNG foreground image folder:");
if (pngFolder === null) {
alert('Script cancelled!');
return;
}
// Validate input folders
var validateInputDir = (jpgFolder.fsName === pngFolder.fsName);
if (validateInputDir === true) {
alert("Script cancelled as both the input folders are the same!");
return;
}
// Limit the file input
var jpgList = jpgFolder.getFiles(/\.(jpg|jpeg)$/i);
var pngList = pngFolder.getFiles(/\.(png)$/i);
// Validate that the JPEG list isn't empty
var validateJPEGEmptyList = (jpgList.length > 0);
if (validateJPEGEmptyList === false) {
alert("Script cancelled as the JPEG input folder is empty!");
return;
}
// Validate that the PNG list isn't empty
var validatePNGEmptyList = (jpgList.length > 0);
if (validatePNGEmptyList === false) {
alert("Script cancelled as the PNG input folder is empty!");
return;
}
// Output folder selection
var saveFolder = Folder.selectDialog("Please select the folder to save to...");
if (saveFolder === null) {
alert('Script cancelled!');
return;
}
// Save and set the dialog display settings
var savedDisplayDialogs = app.displayDialogs;
app.displayDialogs = DialogModes.NO;
// Perform the stacking and saving
for (var i = 0; i < pngList.length; i++) {
var doc = open(pngList[i]);
var docName = activeDocument.name.replace(/\.[^\.]+$/, '');
activeDocument.resizeCanvas(UnitValue(1000, "px"), UnitValue(1000, "px"), AnchorPosition.MIDDLECENTER);
// Count the JPEG files
var bgCount = jpgList.length;
// Random generator based on the JPEG files count
var bgNumber = Math.floor(Math.random() * bgCount) + 1;
// Random background file name using random variable
var randomBaseName = jpgList[0].displayName.replace(/\d+/, bgNumber);
var bgFileName = jpgFolder + "/" + randomBaseName;
placeFile(bgFileName, 100);
centreActiveLayerToCanvas();
moveLayerRelativeStack("previous");
// JPEG save options
var jpgOptions = new JPEGSaveOptions();
jpgOptions.formatOptions = FormatOptions.STANDARDBASELINE;
jpgOptions.embedColorProfile = true;
jpgOptions.matte = MatteType.NONE;
jpgOptions.quality = 10;
doc.saveAs(new File(saveFolder + '/' + docName + '.jpg'), jpgOptions);
doc.close(SaveOptions.DONOTSAVECHANGES);
}
// End of script
app.displayDialogs = savedDisplayDialogs;
app.beep();
alert('Script completed!' + '\r' + pngList.length + ' JPEG files (quality level 10) saved to:' + '\r' + saveFolder.fsName);
} catch (err) {
while (documents.length > 0) {
activeDocument.close(SaveOptions.DONOTSAVECHANGES);
}
alert("An unexpected error has occurred!");
}
/***** FUNCTIONS *****/
function centreActiveLayerToCanvas() {
var doc = app.activeDocument;
var docLay = app.activeDocument.activeLayer;
docLay.translate(doc.width / 2 - (docLay.bounds[0] + docLay.bounds[2]) / 2,
doc.height / 2 - (docLay.bounds[1] + docLay.bounds[3]) / 2);
}
function moveLayerRelativeStack(relPos) {
// "previous" or "next" or "front" or "back"
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
var reference2 = new ActionReference();
reference.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
descriptor.putReference(c2t("null"), reference);
reference2.putEnumerated(s2t("layer"), s2t("ordinal"), s2t(relPos));
descriptor.putReference(s2t("to"), reference2);
executeAction(s2t("move"), descriptor, DialogModes.NO);
}
function placeFile(file, scale) {
try {
var idPlc = charIDToTypeID("Plc ");
var desc2 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
desc2.putPath(idnull, new File(file));
var idFTcs = charIDToTypeID("FTcs");
var idQCSt = charIDToTypeID("QCSt");
var idQcsa = charIDToTypeID("Qcsa");
desc2.putEnumerated(idFTcs, idQCSt, idQcsa);
var idOfst = charIDToTypeID("Ofst");
var desc3 = new ActionDescriptor();
var idHrzn = charIDToTypeID("Hrzn");
var idPxl = charIDToTypeID("#Pxl");
desc3.putUnitDouble(idHrzn, idPxl, 0.000000);
var idVrtc = charIDToTypeID("Vrtc");
var idPxl = charIDToTypeID("#Pxl");
desc3.putUnitDouble(idVrtc, idPxl, 0.000000);
var idOfst = charIDToTypeID("Ofst");
desc2.putObject(idOfst, idOfst, desc3);
var idWdth = charIDToTypeID("Wdth");
var idPrc = charIDToTypeID("#Prc");
desc2.putUnitDouble(idWdth, idPrc, scale);
var idHght = charIDToTypeID("Hght");
var idPrc = charIDToTypeID("#Prc");
desc2.putUnitDouble(idHght, idPrc, scale);
var idAntA = charIDToTypeID("AntA");
desc2.putBoolean(idAntA, true);
executeAction(idPlc, desc2, DialogModes.NO);
} catch (e) {}
}
}());