Export custom bags to XMP

Started by cidthecoatrack, April 01, 2020, 03:15:11 PM

Previous topic - Next topic

cidthecoatrack

I am trying to take some custom metadata in JSON format and export them as values in an XMP.  The values I am trying to send are:


{
    "sourceFile": "*",
    "xmP-dc:Format": "image/jpeg",
    "xmP-dc:Contributor": "",
    "xmP-dc:Creator": "",
    "xmP-dc:Relation": "",
    "xmP-dc:Subject": [
        "this",
        "is",
        "a",
        "tag",
        "field"
    ],
    "xmP-dc:Type": "",
    "xmP-dc:Description": "",
    "ifD0:Orientation": "Horizontal (normal)",
    "xmP-xmp:MetadataDate": "2020:03:31 17:20:17-04:00",
    "xmP-xmp:Advisory": "",
    "xmP-xmp:Identifier": "",
    "xmP-CS1:IsTalent": false,
    "xmP-CS1:TalentName": "Alejandro Naranjo",
    "xmP-CS1:ImageDate": "2020:02:21 00:00:00.0-05:00",
    "xmP-CS1:TalentTags": [
        "short",
        "happy",
        "kind"
    ],
    "file:ImageWidth": 1600,
    "file:ImageHeight": 1200,
    "xmP-xmpRights:Owner": "",
    "xmP-photoshop:Headline": "",
    "xmP-photoshop:TransmissionReference": "",
    "xmP-photoshop:Instructions": "",
    "xmP-photoshop:SupplementalCategories": "",
    "exifIFD:ColorSpace": "Uncalibrated"
}


This is being stamped to a jpg with the command exiftool -config tags.config -json=- /tmp/temp.jpg .

This is the config:


%Image::ExifTool::UserDefined::Shortcuts=(GEDefaultTags=>['XMP-cs2:MyList','XMP-cs2:MyText','XMP-cs2:MyCheckbox','XMP-cs2:MyDate','XMP-CS1acs:ImageDate','XMP-CS1acs:TalentName','XMP-CS1:TalentName','XMP-CS1:TalentTags','XMP-CS1:ImageDate','XMP-CS1:BadMoon','XMP-CS1:IsTalent','XMP-dc:Contributor','XMP-dc:Coverage','XMP-dc:Creator','XMP-dc:Date','XMP-dc:Description','XMP-dc:Format','XMP-dc:Identifier','XMP-dc:Language','XMP-dc:Publisher','XMP-dc:Relation','XMP-dc:Rights','XMP-dc:Source','XMP-dc:Subject','XMP-dc:Title','XMP-dc:Type','XMP-aux:Lens','IFD0:Make','IFD0:Model','IFD0:Orientation','IFD0:XResolution','IFD0:YResolution','IFD0:ResolutionUnit','XMP-exifEX:SerialNumber','XMP-exifEX:LensInfo','XMP-xmp:Advisory','XMP-xmp:BaseURL','XMP-xmp:CreateDate','XMP-xmp:CreatorTool','XMP-xmp:Identifier','XMP-xmp:Label','XMP-xmp:MetadataDate','XMP-xmp:ModifyDate','XMP-xmp:Nickname','XMP-xmp:Rating','File:ImageWidth','File:ImageHeight','IPTC:Urgency','XMP-xmpRights:Certificate','XMP-xmpRights:Marked','XMP-xmpRights:Owner','XMP-xmpRights:UsageTerms','XMP-xmpRights:WebStatement','XMP-iptcCore:CountryCode','XMP-iptcCore:CreatorCity','XMP-iptcCore:CreatorCountry','XMP-iptcCore:CreatorAddress','XMP-iptcCore:CreatorPostalCode','XMP-iptcCore:CreatorRegion','XMP-iptcCore:CreatorWorkEmail','XMP-iptcCore:CreatorWorkTelephone','XMP-iptcCore:CreatorWorkURL','XMP-iptcCore:IntellectualGenre','XMP-iptcCore:Location','XMP-iptcCore:Scene','XMP-iptcCore:SubjectCode','XMP-photoshop:AuthorsPosition','XMP-photoshop:CaptionWriter','XMP-photoshop:Category','XMP-photoshop:City','XMP-photoshop:ColorMode','XMP-photoshop:Country','XMP-photoshop:Credit','XMP-photoshop:DateCreated','XMP-photoshop:Headline','XMP-photoshop:ICCProfileName','XMP-photoshop:Instructions','XMP-photoshop:Source','XMP-photoshop:State','XMP-photoshop:SupplementalCategories','XMP-photoshop:TransmissionReference','XMP-photoshop:Urgency','XMP-exif:FlashFunction','XMP-exif:FlashMode','XMP-exif:FlashRedEyeMode','XMP-exif:FlashReturn','ExifIFD:ExposureTime','ExifIFD:FNumber','ExifIFD:ExposureProgram','ExifIFD:ISO','ExifIFD:DateTimeOriginal','ExifIFD:CompressedBitsPerPixel','ExifIFD:ApertureValue','ExifIFD:MaxApertureValue','ExifIFD:MeteringMode','ExifIFD:LightSource','ExifIFD:Flash','ExifIFD:FocalLength','ExifIFD:ColorSpace','ExifIFD:ExifImageWidth','ExifIFD:ExifImageHeight','ExifIFD:FileSource']);
%Image::ExifTool::UserDefined = (
                                     'Image::ExifTool::XMP::Main' => {cs2 => {
                                         SubDirectory => {
                                             TagTable => 'Image::ExifTool::UserDefined::cs2'
                                             },
                                         },CS1acs => {
                                         SubDirectory => {
                                             TagTable => 'Image::ExifTool::UserDefined::CS1acs'
                                             },
                                         },CS1 => {
                                         SubDirectory => {
                                             TagTable => 'Image::ExifTool::UserDefined::CS1'
                                             },
                                         }});
