Tile assembly script - final touch help

New Here ,
Nov 12, 2018 Nov 12, 2018

Copy link to clipboard

Copied

Hello everyone,

I need some help with this script. This script was written by Paul Riggott I believe and posted on the forums. It stitches together tiles of images. I've touched a few lines so it suits my needs (deleted mostly ). It works but I've hit a bump. The output tiles are numbered 1, 2, 3, ..., 10, 11, ..., etc. As you can seen in the image attached Photoshop sorts tile number 10 right before tile number 1.

Could you point me to what/how should I change the script code so Photoshop understands the sorting the way I need it? I really am a total newbie at this - first time I've touched PS script (or any other) was this morning so all your advises would be much appreciated

script_help.jpg

There is the script code I'm using:

if(version.substr(0,version.indexOf('.'))>9){

win.panel0.title.graphics.font = ScriptUI.newFont("Times","BOLDITALIC",20);

g = win.graphics;

var myBrush = g.newBrush(g.BrushType.SOLID_COLOR, [1.00, 1.00, 1.00, 1]);

g.backgroundColor = myBrush;

var myPen =g.newPen (g.PenType.SOLID_COLOR, [1.00, 0.00, 0.00, 1],lineWidth=1);

}

win.panel0.panel1.folder1.enabled=false;

win.center();

//var inputFolder = Folder.selectDialog("Please select the folder with Files to process");

win.panel0.panel1.Browse.onClick = function() {

inputFolder = Folder.selectDialog("Please select the folder with Files to process");

if(inputFolder !=null){

  win.panel0.panel1.folder1.text =  decodeURI(inputFolder.fsName);

  }

}

win.panel0.process.onClick = function() {

if(win.panel0.panel1.folder1.text == '') {

   alert("No input folder selected!");

   return;

  }

win.close(1);

ProcessFiles();

}

win.show();

function ProcessFiles(){

var fileList = inputFolder.getFiles(/\.(jpeg|tif|eps|psd|png)$/i);

var startRulerUnits = preferences.rulerUnits;

preferences.rulerUnits = Units.PIXELS;

var Down = (fileList.length);

fileList = fileList.sort();

var Across = Down;

open(fileList[0]);

app.activeDocument.duplicate(fileList[0].name.match(/(.*)\.[^\.]+$/)[1]+"-combined");

app.documents[0].close(SaveOptions.DONOTSAVECHANGES);

var FillColor = new SolidColor;

FillColor.rgb.hexValue = 'ffffff';

activeDocument.selection.selectAll();

activeDocument.selection.fill(FillColor);

activeDocument.selection.deselect();

var w=app.activeDocument.width*Down;

var h=app.activeDocument.height*1;

var offsetX = app.activeDocument.width.value;

var offsetY = app.activeDocument.height.value;

app.activeDocument.resizeCanvas(w, h, AnchorPosition.TOPLEFT);

TLX = 0; TLY = 0; TRX = offsetX; TRY = 0;

BRX = offsetX; BRY = offsetY; BLX = 0; BLY = offsetY;

var z =0;

for(var a = 0; a < Down; a++){

  for(var i = 0;i <Across; i++){

    activeDocument.selection.select([[TLX,TLY],[TRX,TRY],[BRX,BRY],[BLX,BLY]], SelectionType.REPLACE, 0, false);

    placeFile(fileList);

    if(!win.panel0.panel1.smart.value){

    rasterLayer();

    }

    activeDocument.activeLayer.name = fileList.name.match(/(.*)\.[^\.]+$/)[1];

    app.activeDocument.selection.deselect();

    z++;

TLX = offsetX * (i+1) ; TRX  = TLX + offsetX; BRX = TRX; BLX = TLX; 

    }

TLX = 0; TLY = offsetY * (a +1); TRX = offsetX; TRY = offsetY * (a +1);

BRX = offsetX; BRY = TRY + offsetY; BLX = 0; BLY = (offsetY * (a +1)+offsetY);

}

if(win.panel0.panel1.flatten.value){

activeDocument.flatten();

}

app.preferences.rulerUnits = startRulerUnits;

}

}

