PerLayerMetadata.jsx

Summary

The script contains a functions to retrieve the metadata of a selected layer. The script also contains two functions to set the description metadata and the user comments metadata of a selected layer. There are also four utility functions that retrieves and calculates the last time a layer was modified, load and unload the XMP Script Library, and converting a property with an identifier to XML for the SWF file and the CSXS Library to parse and use properly. This script is to be used by a SWF file called PerLayerMetadata.swf created though Adobe Flex.

Author: John Huan Vu, Photoshop Engineering Intern, Adobe Systems Incorporated , Pete Falco, Photoshop Lead Computer Scientist, Adobe Systems Incorporated , Allen Jeng, Photoshop Software Quality Engineering Developer, Adobe Systems Incorporated


Method Summary
static void exportLayerMetadata()
           The function exports the raw metadata from the selected layer into the specified path by the user.
static String getLayerChangedDate()
           The function finds the date and time in which the selected layer has been last modified.
static String getLayerMetadata()
           Retrieve information on the layer includes its name, when it was last modified, the description from the Dublin Core metadata schema, and any of the user's comments from the EXIF metadata schema.
static Boolean loadXMPLibrary()
           The function loads the XMP Script Library.
static void setCommMetadata(<String> comm)
           The function takes in the user comments input field from the user and place in the EXIF's description metadata field of the image.
static void setDescMetadata(<String> desc)
           The function takes in the description input field from the user and places in the Dublin Core's description metadata field of the image.
static void unloadXMPLibrary()
           The function unloads the XMP Script Library.

/**************************************************************************
	ADOBE SYSTEMS INCORPORATED
	 Copyright 2008 Adobe Systems Incorporated
	 All Rights Reserved.

	NOTICE:  Adobe permits you to use, modify, and distribute this file
	in accordance with the terms of the Adobe license agreement accompanying
	it.  If you have received this file from a source other than Adobe, then
	your use, modification, or distribution of it requires the prior written
	permission of Adobe.
**************************************************************************/

/**  Name:			PerLayerMetdata.jsx
	@author John Huan Vu, Photoshop Engineering Intern, Adobe Systems Incorporated
	@author Pete Falco, Photoshop Lead Computer Scientist, Adobe Systems Incorporated
	@author Allen Jeng, Photoshop Software Quality Engineering Developer, Adobe Systems Incorporated
	@fileoverview The script contains a functions to retrieve the metadata
			of a selected layer. The script also contains two
			functions to set the description metadata and the user
			comments metadata of a selected layer.
			There are also four utility functions that retrieves
			and calculates the last time a layer was modified, load
			and unload the XMP Script Library, and converting a
			property with an identifier to XML for the SWF file and the
			CSXS Library to parse and use properly. This script
			is to be used by a SWF file called PerLayerMetadata.swf
			created though Adobe Flex.
*/

/**
	Retrieve information on the layer includes its name,
			when it was last modified, the description from the Dublin
			Core metadata schema, and any of the user's comments from
			the EXIF metadata schema.
	@returns An XML object containing the values for the variables:
			layerName, layerChangeDate, description, and comments of
			the layer that is currently selected.
	@type String
*/
function getLayerMetadata(){	
	var xml = "<object>";
	if( app.activeDocument.activeLayer.isBackgroundLayer || !loadXMPLibrary()){
		xml += convertToXML("", "layerName");
		xml += convertToXML("", "layerChangedDate");
		xml += convertToXML("", "description");
		xml += convertToXML("", "comments");
	} else {
		var xmp;
		try {
			xml += convertToXML(app.activeDocument.activeLayer.name.toString(), "layerName");
		} catch(e) {
			xml += convertToXML("", "layerName");
		}
		
		try {
			xml += convertToXML(getLayerChangedDate().toString(), "layerChangedDate");
		} catch(e) {
			xml += convertToXML("", "layerChangedDate");
		}
		
		try { 
			xmp = new XMPMeta(app.activeDocument.activeLayer.xmpMetadata.rawData);
		} catch(e) {
			xml += convertToXML("", "description");
			xml += convertToXML("", "comments");
			xml += "</object>";
			unloadXMPLibrary();
			return xml;
		}
	
		try {
			xml += convertToXML(
				xmp.getArrayItem(XMPConst.NS_DC, "description", 1).toString(), "description");
		} catch(e) {
			xml += convertToXML("", "description");
		}
	
		try {
			xml += convertToXML(
				xmp.getProperty(XMPConst.NS_EXIF, "userComment").toString(), "comments");
		} catch(e) {
			xml += convertToXML("", "comments");
		}
	}
	xml += "</object>";
	unloadXMPLibrary();
	return xml;
}