%Image::ExifTool::UserDefined::cs2 = (
                                           GROUPS        => { 0 => 'XMP', 1 => 'XMP-cs2', 2 => 'Image' },
                                           NAMESPACE     => { 'cs2' => 'http://custom-schema.com/2' },'MyList' => { List => 'Bag' },'MyText' => { Writable => 'string' },'MyCheckbox' => { Writable => 'boolean' },'MyDate' => { Writable => 'date' });
%Image::ExifTool::UserDefined::CS1acs = (
                                           GROUPS        => { 0 => 'XMP', 1 => 'XMP-CS1acs', 2 => 'Image' },
                                           NAMESPACE     => { 'CS1acs' => 'http://essex.com' },'ImageDate' => { Writable => 'date' },'TalentName' => { Writable => 'string' });
%Image::ExifTool::UserDefined::CS1 = (
                                           GROUPS        => { 0 => 'XMP', 1 => 'XMP-CS1', 2 => 'Image' },
                                           NAMESPACE     => { 'CS1' => 'http://cs1.com' },'TalentName' => { Writable => 'string' },'TalentTags' => { List => 'Bag' },'ImageDate' => { Writable => 'date' },'BadMoon' => { List => 'Bag' },'IsTalent' => { Writable => 'boolean' });


We then extract from the jpg into the XMP file with the command exiftool -config tags.config /tmp/temp.jpg -o -.xmp . This will send the XMP to the standard output stream, which we intercept and upload to S3

The resulting XMP looks like this:


<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 11.29'>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>

<rdf:Description rdf:about=''
  xmlns:CS1='http://cs1.com'>
  <CS1:ImageDate>2020-02-21T00:00:00.0-05:00</CS1:ImageDate>
  <CS1:IsTalent>False</CS1:IsTalent>
  <CS1:TalentName>Alejandro Naranjo</CS1:TalentName>
</rdf:Description>

