• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Quickly retrieve Exif metadata

Explorer ,
Mar 29, 2015 Mar 29, 2015

Copy link to clipboard

Copied

I've got a script for Photoshop CC 2014 that makes some exposure value (EV) calculations based on Exif metadata in camera raw files and then adjusts the image exposure to the target EV.  I know that this information is quickly available in Bridge, but when I try to get the metadata in Photoshop, I have to use the Document.open() command, and that opens the file (which takes a long time) instead of just grabbing the Exif metadata.  I can get it quickly in a Bridge script, but I'm having a hard time embedding that stuff in a Photoshop-targeted script (the BridgeTalk stuff is a bit confusing to me, or it isn't working on my computer).

I've also attempted to use "bridge.executeScript()", but the bridge object apparently is not available to scripts targeting Photoshop (or else something is messed up with my installation).  Bridge is available in bridge-targeted scripts only.

Here's how it's working in Photoshop scripting (I include only the relevant part).

    for (var nfile = nstart; nfile < nstop; nfile++){
        var Name = File(testListing[nfile]).name.replace(/\.[^\.]+$/, '');
        var file = File(testListing[nfile].path + "/" + Name + ".JPG");
        if (file.exists){
            app.open(file);
            }
        else{
            app.open(testListing[nfile]);
            }
        var DocInfo = app.activeDocument.info;
        var docRef = app.activeDocument
       EV[nfile] = CalcEV (DocInfo, BaseISO);
        app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
        }

(FYI, I use the jpeg file if it's there because Photoshop reads the exif from that file more quickly than it does from the raw file)

Here's how it's working in Bridge scripting:

firstfile = '7A7A5842.CR2';

lastfile = '7A7A5843.CR2';

var ExifProperty = 'exif:DateTimeOriginal';

var ExifNamespace = 'http://ns.adobe.com/exif/1.0/';

app.document.deselectAll();

app.document.selectAll();

var myThumbs = app.document.getSelection("cr2");

var fstart = -999;

var fend = -999;

for (var n = 0; n < myThumbs.length; n++){

    if (myThumbs.name == firstfile) fstart = n;

    if (myThumbs.name == lastfile) fend = n;

}

var NumFiles = myThumbs.length;

var fileThumbs = myThumbs.slice(fstart,fend);

flen = fend-fstart+1;

var EVarray = new Array(flen);

for (var n = 0; n < fileThumbs.length; n++){

    var md = fileThumbs.metadata;

    ISO = md.read(ExifNamespace,'exif:ISOSpeedRatings');

    SS_string = md.read(ExifNamespace,'exif:ExposureTime');

    var test = SS_string.split("/");

    ShutterSpeed = test[0]/test[1];

    var Aperture_string = md.read(ExifNamespace,'exif:FNumber');

    if (Aperture_string == '') {

        var Aperture = Number(1.4); // assume Samyang set at f1.4

    }

    else {

        var test = Aperture_string.split("/");

        Aperture = test[0]/test[1];

    }

    var ISOadjust = Number(1.);

    EVarray = Math.log(Math.pow(Aperture,2)/(ShutterSpeed*ISOadjust))/Math.LN2;

    $.writeln('ISO ',ISO,' SS ',SS,' Av ',Aperture, ' EV=',EVarray);

}

app.document.deselectAll();

"Done...";

TOPICS
Actions and scripting

Views

2.2K

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

correct answers 1 Correct answer

Enthusiast , Mar 30, 2015 Mar 30, 2015

This example works for me with CS6 (don't have CC)

Create a "test" folder off the desktop and place a few cr2 files in the folder and try the following script.

#target photoshop;

main();

function main(){

var bt = new BridgeTalk();

bt.target = "bridge";

bt.body = "var ftn = " + getInfoFromBridge.toSource() + "; ftn();";

bt.onResult = function( info ) { processInfo(eval( info.body ));}

bt.send(10);

};

function processInfo(info){

//do whatever to data

alert(info.join('\n'));

};

function getInfoFro

...

Votes

Translate

Translate
Adobe
Explorer ,
Mar 29, 2015 Mar 29, 2015

Copy link to clipboard

Copied

Looks like I'm running up against a problem with BridgeTalk between Photoshop and Bridge.  Bridge is not returning messages for Bridgetalk.OnResult to evaluate.  I can use the supplied SndSendArray.jsx script and see that it works, but I cannot do it backwards.

Votes

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 ,
Mar 30, 2015 Mar 30, 2015

Copy link to clipboard

Copied

This example works for me with CS6 (don't have CC)

Create a "test" folder off the desktop and place a few cr2 files in the folder and try the following script.

#target photoshop;

main();

function main(){

var bt = new BridgeTalk();

bt.target = "bridge";

bt.body = "var ftn = " + getInfoFromBridge.toSource() + "; ftn();";

bt.onResult = function( info ) { processInfo(eval( info.body ));}

bt.send(10);

};

function processInfo(info){

//do whatever to data

alert(info.join('\n'));

};

function getInfoFromBridge(){

var Info = [];

app.document.thumbnail = Folder("~/desktop/test");

app.document.deselectAll();

var thumbs = app.document.getSelection("cr2");

for(var a in thumbs){

var t = new Thumbnail(thumbs);   

var md = t.synchronousMetadata;

Info.push([[thumbs.name],[md.read( "http://ns.adobe.com/exif/1.0/","exif:FNumber")]]);

}

return Info.toSource();

};

Votes

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
Explorer ,
Mar 30, 2015 Mar 30, 2015

Copy link to clipboard

Copied

That looks promising.  I'll give it a shot when I'm back at my home desktop this evening.

There's a lot about Javascript I don't know.  Certainly, it might be better to ask questions here much earlier in the process rather than spending most of the weekend frustrated .  Thanks for your help!  I'll let you know how it works.

Votes

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
Explorer ,
Mar 30, 2015 Mar 30, 2015

Copy link to clipboard

Copied

Philip,

The script worked mostly as intended.  On the first try, the alert box is empty, but on the second try, it worked.  It seems Bridge needs to be on the folder at the beginning of the script.  If it has to change folders to display /desktop/test in the content pane, it doesn't get the exif info back to Photoshop.  I'm thinking there has to be another function, maybe a call back function, to get Bridge to the right place before getting the info.

I'll have to look into the Info data type (?) and the "push" and "join" methods, which I have not tried before. For some reason, the values returned from functions I've used did not get back to Photoshop, but there's a lot about the scripting that I don't understand.

Thanks for your help!

[edit] I now realize Info is an Array object that has "push" and "join" methods.  Still not sure what I was doing wrong before, but maybe it simply not putting a "return" statement at the end of the function.

-Bob

Votes

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
Explorer ,
Mar 30, 2015 Mar 30, 2015

Copy link to clipboard

Copied

I was doing the following wrong:

1) not making sure the returned object was a string

2) not being aware of the timeout value in bt.send(timeout_value)

3) using $.writeln commands in the bt.body.  They seem to hang the execution of the function to be evaluated.

Now, I'm wondering if there's any way to get the result of the execution of the script back into the main() function.  For now, there seems to be no way of extracting it from the bt.onResult function unless you write it out to a file.

-Bob

Votes

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 ,
Mar 31, 2015 Mar 31, 2015

Copy link to clipboard

Copied

Hi Bob, if Bridge was closed then no info would be returned, so make sure Bridge is running.

Here is the script with slight modifications showing how to process the data in the main function.

#target photoshop;

main();

function main(){

var bt = new BridgeTalk();

cameraRawData = new Object();

bt.target = "bridge";

bt.body = "var ftn = " + getInfoFromBridge.toSource() + "; ftn();";

bt.onResult = function( returnedData ) {  cameraRawData = eval( returnedData.body );}

bt.onError = function( sumatWentWrong ) {  alert(sumatWentWrong.body);}

bt.send(10);

//If you get here all should be well and you can process the data

for(var a = 0; a< cameraRawData.Name.length; a++){

$.writeln(cameraRawData.Name + " - " + cameraRawData.FNumber);

}

};

function getInfoFromBridge(){

/* all comments in this function must be in this format ! */

Info = {}; /* new Object, can be written as var Info = new Object(); */

/* create new arrays within the object */

Info.Name = new Array();

Info.FNumber = new Array();

/* change folder to */

app.document.thumbnail = Folder("~/desktop/test");

app.document.deselectAll();

/*get  a list of all cr2 documents */

var thumbs = app.document.getSelection("cr2");

for(var a in thumbs){

var t = new Thumbnail(thumbs);   

var md = t.synchronousMetadata;

/*populate the arrays */

Info.Name.push(thumbs.name);

Info.FNumber.push(md.read( "http://ns.adobe.com/exif/1.0/","exif:FNumber"));

}

return Info.toSource();

};

Votes

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
Explorer ,
Apr 01, 2015 Apr 01, 2015

Copy link to clipboard

Copied

Thanks!  I'll give that a try.

Votes

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
Explorer ,
Apr 10, 2015 Apr 10, 2015

Copy link to clipboard

Copied

This definitely works and I've used that style of code.

For some reason, Bridge doesn't always want to deliver the information.  However, I can get around that by having my script try again until it successfully retrieves the information.  That seems to work.

Votes

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 10, 2015 Apr 10, 2015

Copy link to clipboard

Copied

You could try increasing the timeout in the bt.send() to see if it improves things Bob, glad you have it working now!

Votes

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
Explorer ,
Apr 10, 2015 Apr 10, 2015

Copy link to clipboard

Copied

I tried increasing the timeout, but for some reason, Bridge gets in a "Not Responding" mode, so I have to let it timeout, wait a couple seconds, then try again.  When it decides to deliver the information, it's very fast.

Votes

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
Advisor ,
Apr 10, 2015 Apr 10, 2015

Copy link to clipboard

Copied

I wrote a js file that handles a lot of variant ways of dealing with metadata:

http://ps-scripts.cvs.sourceforge.net/viewvc/ps-scripts/xtools/xlib/metadata.js

You can pass the Metadata constructor a Document, File, (XML) String, or XMPMeta and retrieve metadata fairly easily.

It also has an strf method so you can do stuff like:

  var doc = app.activeDocument;

  var md = new Metadata(doc);

  var str3 = "%X{xap:CreateDate} %I{Author} %X{dc:format}";

  alert(md.strf(str3));

The strf function requires a couple of strf functions from stdlib.js, and I should probably document the interesting stuff, but everything is there.

There is not Bridge support because using File is probably as fast or faster and doesn't need to have Bridge running.

But I may add Bridge support just because it might be an interesting exercise.

Votes

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
Explorer ,
Apr 12, 2015 Apr 12, 2015

Copy link to clipboard

Copied

Thanks!  I will give that a try and see if it works better than Bridge (Bridge often is slow to respond-- it could be something I'm doing in my script, but Bridge tends to be slow).

Votes

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
Advisor ,
Apr 15, 2015 Apr 15, 2015

Copy link to clipboard

Copied

One quick note: If you want metadata.js to work with Files, you need to first //@include this file:

http://ps-scripts.cvs.sourceforge.net/viewvc/ps-scripts/xtools/xlib/XMPTools.jsx

If handles all of the code that interfaces with XMPScript.

-X

Votes

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
Explorer ,
Aug 09, 2015 Aug 09, 2015

Copy link to clipboard

Copied

LATEST

I upgraded my O.S. hard drive to a solid state drive, and I also upgraded to Windows 8 (and again to Windows 10 last week).  Bridge seems to pass the information much better now.

Votes

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