Copy link to clipboard
Copied
I have a lot of images that I need to add dates too. 4 images get the same date and are in the same folder. There are videos in that folder too. Attatched images is an example of what I am trying to achieve.
I'd like to be able to select every jpg in a folder add the date to it and save it back to the folder with " date" appended to the end.
I tried this with actions and batch to select the folder but I'm unsure how to quickly change the date for each folder so I don't have to record the text date each time.
I tried this with photoshop variables but I get stuck because I have to use the title of each file and that's just as time consuming as manually adding the date. This would be a great solution if I could tell it to grab every jpg in the folder when using it instead of naming each individaul file.
I've not familiar enough with scripts to have tried them.
Copy link to clipboard
Copied
@JJMack Sorry for the delayed response.
Poorly is the short answer.
I was trying to reference open documents(or files) in the subfolders of my target folder script and use it to target the folders and then make my output folder = to the array folder but it's not functioning. I'm not knowledgeable enough in javascript to do that. Hoping to learn more but at some point on this project I'm going have to spend time converting the files with the script I have instead of working on a better script. Though adding this would reduce my time by 1/3.
I attached my attempt if you want to look at it. I kept getting an error and realized I'm in over my head and you all have already been so helpful I didn't want to come back and take up more of your time.
#target photoshop
if (app.documents.length === 0) {
// The "Test if Cancel..." needs to be within a function
(function () {
var folders =[];
var topLevel = Folder.selectDialog(""); // select top folder
if(topLevel == null) return; //if cancelled quit
folders = FindAllFolders(topLevel, folders); // call function FindAllFolders
for(var z=0; z < folders.length; z++){// loop through all subfolders
var savedDisplayDialogs = app.displayDialogs;
var inputFolder = folders;
var inputFiles = inputFolder.getFiles(/\.(jpg|jpeg|png)$/i);
// var outputFolder = inputFolder;
var outputFolder = inputFolder;
// Test if Cancel button returns null, then do nothing
var dateString = prompt("Enter the date (Month, Day Year)", "MONTH, ## ####");
// Test if Cancel button returns null, then do nothing
if (dateString === null) {
app.beep();
return;
}
app.displayDialogs = DialogModes.NO;
for (var i = 0; i < inputFiles.length; i++) {
open(inputFiles[i]);
var docName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
// var saveFileJPG = new File(new File(outputFolder + '/' + docName + ' ' + dateString + '.jpg'));
var saveFileJPG = new File(new File(outputFolder + '/' + docName + ' date' + '.jpg'));
dateStamp();
// As this appears to be created from a template
deleteDocumentAncestorsMetadata();
saveJPG(saveFileJPG);
app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
}
app.displayDialogs = savedDisplayDialogs;
app.beep();
alert("Script Completed! Files saved to: " + "\r" + outputFolder.fsName);
/************ Functions ************/
function dateStamp() {
var doc = app.activeDocument;
// Ruler units
var origRuler = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.POINTS;
// Doc resolution
var origRes = app.activeDocument.resolution;
app.activeDocument.resizeImage(null, null, 72, ResampleMethod.NONE);
// Text layer, based on a 72ppi resolution
var layerRef = doc.artLayers.add();
layerRef.name = "Date Info";
layerRef.kind = LayerKind.TEXT;
var textRef = layerRef.textItem;
var textColor = new SolidColor();
textColor.rgb.red = 255;
textColor.rgb.green = 255;
textColor.rgb.blue = 255;
textRef.color = textColor;
textRef.contents = dateString;
textRef.position = new Array(0, 0);
textRef.font = 'Graphik-Bold';
textRef.size = 60;
textRef.useAutoLeading = true;
textRef.justification = Justification.CENTER;
addStyle("Bold")
// Add drop shadow to text
dropShadow();
// Ruler units for positioning on canvas
app.preferences.rulerUnits = Units.PIXELS;
// Align text to horizontal centre
align2SelectAll('AdCH');
// Align text to bottom
align2SelectAll('AdTp');
// move text layer down
doc.activeLayer.translate(0, 42);
// Restore original doc resolution
app.activeDocument.resizeImage(null, null, origRes, ResampleMethod.NONE);
// Restore original ruler units
app.preferences.rulerUnits = origRuler;
function align2SelectAll(method) {
/*
AdLf = Align Left
AdRg = Align Right
AdCH = Align Centre Horizontal
AdTp = Align Top
AdBt = Align Bottom
AdCV = Align Centre Vertical
*/
doc.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) { }
doc.selection.deselect();
}
}
function saveJPG(saveFileJPG) {
var jpgOptions = new JPEGSaveOptions();
jpgOptions.formatOptions = FormatOptions.STANDARDBASELINE;
jpgOptions.embedColorProfile = true;
jpgOptions.matte = MatteType.NONE;
jpgOptions.quality = 12;
app.activeDocument.saveAs(saveFileJPG, jpgOptions, true, Extension.LOWERCASE);
}
function deleteDocumentAncestorsMetadata() {
// https://prepression.blogspot.com/2017/06/metadata-bloat-photoshopdocumentancestors.html
// https://forums.adobe.com/message/8456985#8456985
if (ExternalObject.AdobeXMPScript === undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
var xmp = new XMPMeta(activeDocument.xmpMetadata.rawData);
xmp.deleteProperty(XMPConst.NS_PHOTOSHOP, "DocumentAncestors");
app.activeDocument.xmpMetadata.rawData = xmp.serialize();
}
function dropShadow()
{
var idset = stringIDToTypeID( "set" );
var desc7 = new ActionDescriptor();
var idnull = stringIDToTypeID( "null" );
var ref1 = new ActionReference();
var idproperty = stringIDToTypeID( "property" );
var idlayerEffects = stringIDToTypeID( "layerEffects" );
ref1.putProperty( idproperty, idlayerEffects );
var idlayer = stringIDToTypeID( "layer" );
var idordinal = stringIDToTypeID( "ordinal" );
var idtargetEnum = stringIDToTypeID( "targetEnum" );
ref1.putEnumerated( idlayer, idordinal, idtargetEnum );
desc7.putReference( idnull, ref1 );
var idto = stringIDToTypeID( "to" );
var desc8 = new ActionDescriptor();
var idscale = stringIDToTypeID( "scale" );
var idpercentUnit = stringIDToTypeID( "percentUnit" );
desc8.putUnitDouble( idscale, idpercentUnit, 416.666667 );
var iddropShadow = stringIDToTypeID( "dropShadow" );
var desc9 = new ActionDescriptor();
var idenabled = stringIDToTypeID( "enabled" );
desc9.putBoolean( idenabled, true );
var idpresent = stringIDToTypeID( "present" );
desc9.putBoolean( idpresent, true );
var idshowInDialog = stringIDToTypeID( "showInDialog" );
desc9.putBoolean( idshowInDialog, true );
var idmode = stringIDToTypeID( "mode" );
var idblendMode = stringIDToTypeID( "blendMode" );
var idmultiply = stringIDToTypeID( "multiply" );
desc9.putEnumerated( idmode, idblendMode, idmultiply );
var idcolor = stringIDToTypeID( "color" );
var desc10 = new ActionDescriptor();
var idred = stringIDToTypeID( "red" );
desc10.putDouble( idred, 0.000000 );
var idgrain = stringIDToTypeID( "grain" );
desc10.putDouble( idgrain, 0.000000 );
var idblue = stringIDToTypeID( "blue" );
desc10.putDouble( idblue, 0.000000 );
var idRGBColor = stringIDToTypeID( "RGBColor" );
desc9.putObject( idcolor, idRGBColor, desc10 );
var idopacity = stringIDToTypeID( "opacity" );
var idpercentUnit = stringIDToTypeID( "percentUnit" );
desc9.putUnitDouble( idopacity, idpercentUnit, 35.000000 );
var iduseGlobalAngle = stringIDToTypeID( "useGlobalAngle" );
desc9.putBoolean( iduseGlobalAngle, true );
var idlocalLightingAngle = stringIDToTypeID( "localLightingAngle" );
var idangleUnit = stringIDToTypeID( "angleUnit" );
desc9.putUnitDouble( idlocalLightingAngle, idangleUnit, 90.000000 );
var iddistance = stringIDToTypeID( "distance" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc9.putUnitDouble( iddistance, idpixelsUnit, 8.000000 );
var idchokeMatte = stringIDToTypeID( "chokeMatte" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc9.putUnitDouble( idchokeMatte, idpixelsUnit, 42.000000 );
var idblur = stringIDToTypeID( "blur" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc9.putUnitDouble( idblur, idpixelsUnit, 139.000000 );
var idnoise = stringIDToTypeID( "noise" );
var idpercentUnit = stringIDToTypeID( "percentUnit" );
desc9.putUnitDouble( idnoise, idpercentUnit, 0.000000 );
var idantiAlias = stringIDToTypeID( "antiAlias" );
desc9.putBoolean( idantiAlias, false );
var idtransferSpec = stringIDToTypeID( "transferSpec" );
var desc11 = new ActionDescriptor();
var idname = stringIDToTypeID( "name" );
desc11.putString( idname, """Linear""" );
var idshapeCurveType = stringIDToTypeID( "shapeCurveType" );
desc9.putObject( idtransferSpec, idshapeCurveType, desc11 );
var idlayerConceals = stringIDToTypeID( "layerConceals" );
desc9.putBoolean( idlayerConceals, true );
var iddropShadow = stringIDToTypeID( "dropShadow" );
desc8.putObject( iddropShadow, iddropShadow, desc9 );
var idlayerEffects = stringIDToTypeID( "layerEffects" );
desc7.putObject( idto, idlayerEffects, desc8 );
executeAction( idset, desc7, DialogModes.NO );
}
function addStyle(Style){
var idASty = charIDToTypeID( "ASty" );
var desc20 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref3 = new ActionReference();
var idStyl = charIDToTypeID( "Styl" );
ref3.putName( idStyl, Style );
desc20.putReference( idnull, ref3 );
var idT = charIDToTypeID( "T " );
var ref4 = new ActionReference();
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref4.putEnumerated( idLyr, idOrdn, idTrgt );
desc20.putReference( idT, ref4 );
try{
executeAction( idASty, desc20, DialogModes.NO);
}catch(e){}
}
};
}
})();
else {
alert('No documents should be open when running this script!');
}
Copy link to clipboard
Copied
What you posted is bad its incompler and mess up the firts function it use is missing. Pgitsop scprts put out an error
folders = FindAllFolders(topLevel, folders); // call function FindAllFolders
The FindAllFolders fubction is not in your post and the ends of the script look all messed up
Copy link to clipboard
Copied
Here is a script I put the together it has a few function I wrote to build File List to process. The functions should be easy to use to build you list of files, The is a parameter that you can set to true to process sub folders. The function will recursively use itself. There are also file type filtering parameters that cans be used. I have a demo script that can build file lists many ways using these functions, It only takes one line of code to build the file list you want to create. So in the demo I have code several of these one line file list creators. They are all comment ant the are all commented out but one the one to want to text. The demo process the file list you build. All the process does is toe created a log of the files paths.. It could just as easily opened the files and process them. Just look at the Main...
Here is the script with the functions...
/* =======================================================================
// 2021 John J. McAssey (JJMack)
// ======================================================================= */
// This script is supplied as is. It is provided as freeware.
// The author accepts no liability for any problems arising from its use.
// enable double-clicking from Mac Finder or Windows Explorer
#target photoshop // this command only works in Photoshop CS2 and higher
// bring application forward for double-click events
app.bringToFront();
/////////////////////////////////////////////////////////////////////////
// SET-UP Global Variables //
/////////////////////////////////////////////////////////////////////////
var scriptPath = $.fileName.substr(0,$.fileName.lastIndexOf("/")+1);
var scriptName = $.fileName.substr($.fileName.lastIndexOf("/")+1,$.fileName.lastIndexOf("."));
scriptName = scriptName.substr(0,scriptName.lastIndexOf("."));
var scriptExt = $.fileName.substr($.fileName.lastIndexOf("."));
//alert(scriptPath + scriptName + scriptExt);
// Initialize variables used in mainline
var folderListCopy = new Array;
var fileListCopy = new Array;
var fileTypes = "";
var logData = "";
// Save the current preferences and Set Photoshop to use pixels and display no dialogs
var startRulerUnits = app.preferences.rulerUnits;
var startTypeUnits = app.preferences.typeUnits;
var startDisplayDialogs = app.displayDialogs;
app.displayDialogs = DialogModes.NO;
app.preferences.rulerUnits = Units.PIXELS;
app.preferences.typeUnits = TypeUnits.PIXELS;
try {
startDate = (getDateTime());
var time1 = Number(timeString());
var processed = main(); // Select root folder and file types to process, crawl tree creating folderList and fileList then process file list
if (processed!=undefined) { } //alert(processed + " Files Processed");
if (logData!="") logInfo(timeStamp() + "\nFolders " + folderListCopy.length + " Files " + fileListCopy.length + "\n" + fileTypes + "\n\n" + logData);
var time2 = Number(timeString());
endDate = (getDateTime());
alert(startDate + " Start\n"
// +((time2-time1)/1000 )+" Seconds "
+((time2-time1)/60000 ).toPrecision(2)+" Minutes "
// +((time2-time1)/3600000 ).toPrecision(1)+" Hours "
+ "\n" + endDate + " End"
+"\nProcessed " + folderListCopy.length + " Folders Selected " + fileListCopy.length + " Files Types Matching\n"
+ fileTypes + "\n"
);
}
catch(e) { alert(e + ': on line ' + e.line, 'Photoshop Error', true); }
// Return the app preferences
app.preferences.rulerUnits = startRulerUnits;
app.preferences.typeUnits = startTypeUnits;
app.displayDialogs = startDisplayDialogs;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function main() {
//var files = buildFilelist (); // Select image files from any folder till you stop and cancel
//var files = selectFile(true); // Select Image files from a single folder
//var files = selectsImagesFolder("x","x","jpg|jpe"); // Select a folder containg Image tree all jpeg image file types in the tree will be selected
//var files = selectsImagesFolder(true,true,"jpg|jpeg"); // Select the root of the Image tree all jpeg image file types in the tree will be selected
//var files = selectsImagesFolder(true,false); // Select the root of the Image tree all image file types in the tree will be Selected
var files = selectsImagesFolder(true,true); // Select the root of the Image tree and filter image file types to selected
//var files = selectsImagesFolder(false,false); // Select a folder containg Image files all image file types in the folder will be Selected
//var files = selectsImagesFolder(); // Select a folder containg Image files all image file types in the folder will be Selected
//var files = selectsImagesFolder(false,true); // Select a folder containg Image files and filter image file types to be Selected
//var files = selectsImagesFolder(true,true); // Select image files
if (files!=undefined) {
fileListCopy = files; // So boilerplate can see file processes
for( var i=0; i < files.length; i++) { processFile(files[i]); } // Process Files
return files.length;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function selectsImagesFolder (multi,selection,types) { // Build a file list of selected image file types in folder
var folderList = new Array;
var fileList = new Array;
if (multi == true) {var theString = "Please select root folder"} // Process Sub Folders
else {var theString = "Please select a folder"}; // Just a single folder
var rootFolder = Folder.selectDialog(theString, ""); // Select root
if (rootFolder === null) { return}; // Test if Cancel button returns null, then do nothing
if (types!=undefined) typeList = types; // filter these
else {
var typeList = "nef|cr3|cr2|crw|dcs|raf|arw|orf|dng|psd|tif|tiff|jpg|jpe|jpeg|png|bmp"; // Get file types
if (selection == true) var typeList = prompt("Add or Remove file type to Process.",typeList); // User modifies file type selection
if (typeList === "" || typeList === null ) { return}; // Test if Cancel button returns null, then do nothing
}
fileTypes = typeList; // Add Global for boiler plate
var matchString = String("/\\.(" + typeList + ")$/i"); // Add the rest of the regular expression
folderList.push(rootFolder); // Start the Folder list at the root
if (multi == true) getFolders(rootFolder,folderList); // folderlist
getFilelist(folderList,matchString,fileList) // fileList
if (fileList=="") { return}; // Return if no files selected
function getFolders(pfolder,list) { // Recursively crawl the tree build the folder List
var dirList = pfolder.getFiles(); // Get files and sub-folders
for (var i = 0; i < dirList.length; i++) {
if (dirList[i] instanceof File) { } // Just process Folders
else {
list.push(dirList[i]); // Add to folder list
getFolders(dirList[i],list); // Add its sub-folders
};
}
}
function getFilelist(folders,filter,list) {
for( var i=0; i < folders.length; i++) { // Process folders
var files = folders[i].getFiles(eval(filter)); // Select files
for( var f=0; f < files.length; f++) {list.push(files[f]);} // Add files to selected fileList
}
}
folderListCopy = folderList; // Add Global for boiler plate
return fileList; // Return files
}
function buildFilelist () { // Build a file list of image files
var buildList = new Array;
var addfiles = selectFile(true);
if (addfiles !== null ) {
while (addfiles !== null ) {
if (addfiles.length ==1) buildList.push(addfiles);
else for( var i=0; i < addfiles.length; i++) {buildList.push(addfiles[i]);}
var addfiles = selectFile(true);
}
}
return buildList;
}
function selectFile (multi) { // Select image files only
if (multi == true) {var theString = "Please select files to be processed"}
else {var theString = "Please select a file"};
if ($.os.search(/windows/i) != -1) {var theFiles = File.openDialog (theString, '*.nef;*.cr3;*.cr2;*.crw;*.dcs;*.raf;*.arw;*.orf;*.dng;*.psd;*.psdt;*.tif;*.tiff;*.jpg;*.jpe;*.jpeg;*.png;*.bmp', multi)}
else {var theFiles = File.openDialog (theString, getFiles, multi)};
function getFiles (theFile) { ////// filter files for mac //////
if (theFile.name.match(/\.(nef|cr3|cr2|crw|dcs|raf|arw|orf|dng|psd|tif|tiff|jpg|jpe|jpeg|png|bmp)$/i) || theFile.constructor.name == "Folder") {
return true
};
};
return theFiles
};
function logInfo(Txt){ // Create write and open log file
try {
var file = new File(Folder.desktop + "/" + scriptName + " Log.txt");
file.open("w", "TEXT", "????");
file.encoding = "UTF8";
file.seek(0,2);
$.os.search(/windows/i) != -1 ? file.lineFeed = 'windows' : file.lineFeed = 'macintosh';
file.writeln(Txt);
if (file.error) alert(file.error);
file.close();
file.execute();
}
catch(e) { alert(e + ': on line ' + e.line, 'Script Error', true); }
};
function getDateTime() { // Function for returning current date and time
var date = new Date();
var dateTime = "";
if ((date.getMonth() + 1) < 10) { dateTime += "0" + (date.getMonth() + 1) + "/"; }
else { dateTime += (date.getMonth() + 1) + "/";}
if (date.getDate() < 10) { dateTime += "0" + date.getDate() + "/"; }
else { dateTime += date.getDate() + "/"; }
dateTime += date.getFullYear() + "_";
if (date.getHours() < 10) {dateTime += "0" + date.getHours() + ":"; }
else { dateTime += date.getHours() + ":"; }
if (date.getMinutes() < 10) { dateTime += "0" + date.getMinutes() + ":"; }
else { dateTime += date.getMinutes() + ":"; }
if (date.getSeconds() < 10) { dateTime += "0" + date.getSeconds(); }
else { dateTime += date.getSeconds(); }
return dateTime;
}
function timeString () { // Function for returning raw time
var now = new Date();
return now.getTime()
};
function timeStamp(){
// Get the time and format it
var digital = new Date();
var hours = digital.getHours();
var minutes = digital.getMinutes();
var seconds = digital.getSeconds();
var amOrPm = "AM";
if (hours > 11) amOrPm = "PM";
if (hours > 12) hours = hours - 12;
if (hours == 0) hours = 12;
if (minutes <= 9) minutes = "0" + minutes;
if (seconds <= 9) seconds = "0" + seconds;
// Get the date and format it
var date = new Date();
var d = date.getDate();
var day = (d < 10) ? '0' + d : d;
var m = date.getMonth() + 1;
var month = (m < 10) ? '0' + m : m;
var yy = date.getYear();
var year = (yy < 1000) ? yy + 1900 : yy;
// create a variable with the fully formatted the time and date
// todaysDate = hours + ":" + minutes + ":" + seconds + " " + amOrPm + " - " + day + "/" + month + "/" + year;
// todaysDate = hours + ":" + minutes + ":" + seconds + " " + amOrPm + " - " + month + "/" + day + "/" + year;
MonthNames = new Array("January","February","March","April","May","June","July","August","September","October","November","December");
//todaysDate = hours + ":" + minutes + ":" + seconds + " " + amOrPm + " " + MonthNames[date.getMonth()] + " " + date.getDate() + ", " + year;
todaysDate =MonthNames[date.getMonth()] + " " + date.getDate() + ", " + year +" " + hours + ":" + minutes + ":" + seconds + " " + amOrPm;
return todaysDate;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Selected file are processed here
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function processFile(file) { // Process Your files here
// Here I just parse the Files Into Path Name and Extension and Log them
// var startDate Could be used for output File Name suffix
// var scriptName could also be useful
var filePath = String(file).substr(0,String(file).lastIndexOf("/")+1);
var fileName = String(file).substr(String(file).lastIndexOf("/")+1,String(file).lastIndexOf("."));
fileName = fileName.substr(0,fileName.lastIndexOf("."));
var fileExt = String(file).substr(String(file).lastIndexOf("."));
logData = logData + filePath + "\nName: " + fileName + "\nExt : " + fileExt + "\n\n";
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// When last file is process the script will end
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Copy link to clipboard
Copied
JjMack,
Thanks for the script. I'm now finished with my project but still want to learn. I've started going through some javascript courses. And am excited to keep learning and applying these to projects going forward in photoshop. I do a lot of task that are repetitive and I'm hoping to write some scripts to reduce time. Thanks again for all your help!
I was able to run your script and get the results printed of all the folders. I was not however able to pass those variables into Stephen's script and I'm perplexed. I'll continue to come back to this script as I'm learning more to see how to get these to pass through, I tried using some of your global variables in replacement of some of Stephen's to no avail.
Do you have any advice on code editors to help me see where the code is stopping? I'm currently running it in Photoshop. I'm not getting any errors so the syntax is correct but the code is incorrect because I'm not getting any results.
I'm writing/editing in Dreamweaver and then running it in photoshop.
Copy link to clipboard
Copied
Adobe recommends using Microsoft Visual Studio Code for editing, there are some Extendscript-specific plugins available to make things easier.
Copy link to clipboard
Copied
I only hack at Photoshop Scripting. I'm a retired programmer I was never prolific programmer. I can type or spell never went to programming school. However, it turned out I was good at debugging, designing and developing programing development tools so I made a decent living as a Programmer for 30+ years.
To script Photoshop you need to understand how Photoshop works well so you can design processes to accomplish what you want to do. Photoshop Scripting DOM does not cover all of Photoshop features. Most Scripts need to include some Action Manager code to accoplish what need to be done.
Adobe has a Photoshop plug-in Scriptlistener that is like an Action recorder that records the steps you do in Photoshop into two log files on your desktop. One is log is JavaScript Code the other VSB code all that can be recorded is recorded there are no controls. The coed is like action step. All settings are hard coded the is noe logic. You need to add the logic and variable settings. The code is not easy to read and its also one sided as far as the action manager goes. The execute side of the Action Manger the manger other side can retrieve information about Photoshop and documents states. Because I do know JaveScript or much about objects. I have very hard time scripting Photoshop.
At my age it to teach myself all that is required is not worthwhile for me. I'm content at being able to hack some simple processes like Collages, Mockup placing logos etcs. senility could bet around the corner hacking slows my progress around the corner.
There is very few Photoshop scripting resource the are a few books . Reading the code in Adobe sample script is a good starting point as is reading code in Photoshop Scripts folder. Some of them are over my head . However I would state Fit Image JSX is a very good and relatively easy example for creating Dialogs and Photoshop Plug-in in using Javs script. I stole the code in Fit image to create my AspecctRatioSelection and LongPrintSide plug-ins to be use in actions. The forum is the resource I turn to most.
Copy link to clipboard
Copied
Thanks! The advice by @Lumigraphics helped me get a code software that is showing me were the breakdown in the code is. Which will make learning and tinkering to get this to work more manageable for me. I am a designer for many years and do some web coding. I'm excited to be able to dive into javascript and be able to apply it in photoshop and web.
I'm pretty familiar with actions but they don't often have the logic I need. This blog has been great and you @JJMack have been a great help. I hope to post my code here when I conquer getting these too to work together!
Copy link to clipboard
Copied
Scripts can be use in Actions so some very small trivial scripts use in actions can add some logic into actions, Run twice scripts can save things for actions the action can the make changes then use the use the script a second time to restore saved things. So a little scripting can go a long way.
It is ease to record actions. Scripts can also use Actions look at how powerful Image Processor Pro
can be when you add simple lithe actions to it run. Inage Processor Pro... is A Photoshop Plug_in it supports itself being recorded into actions. adding a messaget to be set to itsself when the action is played
Copy link to clipboard
Copied
Stephen recursion can be hard to get a grip on. You may want to look at Adobe Script Image Processor. It has an option to process subfolder Images and also to keep the structure in the output folder.
Here is a sample of recursion code used to process a document layer stack. The function processArtLayers is used recursively to process layers in an object. The script is as simple as I can make it. What you need to understand is the Function varable are local there is not one obj array every recursion of processArtLayers has its own local obj array. Only var allLayers is global. The first processArtLayers used in main is the last to end You may want to run this script on a few different structure Photoshop documents. The order the image layers are processed may surprise you
// declare Global variables
var allLayers = "";
main();
alert(allLayers);
function main() {
processArtLayers(activeDocument)
}
function processArtLayers(obj) {
for( var i = obj.artLayers.length-1; 0 <= i; i--) {/* alert(obj.artLayers[i]); */processLayers(obj.artLayers[i])}
for( var i = obj.layerSets.length-1; 0 <= i; i--) {/* alert(obj.layerSets[i]); */processArtLayers(obj.layerSets[i])} // Process Layer Set Layers
}
function processLayers(layer) {
//alert('Layer Name = "' + layer.name + '" Layer Kind ' + layer.kind );
allLayers = allLayers + "ID " + layer.id + ", " + layer.name + ", " + layer.kind + "\n";
}
Copy link to clipboard
Copied
Sheaffer
You have Stephen's script to work from. If you want it to also process all lower subfolders he replied to you that a recursive process. The script will need to handle the entire folder selected process the Jpeg and recursively process all folders. However, the current process would need to be to be modified to handle the recursion, For the output files for each subfolder would also need to be saved into subfolders for the dated jpegs. I my opinion you should try the make the modification. Stephen likes to help but he is not your employee you should reward him with at least some good praise.
Copy link to clipboard
Copied
The script look good. It could be improved some by adding a drop shadow on the text layer for white on white does not show the text. Also the text size should probably be set relative to the width of the document so the text will fit in narrow documents. Also the save file name you added a suffix ' date' not the entered date. I'm not sure which the OP wants.
Copy link to clipboard
Copied
@JJMack – thank you!
I personally prefer using the following for white on white;
layerRef.blendMode = BlendMode.DIFFERENCE;
I decided not to do that and some of the other things that I did in Print metadata on bottom of photo that you mention which I have done in the past, until there is some feedback.
I asked @Sheaffer about the ' date' suffix, that is easily changed,.. However, if you re-read the post and look at both of the attached filenames ' date' seems appropriate for now.
There is always room for adjustments, this is only a v1.0 script after all.
Copy link to clipboard
Copied
When using variables and data sets you can not rename files. Also when using data sets you can export or save files only in PSD file format. There are other ways to append to file name but the question is whether you want word date, actual date or both as already asked by @Stephen Marsh
You can also count on variables to add text and some other way to append whatever you want to file name while converting PSD to desired output format.
Copy link to clipboard
Copied
Could you use Batch Rename in Bridge?