main();

function placeFile(placeFile) {

  function cTID(s) { return app.charIDToTypeID(s); };

    var desc21 = new ActionDescriptor();

    desc21.putPath( cTID('null'), new File(placeFile) );

    desc21.putEnumerated( cTID('FTcs'), cTID('QCSt'), cTID('Qcsa') );

        var desc22 = new ActionDescriptor();

        desc22.putUnitDouble( cTID('Hrzn'), cTID('#Pxl'), 0.000000 );

        desc22.putUnitDouble( cTID('Vrtc'), cTID('#Pxl'), 0.000000 );

    desc21.putObject( cTID('Ofst'), cTID('Ofst'), desc22 );

    executeAction( cTID('Plc '), desc21, DialogModes.NO );

};

function rasterLayer() {

    var desc9 = new ActionDescriptor();

        var ref4 = new ActionReference();

        ref4.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );

    desc9.putReference( charIDToTypeID('null'), ref4 );

    executeAction( stringIDToTypeID('rasterizeLayer'), desc9, DialogModes.NO );

};

    pngOptions = new PNGSaveOptions()

    pngOptions.compression = 0

    pngOptions.interlaced = false

    savePath = inputFolder;

    activeDocument.saveAs(savePath, pngOptions, false, Extension.LOWERCASE)

TOPICS
Actions and scripting

Views

734

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Nov 12, 2018 Nov 12, 2018

Copy link to clipboard

Copied

I’m getting some errors with your script, so I can’t even run it to see what the result is… perhaps you cut too much?

Are the layer names the original filenames, or is the script creating the layer names differently to the input files?

I just hunted down the original thread and will take a look at the original code:

Re: Request for Script - Restitching image tiles

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Nov 12, 2018 Nov 12, 2018

Copy link to clipboard

Copied

Hello Stephen,

The layer names are the original file names - yes. The script doesn't interfere with file names. It just arranges them in sequentially. I think the problem comes from that PS needs a 0 for the digits ( for example - 01, 02, 03, etc.).

I can work around it by splitting the image in 9 tiles if there is no solution to the problem

By the way, the script is running on my side, I don't know why it misbehaves with you.

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Nov 13, 2018 Nov 13, 2018

Copy link to clipboard

Copied

So could you try changing the filenames first?

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Nov 13, 2018 Nov 13, 2018

Copy link to clipboard

Copied

I could, but they are saved like that automatically after rendering. Which means I'll have to rename them manually (or by some other script) and I have like 50 +/- passes x 10 tiles... which would be quite time consuming

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Nov 13, 2018 Nov 13, 2018

Copy link to clipboard

Copied

Adobe Bridge’s Batch Rename tool with regular expression based string substitution excels at such tasks, however we need to find out some sort of pattern to the filenames. If the names are preset by some other software, then there is likely a variable but consistent pattern. It would be best if this other software could write out the files using the zero padding in the first place.

Do you have different examples of filenames?

Would you only need a max of up to 2 digits, i.e. 01, 02…10 ? Or pad out with 001 or 0001 etc?

Example:

regex101.png

Find: (^\w+tile_)(\dx.+)

Replace: $10$2

batch-rename.png

Scripting could do this in your script in a single pass (either using regular expressions or some other method of file filtering/sorting), however I probably can’t help too much there… so the two pass/step batch rename input files then run your tile script is just an interim suggestion to get the job done until you find a better alternative.

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Nov 13, 2018 Nov 13, 2018

Copy link to clipboard

Copied

Stephen,

Thank you for the input. All file names have the same pattern. I'll try to figure something out with that expression when I have more time.

JJMack,

Thank you for the script, looks really good. Unfortunately it is not what I need for my workflow.

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Nov 14, 2018 Nov 14, 2018

