MWG Keywords Conversion user defined tags

Started by StarGeek, July 16, 2018, 03:54:51 PM

Previous topic - Next topic

StarGeek

Here's a config file to copy MWG Keywords to HierarchicalSubject and to do the reverse.  Inspired by this post from @colink.

As usual with the stuff I do, it has had limited testing and there are probably some edge cases where it will fail (keywords with pipe characters come to mind, is a pipe character in a keyword legal in HierarchicalSubject?).  But using the hierarchy mentioned in the MWG pdf (with the addition of a keyword without a hierarchy), it seems to work.  Any tweaks, suggestions, or examples of problems to be fixed are welcome.

HS is a shortcut I created in my config file for HierarchicalSubject, as I find it easier to type out and always forget how to spell Hierarchical. 

To be honest, I have doubts this will get used as I don't know of any software that actually uses MWG Keywords.  But it was a good learning experience and if someone does actually find it useful, all the better.

Example output:
C:\>exiftool -echo "List tags at start" -g1 -a -s -hs -XMP-mwg-kw:all y:\!temp\Test3.jpg
List tags at start
---- XMP-lr ----
HierarchicalSubject             : No Hierarchy Keyword, Animals|Mammals|Dog, Animals|Mammals|Cat, People|Georgia, People|Cat, Places|States|Georgia, Places|States|Wyoming

C:\>exiftool -config MWGKeywordsConversion.config -echo "Copy HS to MWG" -P -overwrite_original "-KeywordInfo<HSToMWGKeywords" y:\!temp\Test3.jpg
Copy HS to MWG
    1 image files updated

C:\>exiftool -echo "List tags after copy" -g1 -a -s -hs -XMP-mwg-kw:all y:\!temp\Test3.jpg
List tags after copy
---- XMP-lr ----
HierarchicalSubject             : No Hierarchy Keyword, Animals|Mammals|Dog, Animals|Mammals|Cat, People|Georgia, People|Cat, Places|States|Georgia, Places|States|Wyoming
---- XMP-mwg-kw ----
HierarchicalKeywords3           : Dog, Cat, Georgia, Wyoming
HierarchicalKeywords2           : Mammals, States, Cat, Georgia
HierarchicalKeywords1           : Animals, Places, People, No Hierarchy Keyword

C:\>exiftool -echo "List Struct after copy" -g1 -a -s -hs -XMP-mwg-kw:all -struct y:\!temp\Test3.jpg
List Struct after copy
---- XMP-lr ----
HierarchicalSubject             : [No Hierarchy Keyword,Animals||Mammals||Dog,Animals||Mammals||Cat,People||Georgia,People||Cat,Places||States||Georgia,Places||States||Wyoming]
---- XMP-mwg-kw ----
KeywordInfo                     : {Hierarchy=[{Children=[{Children=[{Keyword=Dog},{Keyword=Cat}],Keyword=Mammals}],Keyword=Animals},{Children=[{Children=[{Keyword=Georgia},{Keyword=Wyoming}],Keyword=States}],Keyword=Places},{Children=[{Keyword=Cat},{Keyword=Georgia}],Keyword=People},{Keyword=No Hierarchy Keyword}]}

C:\>exiftool -echo "Clear HierarchicalSubject" -P -overwrite_original -hs= y:\!temp\Test3.jpg
Clear HierarchicalSubject
    1 image files updated

C:\>exiftool -config MWGKeywordsConversion.config -echo "Copy MWG Keywords to HierarchicalSubject" -P -overwrite_original "-HierarchicalSubject<MWGKeywordsToHS" y:\!temp\Test3.jpg
Copy MWG Keywords to HierarchicalSubject
    1 image files updated

C:\>exiftool -echo "List tags at end" -g1 -a -s -hs -XMP-mwg-kw:all y:\!temp\Test3.jpg
List tags at end
---- XMP-lr ----
HierarchicalSubject             : Animals|Mammals|Dog, Animals|Mammals|Cat, Places|States|Georgia, Places|States|Wyoming, People|Cat, People|Georgia, No Hierarchy Keyword
---- XMP-mwg-kw ----
HierarchicalKeywords3           : Dog, Cat, Georgia, Wyoming
HierarchicalKeywords2           : Mammals, States, Cat, Georgia
HierarchicalKeywords1           : Animals, Places, People, No Hierarchy Keyword


