Copy link to clipboard
Copied
I want to combine several thousand thin images horizontally into one Photoshop file using Batch.
I have looked at the contract sheet tool and it only goes to 100 and also leaves a 1 pixel gap.
Is there way to automatically add an image to the right of the last resizing the canvas as it goes? I managed to get resizing working but can't work out how to add +X to the width of an image with each new image, place it at the right then repeat.
Any batch experts know how to do this?
You can alternatively use the File > Scripts > Load files into stack script to produce a single file with all of the layers, presuming that they sort alphabetically in the correct order.
Change the canvas width to the required size.
Move the last layer to the right hand side of the canvas edge.
Next select all layers in the layers panel and then use the move tool's align/distribute option to distribute all layers horizontally.
EDIT: To automate the above, simply run the following script.
...I changed all references from vertical to horizontal and height to width and the alignment options etc... It seems to work as expected, but it has not been extensivly tested:
/*
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-combine-images-horizontally-via-batch/m-p/12716190#M619600
Files to Horizontally Stacked Layers.jsx
based on:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-create-one-big-png-image-from-multiple-png-images/td-p/12359415
Files
...
Copy link to clipboard
Copied
I believe that you can use a script developed by the late JJMack for this task:
http://www.mouseprints.net/old/dpr/PasteImageRoll.html
Edit: I wrote a different script for vertical stacking, should be easy enough to adapt when I have time.
Copy link to clipboard
Copied
I changed all references from vertical to horizontal and height to width and the alignment options etc... It seems to work as expected, but it has not been extensivly tested:
/*
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-combine-images-horizontally-via-batch/m-p/12716190#M619600
Files to Horizontally Stacked Layers.jsx
based on:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-create-one-big-png-image-from-multiple-png-images/td-p/12359415
Files to Vertically Stacked Layers.jsx
*/
#target photoshop
if (app.documents.length === 0) {
(function () {
// Save the current dialog display settings
var savedDisplayDialogs = app.displayDialogs;
app.displayDialogs = DialogModes.NO;
// Capture the original ruler units and set the ruler units to pixels
var origUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// Select the input folder
var inputFolder = Folder.selectDialog('Please select the input folder:');
// Test if Cancel button returns null, then do nothing
if (inputFolder === null) {
app.beep();
return;
}
// Supported file formats
var inputFiles = inputFolder.getFiles(/\.(jpg|jpeg|tif|tiff|png|psd|psb)$/i);
// Alpha numeric sort
// inputFiles.sort().reverse;
inputFiles.sort();
// Process the first "base" file
var firstFile = app.open(File(inputFiles[0]));
var firstFileName = app.activeDocument.name;
app.activeDocument.duplicate("Horizontal-Stacker", false);
firstFile.close(SaveOptions.DONOTSAVECHANGES);
var docStack = app.documents[0];
app.activeDocument = docStack;
docStack.activeLayer.name = firstFileName;
var baseHeight = app.activeDocument.width.value;
// Process the remaining file layers to the "base" file
for (var i = 1; i < inputFiles.length; i++) {
var remainingFiles = app.open(File(inputFiles[i]));
var fileName = remainingFiles.name;
remainingFiles.activeLayer.name = fileName;
remainingFiles.layers[0].duplicate(docStack, ElementPlacement.PLACEATBEGINNING);
remainingFiles.close(SaveOptions.DONOTSAVECHANGES);
relativeCanvasSize(true, baseHeight);
align2SelectAll('AdCV');
align2SelectAll('AdLf');
}
app.runMenuItem(stringIDToTypeID("selectAllLayers"));
reverseLayerStack();
app.activeDocument.flatten();
app.beep();
alert(inputFiles.length + ' files horizontally stacked!');
// Restore the dialogs
app.displayDialogs = savedDisplayDialogs;
// Return the original ruler units
app.preferences.rulerUnits = origUnits;
// Functions
function relativeCanvasSize(relative, width) {
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
descriptor.putBoolean(s2t("relative"), relative);
descriptor.putUnitDouble(s2t("width"), s2t("pixelsUnit"), width);
descriptor.putEnumerated(s2t("horizontal"), s2t("horizontalLocation"), s2t("top"));
executeAction(s2t("canvasSize"), descriptor, DialogModes.NO);
}
function align2SelectAll(method) {
app.activeDocument.selection.selectAll();
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
desc.putReference(charIDToTypeID("null"), ref);
desc.putEnumerated(charIDToTypeID("Usng"), charIDToTypeID("ADSt"), charIDToTypeID(method));
try {
executeAction(charIDToTypeID("Algn"), desc, DialogModes.NO);
} catch (e) { }
app.activeDocument.selection.deselect();
}
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);
}
})();
} else {
alert('Please close all open files before running this script...');
}
https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html
Copy link to clipboard
Copied
You can alternatively use the File > Scripts > Load files into stack script to produce a single file with all of the layers, presuming that they sort alphabetically in the correct order.
Change the canvas width to the required size.
Move the last layer to the right hand side of the canvas edge.
Next select all layers in the layers panel and then use the move tool's align/distribute option to distribute all layers horizontally.
EDIT: To automate the above, simply run the following script. I have updated the code to automatically run the load files into stack script, so it is now fully automated.
/*
Combine Images Horizontally.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-combine-images-horizontally-via-batch/td-p/12716190
Stephen Marsh, v1.0 - 31st January 2022
*/
$.evalFile(File(app.path + '/Presets/Scripts/Load Files into Stack.jsx'));
var newWidth = app.activeDocument.layers.length * 100;
canvasSize(newWidth);
align2SelectAll('AdRg');
app.runMenuItem(stringIDToTypeID('selectAllLayers'));
distributeHorizontally();
// Functions
function distributeHorizontally() {
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
reference.putEnumerated( s2t( "layer" ), s2t( "ordinal" ), s2t( "targetEnum" ));
descriptor.putReference( s2t( "null" ), reference );
descriptor.putEnumerated( s2t( "using" ), s2t( "alignDistributeSelector" ), s2t( "ADSDistH" ));
executeAction( s2t( "distort" ), descriptor, DialogModes.NO );
}
function canvasSize(width) {
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
descriptor.putUnitDouble( s2t( "width" ), s2t( "percentUnit" ), width );
descriptor.putEnumerated( s2t( "horizontal" ), s2t( "horizontalLocation" ), s2t( "left" ));
executeAction( s2t( "canvasSize" ), descriptor, DialogModes.NO );
}
function align2SelectAll(method) {
app.activeDocument.selection.selectAll();
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
desc.putReference(charIDToTypeID("null"), ref);
desc.putEnumerated(charIDToTypeID("Usng"), charIDToTypeID("ADSt"), charIDToTypeID(method));
try {
executeAction(charIDToTypeID("Algn"), desc, DialogModes.NO);
} catch (e) { }
app.activeDocument.selection.deselect();
}
https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html
Copy link to clipboard
Copied
You can also try the following scripts here, just use a row value of 1 with a column value as required. You may wish to work in smaller batches, not sure how things would work on "thousands of images" even if they are small:
Copy link to clipboard
Copied
Thank you for giving me multiple options here. I'll give each a go and see which one works the best. This is for a long term art project I've been putting off. This has been very helpful.
Copy link to clipboard
Copied
Thanks, feedback on each of the proposed solutions would be appreciated. This all presumes that each separate file is the same width.
P.S. Batch/Action isn't really designed for this task, it may be possible but wouldn't be my preferred approach when scripts are available.