10 Replies Latest reply on Jun 7, 2016 4:11 AM by Heimdaal

    Per-layer metadata

    Heimdaal Level 1

      I've searching around the web quite a lot regarding this but haven't been able to find any kind of official information about it:

      Does this functionality exists in PS CC, and if so: where can I find code examples?

        • 1. Re: Per-layer metadata
          SuperMerlin Level 5

          Here is a script written by Paul Riggott, "Per Layer Guides"

           

          #target photoshop
          //Written by Paul Riggott
          main();
          function main(){
          if(Number(app.version.match(/\d+/)) <12) return;
          if(!documents.length) return;
          var doc =activeDocument;
          if(doc.activeLayer.isBackgroundLayer) return;
          if(doc.activeLayer.kind != LayerKind.NORMAL) return;
          if (ExternalObject.AdobeXMPScript == undefined)  ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
          var startRulerUnits = app.preferences.rulerUnits;
          app.preferences.rulerUnits = Units.PIXELS;
          if(ScriptUI.environment.keyboardState.shiftKey ){
              setGuides();
              }else{
                  displayGuides();
                  }
          app.preferences.rulerUnits = startRulerUnits;
          
          function setGuides(){
          try{
              xmp = doc.activeLayer.xmpMetadata.rawData;
              xmpObject = new XMPMeta(xmp);
          } catch(e){
              xmpObject = new XMPMeta();
          }
          var psNamespace = "http://ns.layerguides/1.0/";
          var psPrefix = "pmrGuides:";
          XMPMeta.registerNamespace(psNamespace, psPrefix);
          var guides = app.activeDocument.guides;
          if(guides.length == 0){
              alert("No guides exist");
              return;
              }
          var gH = '';
          var gV = '';
          for( var g = 0; g < guides.length; g++ ){
              if(guides[g].direction.toString() == 'Direction.HORIZONTAL'){
                  gH+=(parseInt(guides[g].coordinate.value));
                  gH+=',';
                  }else{
                      gV+=(parseInt(guides[g].coordinate.value));
                      gV+=','
                      }
          }
          gH=gH.replace(/,$/,'');
          gV=gV.replace(/,$/,'');
          currentGuides = 'Layer Guides' + "¬" + gH + "¬" + gV;
          xmpObject.deleteProperty(psNamespace, "LayerGuides");
          xmpObject.setProperty(psNamespace, "LayerGuides",currentGuides);
          app.activeDocument.activeLayer.xmpMetadata.rawData = xmpObject.serialize();
          }
          function displayGuides(){
          try{
              xmp = doc.activeLayer.xmpMetadata.rawData;
              xmpObject = new XMPMeta(xmp);
          } catch(e){
              return;
          }
          var psNamespace = "http://ns.layerguides/1.0/";
          var psPrefix = "pmrGuides:";
          var layerGuides = xmpObject.getProperty(psNamespace, "LayerGuides");
          clearGuides();
          var ar1 = layerGuides.toString().split('¬');
          var Hor = ar1[1].toString().split(',');
          var Ver = ar1[2].toString().split(',');
          for(var H in Hor){
              activeDocument.guides.add(Direction.HORIZONTAL,new UnitValue(Number(Hor[H]),'px'));
              }
          for(var V in Ver){
              activeDocument.guides.add(Direction.VERTICAL,new UnitValue(Number(Ver[V]),'px'));
              }
          }
          }
          function clearGuides() { 
             var id556 = charIDToTypeID( "Dlt " ); 
                 var desc102 = new ActionDescriptor(); 
                 var id557 = charIDToTypeID( "null" ); 
                     var ref70 = new ActionReference(); 
                     var id558 = charIDToTypeID( "Gd  " ); 
                     var id559 = charIDToTypeID( "Ordn" ); 
                     var id560 = charIDToTypeID( "Al  " ); 
                     ref70.putEnumerated( id558, id559, id560 ); 
                 desc102.putReference( id557, ref70 ); 
             executeAction( id556, desc102, DialogModes.NO ); 
          };
          
          
          1 person found this helpful
          • 2. Re: Per-layer metadata
            lamenace Level 1

            const ns= 'http://www.smartobjectlinks.com/1.0/';

            var __xmp = new XMPMeta( activeDocument.activeLayer.xmpMetadata.rawData );

            __xmp.setProperty( __ns, "layerName", activeDocument.activeLayer.name );

            1 person found this helpful
            • 3. Re: Per-layer metadata
              Heimdaal Level 1

              Thank you both.

              I found the xmpMetadata function in the docs now and this is starting to make sense to me.

              However, I find no information in the docs about the XMPMeta -class and it's functions. I see that setProperty, getProperty, deleteProperty are serialize are some of these, but where can I find more info on this class?

              • 4. Re: Per-layer metadata
                SuperMerlin Level 5

                You will find the info in "The Javascript Tools Guide" that can be accesed from the help menu in Extendscript Toolkit

                • 6. Re: Per-layer metadata
                  Heimdaal Level 1

                  For some reason, the jsx-script comes to a halt because it catches an exception:

                  1. try
                  2.     xmp = doc.activeLayer.xmpMetadata.rawData; 
                  3.     xmpObject = new XMPMeta(xmp); 
                  4. } catch(e){ 
                  5.     xmpObject = new XMPMeta(); 
                  6. }

                  No XMP object is created. Why?

                  • 7. Re: Per-layer metadata
                    SuperMerlin Level 5
                    if (ExternalObject.AdobeXMPScript == undefined)  ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
                        try{ 
                            xmp = activeDocument.activeLayer.xmpMetadata.rawData; 
                            xmpObject = new XMPMeta(xmp); 
                        } catch(e){ 
                            xmpObject = new XMPMeta(); 
                        }
                    
                    
                    • 8. Re: Per-layer metadata
                      Heimdaal Level 1

                      JS

                      /*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
                      /*global $, window, location, CSInterface, SystemPath, themeManager*/
                      
                      (function(){
                          'use strict';
                          var csInterface = new CSInterface();
                      
                          function init(){
                              themeManager.init();
                              
                              $("#readButton").click(function(){
                                  var property = document.getElementById("dataField"); 
                                  //csInterface.evalScript("getMetadata('" + property + "')");
                      
                                  csInterface.evalScript("getMetadata('" + property + "')", function(result){
                                      document.getElementById("dataField").innerHTML = result; 
                                  });
                              });
                      
                              $("#writeButton").click(function(){
                                  var propertyValue = document.getElementById("dataField").value;
                                  csInterface.evalScript("setMetadata('dataField', '" + propertyValue + "')");
                              });
                      
                          }
                          init();
                      }());
                      

                       

                      JSX

                      /*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
                      /*global $, Folder*/
                      
                      function getMetadata(property){
                      
                          // Create XMP object
                          if (ExternalObject.AdobeXMPScript == undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
                          try{
                              xmp = activeDocument.activeLayer.xmpMetadata.rawData;
                              xmpObject = new XMPMeta(xmp);
                          }catch(e){
                              alert("Failed to create XMP Object!");
                              return;
                          }
                      
                          // Retrieve metadata from active layer and return it
                          var myNamespace = "myNS";
                          var metadata = xmpObject.getProperty(myNamespace, property);
                          // alert("propert read! it is " + metadata); // Just for testing
                          return(metadata);
                      }
                      
                      function setMetadata(property, propertyValue){
                          
                          // Create XMP object
                          if (ExternalObject.AdobeXMPScript == undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
                          try{
                              xmp = activeDocument.activeLayer.xmpMetadata.rawData;
                              xmpObject = new XMPMeta(xmp);
                          }catch(e){
                              // alert("Failed to create XMP Object!");
                              xmpObject = new XMPMeta();
                          }
                          // Register and update metadata
                          var myNamespace = "myNS";
                          var myPrefix = "myPrefix_";
                          XMPMeta.registerNamespace(myNamespace, myPrefix);
                          xmpObject.deleteProperty(myNamespace, property);
                          xmpObject.setProperty(myNamespace, property, propertyValue);
                          activeDocument.activeLayer.xmpMetadata.rawData = xmpObject.serialize();
                          alert("property set!");
                      }
                      


                      Seems like I can write but not read.
                      getMetadata() appears to fail at var metadata = xmpObject.getProperty(myNamespace, property);
                      ...as I can print (alert) on the row above.

                      • 9. Re: Per-layer metadata
                        SuperMerlin Level 5

                        Your jsx functions work fine and return the correct property.

                        I don't have CC so can't test the CSInterface

                        • 10. Re: Per-layer metadata
                          Heimdaal Level 1

                          Yea I was wrong. With the following JS-code it works:

                                  $("#readButton").click(function(){
                                      csInterface.evalScript("getMetadata('dataField')", function(result){
                                          document.getElementById("dataField").value = result;
                                      });
                                  });
                          
                          
                                  $("#writeButton").click(function(){
                                      var propertyValue = document.getElementById("dataField").value;
                                      csInterface.evalScript("setMetadata('dataField', '" + propertyValue + "')");
                                  });