13 Replies Latest reply on Aug 17, 2010 1:08 AM by Marijan Tompa [tomaxxi]

    [CS3 JS] Possible to Inspect Custom XMP Metadata With JavaScript?

    ekimber
      I am using custom XMP metadata in InCopy and InDesign docs in CS3 to hold custom metadata that can vary wildly. I know the full set of possible items but not what values will be in a particular document.

      Short of writing the XMP to a file and then processing that from my script, is there a way to inspect the custom properties from JavaScript. I didn't see a way to do it from the data model.

      Thanks,

      Eliot
        • 1. Re: [CS3 JS] Possible to Inspect Custom XMP Metadata With JavaScript?
          Level 1
          Hi Eliot,

          Getting custom XMP data is not discoverable by design (I disagree with the design of XMP on this matter, but that's the way it is). But if you know where the data is, it's relatively easy. Take a look at the example script Metadata.jsx that goes with the Scripting Guide--it creates a custom XMP field "email". In short, it looks like this:

          //Create a custom XMP container, "email"
          
          var myString = "http://ns.adobe.com/xap/1.0/";
          var myNewContainer = myDocument.metadataPreferences.createContainerItem(myString, "email");
          myDocument.metadataPreferences.setProperty(myString, "email/*[1]", "someone@adobe.com");
          //Retrieve the value from the XMP container:
          myString = myDocument.metadataPreferences.getProperty("http://ns.adobe.com/xap/1.0/","email/*[1]");


          Thanks,

          Ole
          • 2. Re: [CS3 JS] Possible to Inspect Custom XMP Metadata With JavaScript?
            ekimber Level 1
            Hmm, not discoverable by design. That seems a little odd.

            Unfortunately, I don't know where the data is (or rather, I do know where the data is, I just don't know how much of it there might be).

            I guess that leaves with saving the XMP to a file and processing it separately, which isn't that big a deal but still.

            Thanks,

            Eliot
            • 3. Re: [CS3 JS] Possible to Inspect Custom XMP Metadata With JavaScript?
              Level 1
              > I guess that leaves with saving the XMP to a file and processing it separately, which isn't that big a deal but still.

              The other alternative is to have some script code that calls Bridge to get at
              the metadata. In Bridge, you can use the Metadata object to poke around provided
              you know the namespace and the property names. The XMPScript lib is also an
              option in Bridge CS3, but it references only metadata stored in the XMP packet
              in the file. It does not handle derived/implicit metadata, like the EXIF data
              that is a part of images. A lot of my Photoshop work relies heavily on metadata
              so I've got this all worked out fairly well, including rough 'parsing' for
              canonical XMP format and Metadata.serialize() format.

              -X
              • 4. Re: [CS3 JS] Possible to Inspect Custom XMP Metadata With JavaScript?
                Level 1
                X wrote: "In Bridge, you can use the Metadata object to poke around provided you know the namespace and the property names."

                That's the trouble--you have to know where things are. I think that the original poster was looking for a way to browse the XMP without knowing the namespace/container names. XMP doesn't want people to be able to do that for some reason (probably having to do with intellectual property protection, etc.).

                You can browse standard fields, of course--but the custom ones won't even tell you if they're present or not--they'll just return an empty string when you try to retrieve the data.

                Thanks,

                Ole
                • 5. Re: [CS3 JS] Possible to Inspect Custom XMP Metadata With JavaScript?
                  ekimber Level 1
                  Right--the problem is that I don't know what might be there in a given document instance.

                  The argument that not allowing inspection somehow protects somebody is pretty bogus given that I can save the entire XMP data to a file from a script using one line of code, or just inspect the INCX or INX document.

                  Also, the document properties dialog shows all the custom metadata, so there must be C++ code that can access it. Just not script code. So the argument is doubly bogus. Hmph.

                  In any case, since I'm generating the INCX from XML I just added a script label to the Story object that lists the custom metadata fields I add as part of the INCX generation. Then my script can just iterate over the list and get the stuff out.

                  The only problem with that solution is when I need to start from a blank document and still allow authors to add custom metadata from InCopy (where I will be creating my own dialog for inspecting and setting custom metadata).

                  On the subject of Bridge--if a user only has InCopy and not InDesign, would they still have Bridge? That is, for InCopy-only users, can I even depend on the presence of Bridge?

                  Thanks,

                  Eliot
                  • 6. Re: [CS3 JS] Possible to Inspect Custom XMP Metadata With JavaScript?
                    Level 1
                    > That's the trouble--you have to know where things are. I think that the original poster was looking for a way to browse the XMP without knowing the namespace/container names. XMP doesn't want people to be able to do that for some reason (probably having to do with intellectual property protection, etc.).
                    >

                    XMPScript does have an iterator object which may address this shortcoming though
                    I haven't tested it yet.

                    XMPIterator object
                    Created by a call to XMPMeta.iterator(). Walks recursively through the
                    properties and qualifiers of an XMPMeta object, and returns them as
                    XMPProperty objects.

                    -X
                    • 7. Re: [CS3 JS] Possible to Inspect Custom XMP Metadata With JavaScript?
                      Did anybody say about the basics of XMP Metadata
                      • 8. Re: [CS3 JS] Possible to Inspect Custom XMP Metadata With JavaScript?
                        Level 1
                        Did anybody give the basics things of XMP Metadata

                        1) How to create?
                        2) How to import in the InDesign?
                        • 9. Re: [CS3 JS] Possible to Inspect Custom XMP Metadata With JavaScript?
                          Level 1
                          Hi venkan,

                          There are examples of both in the "Working with Documents" chapter of the InDesign Scripting Guide.

                          Thanks,

                          Ole
                          • 10. Re: [CS3 JS] Possible to Inspect Custom XMP Metadata With JavaScript?
                            Level 1
                            hi iam new to XMP . please tell me How to develop XMp in .net

                            Rami Reddy.b
                            bandiramireddy@aol.com
                            • 11. Re: [CS3 JS] Possible to Inspect Custom XMP Metadata With JavaScript?
                              Loic.Aigon Adobe Community Professional
                              I believe this subject has been already discussed by here. Have a look on the archives via the search function of this forum. I am quite sure you will find good infos.
                              Loic
                              • 12. Re: [CS3 JS] Possible to Inspect Custom XMP Metadata With JavaScript?
                                Martin Fischer Level 2
                                Here is another script to catch MetaData, some more than the basic:


                                // metaDataOfLinks.jsx
                                //DESCRIPTION: Catches MetaData of linked images and creates a report at the DeskTop.
                                // Martin Fischer 10/2008

                                var myLinkXmpArray = ["author", "copyrightInfoURL", "copyrightNotice", "copyrightStatus   ", "creationDate", "creator", "description", "documentTitle", "format", "jobName", "keywords", "modificationDate", "serverURL"];
                                var myIPTCArray = ["CiAdrCity", "CiAdrCtry", "CiAdrExtadr", "CiAdrPcode", "CiAdrRegion", "CiEmailWork", "CiTelWork", "City", "CiUrlWork", "CopyrightNotice", "Country", "CountryCode", "Creator", "CreatorContactInfo", "CreatorJobtitle", "DateCreated", "Description", "DescriptionWriter", "Headline", "Instructions", "IntellectualGenre", "JobID", "Keywords", "Location", "Provider", "Province-State", "RightsUsageTerms", "Scene", "Source", "SubjectCode", "Title"];
                                var myPSArray = ["photoshop:AuthorsPosition", "photoshop:CaptionWriter", "photoshop:Category", "photoshop:City", "photoshop:Country", "photoshop:Credit", "photoshop:DateCreated", "photoshop:Headline", "photoshop:Instructions", "photoshop:Source", "photoshop:State", "photoshop:SupplementalCategories", "photoshop:TransmissionReference", "photoshop:Urgency"];//var myPSArray = ["photoshop:AuthorsPosition", "CaptionWriter", "Category", "City", "Country", "Credit", "DateCreated", "Headline", "Instructions", "Source", "State", "SupplementalCategories", "TransmissionReference", "Urgency"];
                                var myTiffArray = ["tiff:ImageWidth", "tiff:ImageLength", "tiff:BitsPerSample", "tiff:Compression", "tiff:PhotometricInterpretation", "tiff:Orientation", "tiff:SamplesPerPixel", "tiff:PlanarConfiguration", "tiff:YCbCrSubSampling", "tiff:YCbCrPositioning", "tiff:XResolution", "tiff:YResolution", "tiff:ResolutionUnit", "tiff:TransferFunction", "tiff:WhitePoint", "tiff:PrimaryChromaticities", "tiff:YCbCrCoefficients", "tiff:ReferenceBlackWhite", "tiff:DateTime", "tiff:ImageDescription", "tiff:MakeProperName", "tiff:Model", "tiff:Software", "tiff:Artist", "tiff:Copyright"];
                                var myExifArray = ["exif:ExifVersion", "exif:FlashpixVersion", "exif:ColorSpace", "exif:ComponentsConfiguration", "exif:CompressedBitsPerPixel", "exif:PixelXDimension", "exif:PixelYDimension", "exif:UserComment", "exif:RelatedSoundFile", "exif:DateTimeOriginal", "exif:DateTimeDigitized", "exif:ExposureTime", "exif:FNumber", "exif:ExposureProgram", "exif:SpectralSensitivity", "exif:ISOSpeedRatings", "exif:OECF", "exif:ShutterSpeedValue", "exif:ApertureValue", "exif:BrightnessValue", "exif:ExposureBiasValue", "exif:MaxApertureValue", "exif:SubjectDistance", "exif:MeteringMode", "exif:LightSource", "exif:Flash", "exif:FocalLength", "exif:SubjectArea", "exif:FlashEnergy", "exif:SpatialFrequencyResponse", "exif:FocalPlaneXResolution", "exif:FocalPlaneYResolution", "exif:FocalPlaneResolutionUnit", "exif:SubjectLocation", "exif:ExposureIndex", "exif:SensingMethod", "exif:FileSource", "exif:SceneType", "exif:CFAPattern", "exif:CustomRendered", "exif:ExposureMode", "exif:WhiteBalance", "exif:DigitalZoomRatio", "exif:FocalLengthIn35mmFilm", "exif:SceneCaptureType", "exif:GainControl", "exif:Contrast", "exif:Saturation", "exif:Sharpness", "exif:DeviceSettingDescription", "exif:SubjectDistanceRange", "exif:ImageUniqueID", "exif:GPSVersionID", "exif:GPSLatitude", "exif:GPSLongitude", "exif:GPSAltitudeRef", "exif:GPSAltitude", "exif:GPSTimeStamp", "exif:DateTimeOriginal,", "exif:DateTimeDigitized.", "exif:GPSTimeStamp", "exif:GPSSatellites", "exif:GPSStatus", "exif:GPSMeasureMode", "exif:GPSDOP", "exif:GPSSpeedRef", "exif:GPSSpeed", "exif:GPSTrackRef", "exif:GPSTrack", "exif:GPSImgDirectionRef", "exif:GPSImgDirection", "exif:GPSMapDatum", "exif:GPSDestLatitude", "exif:GPSDestLongitude", "exif:GPSDestBearingRef", "exif:GPSDestBearing", "exif:GPSDestDistanceRef", "exif:GPSDestDistance", "exif:GPSProcessingMethod", "exif:GPSAreaInformation"];
                                var myCameraRawArray = ["crs:AutoBrightness", "crs:AutoContrast", "crs:AutoExposure", "crs:AutoShadows", "crs:BlueHue", "crs:BlueSaturation", "crs:Brightness", "crs:CameraProfile", "crs:ChromaticAberrationB", "crs:ChromaticAberrationR", "crs:ColorNoiseReduction", "crs:Contrast", "crs:CropTop", "crs:CropLeft", "crs:CropBottom", "crs:CropRight", "crs:CropAngle", "crs:CropWidth", "crs:CropHeight", "crs:CropUnits", "crs:Exposure", "crs:GreenHue", "crs:GreenSaturation", "crs:HasCrop", "crs:HasSettings", "crs:LuminanceSmoothing", "crs:RawFileName", "crs:RedHue", "crs:RedSaturation", "crs:Saturation", "crs:Shadows", "crs:ShadowTint", "crs:Sharpness", "crs:Temperature", "crs:Tint", "crs:ToneCurve", "crs:ToneCurveName", "crs:Version", "crs:VignetteAmount", "crs:VignetteMidpoint", "crs:WhiteBalance"];

                                var myInfo = new Array;
                                var myDoc = app.activeDocument;
                                var myLinks = app.documents[0].links;

                                for ( i = 0; i < myLinks.length; i++)
                                   getMetaData ( myLinks[i] );

                                writeData ( 'Metadaten zu ' + myDoc.name + '\r-----------\r\r' + myInfo.join ( '\r\r'), File ('~/Desktop/Metadaten_' + myDoc.name.replace(/.indd$/, '') + '.txt'));

                                // ===============================================================
                                //                                  Funktionen
                                // ===============================================================
                                function getMetaData ( aLink )
                                {
                                   var myLinkXmp = aLink.linkXmp.properties.toSource().replace( /^\(\{/,'' ).replace (/\)\}$/,'').replace( /parent.+$/,'').replace(/:/g, ':\t').split( ', ');
                                   var myString = aLink.name;
                                   myString += loopLinkXmp ( aLink, myLinkXmpArray );
                                   myString += loopArray ( aLink, "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/",  "Iptc4xmpCore:CreatorContactInfo/Iptc4xmpCore:",  myIPTCArray);
                                   myString += loopArray ( aLink, "http://ns.adobe.com/photoshop/1.0/",  "", myPSArray );
                                   myString += loopArray ( aLink, "http://ns.adobe.com/tiff/1.0/", "", myTiffArray );
                                   myString += loopArray ( aLink, "http://ns.adobe.com/exif/1.0/", "", myExifArray );
                                   myString += loopArray ( aLink, "http://ns.adobe.com/camera-raw-settings/1.0/",  "", myCameraRawArray );
                                   myInfo.push( myString.replace( /, $/,'') );
                                }

                                function loopArray( aLink, s1, s2, anArray )
                                {
                                   var temp = '\r\t--- ' + s1 + ' ---\r\t';
                                   for ( var a = 0; a < anArray.length; a++)
                                   {
                                      try {
                                         var theEvalString = 'aLink.linkXmp.getProperty(\"' + s1 + '\", \"' + s2 + anArray[a] + '\")';
                                         var myCode = eval( theEvalString );
                                         if ( myCode != '' )
                                            temp += '[' + anArray[a] + ']\t' +  myCode + '\r\t'; 
                                      } catch (e){ //temp +=e + '\r'
                                      }
                                   }
                                   return temp;
                                }

                                function loopLinkXmp( aLink, anArray )
                                {
                                   var temp = '\r\t--- LinkMetadata ---\r\t';
                                   for ( var a = 0; a < anArray.length; a++)
                                   {
                                      try {
                                         var theEvalString = 'aLink.linkXmp.' + anArray[a] ;
                                         var myCode = eval( theEvalString );
                                         if ( myCode != '' )
                                            temp += '[' + anArray[a] + ']\t' +  myCode + '\r\t'; 
                                      } catch (e){ //temp +=e + '\r'
                                      }
                                   }
                                   return temp;
                                }

                                function writeData ( aData, theFile )
                                {
                                   theFile.open ( 'w', 'Text', 'R*ch' );
                                   theFile.encoding = 'UTF-8';
                                   theFile.write ( aData );
                                   theFile.close ();
                                }


                                Ressources:
                                Adobe XMP Developer Center: http://www.adobe.com/devnet/xmp/
                                XMP Specification: http://www.adobe.com/devnet/xmp/pdfs/xmp_specification.pdf

                                Martin Fischer
                                1 person found this helpful