Project

General

Profile

Converting ACDSee Categories to LightRoom Hierarchical

Added by Alan Pater over 6 years ago

ACDSee uses it's own XMP format to store hierarchical keywords. Is there some programmable way for exiv2 to convert these to LR Hierarchical keywords?

I created a test image (attached) and used a trial version of ACDSee to create hierarchical categories. This is what exiv2 reports:

Xmp.acdsee.categories  XmpText   137  <Categories><Category Assigned="0">ACDSee<Category Assigned="0">Pro<Category Assigned="1">8</Category></Category></Category></Categories>

An image with LR Hierarchical keywords has the following structure:

Xmp.lr.hierarchicalSubject                   XmpBag      1  lr|hierarchical|tags


Replies (14)

RE: Converting ACDSee Categories to LightRoom Hierarchical - Added by Robin Mills over 6 years ago

Alan

Good to hear from you. Andreas has accepted the challenge in 2015 to update the XMPsdk code in Exiv2 to the current offering from Adobe. Do you think that will be able to deal with this, or is something else required?

To be honest, I don't know what hierarchical keywords are! Are you expecting exiv2 to report keys such as (in your example):

Xmp.acdsee.categories.ACDSee.Pro 8
or something like that?

It's possible to post-process the tag with xmllint

649 rmills@rmillsmbp:/ $ exiv2 -pa -g Xmp.acdsee.categories ~/Downloads/acdsee.test.jpg | sed -e 's/.* </</'  | xmllint --format --pretty 1 -
<?xml version="1.0"?>
<Categories>
  <Category Assigned="0">ACDSee<Category Assigned="0">Pro<Category Assigned="1">8</Category></Category></Category>
</Categories>
650 rmills@rmillsmbp:/ $ 

RE: Converting ACDSee Categories to LightRoom Hierarchical - Added by Alan Pater over 6 years ago

Robin, likewise!

I doubt that the XMPsdk will make a difference in this, as ACDSee is using it's own custom XMP for these fields.

What I am looking for is to change this:

Xmp.acdsee.categories  XmpText   137  <Categories><Category Assigned="0">ACDSee<Category Assigned="0">Pro<Category Assigned="1">8</Category></Category></Category></Categories>
to:
Xmp.lr.hierarchicalSubject                   XmpBag      1  ACDSee|Pro|8

RE: Converting ACDSee Categories to LightRoom Hierarchical - Added by Robin Mills over 6 years ago

Alan

I assume the 'likewise' is Good to hear from you !!

Right. I think I understand. When we see the tag "Xmp.acdsee.categories', we can parse the XML in the value into ACDSee|Pro|8 and change the "type" to XmpText (not too sure about your length of 1). If it wasn't so late, I think I could write down the XPath for the transformation. The library would use expat as it's already compiled and linked.

However, there's something missing in this puzzle. How do we know to transform 'acdsee.categories' to lr.hierarchicalSubject ? I can see three possibilities:

  1. If we see Xmp.foooooo.categories and the value has <Categories>..</Categories> we do the transformation -> Xmp.lr.hierarchicalSubject
  2. I recall you provided a patch last year about lr (lightroom) magic. Is that part of this?
  3. Something else that you know and I don't!

Robin

RE: Converting ACDSee Categories to LightRoom Hierarchical - Added by Alan Pater over 6 years ago

Yes, very nice to hear from you Robin! Is it spring yet in your corner of the planet?

What I had in mind was a way to do option 1, but manually, or in a script. It seems outside of the scope of exiv2 to internally convert tags from one form to another. The patch I provided allows exiv2 to write to lr.hierarchicalSubject, so that should make it possible.

So the question becomes, are there any script wizards out there that know how to use exiv2 to change acdsee.categories to lr.hierarchicalSubject?

RE: Converting ACDSee Categories to LightRoom Hierarchical - Added by Robin Mills over 6 years ago

Yes, it's a beautiful spring day in England. We retired last year and returned from California in June to our 'old' house in England. Very happy to be home after 14 happy years in California. I'll always love California (and Scotland).

I am a script wizard (bash, Python, Perl, JavaScript and others). I suspect this is an easy change to perform with expat inside the library.

