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

Setting metadata in Bridge

New Here ,
Jun 29, 2005 Jun 29, 2005
Can someone give some advice on setting metadata values within Bridge using javascript? The examples all seem to deal with Text types like the following:

md = tn.metadata;
md.namespace = "http://ns.adobe.com/photoshop/1.0/";
md.Author = "Jane Smith";

But when trying to set other types, like the "caption" (which gets mapped to "http://purl.org/dc/elements/1.1/description"), the script will throw an exception.

md.namespace = "http://purl.org/dc/elements/1.1/";
md.description = "New Caption"
-- Uncaught exception description --

I'm thinking this is probably because dc:description is defined as a "Lang Alt" type in the xmp specification which in turn is defined as:

"Language alternatives are a form of rdf:Alt array, referred to as the Lang Alt type. In this
example, each array item is a simple text value; the value has a property qualifier, specified as
the property xml:lang, giving the language of that value. "

But no matter how I try accessing this object (there is no "reflect" available on metadata objects), I can't seem to change the string value.

Any ideas would be much appreciated.

-----

On another topic, would it be possible for someone to post the Export Metadata Script here in this forum for those of us who don't have access to the partners site? Here's is my working go at an export metadata script for Bridge that simply prints to the debugger. It's basically a quick hack of some of the routines in AdobeLibrary3.jsx which it also needs in order to run.

Thanks,

Bruce

#target bridge



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



DebugMeta = {};

DebugMeta.execute = function() {



// print out the metadata for the selected thumbnails

var sels = app.document.selections;

for (var i = 0; i < sels.length; i++) {

var t = sels;

var m = t.synchronousMetadata;

// loop through all possible elements (properties)

var elements = MdNs.elements.keyList;

for (var j = 0; j < elements.length; j++) {

var el = MdNs.elements.get(elements);

if (el.scriptAccessible) {

try {

// print the value (and the mapping if it's redirected)

var val = el.getValue(m);

if ( isValidReference( val )

&& ( val.length > 0 )

&& ( trim( val ) != null ) ) {



$.write(el.handle + " = " + val);

if (el.redirected) {

$.writeln(" (" + el.redirectElement.ns.ns + el.redirectElement.property + ")");

} else {

$.writeln();

}

}

} catch (e) {

}

}

}

}

}



// setup menu

var myMenu = createMenu( "command", "DebugMeta",

"-at the end of Tools-", "tools/DebugMeta", DebugMeta.execute);

var contextMenu = createMenu ( "command", "DebugMeta",

"-at the end of Thumbnail-", "thumbnail/DebugMeta", DebugMeta.execute);



}
TOPICS
Scripting
1.5K
Translate
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
Community Beginner ,
Jun 29, 2005 Jun 29, 2005
Test Reply
Translate
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
Community Beginner ,
Jun 29, 2005 Jun 29, 2005
OK, I posted a response that errored, and now I get to write it again!

grrrrr...

Anyway,

It's not kosher to post an ASN script directly to this site. But it is OK to take an ASN script, modify it to be your own, and post it. All of the ASN scripts are intended as developer examples, you are free to modify them and use them in your own scripts.

Your instincts are correct. The metadata object can only write to simple XMP types.

I see you found the MdNs object in AdobeLibrary3, that certainly makes that script easier to write, eh?

If you look at the MdNs object, specifically the area that creates new elements, you'll see comments at the end of the lines like this:

new MdNs.MdElement( "EXIF", "SubjectLocation", true ); // false );

That "// false" means that the metadata object can not write to this element. All of the elements that can not be written have the // false comment at the end of their lines. I had intended to implement a warning mechanism, but ran out of time.

Enough of what you can't do. Here's what you CAN do:

You can create an XMP template (using JS), save it to the templates file location, and then apply it using the metadata object.

metadata.applyMetadataTemplate( templateFileName, mode );

mode is "append" or "replace"- you'll want to use "append"

The XML templates are in:

(Windows)
c:\documents and settings\[user]\application data\adobe\xmp\metadata templates
(Mac)
{user area]/application support/adobe/xmp/metadata templates

You can look at a template to see how to write them.

Also, there's a scripting project being managed by Thomas White. It's on Yahoo groups at:

http://groups.yahoo.com/group/xmp-blaster/

It's an XMP template maker that makes it relatively easy to create templates contain no "extra" data (like when you try to make one from an existing file).

