Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Method to write LocationShown and LocationCreated in IPTC Extension schema #1254

Closed
amarlakhani opened this issue Jul 22, 2020 · 20 comments
Closed
Assignees
Labels
support Anything related to a user needing help with exiv2
Milestone

Comments

@amarlakhani
Copy link

amarlakhani commented Jul 22, 2020

Per https://exiv2.org/tags-xmp-iptcExt.html and the associated IPTC Extension specifications, the value type of LocationShown and LocationCreated is a LocationDetails bag. The resulting Xmp section would look something like:

<Iptc4xmpExt:LocationCreated>
  <rdf:Bag>
    <rdf:li rd:parseType=“Resource”>
      <Iptc4xmpExt:Sublocation/>
      <Iptc4xmpExt:City>Paris</Iptc4xmpExt:City>
      <Iptc4xmpExt:ProvinceState/>
      <Iptc4xmpExt:CountryName>France</Iptc4xmpExt:CountryName>
      <Iptc4xmpExt:CountryCode/>
      <Iptc4xmpExt:WorldRegion/>
    </rdf:li>
  </rdf:Bag>
<Iptc4xmpExt:LocationCreated>

I haven't been able to find anything in the docs that would allow keys to be nested within a Bag like this.

If there is a way, I would be grateful if somebody would be able to share it with me.

@amarlakhani amarlakhani added the request feature request or any other kind of wish label Jul 22, 2020
@clanmills clanmills self-assigned this Jul 22, 2020
@clanmills clanmills added this to the v0.27.4 milestone Jul 22, 2020
@clanmills
Copy link
Collaborator

I don't know anything about this. However, I'm writing a book Image Metadata and Exiv2 Architecture. Here's the current draft: https://clanmills.com/exiv2/book

I intend to start work for the book on IPTC in next week or two. I've been working on Exiv2 for 12 years and most of my effort has been focused on bugs, build and test. The IPTC code is very stable, so I don't know much about it! The XMP code is the Adobe XMPsdk 4.4.0 and you can build/link more recent Adobe offerings.

I will investigate.

@clanmills
Copy link
Collaborator

clanmills commented Jul 23, 2020

There have been a few discussions about this in years gone by. For example:

https://dev.exiv2.org/boards/3/topics/2016?r=2025#message-2025

As you can see, Scott Renton concluded that "we're heading in the right direction now", although to be honest, I didn't really know what we were discussing! I recommend that you use the search on the "old" bug tracker and you might find what you want.

@clanmills
Copy link
Collaborator

I'm pretty sure that your answer is in the discussion with the person at the University of Edinburgh. If you agree, could you close this issue please. If you need further assistance, I will try to help although I really don't know much about XMP and/or IPTC.

@clanmills clanmills added support Anything related to a user needing help with exiv2 and removed request feature request or any other kind of wish labels Jul 23, 2020
@amarlakhani
Copy link
Author

Thanks for your help Robin. It doesn't look like we can do exactly what I was looking for in Exiv2 but no worries, I think it's fair to say that this seems like more of a job for Adobe's XMP Toolkit. I'll close the issue.

@clanmills
Copy link
Collaborator

I'm glad to not have this sitting "on my plate". Thanks for closing this.

If you can do this with XMPsdk, it's probably possible to do it from Exiv2 which mostly puts an Exiv2 veneer over XMPsdk. I don't want to increase the scope of the book, however I will think about adding a chapter to discuss XMP as I haven't found Adobe's documentation to be very illuminating.

The primary focus of the book is to deal with file formats and to explain how the metadata is stored in the image and how it is parsed.

@clanmills
Copy link
Collaborator

I've done the following:

566 rmills@rmillsmbp:~/temp $ curl -OL http://clanmills.com/Stonehenge.jpg
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 6599k  100 6599k    0     0  85456      0  0:01:19  0:01:19 --:--:-- 80968
https://github.com/Exiv2/exiv2/issues/1254
567 rmills@rmillsmbp:~/temp $ exiv2 -M'set Xmp.iptc.LocationCreated XmpBag something' Stonehenge.jpg 
568 rmills@rmillsmbp:~/temp $ exiv2 -pX Stonehenge.jpg | xmllint --pretty 2 -
exiv2 -pX Stonehenge.jpg | xmllint --pretty 1 -
<?xml version="1.0"?>
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0-Exiv2">
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <rdf:Description xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/" rdf:about="" xmp:Rating="0" xmp:ModifyDate="2015-07-16T20:25:28+01:00">
      <dc:description>
        <rdf:Alt>
          <rdf:li xml:lang="x-default">Classic View</rdf:li>
        </rdf:Alt>
      </dc:description>
      <Iptc4xmpCore:LocationCreated>
        <rdf:Bag>
          <rdf:li>something</rdf:li>
        </rdf:Bag>
      </Iptc4xmpCore:LocationCreated>
    </rdf:Description>
  </rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>
569 rmills@rmillsmbp:~/temp $ 

So it created the bag and added something. We want to edit that now to be what you discussed above.

<Iptc4xmpExt:LocationCreated>
  <rdf:Bag>
    <rdf:li rd:parseType=“Resource”>
      <Iptc4xmpExt:Sublocation/>
      <Iptc4xmpExt:City>Paris</Iptc4xmpExt:City>
      <Iptc4xmpExt:ProvinceState/>
      <Iptc4xmpExt:CountryName>France</Iptc4xmpExt:CountryName>
      <Iptc4xmpExt:CountryCode/>
      <Iptc4xmpExt:WorldRegion/>
    </rdf:li>
  </rdf:Bag>
<Iptc4xmpExt:LocationCreated>

@clanmills
Copy link
Collaborator

Progress:

628 rmills@rmillsmbp:~/temp $ cp ~/Stonehenge.jpg .
629 rmills@rmillsmbp:~/temp $ exiv2 -M'set Xmp.iptc.LocationCreated XmpBag something' Stonehenge.jpg 
630 rmills@rmillsmbp:~/temp $ exiv2 -M'set Xmp.iptc.LocationCreated[1] London' Stonehenge.jpg 
631 rmills@rmillsmbp:~/temp $ exiv2 -M'set Xmp.iptc.LocationCreated[2] Paris' Stonehenge.jpg 
632 rmills@rmillsmbp:~/temp $ exiv2 -pX Stonehenge.jpg | xmllint --pretty 1 -
<?xml version="1.0"?>
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0-Exiv2">
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <rdf:Description xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/" rdf:about="" xmp:Rating="0" xmp:ModifyDate="2015-07-16T20:25:28+01:00">
      <dc:description>
        <rdf:Alt>
          <rdf:li xml:lang="x-default">Classic View</rdf:li>
        </rdf:Alt>
      </dc:description>
      <Iptc4xmpCore:LocationCreated>
        <rdf:Bag>
          <rdf:li>London</rdf:li>
          <rdf:li>Paris</rdf:li>
        </rdf:Bag>
      </Iptc4xmpCore:LocationCreated>
    </rdf:Description>
  </rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>
633 rmills@rmillsmbp:~/temp $ 

@amarlakhani
Copy link
Author

Thank you for the help so far! I'm trying from my end too but obviously can't quite match your expertise.

@clanmills
Copy link
Collaborator

I assure you that I have no expertise with this. I'm floundering in the dark. I think I know everything about image formats and how Exif and ICC is stored and manipulated. The XMPsdk is however a total mystery to me. I know even less about IPTC - although at least IPTC is on my TODO list for the book.

I've had another idea. If we express this in IPTC, the convertor magic will probably move it into XMP. I'm looking at the test and sample code for IPTC.

@clanmills
Copy link
Collaborator

I know how to solve this although I don't know the solution:

The command $ cat foo.xml | exiv2 -iX- Stonehenge.jpg will replace the XMP packet in Stonehenge.jpg. Once we have the XMP in the file, we can use the command $ exiv2 -pi Stonehenge.jpg and he'll reveal the solution. Like this:

745 rmills@rmillsmbp:~/temp $ cat another.xml 
<?xml version="1.0"?>
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0-Exiv2">
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <rdf:Description xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/" rdf:about="" xmp:Rating="0" xmp:ModifyDate="2015-07-16T20:25:28+01:00">
      <dc:description>
        <rdf:Alt>
          <rdf:li xml:lang="x-default">Different Title</rdf:li>
        </rdf:Alt>
      </dc:description>
    </rdf:Description>
  </rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>746 rmills@rmillsmbp:~/temp $ cat another.xml | exiv2 -iX- Stonehenge.jpg  ; 
747 rmills@rmillsmbp:~/temp $ exiv2 -px Stonehenge.jpg 
Xmp.xmp.Rating                               XmpText     1  0
Xmp.xmp.ModifyDate                           XmpText    25  2015-07-16T20:25:28+01:00
Xmp.dc.description                           LangAlt     1  lang="x-default" Different Title
748 rmills@rmillsmbp:~/temp $ 

When I try your proposed XML/xmp:

738 rmills@rmillsmbp:~/temp $ cat foo.xml 
<?xml version="1.0"?>
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0-Exiv2">
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <rdf:Description xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/" rdf:about="" xmp:Rating="0" xmp:ModifyDate="2015-07-16T20:25:28+01:00">
      <dc:description>
        <rdf:Alt>
          <rdf:li xml:lang="x-default">Classic View</rdf:li>
        </rdf:Alt>
      </dc:description>
      <Iptc4xmpExt:LocationCreated>
        <rdf:Bag>
          <rdf:li>
            <Iptc4xmpExt:Sublocation/>
            <Iptc4xmpExt:City>Paris</Iptc4xmpExt:City>
            <Iptc4xmpExt:ProvinceState/>
            <Iptc4xmpExt:CountryName>France</Iptc4xmpExt:CountryName>
            <Iptc4xmpExt:CountryCode/>
            <Iptc4xmpExt:WorldRegion/>
          </rdf:li>
        </rdf:Bag>
      <Iptc4xmpExt:LocationCreated>
    </rdf:Description>
  </rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>739 rmills@rmillsmbp:~/temp $ 
739 rmills@rmillsmbp:~/temp $ cp ~/Stonehenge.jpg .
740 rmills@rmillsmbp:~/temp $ cat foo.xml | exiv2 -iXX- Stonehenge.jpg 
Error: XMP Toolkit error 201: XML parsing failure
Exiv2 exception in insert action for file Stonehenge.jpg:
741 rmills@rmillsmbp:~/temp $ 

That '201' is coming directly from XMPsdk. He's saying "I hate your XML/xmp".

So now we have better focus. A couple ways to progress:

1 Use an Adobe Application
Lightroom, or PhotoShop and set fields on interest.
Dump the XMP to the terminal

OR
2 Build the XMPsdk and mess around with their sample programs.

The XmpBag with the <li> doesn't smell right. I believe an XmpBag is something like a JavaScript object and an XmpSeq is something like a JavaScript array.

Time for lunch. I'm fairly confident that we can fix this. The road to the solution is to use an Adobe Application to set up a good file and then we can figure out how to create a similar file with Exiv2.

Do you have PhotoShop or LightRoom?

@clanmills
Copy link
Collaborator

I've taken my own medicine. I've loaded a photo in ACDC PhotoStudio 5 for Mac and edited the IPTCExt metadata. I set the City to "Camberley" and he stored as at XML attribute: Iptc4xmpExt_1_:LocationCreatedCity="Camberley"

Your turn. We need a solid definition of what we want/need and then we'll figure out how to get there.