Several questions:
  1. Are all xml strings simple: <Cs><C>.</C>.</C></C></Cs>, or can they be infinitely complicated?
  2. What happens if there is a | in the child? For example: <Category>in | dead | trouble</Category>
  3. What does "Assigned" mean?

I could add option "-L" to exiv2(.exe) -L = perform Lightroom Category XML substitution or I can just do it (not an option, just do it).

RE: Converting ACDSee Categories to LightRoom Hierarchical - Added by Alan Pater over 6 years ago

I'll go back into ACDSee and create some more complex examples, and ask some regular users of the program to supply some samples as well.

I interpret the <Category Assigned=" "> to indicate the level of nesting. 0 is top level, 1 is below that, etc. Let's see what happens with the complex samples.

RE: Converting ACDSee Categories to LightRoom Hierarchical - Added by Robin Mills over 6 years ago

That's fine, Alan. Let me know when you have your arms around this one.

I'm not very confident about your explanation of "Assigned". The values in the example are 0,0,1. The nesting is <C><C><C></C></C></C>. XML intrinsically defines nesting - you don't need "Assigned" to confuse matters. However - you go and find out more about this.

As always, can I ask about the business case here. Why are you interested in this? It's odd that Adobe's XMLsdk doesn't deal with this when it involves their application Lightroom.

Once we have this task defined, let's open an "Issue/feature" to track this.

RE: Converting ACDSee Categories to LightRoom Hierarchical - Added by Alan Pater over 6 years ago

You are right, the values in the example don't make sense, I'll have to look further into that. Once I have it figured out, I'll present the business case, assuming I can come up with one!

Categories is from the ACDSee program, not from Lightroom.

RE: Converting ACDSee Categories to LightRoom Hierarchical - Added by Alan Pater over 6 years ago

I created a complex example, with 6 Categories with different levels of nested tags. See attached screenshot.

Exiv2 shows it as:

Xmp.acdsee.categories XmpText <Categories><Category Assigned="1">1 Level</Category><Category Assigned="1">2 Level<Category Assigned="1">2.2 Level</Category></Category><Category Assigned="1">3 Level<Category Assigned="1">3.2 Level<Category Assigned="1">3.3 Level</Category></Category></Category><Category Assigned="1">4 Level<Category Assigned="1">4.2 Level<Category Assigned="1">4.3 Level<Category Assigned="1">4.4 Level</Category></Category></Category></Category><Category Assigned="1">5 Level<Category Assigned="1">5.2 Level<Category Assigned="1">5.3 Level<Category Assigned="1">5.4 Level<Category Assigned="1">5.5 Level</Category></Category></Category></Category></Category><Category Assigned="1">6 Level<Category Assigned="1">6.2 Level<Category Assigned="1">6.3 Level<Category Assigned="1">6.4 Level<Category Assigned="1">6.5 Level<Category Assigned="1">6.6 Level</Category></Category></Category></Category></Category></Category></Categories>

Converted to Xmp.lr.hierarchicalSubject, I believe would look like this:

1 Level, 2 Level|2.2 Level, 3 Level|3.2 Level|3.3 Level, 4 Level|4.2 Level|4.3 Level|4.4 Level, 5 Level|5.2 Level|5.3 Level|5.4 Level|5.5 Level, 6 Level|6.2 Level|6.3 Level|6.4 Level|6.5 Level|6.6 Level

RE: Converting ACDSee Categories to LightRoom Hierarchical - Added by Alan Pater over 6 years ago

I now realize what the Assigned values are in ACDSee. Kind of obvious when one looks at it ...

Assigned="1" means that the category is actually assigned to the image.

Assigned="0" indicates a category one level up. It exists in the hierarchy but is not assigned to this particular image.

Categories that might exist lower in the hierarchy but that are not assigned to this image are missing from Xmp.acdsee.categories.

For example, I tagged "5.4 Level" in a test image. The result is:

<Category Assigned="0">5 Level
<Category Assigned="0">5.2 Level
<Category Assigned="0">5.3 Level
<Category Assigned="1">5.4 Level
In the ACDSee application, there is a "5.5 Level", but we cannot see this from the metadata written to the image.

