Calendar

<<  April 2017  >>
MonTueWedThuFriSatSun
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

View posts in large calendar

RecentComments

None

 
 
     
 

I wanted to get the raw XMP RDF data from some JPEG files. I looked at Microsoft Windows Imaging Component and although it will get individual metadata properties I couldn't find a way to get the whole XMP RDF packet. I saw some posts about extracting it using a substring aproach by getting all the data between <?xpacket begin='´╗┐' id='some uid'?> and <?xpacket end='w'?> but there can be several RDF packets in a file and it also seems that it can be zipped so it doesn't work so well.

I then spotted the Adobe XMP Toolkit and this has handlers for about 24 different file types. It is written in C++ and is only provided as source code. However it does have Visual Studio Solution files and can be built with Visual Studio Express C++ free edition. So download that. There are a couple of third-party things it needs (expat, zlib, QT) so download those too and put them in the third-party folder as per the ReadMe.txt files.

There are some walkthroughs showing how to use the toolkit and the ReadingXMP project is a good place to start. It shows how to read individual properties which is what we don't want so remove all of that properties code and replace it with this

    if(ok)
    {
        // Create the xmp object and get the xmp data
        SXMPMeta meta;
        string rawrdf;
        myFile.GetXMP(&meta, &rawrdf, 0);

        cout << rawrdf << endl;
        
        // Close the SXMPFile.  The resource file is already closed if it was
        // opened as read only but this call must still be made.
        myFile.CloseFile();
    }
    else
    {
        cout << "Unable to open " << filename << endl;
    }

In case you don't know C++ here is the file. Just replace the ReadingXMP.cpp file in the source folder.

ReadingXMP.cpp.zip

Build the solution and you will get a ReadingXMP.exe file in the targets folder. In case you don't want to go to all that trouble here is the executable.

ReadingXMP.exe.zip

You can use it from the DOS command line

> ReadingXMP.exe somefile.jpg

You can extract the data into a 'sidecar file' like this

> ReadingXMP.exe somefile.jpg > somefile.jpg.xmp

You can use it in Powershell like this

PS> [xml]$xmp = (.\ReadingXMP.exe somefile.jpg)

Which reads the XMP RDF directly into the $xmp object.

To keep in the theme of my previous posts a useful -CustomProps param for Get-DirAsXml can go something like this if you only want one or two properties (or just use WIC).

get-dirasxml ..\test -CustomProps {
    param ($element, $directory, $file, $prefix, $namespace)
    try{
        [xml]$xmp = (.\ReadingXMP.exe $file.FullName)
        $long = $xmp.SelectSingleNode("//*[local-name() = 'GPSLongitude']/text()").Value
        $lati = $xmp.SelectSingleNode("//*[local-name() = 'GPSLatitude']/text()").Value
        [void]$element.SetAttribute("GPSLongitude", $namespace, $long)
        [void]$element.SetAttribute("GPSLatitude", $namespace, $lati)
    }catch{}
} | Format-Xml

and might produce

<root Name="root" Root="True" Date="2010/01/22 01:24:45">
    
<folder Name="test" Base="D:\powershell\blog\test" Parent="D:\powershell\blog">
        
<folder Name="test2">
            
<file Name="test.ps1" />
            
<file Name="test.txt" />
            
<file Name="test.zip" />
            
<file Name="tmp.xml" />
        
</folder>
        
<file Name="test.jpg" GPSLongitude="0,0E" GPSLatitude="51,28.927873651518N" />
        
<file Name="test.ps1" />
        
<file Name="test.txt" />
        
<file Name="test.zip" />
        
<file Name="tmp.xml" />
    
</folder>
</root>

If you want the whole XMP RDF packet you can do something like this

get-dirasxml ..\test -CustomProps {
    param ($element, $directory, $file, $prefix, $namespace)
    try{
        [xml]$xmp = (.\ReadingXMP.exe $file.FullName)
        $xmpr = $xmp.SelectSingleNode("/*")
        $inode = $element.OwnerDocument.ImportNode($xmpr, $true)
        [void]$element.AppendChild($inode)
    }catch{}
} | Format-Xml

Which might produce something like this

<root Name="root" Root="True" Date="2010/01/22 02:00:07">
    
<folder Name="test" Base="D:\powershell\blog\test" Parent="D:\powershell\blog">
        
<folder Name="test2">
            
<file Name="test.ps1" />
            
<file Name="test.txt" />
            
<file Name="test.zip" />
            
<file Name="tmp.xml" />
        
</folder>
        
<file Name="test.jpg">
            