<rdf:Description rdf:about=''
  xmlns:CS1acs='http://essex.com'>
  <CS1acs:ImageDate>2020-02-21T00:00:00.0-05:00</CS1acs:ImageDate>
  <CS1acs:TalentName>Alejandro Naranjo</CS1acs:TalentName>
</rdf:Description>

<rdf:Description rdf:about=''
  xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
  <Iptc4xmpExt:Contributor>
   <rdf:Bag>
    <rdf:li rdf:parseType='Resource'/>
   </rdf:Bag>
  </Iptc4xmpExt:Contributor>
  <Iptc4xmpExt:Creator>
   <rdf:Bag>
    <rdf:li rdf:parseType='Resource'/>
   </rdf:Bag>
  </Iptc4xmpExt:Creator>
</rdf:Description>

<rdf:Description rdf:about=''
  xmlns:dc='http://purl.org/dc/elements/1.1/'>
  <dc:contributor>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </dc:contributor>
  <dc:creator>
   <rdf:Seq>
    <rdf:li/>
   </rdf:Seq>
  </dc:creator>
  <dc:description>
   <rdf:Alt>
    <rdf:li xml:lang='x-default'/>
   </rdf:Alt>
  </dc:description>
  <dc:format>image/jpeg</dc:format>
  <dc:identifier/>
  <dc:relation>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </dc:relation>
  <dc:subject>
   <rdf:Bag>
    <rdf:li>this</rdf:li>
    <rdf:li>is</rdf:li>
    <rdf:li>a</rdf:li>
    <rdf:li>tag</rdf:li>
    <rdf:li>field</rdf:li>
   </rdf:Bag>
  </dc:subject>
  <dc:type>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </dc:type>
</rdf:Description>

<rdf:Description rdf:about=''
  xmlns:exif='http://ns.adobe.com/exif/1.0/'>
  <exif:ColorSpace>65535</exif:ColorSpace>
  <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>
  <exif:ExifVersion>0231</exif:ExifVersion>
  <exif:FlashpixVersion>0100</exif:FlashpixVersion>
</rdf:Description>

<rdf:Description rdf:about=''
  xmlns:photoshop='http://ns.adobe.com/photoshop/1.0/'>
  <photoshop:Headline/>
  <photoshop:Instructions/>
  <photoshop:SupplementalCategories>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </photoshop:SupplementalCategories>
  <photoshop:TransmissionReference/>
</rdf:Description>

<rdf:Description rdf:about=''
  xmlns:tiff='http://ns.adobe.com/tiff/1.0/'>
  <tiff:BitsPerSample>
   <rdf:Seq>
    <rdf:li>8</rdf:li>
   </rdf:Seq>
  </tiff:BitsPerSample>
  <tiff:ImageLength>1</tiff:ImageLength>
  <tiff:ImageWidth>1</tiff:ImageWidth>
  <tiff:Orientation>1</tiff:Orientation>
  <tiff:ResolutionUnit>2</tiff:ResolutionUnit>
  <tiff:XResolution>72/1</tiff:XResolution>
  <tiff:YCbCrPositioning>1</tiff:YCbCrPositioning>
  <tiff:YCbCrSubSampling>
   <rdf:Seq>
    <rdf:li>2</rdf:li>
    <rdf:li>2</rdf:li>
   </rdf:Seq>
  </tiff:YCbCrSubSampling>
  <tiff:YResolution>72/1</tiff:YResolution>
</rdf:Description>

<rdf:Description rdf:about=''
  xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
  <xmp:Advisory>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </xmp:Advisory>
  <xmp:MetadataDate>2020-03-31T17:20:17-04:00</xmp:MetadataDate>
</rdf:Description>

<rdf:Description rdf:about=''
  xmlns:xmpRights='http://ns.adobe.com/xap/1.0/rights/'>
  <xmpRights:Owner>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </xmpRights:Owner>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end='w'?>