RE: Converting ACDSee Categories to LightRoom Hierarchical - Added by Robin Mills over 6 years ago

Right. I think I've understood that and I believe this is easy to implement using the expat XML library used by exiv2.

I am puzzled by this request as it involves ACDC and LightRoom. Presumably a Lightroom Hierarchy is some kind of image tagging/searching feature. And ACDC has this 'Category' feature of similar intent. So you're asking for a feature to be added to convert ACDC tags to LR (we haven't discussed LR to ACDC).

I don't see what this has to do with Exiv2. Our mission is to correctly read/write metadata in images. I don't see an issue here for the Exiv2 Project.

Earlier in this discussion, I demonstrated that you can read the metadata from a tag in Exiv2 and process it with xmllint (or any utility of your choice). I should have pointed out that the output of that utility can be used to create a new tag to be written to the image.

I've written some perl (listed below) to "filter" the ACDC XML into the LR and create a new tag for the image. Something like:

tag=$(exiv2 -pa -g Xmp.acdsee.categories ~/Downloads/acdsee.test.jpg | sed -e 's/.* </</'  |  perl ACDSee.pl)
exiv2 -M"set Xmp.lr.hierarchicalSubject XmpBag '$tag'" ~/Downloads/acdsee.test.jpg
A bash warrior will soon boil this done to a single (incomprehensible) one-liner! And we could add an option -L (or something) to instruct the exiv2(.exe) application to perform this action. However you'll have to convince me that this is a necessary feature of exiv2(.exe).

Here's the Perl script (which I called ACDSee.pl)

#!/usr/bin/env perl

use XML::Parser::Expat;

my $recursion=0;
my $comma=0;

##
# process an start-of-element event
sub sh
{
    my ($expat, $el, %atts) = @_;
    print( $recursion++ > 0 ? '|' : $comma ++ > 0 ? ', ' : '') if ( $el eq 'Category' ) ;
}

##
# process a char (string) event
sub ch
{
    my ($expat, $el, %atts) = @_;
    print($el) if $recursion > 0
}

##
# process an end-of-element event
sub eh {
    my ($expat, $el) = @_;
    $recursion -- if $el eq 'Category';
}

$parser = new XML::Parser::Expat;
$parser->setHandlers('Start' => \&sh,'End' => \&eh,'Char'  => \&ch) ;
$parser->parse(*STDIN);
print("\n");

# That's all Folks!
##
I've tested it with your complicated XML string:
$ echo '<Categories><Category Assigned="1">1 Level</Category><Category Assigned="1">2 Level<Category Assigned="1">2.2 Level</Category></Category><Category Assigned="1">3 Level<Category Assigned="1">3.2 Level<Category Assigned="1">3.3 Level</Category></Category></Category><Category Assigned="1">4 Level<Category Assigned="1">4.2 Level<Category Assigned="1">4.3 Level<Category Assigned="1">4.4 Level</Category></Category></Category></Category><Category Assigned="1">5 Level<Category Assigned="1">5.2 Level<Category Assigned="1">5.3 Level<Category Assigned="1">5.4 Level<Category Assigned="1">5.5  Level</Category></Category></Category></Category></Category><Category Assigned="1">6 Level<Category Assigned="1">6.2 Level<Category Assigned="1">6.3 Level<Category Assigned="1">6.4 Level<Category Assigned="1">6.5 Level<Category Assigned="1">6.6 Level</Category></Category></Category></Category></Category></Category></Categories>' | perl ACDEsee.pl

1 Level, 2 Level|2.2 Level, 3 Level|3.2 Level|3.3 Level, 4 Level|4.2 Level|4.3 Level|4.4 Level, 5 Level|5.2 Level|5.3 Level|5.4 Level|5.5  Level, 6 Level|6.2 Level|6.3 Level|6.4 Level|6.5 Level|6.6 Level
$ 

RE: Converting ACDSee Categories to LightRoom Hierarchical - Added by Alan Pater over 6 years ago

Thank you very much, Robin. I appreciate all the time and effort you have put into my question. Not only has it resolved the issue for the most part but has also clarified my understanding of hierarchical keywords in image metadata.