<x:xmpmeta xmlns:x="adobe:ns:meta/">
                
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
                    
<rdf:Description xmlns:dc="http://purl.org/dc/elements/1.1/" rdf:about="uuid:faf5bdd5-ba3d-11da-ad31-d33d75182f1b">
                        
<dc:subject>
                            
<rdf:Bag>
                                
<rdf:li>Chris</rdf:li>
                            
</rdf:Bag>
                        
</dc:subject>
                    
</rdf:Description>
                    
<rdf:Description xmlns:MicrosoftPhoto="http://ns.microsoft.com/photo/1.0" rdf:about="uuid:faf5bdd5-ba3d-11da-ad31-d33d75182f1b">
                        
<MicrosoftPhoto:LastKeywordXMP>
                            
<rdf:Bag>
                                
<rdf:li>Chris</rdf:li>
                            
</rdf:Bag>
                        
</MicrosoftPhoto:LastKeywordXMP>
                    
</rdf:Description>
                    
<rdf:Description xmlns:MP="http://ns.microsoft.com/photo/1.2/">
                        
<MP:RegionInfo>
                            
<rdf:Description>
                                
<MPRI:Regions xmlns:MPRI="http://ns.microsoft.com/photo/1.2/t/RegionInfo#">
                                    
<rdf:Bag>
                                        
<rdf:li>
                                            
<rdf:Description>
                                                
<MPReg:Rectangle xmlns:MPReg="http://ns.microsoft.com/photo/1.2/t/Region#">
                                                    0.200521, 0.257813, 0.072917, 0.054688
                                                
</MPReg:Rectangle>
                                                
<MPReg:PersonDisplayName xmlns:MPReg="http://ns.microsoft.com/photo/1.2/t/Region#">
                                                    Chris Bayes
</MPReg:PersonDisplayName>
                                                    
<MPReg:PersonEmailDigest xmlns:MPReg="http://ns.microsoft.com/photo/1.2/t/Region#">
                                                        267675C2A3CDXXXXXXXXXX799647B6CA144
                                                    
</MPReg:PersonEmailDigest>
                                                    
<MPReg:PersonLiveIdCID xmlns:MPReg="http://ns.microsoft.com/photo/1.2/t/Region#">
                                                        -46641XXXXXXX70720
                                                    
</MPReg:PersonLiveIdCID>
                                                
</rdf:Description>
                                        
</rdf:li>
                                    
</rdf:Bag>
                                
</MPRI:Regions>
                            
</rdf:Description>
                        
</MP:RegionInfo>
                    
</rdf:Description>
                    
<rdf:Description xmlns:xmp="http://ns.adobe.com/xap/1.0/">
                        
<xmp:CreatorTool>Microsoft Windows Live Photo Gallery14.0.8081.709</xmp:CreatorTool>
                        
<xmp:creatortool>Microsoft Pro Photo Tools</xmp:creatortool>
                    
</rdf:Description>
                    
<rdf:Description xmlns:tiff="http://ns.adobe.com/tiff/1.0/">
                        
<tiff:Software>Microsoft Windows Live Photo Gallery14.0.8081.709</tiff:Software>
                        
<tiff:software>Microsoft Pro Photo Tools</tiff:software>
                        
<tiff:Orientation>1</tiff:Orientation>
                    
</rdf:Description>
                    
<rdf:Description xmlns:exif="http://ns.adobe.com/exif/1.0/">
                        
<exif:GPSLatitude>51,28.927873651518N</exif:GPSLatitude>
                        
<exif:GPSLongitude>0,0E</exif:GPSLongitude>
                    
</rdf:Description>
                
</rdf:RDF>
            
</x:xmpmeta>
        
</file>
        
<file Name="test.ps1" />
        
<file Name="test.txt" />
        
<file Name="test.zip" />
        
<file Name="tmp.xml" />
    
</folder>
</root>

and is quite large. Whether to leave the XMP RDF in the file, in sidecar files, or in DAXml, depends on your  'application/ps1 easy script', and how many files you have in your own folders.

I guess the point is that you have easy access to your own data.

P.S. I should have looked harder. ExifTool by Phil Harvey does all of this and more. I assumed from the name that it works on EXIF metadata but it can output all metadata as XMP i.e.

PS> .\exiftool test.jpg -s -o .\%d%f.xmp

will create sidecar files and doing something like this (less than obvious)

[xml]$xmp=(.\exiftool -xmp -b -m $file.FullName)

will produce the equivalent to the xml in the sidecar file. -X though will produce "RDF/Xml" which is less useful.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Add comment