Copy link to clipboard

Copied

Another thought, if you will always have a stack of 10 images and a background image layer, and the incorrect layer is always in the third position from the bottom and needs to go to the top of the stack… Put one of the following at the end of your script to select and move the layer into the correct position.

Option 1: Selecting the back layer, regardless of layer stack quantity (probably the best method compared to option 3?)

//Select back layer 

var doc = app.activeDocument; 

doc.activeLayer = doc.layers[doc.layers.length -1];

//Select forward layer x2

select(), select(); //Run it x2

function select() {

  var c2t = function (s) {

  return app.charIDToTypeID(s);

  };

var s2t = function (s) {

  return app.stringIDToTypeID(s);

  };

  var descriptor = new ActionDescriptor();

  var reference = new ActionReference();

  reference.putEnumerated( s2t( "layer" ), s2t( "ordinal" ), s2t( "forwardEnum" ));

  descriptor.putReference( c2t( "null" ), reference );

  descriptor.putBoolean( s2t( "makeVisible" ), false );

  executeAction( s2t( "select" ), descriptor, DialogModes.NO );

}

//move selected layer to front

move();

function move() {

  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( "front" ));

  descriptor.putReference( s2t( "to" ), reference2 );

  executeAction( s2t( "move" ), descriptor, DialogModes.NO );

}

Option 2: Selecting the _10x1_ layer by absolute layer order in a layer stack of 11

//Select the 3rd layer from the bottom of 11 layers

var doc = app.activeDocument;

doc.activeLayer = doc.layers[8];

//move selected layer to front

move();

function move() {

  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( "front" ));

  descriptor.putReference( s2t( "to" ), reference2 );

  executeAction( s2t( "move" ), descriptor, DialogModes.NO );

}

Option 3: Selecting the _10x1_ layer by it’s position to a layer named “Background” (whether a true Background image layer or standard layer)

//Select layer named "Background"

var doc = app.activeDocument;

doc.activeLayer = doc.layers.getByName ("Background");

//Select forward layer x2

select(), select(); //Run it x2

function select() {

  var c2t = function (s) {

  return app.charIDToTypeID(s);

  };

  var s2t = function (s) {

  return app.stringIDToTypeID(s);

  };

  var descriptor = new ActionDescriptor();

  var reference = new ActionReference();

  reference.putEnumerated( s2t( "layer" ), s2t( "ordinal" ), s2t( "forwardEnum" ));

  descriptor.putReference( c2t( "null" ), reference );

  descriptor.putBoolean( s2t( "makeVisible" ), false );

  executeAction( s2t( "select" ), descriptor, DialogModes.NO );

}

//Move selected layer to front

move();

function move() {

  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( "front" ));

  descriptor.putReference( s2t( "to" ), reference2 );

  executeAction( s2t( "move" ), descriptor, DialogModes.NO );

}

P.S. I’m sure that there are better ways, I’m just a scripting newb, so I am happy to learn from my mistakes!

EDIT: I think that this may be the better option so far!

//Select back layer 

var doc = app.activeDocument; 

doc.activeLayer = doc.layers[doc.layers.length -1];

//Select forward layer x2 

select(), select(); //Run it x2 