That code will have some pretty good examples for you. It also uses a new implementation of XmlNode (in AdobeLibrary1.jsx) that we extended to include namespace support. You can use that beastie to write your XML. Note that the libraries have not been updated to this version of XmlNode.

Bob
Adobe Workflow Scripting
Translate
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
Community Expert ,
Jun 29, 2005 Jun 29, 2005
Funny how many people are looking at exporting metadata. My script may save you some time - you can easily extend it by adding other namespaces/fields.

Bob, why are those scripts on ASN rather than in the Exchange?

John
Translate
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
Community Beginner ,
Jun 29, 2005 Jun 29, 2005
Metadata is a big thing, as we found out. That's one of the big reasons synchronousMetadata made it into the scripting environment in this release.

As far as the ASN thing goes, that gets out of my area of expertise. I do know that we can not post them to Exchange.
Translate
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 ,
Jun 29, 2005 Jun 29, 2005
Thanks for the hints and tips, Robert. Very useful. I've been exploring the xmp angle with Photoshop and Bridge for about a week now. There is just SO much potential there but it still feels a bit rough: no full xmp access from Photoshop, Bridge having problems with non-Text types, people complaining about the XMP sdk not writing to psd files correctly, etc. (I haven't gone through the Photoshop SDK yet to see if that will do what I need). The grand solution is really to find some way to let Photoshop/Bridge manage the metadata since these beasts will always be able to handle any image type you throw at them (versus the unix solutions like imagemagick/xmp sdk/etc. which might end up breaking certain files).

I was really hoping I would be able to finally get away from proprietary Media Managers (which our photographers hate and in their rebelliousness, never seem to use properly), "reunite" our thousands of images with their metadata that is currently being stored in external databases, get back to working with metadata in unix, letting it be indexed on the desktop by things like Apple's spotlight (i.e. freedom from filename-based metadata), creating new images and clicking a button to have it automatically fill in the metadata from a database hosted on a server, etc. etc. I dream of this day coming. Bridge is such a blessing for the photographer who hates to "manage" his own images 🙂 Bridge they seem to be able to handle. They really like Bridge.

Since I'm dealing with a museum of over 200,000 objects, when a new image is taken of an object, it's a real pain to have to pull all the fields for that object by hand and then edit them for that particular view/image. At the best, I can expect to maybe get a filename that hopefully has a correct index number for the object that was shot. Anything beyond that is asking for *a lot*. It would be so elegant to do this with a script. XMP and Bridge/Photoshop scripting is like the holy grail I've been waiting for. I so appreciate all the work you have been doing in this direction. I think it will all be worth it in the end. Keep at it (for the sake of all of us poor saps who have to clean up the mess photographers make).

regards,

Bruce
Translate
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 ,
Jun 30, 2005 Jun 30, 2005
I saw your script, John. It's nice that people are starting to share things here. Thanks for that.

That's the direction I'm going as well. It would nice, though, to be able to "walk" the metadata tree namespace (from within a script). It's kind of weird having to know what you are looking for before you can go off and find it or change it. I'd like to be able to go "Show me all the xmp data in this file" without having to drop out to something like the packetscanner in the xmp sdk or without having to keep around big lists of all possible elements.

The metadata object is a bit weird isn't it? I guess they want to keep the namespace clean for the metadata properties (i.e. how can you do md.reflect if you want to have a property called "reflect" -- the only reserved name seems to be md.namespace which means you can't have a property called "namespace"). Something doesn't feel quite right in how this object is designed. Why not just stick all the properties/namespaces, etc. inside an array/hash/structure then tie it under something like md.elements? It feels like it one more level of abstration could really benefit the object. Just my 2c.

Bruce
Translate
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
Community Beginner ,
Jun 30, 2005 Jun 30, 2005
Bruce,

I think most people here agree with your 2c, but there just wasn't time to do everything.

But one of the great things about Bridge Scripting is, if you don't like it, change it, or create something that will do what you need. If you don't like the way collections work, create your own browse scheme, and do it your way.

The MdNs object has a definition for an object, MdManager. The MdManager constructor takes a thumbnail object. It's "grab" method creates 2 enumerations. MdManager.enumeration contains a KeyedArrayList (object defined in lib3 just above MdNs) of all the metadata elements that actually have values. MdManager.noValue is a KeyedArrayList of metadata elements that do not have values. Now, the standard MdManager only provides checks against the standard XMP schemas. But if you want to extend that, just add a MdNs.MetadataNamespace and the MdNs.MdElement 's necessary to define the non-standard data you want to enumerate.