<?xml version="1.0"?>
<?xpacket
begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta
    xmlns:x="adobe:ns:meta/"
    x:xmptk="XMP Core 5.4.0"
  > <rdf:RDF
      xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    > <rdf:Description
        xmlns:exif="http://ns.adobe.com/exif/1.0/"
        xmlns:tiff="http://ns.adobe.com/tiff/1.0/"
        xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"
        xmlns:exifEX="http://cipa.jp/exif/1.0/"
        xmlns:xmp="http://ns.adobe.com/xap/1.0/"
        xmlns:Iptc4xmpExt_1_="Iptc4xmpExt"
        rdf:about=""
        exif:GPSAltitude="164917/1000"
        exif:FocalLenIn35mmFilm="26"
        exif:GPSLatitude="51,19.98N"
        exif:ExifVersion="0220"
        exif:SceneType="1"
        exif:LightSource="0"
        exif:MeteringMode="2"
        exif:GPSVersionID="2.2.0.0"
        exif:GPSLongitude="0,42.3402W"
        exif:ApertureValue="185/100"
        exif:PixelYDimension="3096"
        exif:MaxApertureValue="185/100"
        exif:SceneCaptureType="0"
        exif:FNumber="190/100"
        exif:FlashPixVersion="0100"
        exif:ExposureTime="1/25"
        exif:SensingMethod="2"
        exif:ColorSpace="1"
        exif:GPSAltitudeRef="0"
        exif:PixelXDimension="4128"
        exif:FocalLength="360/100"
        exif:WhiteBalance="0"
        exif:GPSTimeStamp="2020-07-12T20:09:34+0000"
        exif:UserComment="&#xD7;T"
        exif:ExposureBiasValue="0/10"
        exif:BrightnessValue="58/100"
        exif:ShutterSpeedValue="4643/1000"
        exif:ExposureMode="0"
        exif:ExposureProgram="0"
        tiff:XResolution="72/1"
        tiff:Make="samsung"
        tiff:YResolution="72/1"
        tiff:Model="SM-J610FN"
        tiff:Orientation="1"
        tiff:ResolutionUnit="2"
        photoshop:DateCreated="2020-07-12T21:09:38"
        exifEX:PhotographicSensitivity="160"
        xmp:CreateDate="2020-07-12T21:09:38"
        xmp:ModifyDate="2020-07-12T21:09:38"
        xmp:CreatorTool="J610FNXXS5BTE6"
        Iptc4xmpExt_1_:LocationCreatedCity="Camberley"
      > <exif:Flash
          exif:Function="False"
          exif:Fired="False"
          exif:Return="0"
          exif:Mode="0"
          exif:RedEyeMode="False"
      /> <exif:ISOSpeedRatings
        > <rdf:Seq
          > <rdf:li
            >160</rdf:li
          > </rdf:Seq
        > </exif:ISOSpeedRatings
      > <exif:ComponentsConfiguration
        > <rdf:Seq
          > <rdf:li
            >1</rdf:li
          > <rdf:li
            >2</rdf:li
          > <rdf:li
            >3</rdf:li
          > <rdf:li
            >0</rdf:li
          > </rdf:Seq
        > </exif:ComponentsConfiguration
      > </rdf:Description
    > </rdf:RDF
  > </x:xmpmeta
>
<?xpacket
end="w"?>

20200712_210938

@clanmills clanmills reopened this Jul 23, 2020
@amarlakhani
Copy link
Author

amarlakhani commented Jul 23, 2020

I do indeed have Photoshop, I've set the fields through there and the XMP dump gives:

<?xml version="1.0"?>
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.6-c148 79.164036, 2019/08/13-01:06:57        ">
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <rdf:Description xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/" xmlns:aux="http://ns.adobe.com/exif/1.0/aux/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" xmlns:Iptc4xmpExt="http://iptc.org/std/Iptc4xmpExt/2008-02-29/" rdf:about="" xmp:Rating="0" xmp:ModifyDate="2020-07-23T12:52:38+01:00" xmp:CreatorTool="Ver.1.00" xmp:CreateDate="2015-07-16T15:38:54" xmp:MetadataDate="2020-07-23T12:52:38+01:00" dc:format="image/jpeg" photoshop:LegacyIPTCDigest="339EEC4DFAF745C97718CD29D287C258" photoshop:DateCreated="2015-07-16T15:38:54" photoshop:ColorMode="3" photoshop:ICCProfile="sRGB IEC61966-2.1" aux:SerialNumber="2567806" aux:LensInfo="180/10 2500/10 35/10 63/10" aux:Lens="18.0-250.0 mm f/3.5-6.3" aux:LensID="146" aux:ImageNumber="9608" aux:ApproximateFocusDistance="316/10" xmpMM:DocumentID="E7252228B868FDB85562B08938C3DFB1" xmpMM:InstanceID="xmp.iid:c2b9c606-2012-4623-bcb5-14ae0034462a" xmpMM:OriginalDocumentID="E7252228B868FDB85562B08938C3DFB1">
      <dc:description>
        <rdf:Alt>
          <rdf:li xml:lang="x-default">Classic View</rdf:li>
        </rdf:Alt>
      </dc:description>
      <xmpMM:History>
        <rdf:Seq>
          <rdf:li stEvt:action="saved" stEvt:instanceID="xmp.iid:c2b9c606-2012-4623-bcb5-14ae0034462a" stEvt:when="2020-07-23T12:52:38+01:00" stEvt:softwareAgent="Adobe Photoshop 21.0 (Macintosh)" stEvt:changed="/"/>
        </rdf:Seq>
      </xmpMM:History>
      <Iptc4xmpExt:LocationCreated>
        <rdf:Bag>
          <rdf:li Iptc4xmpExt:City="Paris" Iptc4xmpExt:CountryName="France"/>
        </rdf:Bag>
      </Iptc4xmpExt:LocationCreated>
    </rdf:Description>
  </rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>

The initial XML I provided was actually taken from the Raw Data viewer within Photoshop. I checked again, and it does give that same li structure, so there just seems to be some discrepancy in how Photoshop interprets/displays the XML

@clanmills
Copy link
Collaborator

clanmills commented Jul 23, 2020

We're almost there. It's a Bag with a single element and the City CountryName items are attributes. We only need to know the syntax for an attribute and we'll be done. I don't see it in the exiv2 man page.

I'm going to have a break for lunch. Speak later.

@clanmills
Copy link
Collaborator

clanmills commented Jul 23, 2020

Yes, that's right. An XmpBag is like a JavaScript object (key/value pairs). Right. That make sense (sort of).

@amarlakhani
Copy link
Author

Enjoy your lunch! I've been using the C++ library rather than the command line executable, and I can see that example 5 of https://www.exiv2.org/examples.html has what we need, so now it's just a case of finding the command line equivalent

@amarlakhani
Copy link
Author

So it seems like this does the trick:

set Xmp.iptc.LocationCreated XmpText type=Bag
set Xmp.iptc.LocationCreated[1]/iptcExt:City Camberley

@amarlakhani
Copy link
Author

Thank you so much for your help! I'm looking forward to reading the book :)

@clanmills
Copy link
Collaborator

Wonderful. I think we're done on this. Teamwork is really effective. I don't know why nobody uses it in the office and never in the open-source community. Why use teamwork when you can bully or throw a tantrum instead?

I leave you to close this issue if you're happy.

@amarlakhani
Copy link
Author

I am more than happy, thanks again

@clanmills
Copy link
Collaborator

The book is my escape plan. I'll be 70 in January and I want to leave Exiv2 and focus on my musical interests. If I document everything I know about metadata, maybe somebody will maintain Exiv2 or write a new library. I've been a good and diligent servant to the world of open-source.

https://clanmills.com/exiv2/book
https://clanmills.com/exiv2/book/IMaEA.pdf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
support Anything related to a user needing help with exiv2
Projects
None yet
Development

No branches or pull requests

2 participants