function select() { 

  var c2t = function (s) { 

  return app.charIDToTypeID(s); 

  }; 

 

var s2t = function (s) { 

  return app.stringIDToTypeID(s); 

  }; 

 

  var descriptor = new ActionDescriptor(); 

  var reference = new ActionReference(); 

 

  reference.putEnumerated( s2t( "layer" ), s2t( "ordinal" ), s2t( "forwardEnum" )); 

  descriptor.putReference( c2t( "null" ), reference ); 

  descriptor.putBoolean( s2t( "makeVisible" ), false ); 

  executeAction( s2t( "select" ), descriptor, DialogModes.NO ); 

//move selected layer to front

doc.activeLayer.move(doc.layers[0], ElementPlacement.PLACEBEFORE);

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Apr 26, 2021 Apr 26, 2021

Copy link to clipboard

Copied

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Most Valuable Participant ,
Nov 13, 2018 Nov 13, 2018

Copy link to clipboard

Copied

It look like you are trying to tile images. To do the evenly Images need be fitted to a tile size and then tile a canvas that the tiles will fill perfectly.,  There are a couple of potential  problem tiling Image that do not have an aspect ration close to the tile aspect ratio when you want the tile surface filled with image content.  And there is an additional  problem if you want to use PNG images that have transparent boarders and the  boarders are important for you to have borders around  your object subject For both Place and Paste will trim transparent boarder.  Images when fitted to a tile size will have a  tile image content that looks like a centered aspect ratio crop of your  image resized for the tile size.  The problem is Portrait to Landscape and Landscape to Portrait to Landscape centered crops image content in most cases will not be acceptable.  It easy to eliminate Transparent Png Boarder problems  by first eliminating these boarders by putting a 1% opacity pixel in the canvas top left and  bottom right corners.  No Human eye will see these pixels the image will look like it has transparent borders.

In my Photo Collage Toolkit there is a script the you most likely use to tile your image the way you want to.  You set up the paper width and tile size then select the image you want to tile. They need to be in a single folder but you need to select the Image files you want tiled from that folder.  The script's name is PasteImageRoll. About the Script and the PasteImageRoll.jsx

The script just created the tiled document. Your images  are fitted to the tiles  you can tweak the tile images content using  Photoshot  to transform the masked image layer content

JJMack

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Apr 26, 2021 Apr 26, 2021

Copy link to clipboard

Copied

You probably already solved the issue. But i had made a grid image stitcher couple years back. It could do column by column or row by row. I was making a grid cropper last week for some social design template i got. So i went on and tested my old stitcher and seemed the row by row had some issues. My idea was to perhaps combine these scripts into 1, i dropped that idea. But i do have them now combined in the script menu in their own tab, which is nice.

Both scripts allow you to now do either column by column or row by row. hahah tooks me many hours this weekend to get it properly working. I had taken some scripts from a Blender addon which does row by row, my earlier grid cropper only did column by column.

 

Mine works by sorting the images, it does that by the last part of the file name. Something what got me going nuts was the row by row naming. Somehow it was working correct, but because for both methods i use NAME + pos_col + pos_row the export showed a wrong order, it would always show as if it was export as column by column.

 

Currently, I have this delay in the script, so the use first picks the folder, then loads the images and sets orientation, then we choose the ordering. But i think all these settings can be done from the start. I think i used a couple parts of the stack-loader script and adjusted it. My first concept needed manual input of the tile-size to figure out the document size.
But i figured out a new approach and now i can skip that step. As the user now sets the orientation, it will figure out the correct columns and rows and does sizing automatically.

 

Mine is not directed as that one of JJMack, his seems more towards print and scales everything to the document size. Mine was created of the need for my 3d work i also do. I need to be able to stitch up big rendered tiles of scenes i render.

I do need to finish the panel for the cropper, that currently only does the orientation by altering the script. I will be same panel as the stitcher basically. I also want to implement the icons into the script. Currently they are separate small images aside of the script. But i want to make that cleaner.
  

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Apr 26, 2021 Apr 26, 2021

Copy link to clipboard

Copied

PS thanks for pointing out to that script, i already have his scripts collection from github. I noticed he used the place command. I implemented that now i my version as well. That was a huge speed up. It went from 36.8 seconds to 16.4 seconds for 15 images. Thats half the time, huge speedup 🙂 nice!!!

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Apr 26, 2021 Apr 26, 2021

Copy link to clipboard

Copied

Placing or replacing / linking Smart object give you fastest acceleration.

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Apr 26, 2021 Apr 26, 2021

Copy link to clipboard

Copied

@schroef – If this is not a commercial project, then please do share the script code when you are happy with them, from the preview images above they look very useful.

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines