Making a montage in PS - automatically

Discussion in 'Articles of Interest' started by The_Traveler, Feb 15, 2016.

  1. The_Traveler

    The_Traveler Completely Counter-dependent Supporting Member

    Dec 11, 2006
    Likes Received:
    Mid-Atlantic US
    Can others edit my Photos:
    Photos NOT OK to edit
    I wanted to make a montage of pictures from a set of pictures my son-in-law sent me. They travel a good deal and he got into the habit of taking a photo of his shoes with an iPad everywhere.

    I found a script on Adobe Photoshop - Scripts Related to Montaging - NoskeWiki
    that will take a set of ordered (by number) files and make them into a montage.

    Copy the text below the line and save it into a text file with a jsx extension e.g. feet.jsx.
    Go to Files>Scripts>Browse and find your script.
    You will be asked to locate the set of files and enter the number of columns.

    NB: the files should all be in same aspect ratio and the long sides oriented the same way.


    // Assembles a folder full of ordered image tiles into a single montage image
    // with each tile in a separate layer. Before processing and tile translation
    // occurs, you will be prompted to enter the number of columns and whether
    // tiles are ordered by x or y first. If possible, I recommend you name tiles
    // like so: "my_tile_x=0&y=0.jpg". Tiles *should* work as any image type, but
    // I have had trouble before with .png, so you may need to convert to .jpg.
    // All tiles are added to the first tile, and then saved as a PSD (with one
    // tile per layer) at the end.
    // TIPS:
    // > This has been tested up to 80x80 (256x256 pixel tiles), but over 30,000
    // in any dimension is not supported by all photoshop versions.
    // > The final PSD won't save if > 2 GB (easily fixed by saving as a TIF)
    // > Images can be different types, but certain image "modes", including
    // "Indexed" color, fail (fixed by Image > Mode > RGB Color).
    #target photoshop

    // Open folder selection dialog (for user to chose folder):
    alert("You will be prompted for the folder containing your tiles.\n" +
    "Tiles should be named like 'x=10&y=4.jpg' so they sort well, " +
    "all of the identical dimension and the folder should contain " +
    "no other image files.");

    var folder = Folder.selectDialog();
    if (!folder) {alert("Cancelled"); exit;}

    // Set units and guess the number of columns using square root:
    var origUnits = app.preferences.rulerUnits; // Can delete.
    app.preferences.rulerUnits = Units.POINTS;
    var files = folder.getFiles(/\.(jpg|jpeg|tif|tiff|bmp|png|eps)$/i);
    var numColGuess = Math.ceil(Math.sqrt(files.length));

    // Prompt the user to enter the number of columns and if x appears first:
    var numCol = prompt("Found " + files.length + " images.\n" +
    "How many columns are there?", numColGuess);
    var numRows = Math.ceil(files.length / numCol);

    var answer = prompt("Grid will be " + numCol + "x" + numRows + " tiles.\n" +
    "Does x or y appear first in the filenames?", "x");
    var orderedWithYFirst = (answer == "y" || answer == "Y");
    if (!answer || numCol == 0 || numRows == 0) {alert("Bad values"); exit;}

    // Open first file to determine dimensions:
    var firstTile =[0]));
    var tileWidth = firstTile.width;
    var tileHeight = firstTile.height;

    // Resize first file to a size that will fit all tiles:
    var firstLayer = firstTile.layers.length - 1; // Most likely 0.
    firstTile.layers[firstLayer].name = files[0].name.slice(0,-4);
    firstTile.resizeCanvas(firstTile.width * numCol,
    firstTile.height * numRows,

    // Zoom to fit whole image on screen:
    doMenuItemNoInteraction = function(item) {
    var ref = new ActionReference();
    ref.putEnumerated(app.charIDToTypeID("Mn "), app.charIDToTypeID("MnIt"), item);
    var desc = new ActionDescriptor();
    desc.putReference(app.charIDToTypeID("null"), ref);
    executeAction(app.stringIDToTypeID("select"), desc, DialogModes.NO);
    doMenuItemNoInteraction(app.charIDToTypeID('FtOn')); // Fit all on screen.

    // For each tile: open, transfer into a new layer, and re-position:
    for (var i = 1; i < files.length; i++) {
    var tile =;
    if (tile.layers.length > 1) {
    tile.layers[0].duplicate(firstTile, ElementPlacement.PLACEATBEGINNING);
    var layer = firstTile.layers[0]; =,-4); // Omit the file extension.
    // Determine current column and row:
    var col = Math.floor(i / numRows);
    var row = i - (col * numRows);
    if (orderedWithYFirst) {
    row = Math.floor(i / numCol);
    col = i - (row * numCol);
    // Calculate the x/y offsets and translate image:
    var xOffset = (tileWidth * col) - layer.bounds[0];
    var yOffset = (tileHeight * row) - layer.bounds[1];
    layer.translate(xOffset, yOffset);

    // Save as new file;
    var basename =*)\.[^\.]+$/)[1];
    var docPath = firstTile.path;
    psdOpts = new PhotoshopSaveOptions();
    psdOpts.embedColorProfile = true;
    psdOpts.alphaChannels = false;
    psdOpts.layers = true;
    psdOpts.spotColors = true;
    firstTile.saveAs((new File(docPath+'/'+basename.slice(0,-4)+"_comb.psd")),psdOpts,false);
    app.preferences.rulerUnits = origUnits;

    The result is a fairly large montage like this.

    • Like Like x 1
    • Informative Informative x 1

Share This Page