Skip to main content
Known Participant
October 31, 2008
Question

Can I automate the writing of XMP metadata into JPEG and TIFF files?

  • October 31, 2008
  • 91 replies
  • 11727 views
I have written an ASP.NET 3.5 website application on behalf of an annual international photographic competition. Entrants will be uploading digital photos in either JPEG or TIFF format. Ideally, I would write entrant identity and image title information into the XMP metadata for each image immediately after upload - but so far, I have failed to find any way to do this in ASP.NET.

Thousands of images are involved, so I need to find a way to automate the metadata insertion, perhaps with some sort of script that uses a text file (extracted from the SQL Server database on my website) as the source of the metadata for a batch of images. Is this the sort of task that can be done by writing a script for Bridge CS3? Are there any scripts already in existence that I could use? I am a total beginner in this area.

I use a Win XP PC, though I have a colleague who, I think, has CS3 on his Mac (running under the Leopard OS), so scripts for either platform might be usable.

David
This topic has been closed for replies.

91 replies

Known Participant
November 11, 2008
I deleted all previous versions of your script and ran the latest version again. This time, the TempTmpl template DID appear in the Append Metadata menu - but it still doesn't add data.

Where do I find this template file?

David
Known Participant
November 11, 2008
Nope. That template ain't there.
Paul Riggott
Inspiring
November 11, 2008
According to that, it hasn't seen any errors and the TEMPLATE should now exist.
Could you go to Bridge - Tools - Append Metadata and there should be a template "TempTmpl"
Is it there?
If so could you see if it will add data to a file?
If the template exists and it doesn't add data could you post the template?
Known Participant
November 11, 2008
Paul,
I've run the latest script and the resulting error log is shown below. I hope it helps to identify the problem. Thanks again for all your work on this. You are a star!

David

These documents have not been updated
=================================================================
Line From CSV File: C:/Documents and Settings/Administrator/My Documents/Visual Studio 2008/WebSites/SIEWebsite/EntryImages/C3-1261 Moray & Max.jpg,Moray & Max,David Charles Anderson
Ok can read file Checking if File Exists : ~/My Documents/Visual Studio 2008/WebSites/SIEWebsite/EntryImages/C3-1261 Moray & Max.jpg
File Exists~/My Documents/Visual Studio 2008/WebSites/SIEWebsite/EntryImages/C3-1261 Moray & Max.jpgMoray & Max - David Charles Anderson
Back from creating/apply Template
=================================================================
Line From CSV File:
Paul Riggott
Inspiring
November 11, 2008
This time there are a lot more checks and messages sent to the log, could you please try this on that one line CSV file.



#target bridge

if( BridgeTalk.appName == "bridge" ) {

addInfo = MenuElement.create("command", "Update Entry Details", "at the end of Thumbnail");

}

addInfo .onSelect = function () {

mainTitleAuthor();

}



function mainTitleAuthor(){

var csv = File.openDialog("Please select CSV file.","CSV File:*.csv");

if(csv != null){

var errorlog = new File("~/ErrorLog.txt");

errorlog.open('w');

errorlog.writeln("These documents have not been updated");

csv.open("r");

while(!csv.eof){

strInputLine = csv.readln();

errorlog.writeln("=================================================================");

errorlog.writeln("Line From CSV File: " + strInputLine);

if (strInputLine.length > 3) { // Make sure it isn't a blank line

strInputLine = strInputLine.replace(/\\/g,'/'); //Change backslash to forward slash.

inputArray = strInputLine.split(",");

var csvFile = new File(inputArray[0]);

var title = inputArray[1];

var author = inputArray[2];

errorlog.writeln("Ok can read file Checking if File Exists : " +decodeURI(csvFile));

if(!csvFile.exists) errorlog.writeln(decodeURI(csvFile) + " ****Does Not Exist****");

if(csvFile.exists){ //Check if file exists

item = new Thumbnail(csvFile);

md =item.synchronousMetadata;

errorlog.writeln("File Exists" +decodeURI(csvFile) +inputArray[1]+" - " + inputArray[2]);

var result =addTitleAuthor(md,inputArray[1],inputArray[2]);

if(!result) errorlog.writeln(decodeURI(csvFile) + " Unable to apply template");

errorlog.writeln("Back from creating/apply Template");

}

}

}

}

errorlog.close();

errorlog.execute();

}