As you can see, there are a number of oddities in the resulting XMP:


       
  • The schemas "CS1" and "CS1asc" end up sharing fields and values in the XMP, even though their values from JSON are distinct.  In fact, I didn't even send data for "CS1asc", and yet it received values based on the values of "CS1".  Is it simply because they share tag names?  Do tag names have to be "universally" unique?
  • In "cs2", you can see the list field in the values sent, but it does not appear in the XMP.  However, the list field from the "standard" schema (XMP-dc, field dc:subject) appears correctly.  I assume we are configuring something wrong that is causing the bags for custom schemas to fail, but we cannot figure out what.
  • Occasionally, when a list fails, there are other "missing" fields in the resulting XMP.  My assumption is that whatever caused the list/bag to fail also causes the following fields in that schema to not be written.  However, the error stream reports nothing.  Is this how the system would behave, or is there some other issue going on here?
  • Due to having to stamp a temp jpg, we receive extra TIFF schemas (with resolution 1x1) - we would love to not have this, but so far haven't found a way around it.

We also aren't sure if the jpg intermediate step might be the source of the problem.  We would love it if we could write the JSON directly to XMP (there was a post shared by a team member here: https://exiftool.org/forum/index.php?topic=9801.0), but those examples have failed for us due to either claiming that there was "nothing to write", or (if we write directly to a file instead of a stream, using command exiftool -config tag.config -j=test.json test.xmp) that "no SourceFile 'test.xmp' in imported JSON database" - even if we have altered the JSON to include * or the xmp file name.

So, in summary:


  • We are not sure if we are properly configuring our exiftool config for exporting custom bag fields to XMP
  • We would love to write JSON directly to XMP without an intermediary JPG, but haven't been able to get it to work
  • We are having some duplicate values written between disparate schemas, and we are not sure why

Any help will be appreciated.  Many thanks.

Phil Harvey

Quote from: cidthecoatrack on April 01, 2020, 03:15:11 PM
We then extract from the jpg into the XMP file with the command exiftool -config tags.config /tmp/temp.jpg -o -.xmp .

Instead, try this:

exiftool -config tags.config /tmp/temp.jpg -o -.xmp -all:all

Without -all:all, ExifTool feels free to move tags to their preferred groups.  The -tagsFromFile documentation details this, but it may not be obvious that this applies here because you are using the -tagsFromFile option implicitly when the output is a different file format.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

cidthecoatrack

Hey Paul,

Thanks again.  The -all:all did help with the duplicate field values - I now see the distinct values between the tags in different schemas.  Also, the 1x1 tiff data from the intermediary jpg is now gone, which is excellent.  However, the other issues around the bags still persist (they do not write, and other random fields presumably "after" them also do not write).

Here is the new XMP:


<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 11.29'>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>

<rdf:Description rdf:about=''
  xmlns:CS1='http://cs1.com'>
  <CS1:ImageDate>2020-02-21T00:00:00.0-05:00</CS1:ImageDate>
  <CS1:TalentName>Alejandro Naranjo</CS1:TalentName>
</rdf:Description>

<rdf:Description rdf:about=''
  xmlns:CS1acs='http://essex.com'>
  <CS1acs:TalentName>Wisp</CS1acs:TalentName>
</rdf:Description>

<rdf:Description rdf:about=''
  xmlns:cs2='http://custom-schema.com/2'>
  <cs2:MyCheckbox>True</cs2:MyCheckbox>
  <cs2:MyText>this is my text</cs2:MyText>
</rdf:Description>

<rdf:Description rdf:about=''
  xmlns:dc='http://purl.org/dc/elements/1.1/'>
  <dc:contributor>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </dc:contributor>
  <dc:creator>
   <rdf:Seq>
    <rdf:li/>
   </rdf:Seq>
  </dc:creator>
  <dc:relation>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </dc:relation>
  <dc:subject>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </dc:subject>
  <dc:type>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </dc:type>
</rdf:Description>

<rdf:Description rdf:about=''
  xmlns:photoshop='http://ns.adobe.com/photoshop/1.0/'>
  <photoshop:Headline/>
  <photoshop:Instructions/>
  <photoshop:SupplementalCategories>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </photoshop:SupplementalCategories>
  <photoshop:TransmissionReference/>