I agree that this does not seem to be a good candidate for a new feature of exiv2(.exe) as it is more appropiate for higher level imaging applications to do these types of conversions internally.

Saludos,
Alan

RE: Converting ACDSee Categories to LightRoom Hierarchical - Added by Robin Mills over 6 years ago

I'm happy that you're happy. And thank you for saying thanks. You'd be surprised at how seldom users bother with such pleasantries. Right. Case closed. Onwards to places unknown.....

Have a nice weekend.

RE: Converting ACDSee Categories to LightRoom Hierarchical - Added by Robin Mills over 6 years ago

I have added a new option to exiv2(.exe) -pX to extract the XMP block from an image. With this option, you can easily extract the xml and process it with xmllint, perl, python, xslt or any external tool. r3650

515 rmills@rmillsmbp:~/clanmills $ exiv2 -pX ~/Downloads/BabyGnuTux-BigWLPG.jpg  | xmllint --pretty 1 --noblanks -
<?xml version="1.0"?>
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        ">
  <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:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" rdf:about="" xmp:CreatorTool="Adobe Photoshop CS5 Windows" xmp:CreateDate="2012-01-04T20:32:52+01:00" xmp:ModifyDate="2012-01-04T20:34:45+01:00" xmp:MetadataDate="2012-01-04T20:34:45+01:00" dc:format="image/jpeg" photoshop:ColorMode="3" photoshop:ICCProfile="sRGB IEC61966-2.1" xmpMM:InstanceID="xmp.iid:4E9C1E280B37E111A568FF94F417581A" xmpMM:DocumentID="xmp.did:4D9C1E280B37E111A568FF94F417581A" xmpMM:OriginalDocumentID="xmp.did:4D9C1E280B37E111A568FF94F417581A">
      <xmpMM:History>
        <rdf:Seq>
          <rdf:li stEvt:action="created" stEvt:instanceID="xmp.iid:4D9C1E280B37E111A568FF94F417581A" stEvt:when="2012-01-04T20:32:52+01:00" stEvt:softwareAgent="Adobe Photoshop CS5 Windows"/>
          <rdf:li stEvt:action="converted" stEvt:parameters="from image/png to image/jpeg"/>
          <rdf:li stEvt:action="saved" stEvt:instanceID="xmp.iid:4E9C1E280B37E111A568FF94F417581A" stEvt:when="2012-01-04T20:34:45+01:00" stEvt:softwareAgent="Adobe Photoshop CS5 Windows" stEvt:changed="/"/>
        </rdf:Seq>
      </xmpMM:History>
    </rdf:Description>
    <rdf:Description xmlns:MP="http://ns.microsoft.com/photo/1.2/">
      <MP:RegionInfo>
        <rdf:Description xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
          <MPRI:Regions xmlns:MPRI="http://ns.microsoft.com/photo/1.2/t/RegionInfo#">
            <rdf:Bag xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
              <rdf:li>
                <rdf:Description xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
                  <MPReg:Rectangle xmlns:MPReg="http://ns.microsoft.com/photo/1.2/t/Region#">0.661608, 0.244310, 0.130501, 0.261002</MPReg:Rectangle>
                  <MPReg:PersonDisplayName xmlns:MPReg="http://ns.microsoft.com/photo/1.2/t/Region#">Baby Tux</MPReg:PersonDisplayName>
                </rdf:Description>
              </rdf:li>
              <rdf:li>
                <rdf:Description xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
                  <MPReg:Rectangle xmlns:MPReg="http://ns.microsoft.com/photo/1.2/t/Region#">0.205615, 0.226100, 0.130501, 0.261002</MPReg:Rectangle>
                  <MPReg:PersonDisplayName xmlns:MPReg="http://ns.microsoft.com/photo/1.2/t/Region#">Baby Gnu</MPReg:PersonDisplayName>
                </rdf:Description>
              </rdf:li>
            </rdf:Bag>
          </MPRI:Regions>
        </rdf:Description>
      </MP:RegionInfo>
    </rdf:Description>
  </rdf:RDF>
</x:xmpmeta>
<?xpacket end='w'?>
516 rmills@rmillsmbp:~/clanmills $ 

    (1-14/14)