I am running javascript via Photoshop's scripts tool/option in order to batch process a folder of images. The script adds a second image layer from a single image in folder 02 to a number of images in folder 01. That works fine, however, I am trying to decrement the opacity of the layer that is added, so that the image that is added from folder 02 is increasingly more transparent for each subsequent image processed from folder 01. I'm basically creating a fade that transitions from the image in folder 02 to revealing the images processed from folder 01. The opacity change is happening as expected (decrementing opacity for each processed image); however, they seem to get processed out of order, so as I view the images in order, the opacity of that added layer jumps around. I can also see that as the newly processed images save to the processed image folder, they arrive out of order (something like 1, 3, 2, 5, 6, 4; though it might be different each time). I suspect I need to force my code to process the images one at a time in order, but I'm not sure how to go about that. Thanks in advance! I don't believe file naming is the issue since I've tried naming the images in folder 01 as both 1, 2, 3, (and so on) as well as 01, 02, 03. But that doesn't help.
Thanks in advance!
#target photoshop
// FOLDERS
var folder1 = new Folder('~/Desktop/1/');
var folder2 = new Folder('~/Desktop/2/');
var saveFolder = new Folder('~/Desktop/done/');
//
var searchMask = '*.???'; // get files named as this
var list1 = folder1.getFiles(searchMask);
var list2 = folder2.getFiles(searchMask);
var psdOptions = new PhotoshopSaveOptions();
psdOptions.layers = true;
opacityLevel = 100;
for (var i = 0; i < list1.length; i++) {
var doc = open(list1[i]);
var docName = doc.name;
placeFile('~/Desktop/2/1.jpg', 100); // for adding only one file each source file
doc.activeLayer.blendMode = BlendMode.LIGHTEN; // ## change BLEND MODE
placeFile('~/Desktop/2/2.png', 100); // for adding only one file each source file
doc.activeLayer.blendMode = BlendMode.MULTIPLY; // ## change BLEND MODE
doc.activeLayer.opacity = opacityLevel; // set layer opacity
// Decrement opacity level for each image
if (doc.activeLayer.opacity > 5) {
opacityLevel = Math.round(doc.activeLayer.opacity) - 5;
}
// SAVING
doc.saveAs(new File(saveFolder + '/' + docName.split('.')[0] + '.psd'), psdOptions);
doc.close(SaveOptions.DONOTSAVECHANGES);
};
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) { }
}//end function placeFile
Never count on file list functions to maintain a logical order...
Try sorting the file lists after creating them.
var list1 = folder1.getFiles(searchMask);
var list2 = folder2.getFiles(searchMask);
list1.sort();
list2.sort();
Make sure the filenames sort ascibetically. Zerofix if you use numbers.
Alternatively, you can supply Array.sort() with a sorting function to allow for a custom sorting. Read more about how that works here.
Related
I've been trying to find a way to select all visible artboards, so i can later Quick Export them all as PNGs. I'd also love if i've could also include the exporting part inside the script, but that's not the main problem now.
I have this code that finds all the visibile artboards and stores them inside visibleArtboards, but I can't seem to find a way to make a selection of them.
var artboards = activeDoc.layers;
var visibleArtboards = [];
for (var i=0; i<artboards.length; i++){
if(artboards[i].visible){
visibleArtboards.push(artboards[i]);
}
}
activedoc.activeLayer can make a selection, but only of 1 single artboard.
If anybody can help me with the missing piece, I'd appreciate it a lot
You can get the layer ID of the artboards and add that to a selection. Using your code, visibleArtboards now is the ID of the artboard layers.
// call the source document
var activeDoc = app.activeDocument;
var artboards = activeDoc.layers;
var visibleArtboards = [];
for (var i=0; i<artboards.length; i++)
{
if(artboards[i].visible)
{
// select ID as we go along
var layerID = artboards[i].id;
visibleArtboards.push(layerID);
}
}
// Loop over the layers again and select all the art boards
for (var i=0; i<visibleArtboards.length; i++)
{
// add to current selection of layers
select_by_ID(visibleArtboards[i], true);
}
function select_by_ID(id, add)
{
if (add == undefined) add = false;
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putIdentifier(charIDToTypeID('Lyr '), id);
desc1.putReference(charIDToTypeID('null'), ref1);
if (add) desc1.putEnumerated(stringIDToTypeID("selectionModifier"), stringIDToTypeID("selectionModifierType"), stringIDToTypeID("addToSelection"));
executeAction(charIDToTypeID('slct'), desc1, DialogModes.NO);
} // end of selectByID()
It will, however, add the background (if included). I'm sure you can get around that.
So I am a noob in coding but managed to adjust the code a bit to do what I need it to do and that is to list the files inside a folder and its subfolder files.
The issue is that the files total is about 50k or more and keeps increasing each day XD
so now most of the time I get a "Exceeded maximum execution time" and sometimes's I don't. Inside the script, there is a flush function so it should reset the timer if I am correct?
I run the script every day I do not know what to do to fix this?
I think the best would be to have a function that will check if it is already listed and if not updated to skip it to speed up the script but again I just do not know atm ware to start.
If someone could help me to fix the " Exceeded maximum execution time" I would be extremely grateful.
this is the script:
function ListarTodo() {
/* Adapted from Code written by #Andres Duarte in this link:
https://stackoverflow.com/questions/59045664/how-to-list-also-files-inside-subfolders-in-google-drive/63182864#63182864
*/
// List all files and sub-folders in a single folder on Google Drive
// declare the folder name
var foldername = 'Beelden';
// declare this sheet
var sheet = SpreadsheetApp.getActiveSheet();
// clear any existing contents
sheet.clear();
// append a header row
sheet.appendRow(["Folder","Name", "Last Updated", "Size MB", "URL"]);
// getFoldersByName = Gets a collection of all folders in the user's Drive that have the given name.
// folders is a "Folder Iterator" but there is only one unique folder name called, so it has only one value (next)
var folders = DriveApp.getFoldersByName(foldername);
var foldersnext = folders.next();
var lintotal = 2;
// Initiate recursive function
lintotal = SubCarpetas(foldersnext, foldername, lintotal);
}
function SubCarpetas(folder, path, cantlineas) {
cantlineas = ListarArchivos(folder, path, cantlineas);
var subfolders = folder.getFolders();
while (subfolders.hasNext()) {
var mysubfolders = subfolders.next();
var mysubfolderName = mysubfolders.getName();
var newpath = "";
newpath = path + "/" + mysubfolderName;
cantlineas = SubCarpetas(mysubfolders, newpath, cantlineas);
}
return(cantlineas)
}
// list files in this folder
// myfiles is a File Iterator
function ListarArchivos(mifoldersnext, mipath, milintotal) {
var datos = []; //temporary array that we are going to use to record on the sheet
var files = []; //array with all the files that we find in the folder that we are evaluating
var file = []; //array that we use to dump the data of each file before saving it
var total = 0;
var sheet = SpreadsheetApp.getActiveSheet();
var myfiles = mifoldersnext.getFiles();
// We create an array with the data of each file and save the total number of files
while (myfiles.hasNext()) {
files.push(myfiles.next());
total++;
}
// we sort the array by file names alphabetically // sorts the files array by file names alphabetically
files = files.sort(function(a, b){
var aName = a.getName().toUpperCase();
var bName = b.getName().toUpperCase();
return aName.localeCompare(bName);
});
////
var vuelta = 0;
var bulk = 500; // We define the number of lines to record each time, in the GoogleDoc spreadsheet
var linea = milintotal; // we define in which line we are going to save in the spreadsheet
for (var i = 0; i < files.length; i++) { // we go through the array of files and format the information we need for our spreadsheet
file = files[i];
var fname = file.getName(); //file name
var fdate = file.getLastUpdated(); // date and time last modified
var fsize = file.getSize()/1024/1024; // file size, we pass it from byte to Kbyte and then to Mb
fsize = +fsize.toFixed(2); // we format it to two decimal places
var furl = file.getUrl(); //File URL
datos[vuelta] = [mipath+" ("+total+")", fname, fdate, fsize, furl]; // we put everything inside a temporary array
vuelta++;
if (vuelta == bulk) {// when it reaches the defined quantity, save this array with 10 lines and empty it
linea = milintotal;
// Logger.log("linea = "+linea); //DEBUG
// Logger.log("vuelta = "+vuelta); //DEBUG
// Logger.log("total = "+total); //DEBUG
// Logger.log("lintotal = "+milintotal); //DEBUG
// Logger.log("registros en datos = "+datos.length); //DEBUG
// Logger.log("data = "+datos); //DEBUG
sheet.getRange(linea, 1, bulk,5).setValues(datos); // we save the data of the temporary array in the sheet
SpreadsheetApp.flush(); // we force the data to appear on the sheet - without this the data does not appear until finished (it generates a lot of impatience)
milintotal = milintotal + vuelta;
datos = []; // empty the temporary array
vuelta = 0;
}
}
if (datos.length>0) {// When exiting the loop we record what is left in the data array
linea = milintotal;
// Logger.log("linea = "+linea); //DEBUG
// Logger.log("vuelta = "+vuelta); //DEBUG
// Logger.log("total = "+total); //DEBUG
// Logger.log("lintotal = "+milintotal); //DEBUG
// Logger.log("records in data = "+ data.length); //DEBUG
// Logger.log("data = "+datos); //DEBUG
sheet.getRange(linea, 1, datos.length,5).setValues(datos);
SpreadsheetApp.flush(); //ansiolítico
milintotal = milintotal + datos.length;
datos = [];
vuelta = 0;
}
return (milintotal)
}
Thank you all
UPDATE!
So after looking at multiple forumes i found that the best thing atm i can do is make a break for this script by using the following script:
function runMe() {
var startTime= (new Date()).getTime();
//do some work here
var scriptProperties = PropertiesService.getScriptProperties();
var startRow= scriptProperties.getProperty('start_row');
for(var ii = startRow; ii <= size; ii++) {
var currTime = (new Date()).getTime();
if(currTime - startTime >= MAX_RUNNING_TIME) {
scriptProperties.setProperty("start_row", ii);
ScriptApp.newTrigger("runMe")
.timeBased()
.at(new Date(currTime+REASONABLE_TIME_TO_WAIT))
.create();
break;
} else {
doSomeWork();
}
}
//do some more work here
}
But after trying I do not understand where to divide this to make it work T-T any ideas?
I think the best would be to have a function that will check if it is already listed and if not updated to skip it to speed up the script but again I just do not know atm ware to start.
These links from the official documentation should help:
https://developers.google.com/apps-script/reference/drive/drive-app#searchFiles(String)
https://developers.google.com/apps-script/reference/drive/drive-app#searchFolders(String)
https://developers.google.com/drive/api/v2/search-files
https://developers.google.com/drive/api/v2/ref-search-terms
You can use the information in the documentation to create a script that only pulls the most recently added and/or updated files.
However, if you need to process a large volume of recently updated files you'll need to leverage some kind of batch processing solution that spans multiple sessions.
I'm struggling with a problem where I need to get JPGs of all the written questions in InDesign since I work at a school. To make the process faster, I decided to go the "Export Objects" way. But i couldn't find a suitable script to achieve what I need.
Basically,
Select All Text Frames in the given Layout(Alternates are present)
Export All Text frames as JPG with given DPI value and name variable.
Both actions are actually available with the Sample codes, but in a different way. For example: SelectObject script works, but when combined with Command+E, the export result is one big image that contains all the selected frames. I want them separately.
I've tried combining the scripts given as applescript or js with my little knowledge of coding but no cigar.
Select Text : Indesign CC 2018 - SelectObjects Sample Code.
Image export: Indesign CC 2018 - Export to JPG scripts are the codes I've tried mingling with.
Goal: Export all text frames individually as variable DPI, variable name and variable destination from separate alternate layouts.
Edit 1: Code that I'm trying to mingle with. I found it on reddit but even though it essentially does what i need, it does in a crooked way and unusable. IT exports ALL items and they are with the page background, I'd need only the stuff that are contained within the TextFrame.
// Set resolution options
var rp = [72,150,300];
// Set EXPORT presets
app.pngExportPreferences.exportResolution = 72;
app.pngExportPreferences.antiAlias = true;
app.pngExportPreferences.pngQuality = PNGQualityEnum.MAXIMUM;
app.pngExportPreferences.pngColorSpace = PNGColorSpaceEnum.RGB;
app.pngExportPreferences.pngExportRange = PNGExportRangeEnum.EXPORT_RANGE;
// Resolution Select Dialog
var w;
w = new Window('dialog', 'Export Presets');
w.orientation = 'row';
with (w)
{
w.sText = add('statictext', undefined, 'Select Export Resolution:');
w.dropdown = add ( 'DropDownList',undefined,undefined,{items:rp});
w.btnOK = add('button', undefined, 'OK');
};
w.dropdown.selection=0;
w.show();
// Set resolution
var x = 0;
x = x + w.dropdown.selection;
app.pngExportPreferences.exportResolution = rp[x];
// SElECT Folder locations
var myFileAmount = 0;
var myFileLocation = Folder.selectDialog("Please select path of InDesign Files");
myFolder = new Folder ([myFileLocation]);
myFolderContents = myFolder.getFiles("*.indd"); // array
myFileAmount = (myFolderContents.length - 1);
// CHECK IF FILES IN FOLDER
if (myFileAmount < 0){alert("No Files in selected folder");}
else
{
var mySaveLocation = Folder.selectDialog("Please select path to Save PNG");
mySaveFolder = new Folder ([mySaveLocation]);
// OPEN FILES One at a time
for (i = myFileAmount; i >= 0; i--)
{
app.open(File (myFolderContents[i]));
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.NEVER_INTERACT;
// SET Active Document
var myDoc = app.activeDocument;
// EXPORT
//One Page at a time
for (var p=0; p < myDoc.pages.length; p++)
{//page loop
var pname = myDoc.pages.item(p).name;
//set all items in file hiden
for (var itemnum=0;itemnum < myDoc.pages.item(p).pageItems.length; itemnum++)
{
myDoc.pages.item(p).pageItems.item(itemnum).visible = false;
}
// set page to export
app.pngExportPreferences.pageString = pname;
//add a 0 in from on less than 10
if (p<9){var pnm=0;}else{var pnm=""}
//LOOP Through items Set Visibility, export a PNG, Set Visibility
for (var itemexport=0;itemexport < myDoc.pages.item(p).pageItems.length; itemexport++)
{
var itm = itemexport+1;//items start at 1 not 0
myDoc.pages.item(p).pageItems.item(itemexport).visible = true;
//ACTUALLY EXPORTING
app.activeDocument.exportFile(
ExportFormat.PNG_FORMAT,
File(mySaveFolder.fsName + "/" + app.activeDocument.name.split(".indd")[0] + "_"+ pnm + pname + "_" + itm +".png"),
false,
);
//SET VISIBILITY
myDoc.pages.item(p).pageItems.item(itemexport).visible = false;
}
}
app.activeDocument.close(SaveOptions.no);
}
}
I am trying to modify original PSD and then delete the original one and only want to save as a new jpg. My code is working fine with this line:
activeDocument.close(SaveOptions.DONOTSAVECHANGES); // Close Original Image
But when I replace above line with this line:
psd.remove(); // I want to delete Original file
It giving me remove() is not a function error.
Here is the complete script. I have tired to read Photoshop JS Guide 2015 and also google this issue but I didn't find any answer.
var defaultRulerUnits = preferences.rulerUnits;
preferences.rulerUnits = Units.PIXELS;
if (documents.length >= 1){
var hres = 0;
var vres = 0;
var OldName = activeDocument.name.substring(0, activeDocument.name.indexOf('.'));
var CurrentFolder = activeDocument.path;
var psd = app.activeDocument;
hres = activeDocument.width;
vres = activeDocument.height;
activeDocument.selection.selectAll();
if (activeDocument.layers.length >1) {
activeDocument.selection.copy(true);
}
else{
if (activeDocument.layers.length =1) {
activeDocument.selection.copy(false);
}
}
psd.remove(); // I want to delete Original file
var newDoc = documents.add(hres, vres, 72, OldName, NewDocumentMode.RGB, DocumentFill.WHITE);
newDoc.paste();
jpgFile = new File(CurrentFolder + "/" + OldName+ ".jpg" );
jpgSaveOptions = new JPEGSaveOptions();
jpgSaveOptions.formatOptions = FormatOptions.STANDARDBASELINE;
jpgSaveOptions.matte = MatteType.NONE;
jpgSaveOptions.quality = 12;
newDoc.saveAs(jpgFile, jpgSaveOptions, true, Extension.LOWERCASE);
}
A little late to the thread, but hope this helps someone else.
The remove method expects a file location. You can accomplish removing the original file like this:
var activeDoc = app.activeDocument;
var docPath = new Folder(activeDoc.path);
var psd = new File(docPath + "/" + activeDoc.name);
...
psd.remove();
Edit: Meant to also include a link to this handy ESTK reference doc where I learned about working with the File object: http://estk.aenhancers.com/3%20-%20File%20System%20Access/file-object.html?highlight=delete
srcDoc.activeLayer.remove();
Will delete the active layer. There's no .remove() method to delete a file.
I'm new in code with Javascript and I have a problem with an array I need to create.
var tabLine = new Array();
var tabCol = new Array();
var tabComplet = new Array();
var fso, f1, ts, s, cl, ln;
var ForReading = 1;
var i = 0;
function ReadFiles() {
fso = new ActiveXObject("Scripting.FileSystemObject");
// Read the contents of the file.
ts = fso.OpenTextFile("PathToAFile\TextFile.txt", ForReading);
s = ts.ReadAll();
tabLine = s.split('\n');
cl = tabLine.length;
ts.Close();
for (i = 0; i <tabLine.length; i++) {
var tabCol = tabLine[i].split("\t");
for (j=0;j<tabCol.length;j++) {
tabComplet[i,j] = tabCol[j];
alert(tabComplet[i,j]);
}
}
alert(tabComplet[10,5]);
alert(tabComplet[3,5]);
}
ReadFiles();
The file I need to read is a text file; It have many line and each line have information separate by tabulation.
This function read the text file and convert it into an array in two dimensions.
I had some alert to check the contain of my array.
The first alert give me the result I want (it display the content of the array witch is different for each element in the array)but the two other give me the same result. I check with another alert and, in the for boucle, these two element are different.
I make more test and all happen like if my array only have the same line copy/paste.
Thanks in advance for all information that can help me.
Here is an example of file I use :
http://www.k-upload.fr/afficher-fichier-2017-05-18-1b0cfa685testimport2.txt.html
Usually there are bigger than this one but for test it's OK.