</rdf:Description>

<rdf:Description rdf:about=''
  xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
  <xmp:Advisory>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </xmp:Advisory>
  <xmp:Identifier>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </xmp:Identifier>
</rdf:Description>

<rdf:Description rdf:about=''
  xmlns:xmpRights='http://ns.adobe.com/xap/1.0/rights/'>
  <xmpRights:Marked>False</xmpRights:Marked>
  <xmpRights:Owner>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </xmpRights:Owner>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end='w'?>


Is there anything regarding the configuration for the custom schemas with bags that are bags that seems incorrect, or needs adjusting?

Phil Harvey

OK, so it seems that I only addressed your point number 3:

Quote1.We are not sure if we are properly configuring our exiftool config for exporting custom bag fields to XMP
2. We would love to write JSON directly to XMP without an intermediary JPG, but haven't been able to get it to work
3. We are having some duplicate values written between disparate schemas, and we are not sure why

For point 2.  What is the exact problem?  You should be able to just specify an XMP file name instead of a JPG file when importing your JSON file.

For point 1.  I don't understand the problem...  There is a lot to wade through in your first post and I don't have much time right now.  Would it be possible to demonstrate the Bag problem with a simpler example?

Also, with the steps I understand that you took, I don't see why XMP-cs2 tags should appear in the output XMP of your last post.  Did they exist in the JPG file to begin with?  They aren't in your JSON file.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

cidthecoatrack

Sorry for the confusion, Paul.  It seems I accidentally posted a different XMP file in that response.

So I did some tweaking of the "direct to json" approach for our context, and it seems to be working now, which is excellent.  That leaves only the issues with Bags and "missing fields"

So, as a simplified example, here is sample input JSON:


{
    "sourceFile": "/tmp/temp.xmp",
    "xmP-dc:Format": "image/jpeg",
    "xmP-dc:Contributor": "",
    "xmP-dc:Creator": "",
    "xmP-dc:Relation": "",
    "xmP-dc:Subject": [
        "this",
        "is",
        "a",
        "tag",
        "field"
    ],
    "xmP-dc:Type": "",
    "xmP-dc:Description": "",
    "ifD0:Orientation": "Horizontal (normal)",
    "xmP-CS1:IsTalent": false,
    "xmP-CS1:TalentName": "Alejandro Naranjo",
    "xmP-CS1:ImageDate": "2020:02:21 00:00:00.0-05:00",
    "xmP-CS1:TalentTags": [
        "short",
        "happy",
        "kind"
    ]
}


Here is the config:


%Image::ExifTool::UserDefined::Shortcuts=(GEDefaultTags=>['XMP-CS1:TalentName','XMP-CS1:TalentTags','XMP-CS1:ImageDate','XMP-CS1:BadMoon','XMP-CS1:IsTalent','XMP-dc:Contributor','XMP-dc:Coverage','XMP-dc:Creator','XMP-dc:Date','XMP-dc:Description','XMP-dc:Format','XMP-dc:Identifier','XMP-dc:Language','XMP-dc:Publisher','XMP-dc:Relation','XMP-dc:Rights','XMP-dc:Source','XMP-dc:Subject','XMP-dc:Title','XMP-dc:Type','IFD0:Make','IFD0:Model','IFD0:Orientation','IFD0:XResolution','IFD0:YResolution','IFD0:ResolutionUnit']);
%Image::ExifTool::UserDefined = (
                                     'Image::ExifTool::XMP::Main' => {CS1 => {
                                         SubDirectory => {
                                             TagTable => 'Image::ExifTool::UserDefined::CS1'
                                             },
                                         }});
%Image::ExifTool::UserDefined::CS1 = (
                                           GROUPS        => { 0 => 'XMP', 1 => 'XMP-CS1', 2 => 'Image' },
                                           NAMESPACE     => { 'CS1' => 'http://cs1.com' },'TalentName' => { Writable => 'string' },'TalentTags' => { List => 'Bag' },'ImageDate' => { Writable => 'date' },'BadMoon' => { List => 'Bag' },'IsTalent' => { Writable => 'boolean' });