/**
	The function takes in the description input field from
			the user and places in the Dublin Core's description metadata
			field of the image.
	@param {String} desc Description metadata the user wrote to be placed
*/
function setDescMetadata(desc){
	if( app.activeDocument.activeLayer.isBackgroundLayer || !loadXMPLibrary()){
		alert("Can't place description metadata on a background layer.\n" +
			"Layer > New > Layer From Background...");
	} else {
		var xmp;
		if (desc == "")
			desc = " ";
			
		try{
			xmp = new XMPMeta(app.activeDocument.activeLayer.xmpMetadata.rawData);
		} catch(e) {
			xmp = new XMPMeta();
		}
	
		try{
			if( xmp.countArrayItems(XMPConst.NS_DC, "description") == 0){
				xmp.appendArrayItem(XMPConst.NS_DC, "description", null,
					XMPConst.PROP_IS_ARRAY, XMPConst.ARRAY_IS_ORDERED);
				xmp.insertArrayItem(XMPConst.NS_DC, "description", 1, desc);
			} else {
				xmp.setArrayItem(XMPConst.NS_DC, "description", 1, desc);
			}
		} catch(e) {
			alert("Unable to place description metadata on selected layer.\n" + e);
		}
		app.activeDocument.activeLayer.xmpMetadata.rawData = xmp.serialize();
	}
	unloadXMPLibrary();
}


/**
	The function takes in the user comments input field from
			the user and place in the EXIF's description metadata
			field of the image.
	@param {String} comm - User comments metadata the user wrote to be placed
*/
function setCommMetadata(comm){
	if( app.activeDocument.activeLayer.isBackgroundLayer || !loadXMPLibrary()){
		alert("Can't place comments metadata on a background layer.\n" +
			"Layer > New > Layer From Background...");
	} else {
		var xmp;
		if (comm == "")
			comm = " ";
			
		try{
			xmp = new XMPMeta(app.activeDocument.activeLayer.xmpMetadata.rawData);
		} catch(e) {
			xmp = new XMPMeta();
		}
		try{
			xmp.setProperty(XMPConst.NS_EXIF, "userComment", comm);
		} catch(e) {
			alert("Unable to place comments metadata on selected layer.\n" + e);
		}
		app.activeDocument.activeLayer.xmpMetadata.rawData = xmp.serialize();
	}
	unloadXMPLibrary();
}


/**
	The function exports the raw metadata from the selected
			layer into the specified path by the user.
*/
function exportLayerMetadata(){
	var path = File.saveDialog();
	var file = new File(path);
	file.encoding = "UTF-8";
	try{
		file.open("w");
		file.write(app.activeDocument.activeLayer.xmpMetadata.rawData.toString());
	} catch(e) {
		alert("Unable to write to file.\n" + e);
	}
	file.close();
}


/**
	The function finds the date and time in which the selected
			layer has been last modified.
	@returns The date and time according to the locale of the computer
	@type String
*/
function getLayerChangedDate(){
	var metadataStrID = stringIDToTypeID("metadata");
	var ref = new ActionReference();
	ref.putProperty(charIDToTypeID('Prpr'), metadataStrID);
	ref.putEnumerated(charIDToTypeID('Lyr '), charIDToTypeID('Ordn'),
													charIDToTypeID('Trgt'));
	var desc = executeActionGet(ref);
	
	if (desc.hasKey(metadataStrID)){
		var descMetadata = desc.getObjectValue( metadataStrID );
		var timeInSeconds = descMetadata.getDouble(stringIDToTypeID("layerTime"));
		var d = new Date();
		d.setTime(timeInSeconds*1000.0);
		return d.toLocaleString();
	}
}


/**
	The function loads the XMP Script Library.
	@returns True if the XMP Script Library was loaded successfully.
	@type Boolean
*/
function loadXMPLibrary(){
	if ( !ExternalObject.AdobeXMPScript ){
		try{
			ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
		}catch (e){
			alert("Can't load XMP Script Library");
			return false;
		}
	}
	return true;
}


/**
	The function unloads the XMP Script Library.
*/
function unloadXMPLibrary(){
	if( ExternalObject.AdobeXMPScript ) {
		try{
			ExternalObject.AdobeXMPScript.unload();
			ExternalObject.AdobeXMPScript = undefined;
		}catch (e){
			alert("Can't unload XMP Script Library");
		}
	}
}


/**
	In order to communicate to the SWF file, it must be written as an XML
		containing the property and identifier. This utility is very helpful for
		a two-way communication between the JSX and SWF.
	@param {String} property The property or value for the identifier
	@param {String} identifier The unique identifier for the property
	@returns An xml containing the property and identifier
	@type String
*/
function convertToXML(property, identifier){
	var type = typeof property;
	var xml = '<property id = "' + identifier + '" >';
	
	switch(type){
		case "number":
			xml += "<number>";
			xml += property.toString();
			xml += "</number>";
			break;
		case "boolean":
			xml += "<" + property.toString() + "/>";
			break;
		case "string":
			xml += "<string>";
			xml += property.toString();
			xml += "</string>";
			break;
		case "object":
			// Object case is currently not supported
			alert("Object case is currently not supported");
			//xml += "<object>";
			//for(var i in property)
			//	xml += convertToXML(property[i], 
			//xml += "</object>";
			break;
		case "undefined":
			xml += "<string>undefined</string>";
			break;
		default:
			alert("Type " + type + " is unknown.");
			return "";
	}
	xml += '</property>';
	return xml;
}


Documentation generated by JSDoc on Wed Sep 3 16:09:11 2008