Table of Contents

Introduction
Who Should Read This?
How Does It Work?
Download(s)
System and Software Requirements
Adobe Photoshop Reserved Words

Tutorials
Overview
  1. Starting a Flex Project
  2. Hello World Panel
  3. Placing the CSXS Library

  4. Shortcut Buttons Panel
    1. JavaScript
    2. Design the Panel
    3. ActionScript
    4. Photoshop Persistent
    5. CSXS Logger AIR Debugger (Optional)

  5. Setting Up Script Listener

  6. Color Picker Panel
    1. JavaScript
    2. Design the Panel
    3. Find Character ID Code to Register Events
    4. ActionScript
    5. Create Custom Icons

  7. Flickr Search Panel
    1. Design the Panel
    2. Create a Flickr Service
    3. Design a Custom Module
    4. Modify Panel's Properties
    5. Connect on Preferences

  8. Per Layer Metadata Panel
    1. View Metadata
    2. JavaScript
    3. Find Character ID Code to Register Events
    4. Designing the Panel
    5. ActionScript
    6. Using Photomerge
Other Samples
Best Practices
Frequently Asked Questions
Acronyms and Definitions
Links
Adobe® Photoshop® Panel Developer's Guide

Per Layer Metadata Panel: JavaScript

The second part of the Per Layer Metadata Panel is creating a JavaScript file. The JavaScript file will have functions to load and unload the XMP Script Library to access the XMP metadata, retrieve the metadata of the active layer, set the metadata of the description and comments of the active layer, and export the metadata of the active layer. The JavaScript file will have utility functions to retrieve the date and time when the active layer was last changed, and create an XML object of the property and value to be sent to the SWF file. The JavaScript file will be created using ExtendScript Toolkit. The result is to place the JavaScript file into the Adobe Photoshop Panels folder for the SWF file to communicate with.

Go to Per Layer Metadata Panel's JavaScript API that covers a summary of functions and scripts used.

Instructions:

  1. Open ExtendScript Toolkit.
  2. Go to File > New JavaScript.
  3. Copy the following JavaScript code into the new file:
  4. 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;
    }
    
    function unloadXMPLibrary(){ if( ExternalObject.AdobeXMPScript ) { try{ ExternalObject.AdobeXMPScript.unload(); ExternalObject.AdobeXMPScript = undefined; }catch (e){ alert("Can't unload XMP Script Library"); } } }

    Code Walkthrough: The two functions, loadXMPLibrary and unloadXMPLibrary, are used respectively to load and unload the XMP Script Library to write and modify metadata. The function unloadXMPLibrary is used to free up the memory when the XMP Script Library is loaded.

  5. Copy the following JavaScript code to retrieve the metadata into the file:
  6. 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;
    }
    

    Code Walkthrough: The function getLayerMetadata retrieves the metadata from the active layer selected in Adobe Photoshop. The function first makes sure that it's not a background layer and that XMP Script Library is loaded for accessing metadata. The background layer, by default, does not have metadata. The function first retrieves the layer name and the date and time the layer was last changed from the function getLayerChangeDate. The function then checks if the metadata can be successfully retrieved from the metadata. If retrieving the metadata was successful, the function retrieves the description field from the Dublin Core metadata schema represented by XMPConst.NS_DC and the comments field from the EXIF metadata schema represented by XMPConst.EXIF. For more information on other metadata schema and its corresponding fields, please refer to Adobe Developer's Center: Extensible Metadata Platform (XMP) including the XMPScript API Reference.

  7. Copy the following JavaScript code to place the metadata into the file:
  8. 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();
    }
    
    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(); }

    Code Walkthrough: The function setDescMetadata takes the user's input metadata in the description field and apply to the description field from the Dublin Core metadata schema represented by XMPConst.NS_DC. The function setCommMetadata takes the user's input metadata in the comments field and apply to the userComment field from the EXIF metadata schema represented by XMPConst.EXIF. For more information on other metadata schema and its corresponding fields, please refer to Adobe Developer's Center: Extensible Metadata Platform (XMP) including the XMPScript API Reference.

  9. Copy the following JavaScript code to place the metadata into the file:
  10. 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();
    }
    
    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(); } }
    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; }

    Code Walkthrough: The function exportLayerMetadata prompts the user for the location to save the metadata and then write to that location. The function getLayerChangedDate retrieves the date and time in which the active layer was last changed and converts to the locale time. The function convertToXML takes a property and a unique identifier to return as an XML object understood by the Per Layer Metadata Panel.

  11. Go to File > Save As....
    1. Under Save As:, type in PerLayerMetadata.jsx.
    2. Save the file into the Panels folder under the Adobe Photoshop CS5\Plug-ins\ folder located under:
      • Applications for Macintosh
      • Program Files for Windows
    3. Press Save.
  12. Close ExtendScript Toolkit.
Continue to Find Character ID Code to Register Events