And here is the resulting XMP after running exiftool -config tags.config -j=/tmp/temp.json /tmp/temp.xmp:


<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 11.29'>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>

<rdf:Description rdf:about=''
  xmlns:CS1='http://cs1.com'>
  <CS1:ImageDate>2020-02-21T00:00:00.0-05:00</CS1:ImageDate>
  <CS1:IsTalent>False</CS1:IsTalent>
  <CS1:TalentName>Alejandro Naranjo</CS1:TalentName>
</rdf:Description>

<rdf:Description rdf:about=''
  xmlns:dc='http://purl.org/dc/elements/1.1/'>
  <dc:contributor>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </dc:contributor>
  <dc:creator>
   <rdf:Seq>
    <rdf:li/>
   </rdf:Seq>
  </dc:creator>
  <dc:description>
   <rdf:Alt>
    <rdf:li xml:lang='x-default'/>
   </rdf:Alt>
  </dc:description>
  <dc:format>image/jpeg</dc:format>
  <dc:relation>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </dc:relation>
  <dc:subject>
   <rdf:Bag>
    <rdf:li>this</rdf:li>
    <rdf:li>is</rdf:li>
    <rdf:li>a</rdf:li>
    <rdf:li>tag</rdf:li>
    <rdf:li>field</rdf:li>
   </rdf:Bag>
  </dc:subject>
  <dc:type>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </dc:type>
</rdf:Description>


You can see that for the list in dc:subject, the list was exported.  However, the list for xmP-CS1:TalentTags did not export to the XMP.  Also, for some reason, the IFD0:Orientation did not export - in fact, the whole IFD0 schema did not export.  So questions:


  • What in the config for the cs1 schema is incorrect for exporting a list?
  • Is IFD0 not supported for export to XMP, or is there some additional parameter to the command needed?  I tried with -all:all, but it did not like that

StarGeek

Quote from: cidthecoatrack on April 03, 2020, 10:57:40 AM
Sorry for the confusion, Paul.

*cough*Phil*cough*  ;)

QuoteAlso, for some reason, the IFD0:Orientation did not export - in fact, the whole IFD0 schema did not export.
<...>
  • Is IFD0 not supported for export to XMP, or is there some additional parameter to the command needed?  I tried with -all:all, but it did not like that

IDF0 is part of the EXIF group, not XMP.  Using -All:All will only copy XMP to XMP.  Since there is, by definition, no EXIF in the XMP group, it won't get copied. 

If you need only specific EXIF tags copied, you can explicitly copy them.  For example, let's say you want to copy Orientation and Software EXIF tags.  The first has an exact match in XMP, while the second has an appropriate tag with a different name.  You would have to add this to your command
-Orientation  "-XMP-xmp:CreatorTool<EXIF:Software"

If you want to copy all EXIF tags into the correct XMP locations, then you could use the exif2xmp.args file, specifically -@ /path/to/exif2xmp.args.  You would want to make sure that the -all:all follows afterwards to make sure the XMP tags have priority, -@ /path/to/exif2xmp.args -all:all

Those are the basics, but I'm not sure how this might have to be changed since you're using a json file.  Phil can weigh in if there's something that needs changing.
"It didn't work" isn't helpful. What was the exact command used and the output.
Read FAQ #3 and use that cmd
Please use the Code button for exiftool output

Please include your OS/Exiftool version/filetype

cidthecoatrack

Quote*cough*Phil*cough*  ;)

*facepalm* Sorry.

Phil Harvey

...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

cidthecoatrack

So after using the exif2xmp.args, we have regressed some.  The custom schemas (cs1) have disappeared, and the IDF0 has also not written to the XMP.

Command: exiftool -@ exif2xmp.args -config tags.config -j=/tmp/temp.json /tmp/temp.xmp