Config file (also attached at end):
#------------------------------------------------------------------------------
# File:         MWGKeywordsConversion.config
#
# Description:  User-defined Composite tag definitions to convert MWG:Keywords
#               to HierarchicalSubject and HierarchicalSubject to MWG:Keywords.
#
# Tag definitions and examples:
#
#   MWGKeywordsToHS
# Creates a HierarchicalSubject List from a MWG KeywordInfo structure that
# can be copied to HierarchicalSubject.
#
# Example:
# exiftool -config MWGKeywordsConversion.config "-HierarchicalSubject<MWGKeywordsToHS" FilesOrDirs
#
# HSToMWGKeywords
# Creates a MWG KeywordInfo structure from HierarchicalSubject that
# can be copied to KeywordInfo.
#
# Example:
# exiftool -config MWGKeywordsConversion.config "-KeywordInfo<HSToMWGKeywords" FilesOrDirs
#
# Revisions:    2018/05/28 - Bryan K. Williams (aka StarGeek) Created
#------------------------------------------------------------------------------


# Main recursive array to convert MWG:Keywords to HierarchicalSubject
sub RecurseArray{
# $_ is array ref
($_)=@_;
my $tempKeyword='';
my %a;
my @Return_Array=();
foreach $a (@$_){
$tempKeyword=%$a{'Keyword'};
if (defined %$a{'Children'}) {
my $arr_ref = %$a{'Children'};
my @x = map{ $_= $tempKeyword.'|'.$_ } RecurseArray($arr_ref);
push @Return_Array, @x;
}
else {
push @Return_Array, $tempKeyword;
}
}
return (@Return_Array);
}


# Builds Hierarchy hash out of Hierarchical Subject
# Easier than trying to add each section of all the
# HierarchicalSubject entries individually
# Blatently stolen from this StackOverflow answer
# https://stackoverflow.com/a/4559059/3525475
sub BuildTree{
   my $hash = shift;
   return unless @_;
   return BuildTree($hash->{shift()} //= {}, @_);
}

# Builds MWGKeywords HashRefKey
# Input: Hash tree result from BuildTree, Array Reference
sub RecurseHS{
my $hashref = shift;
my $ArrRef  = shift;
foreach my $key (keys %$hashref){
my @TempArr;
# Check if there are children for this section of the tree
# If there are, recurse then add Keyword value and Children array
# else add just Keyword value.
if (%{$hashref->{$key}}) {
RecurseHS($hashref->{$key},\@TempArr);
push @{$ArrRef}, { 'Keyword' => $key, 'Children'=>\@TempArr} ;
}
else{
push @{$ArrRef}, { 'Keyword' => $key} ;
}
}
return
}

%Image::ExifTool::UserDefined = (
'Image::ExifTool::Composite' => {
MWGKeywordsToHS =>{
Require => { 0 => 'KeywordInfo'},
ValueConv => sub {
my ($val, $et) = @_;
my $MainArray_Ref = (${@$val[0]}{'Hierarchy'});
my @A = RecurseArray($MainArray_Ref);
return @A ? \@A : undef;
},
},
HSToMWGKeywords => {
Require => 'HierarchicalSubject',
ValueConv => sub{
my ($val, $et) = @_;
my %HashTree;
my $HSArray_Ref =$val->[0];
foreach my $HS (@{$HSArray_Ref}){
BuildTree(\%HashTree,split(m!\|!,$HS));
}
my $hashref = \%HashTree;
my @HierArr;
RecurseHS($hashref,\@HierArr);
my %KeywordInfo;
$KeywordInfo{'Hierarchy'}=\@HierArr;
return \%KeywordInfo;
},
},
########
},
);
1;  #end
* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).