function addTitleAuthor(metadata, Title, Author)

{

var strTmpl = "TempTmpl";

var strUser = Folder.userData.absoluteURI;

var filTmpl = new File(strUser + "/Adobe/XMP/Metadata Templates/" + strTmpl + ".xmp");

var fResult = false;



if (filTmpl.exists) filTmpl.remove();

try{

fResult = filTmpl.open("w");

}catch(e){

alert("Unable to create Template " +filTmpl +"\r"+e.message);

return;

}

try{

if (fResult){

//CS3

//filTmpl.writeln("<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"Adobe XMP Core 4.1-c037 46.282696, Mon Apr 02 2007 18:36:42 \">");

//CS2

filTmpl.writeln("<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"3.1.2-113\">");

filTmpl.writeln("<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">");

filTmpl.writeln("<rdf:Description rdf:about=\"\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">");

filTmpl.writeln("<dc:title>");

filTmpl.writeln("<rdf:Alt>");

filTmpl.writeln("<rdf:li xml:lang=\"x-default\">"+Title+"</rdf:li>");

filTmpl.writeln("</rdf:Alt>");

filTmpl.writeln("</dc:title>");

filTmpl.writeln("<dc:creator>");

filTmpl.writeln("<rdf:Seq>");

filTmpl.writeln("<rdf:li>" + Author + "</rdf:li>");

filTmpl.writeln("</rdf:Seq>");

filTmpl.writeln("</dc:creator>");

filTmpl.writeln("</rdf:Description>");

filTmpl.writeln("</rdf:RDF>");

filTmpl.writeln("</x:xmpmeta>");

fResult = filTmpl.close();

metadata.applyMetadataTemplate(strTmpl, "replace");

//filTmpl.remove();

} }

catch(e) {

alert("There was a problem with the Template");

fResult = false;

}

return fResult;

};

Known Participant
November 10, 2008
Paul,
As far as possible, I did as you suggested. I commented out the line in the script containing 'filTmpl.remove();'. I edited my CSV file to include just one of the images that failed to update. I then ran the modified script. Once again it failed to work and a subsequent search of my PC did not find any document by the name of TempTmpl.xmp.

David
Known Participant
November 10, 2008
Paul,
Ooops! That was a stupid mistake. Of course your code will have problems with a unexpected comma in a COMMA-Separated-Variable file!!

I will try out your other suggestions later tonight, if possible.

David
Paul Riggott
Inspiring
November 10, 2008
You can NOT use a comma anywhere except for the use of seperating the different fields, unless you use a different seperator!
In this case a comma is the seperator!
If you want to use commas you will have to create the csv fill with a unque seperator, and this line will have to be changed to suit.
inputArray = strInputLine.split(",");
If you want to use ; the line would be:
inputArray = strInputLine.split(";");

In the code near the bottom is a line:-
filTmpl.remove();
comment this line out IE:
//filTmpl.remove();
Now in your csv file just have one line. One of the files that does not update.
Run the code again.
This time it will leave the newly created template called "TempTmpl.xmp"
Select the document in Bridge, then - Tools - Replace Metadate - and choose TempTmpl
Check to see if Exif info has been added.
If it hasn't you could try Append Metadata
If this fails could you post the template and I will have a look and see if there is something amiss.
To open the relevant folder you can run the following code from "ExtendScript Toolkit" (This comes with Photoshop);
#target bridge
var filTmpl = new Folder(Folder.userData.absoluteURI + "/Adobe/XMP/Metadata Templates/");
filTmpl.execute();
Known Participant
November 10, 2008
Paul,
Things are still much the same with your latest script, with the exception that the error log is now displayed. It shows a single 'does not exist' message but the quoted filename is only about half of the real filename - up to the position of an embedded comma. Your code obviously cannot cope with embedded punctuation in the filename.

The filename is C4-1261 Die Nieuwe Kerk, Amsterdam.jpg
Error message: ..../C4-1261 Die Nieuwe Kerk does not exist

However, the primary problem still remains. Of the 5 files found by your script, only 2 files were updated (the same 2 as before).

David
Paul Riggott
Inspiring
November 10, 2008
Ok David, there were some modifications done on the last two versions.
To get bak on track this is the one you should try. The error log should automatically open.



#target bridge

if( BridgeTalk.appName == "bridge" ) {

addInfo = MenuElement.create("command", "Update Entry Details", "at the end of Thumbnail");

}

addInfo .onSelect = function () {

mainTitleAuthor();

}



function mainTitleAuthor(){

var csv = File.openDialog("Please select CSV file.","CSV File:*.csv");

if(csv != null){

var errorlog = new File("~/ErrorLog.txt");

errorlog.open('w');

errorlog.writeln("These documents have not been updated");

csv.open("r");

//csv.encoding = "UTF-8";

while(!csv.eof){

strInputLine = csv.readln();

if (strInputLine.length > 3) { // Make sure it isn't a blank line

strInputLine = strInputLine.replace(/\\/g,'/'); //Change backslash to forward slash.

inputArray = strInputLine.split(",");

var csvFile = new File(inputArray[0]);

var title = inputArray[1];

var author = inputArray[2];

//errorlog.writeln("*******Ok can read file" +decodeURI(csvFile) + " - " + inputArray[1]+" - " + inputArray[2]);

if(!csvFile.exists) errorlog.writeln(decodeURI(csvFile) + " does not exist");

if(csvFile.exists){ //Check if file exists

item = new Thumbnail(csvFile);

md =item.synchronousMetadata;

// errorlog.writeln("xxxxxxxFile Exists" +decodeURI(csvFile) +inputArray[1]+" - " + inputArray[2]);

var result =addTitleAuthor(md,inputArray[1],inputArray[2]);

if(!result) errorlog.writeln(decodeURI(csvFile) + " Unable to apply template");

}

}

}

}

errorlog.close();

errorlog.execute();

}



function addTitleAuthor(metadata, Title, Author)

{

var strTmpl = "TempTmpl";

var strUser = Folder.userData.absoluteURI;

var filTmpl = new File(strUser + "/Adobe/XMP/Metadata Templates/" + strTmpl + ".xmp");

var fResult = false;

try

{ if (filTmpl.exists)

filTmpl.remove();

fResult = filTmpl.open("w");

if (fResult)

// CS3

{

//CS3

//filTmpl.writeln("<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"Adobe XMP Core 4.1-c037 46.282696, Mon Apr 02 2007 18:36:42 \">");

//CS2

filTmpl.writeln("<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"3.1.2-113\">");

filTmpl.writeln("<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">");

filTmpl.writeln("<rdf:Description rdf:about=\"\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">");

filTmpl.writeln("<dc:title>");

filTmpl.writeln("<rdf:Alt>");

filTmpl.writeln("<rdf:li xml:lang=\"x-default\">"+Title+"</rdf:li>");

filTmpl.writeln("</rdf:Alt>");

filTmpl.writeln("</dc:title>");

filTmpl.writeln("<dc:creator>");

filTmpl.writeln("<rdf:Seq>");

filTmpl.writeln("<rdf:li>" + Author + "</rdf:li>");

filTmpl.writeln("</rdf:Seq>");

filTmpl.writeln("</dc:creator>");

filTmpl.writeln("</rdf:Description>");

filTmpl.writeln("</rdf:RDF>");

filTmpl.writeln("</x:xmpmeta>");

fResult = filTmpl.close();

metadata.applyMetadataTemplate(strTmpl, "replace");

filTmpl.remove();

} }

catch(e) {

fResult = false;

}

return fResult;

};