Result:


<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 11.29'>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>

<rdf:Description rdf:about=''
  xmlns:dc='http://purl.org/dc/elements/1.1/'>
  <dc:contributor>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </dc:contributor>
  <dc:creator>
   <rdf:Seq>
    <rdf:li/>
   </rdf:Seq>
  </dc:creator>
  <dc:description>
   <rdf:Alt>
    <rdf:li xml:lang='x-default'/>
   </rdf:Alt>
  </dc:description>
  <dc:format>image/jpeg</dc:format>
  <dc:relation>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </dc:relation>
  <dc:subject>
   <rdf:Bag>
    <rdf:li>this</rdf:li>
    <rdf:li>is</rdf:li>
    <rdf:li>a</rdf:li>
    <rdf:li>tag</rdf:li>
    <rdf:li>field</rdf:li>
   </rdf:Bag>
  </dc:subject>
  <dc:type>
   <rdf:Bag>
    <rdf:li/>
   </rdf:Bag>
  </dc:type>
</rdf:Description>


While getting the EXIF fields written to the XMP is also something important, the primary concern here is that, for the custom schemas, the list-bags don't write.  They do for standard schemas, but not custom.

Phil Harvey

The -config option must come first.  There would have been a warning to this effect that you didn't see for some reason.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

cidthecoatrack

That helped some - at least the custom schemas have appeared again.  But the list-bags are still missing from the custom schemas, and the IFD0 schema does not appear. :(

cidthecoatrack

ALRIGHTY, we got some more information.  I added a -v3 to the command, and I got the following output:


Warning: Error opening file - /tmp/b4b2295c-86cc-4590-9bc0-4538b442ed3b.xmp
Sorry, file:ImageHeight doesn't exist or isn't writable
Sorry, file:ImageWidth doesn't exist or isn't writable
Sorry, xmP-CS1:TalentTags is not writable
Invalid date/time (use YYYY:mm:dd HH:MM:SS[.ss][+/-HH:MM|Z]) for XMP-CS1acs:ImageDate
     1 image files created


So, takeaways:


  • I don't know why the TalentTags isn't writable - is the configuration as 'TalentTags' => { List => 'Bag' } incorrect?  The data is in the same format in the JSON as the dc:subject tag, and that tag writes correctly to the XMP
  • The file tags aren't writable - even with the exif2xmp args. Is there anything that can be done about that, or will file tags never be written to the XMP?
  • The image date in the JSON is "xmP-CS1:ImageDate": "2020:02:21 00:00:00.0-05:00" - I know this is a dumb question, but am I missing something?  It seems to be the same as what the requested format is

Hopefully we're closing in on whatever the issue is.  Thanks for your time and patience.

StarGeek

It would help to see the exact command you used.

With regards to File:ImageHeight and File:ImageWidth, those are never writable.  They are the dimensions of the image taken directly from the file.  There is XMP-exif:ExifImageHeight/ExifImageWidth and XMP-tiff:ImageHeight/ImageWidth though.  The exif2xmp.args will copy the EXIF:ExifImageHeight/ExifImageWidth to the first two tags.
"It didn't work" isn't helpful. What was the exact command used and the output.
Read FAQ #3 and use that cmd
Please use the Code button for exiftool output

Please include your OS/Exiftool version/filetype

Phil Harvey

Add this after the NAMESPACE definition in all of your tables:

    WRITABLE => 'string',

This will make your List tags writable.  (You could either do this or add Writable => 'string', to each of these definitions)  With this addition the Writable => 'string' properties for other tags may be removed.

To fix the 'date' problem, the tag definitions should look like this:

ImageDate => {
    Groups => { 2 => 'Time' },
    Writable => 'date',
    Shift => 'Time',
    Validate => 'ValidateXMPDate($val)',
    PrintConv => '$self->ConvertDateTime($val)',
    PrintConvInv => '$self->InverseDateTime($val,undef,1)',
},


The PrintConvInv is what you were missing to be able to write the tag, but for completeness I've added everything else that was missing as well.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

cidthecoatrack

And we have success!  Thanks everyone for your help with this.  And, for future reference, here is the config I eventually used, as well as the command I ran as well:

Config (simplified):

%Image::ExifTool::UserDefined::Shortcuts=(GEDefaultTags=>['XMP-dc:Contributor','XMP-dc:Coverage','XMP-dc:Creator','XMP-dc:Date','XMP-dc:Description','XMP-dc:Format','XMP-dc:Identifier','XMP-dc:Language','XMP-dc:Publisher','XMP-dc:Relation','XMP-dc:Rights','XMP-dc:Source','XMP-dc:Subject','XMP-dc:Title','XMP-dc:Type','XMP-CS1acs:ImageDate','XMP-CS1acs:TalentName','XMP-CS1:TalentName','XMP-CS1:TalentTags','XMP-CS1:ImageDate','XMP-CS1:BadMoon','XMP-CS1:IsTalent','XMP-cs2:MyList','XMP-cs2:MyText','XMP-cs2:MyCheckbox','XMP-cs2:MyDate','File:ImageWidth','File:ImageHeight']);
%Image::ExifTool::UserDefined = (
                                     'Image::ExifTool::XMP::Main' => {CS1acs => {
                                         SubDirectory => {
                                             TagTable => 'Image::ExifTool::UserDefined::CS1acs'
                                             },
                                         },CS1 => {
                                         SubDirectory => {
                                             TagTable => 'Image::ExifTool::UserDefined::CS1'
                                             },
                                         },cs2 => {
                                         SubDirectory => {
                                             TagTable => 'Image::ExifTool::UserDefined::cs2'
                                             },
                                         }});
%Image::ExifTool::UserDefined::CS1acs = (
                                           GROUPS        => { 0 => 'XMP', 1 => 'XMP-CS1acs', 2 => 'Image' },
                                           NAMESPACE     => { 'CS1acs' => 'http://essex.com' },'ImageDate' => { Groups => { 2 => 'Time' },
                     Writable => 'date',
                     Shift => 'Time',
                     Validate => 'ValidateXMPDate($val)',
                     PrintConv => '$self->ConvertDateTime($val)',
                     PrintConvInv => '$self->InverseDateTime($val,undef,1)' },'TalentName' => { Writable => 'string' });
%Image::ExifTool::UserDefined::CS1 = (
                                           GROUPS        => { 0 => 'XMP', 1 => 'XMP-CS1', 2 => 'Image' },
                                           NAMESPACE     => { 'CS1' => 'http://cs1.com' },'TalentName' => { Writable => 'string' },'TalentTags' => { List => 'Bag', Writable => 'string' },'ImageDate' => { Groups => { 2 => 'Time' },
                     Writable => 'date',
                     Shift => 'Time',
                     Validate => 'ValidateXMPDate($val)',
                     PrintConv => '$self->ConvertDateTime($val)',
                     PrintConvInv => '$self->InverseDateTime($val,undef,1)' },'BadMoon' => { List => 'Bag', Writable => 'string' },'IsTalent' => { Writable => 'boolean' });
%Image::ExifTool::UserDefined::cs2 = (
                                           GROUPS        => { 0 => 'XMP', 1 => 'XMP-cs2', 2 => 'Image' },
                                           NAMESPACE     => { 'cs2' => 'http://custom-schema.com/2' },'MyList' => { List => 'Bag', Writable => 'string' },'MyText' => { Writable => 'string' },'MyCheckbox' => { Writable => 'boolean' },'MyDate' => { Groups => { 2 => 'Time' },
                     Writable => 'date',
                     Shift => 'Time',
                     Validate => 'ValidateXMPDate($val)',
                     PrintConv => '$self->ConvertDateTime($val)',
                     PrintConvInv => '$self->InverseDateTime($val,undef,1)' });


Command: exiftool -config tags.config -@ exif2xmp.args -v3 -j=temp.json temp.xmp