So while you can't use the metadata object to traverse the metadata structure, there are always other ways.

The concept of modifying the scripting features of Bridge didn't stop there. In Lib1, we extended the File object prototype in Bridge:

File.isFileType() - give it a comma delimited list of extensions, returns true if file matches any of the extensions

File.isPhotoshop() is the file one of "PSD,PDD,8BPS,JPEG,JPG,GIF,"

File.isPageMaker()

File.isInDesign()

File.isPDF()

File.isIllustrator()

File.isOpenableIllustrator()

File.isOpenablePhotoshop()

File.isScript()

File.getExtension( noDecode ) - gets you the extension of the file - noDecode is a boolean - if true it will not perform a decodeURI on the result. Default is false

File.getNameWithoutExtension( noDecode ) - gets you the name of the file without the extension. noDecode is a boolean - if true it will not perform a decodeURI on the result. Default is false

File.getFileWithExtension( ext ) - creates a new File object with the original file name and the provided extension. You provide only the extension ( "jpg" ), the function adds the dot (".jpg").

We also extended the Thumbnail object prototype:

Thumbnail.isFileType( ext ) - same as File.isFileType but for Thumbnails.

Then there's handy functions like:

ensureUniqueFile( file ) - pass it a file object. If the file object exists, it will return a new File object with a "(integer)" added to the filename. So if My Documents/foo.jpg exists, and you called:

ensureUniqueFile( new File( "~/My Documents/foo.jpg ) );

the result would be a file object: My Documents/foo(1).jpg

These next two are defined in lib3:

ensureUniqueFolder( folder ) - does the same thing for a folder

And one of my personal favorites:

verifyFolder( folder, silent ) - if you give it a Folder, it will verify that the folder actually exists, creating the entire path to the folder if necessary. "silent" is a boolean. If true - it will just make the folder (and path to the folder). If false (the default) it will flip up a "Folder does not exist - Do you want to create it" alert to the user, to give them the choice. IF the user opts not to create the folder, it returns undefined.

If My Documents is empty (no files/folders), and you want to write a file into My Documents/1/2/3/My Folder/foo.txt

var f = new File( "~/My Documents/1/2/3/My Folder/foo.txt" );
var folder = verifyFolder( f.parent, true );
f.open( "w" );
f.write( "Four score and seven years ago..." );
f.close();

The result of that ditty will be the successful writing of the file, and the creation of the entire path to the file. It will only create the path elements that do not exist.

Bob
Adobe Workflow Scripting
Translate
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 ,
Jun 26, 2006 Jun 26, 2006
I am following-up on Bruce Hartzler's original question, specifically, how do you set the value of the description metadata field.

Typically, you would be able to do something like:

md.namespace = "http://purl.org/dc/elements/1.1/";
md.description = "New Caption"

But, in the case of description, the script fails (without a catchable exception being thrown).
Does anyone know the proper way to set the description field so that the caption beneath the image will be updated. Thank you very much for your help.

Evan Appleby
Sony Pictures Imageworks
Translate
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 Employee ,
Jun 27, 2006 Jun 27, 2006
LATEST
There are aliases to a number of the lang alt type Dublin Core properties in the Photoshop namespace. These aliases are registered by the XMP Toolkit used by Bridge 1.0. Setting an array property through the alias sets the first member of the array.

Below is an example of setting these properties through their Photoshop namespace aliases.

-David

if( (app.name == "bridge") ) {

var testName = "QuickTestWritePhotoshopAliasProperties";

var doQuickTest = function( thumbnailsToTest ) {
for( var t = 0; t < thumbnailsToTest.length; ++t ) { var testThumb = thumbnailsToTest;

var md = testThumb.synchronousMetadata;

md.namespace = "http://ns.adobe.com/photoshop/1.0/";
md.Author = "Author is an alias of dc:creator"; // ordered array
md.Caption = "Caption is an alias of dc:description"; // lang alt
md.Copyright = "Copyright is an alias of xmpRights:Copyright"; // lang alt
md.Marked = "True"; // alias to xmpRights:Marked
md.Title = "Title is an alias of dc:title"; // lang alt
md.WebStatement = "WebStatement is an alias of xmpRights:WebStatement"; //simple prop

}
}

var quickTestMenuItem = MenuElement.create( "command", testName, "-at end of Tools", testName );

quickTestMenuItem.onSelect = function() {
var selectedThumbs = app.document.selections;
doQuickTest(selectedThumbs);
}
}
Translate
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