Skip to main content
Participant
April 5, 2020
解決済み

Re: Auto merge files

  • April 5, 2020
  • 返信数 4.
  • 1176 ビュー

Hi, hope you are well and safe.  

I have a similar need to populate a predefined 8x4 grid of identically-sized images.

What would be the best way to populate the matrix of 32 images?  File renaming is a consideration.

Thoughts?

-

Ralph1234

このトピックへの返信は締め切られました。
解決に役立った回答 Stephen Marsh

Hi Ralph1234 I'm going to rehash a recent post as I think it will provide you the answer that you are looking for:

 

Original link to code:

 

https://www.andrewnoske.com/wiki/Adobe_Photoshop_-_Scripts_Related_to_Montaging

 

Here is the original script in full, just in case the original site disappears sometime in the future:

 

 

// 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);
files.sort();
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 = app.open(File(files[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,
                        AnchorPosition.TOPLEFT);

// 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 = app.open(File(files[i]));
  if (tile.layers.length > 1) {
    tile.flatten();
  };
  tile.layers[0].duplicate(firstTile, ElementPlacement.PLACEATBEGINNING);
  tile.close(SaveOptions.DONOTSAVECHANGES);
  var layer = firstTile.layers[0];
  layer.name = files[i].name.slice(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 = firstTile.name.match(/(.*)\.[^\.]+$/)[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;

 

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

 

Presuming nine separate input files named 1-9, here is the result of the input order when X is selected (vertical, left to right):

 

 

And here is the layout order when Y is selected (horizontal, left to right):

 

返信数 4

Stephen Marsh
Community Expert
Community Expert
April 10, 2020

So Ralph1234 is there a like or correct answer to be found here?

Ralph1234作成者
Participant
April 12, 2020

Yes, thanks, all.  Your help is very much appreciated.  Stay well!

Stephen Marsh
Community Expert
Community Expert
April 12, 2020

Thanks for the thanks, did the script solve your problem?

Stephen Marsh
Community Expert
Stephen MarshCommunity Expert解決!
Community Expert
April 5, 2020

Hi Ralph1234 I'm going to rehash a recent post as I think it will provide you the answer that you are looking for:

 

Original link to code:

 

https://www.andrewnoske.com/wiki/Adobe_Photoshop_-_Scripts_Related_to_Montaging

 

Here is the original script in full, just in case the original site disappears sometime in the future:

 

 

// 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);
files.sort();
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 = app.open(File(files[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,
                        AnchorPosition.TOPLEFT);

// 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 = app.open(File(files[i]));
  if (tile.layers.length > 1) {
    tile.flatten();
  };
  tile.layers[0].duplicate(firstTile, ElementPlacement.PLACEATBEGINNING);
  tile.close(SaveOptions.DONOTSAVECHANGES);
  var layer = firstTile.layers[0];
  layer.name = files[i].name.slice(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 = firstTile.name.match(/(.*)\.[^\.]+$/)[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;

 

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

 

Presuming nine separate input files named 1-9, here is the result of the input order when X is selected (vertical, left to right):

 

 

And here is the layout order when Y is selected (horizontal, left to right):

 

Chuck Uebele
Community Expert
Community Expert
April 5, 2020

I moved this comment to start a new post.

Stephen Marsh
Community Expert
Community Expert
April 5, 2020

Thanks Chuck!

Stephen Marsh
Community Expert
Community Expert
April 5, 2020

Ralph1234 I'd suggest that you make a separate, new topic thread post rather than appending it to this one as your request may get buried/lost and is really very different than the original topic.