how to get the tag name for a tag ID in a group?

Started by dae65, August 01, 2020, 06:26:52 AM

Previous topic - Next topic

dae65

Here is a quick and dirty way to find out what tag name a tag ID was assigned in a (QuickTime) group:

#!/usr/bin/perl -w
use strict;
my $group = shift // 'ItemList';
my $id = shift // "\xa9day";
say STDOUT ref ? $_->{Name} : $_ for do
{
  no strict 'refs';
  require Image::ExifTool::QuickTime;
  my $var = "Image::ExifTool::QuickTime::$group";
  ${$var}{$id};
};


Does the API provide a better way to get the tag name corresponding to a tag ID in a group?

Thanks

Phil Harvey

There is no way to do this in general.  The tag name may depend on other metadata in the file, so you won't know the actual tag name until a file is processed.

But for simple tags (ie. when ${$var}{$id} returns a HASH reference and not an ARRAY reference, then what you are doing is close, but instead requiring the table, you should do this:

my $table = Image::ExifTool::GetTagTable("Image::ExifTool::QuickTime::$group");

to prepare the table for access.

- 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 ($).

dae65

Excellent. Thanks. :) The Image::ExifTool::GetTagTable function ensures that tag IDs map, never to scalars, but always to hash references with a Name key, doesn't it? (So, there is no need to test for ref.)


#!/usr/bin/perl -w
use strict;
use Image::ExifTool;
my $type  = shift // 'QuickTime';
my $group = shift // 'ItemList';
my $id    = shift // "\xa9day";
my $table = Image::ExifTool::GetTagTable ( "Image::ExifTool::${type}::${group}" ) or exit;
my $tag = $table->{$id} or exit;
say STDOUT $tag->{Name};

Phil Harvey

Yes.  After calling GetTagTable() the ID's will always map to a HASH ref or an ARRAY of HASH refs.  And Name is guaranteed to exist.  (Not that I recommend accessing ExifTool internals like this, but this is not likely to change.)

- 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 ($).

dae65

#4
Quote from: Phil Harvey on August 03, 2020, 09:44:23 PM
(Not that I recommend accessing ExifTool internals like this, but this is not likely to change.)

I understand the risks. Let me explain the situation. Although the family 7 group names approach is working --- thanks for that --- family 7 group names are... well, group names; and so, an external app that only knows what IDs a file format uses, still needs to find out somehow what tag name an ID corresponds to according to Image::ExifTool, in order to be able use family 7 group names at all.

In other words, family 7 group names can disambiguate a tag, but can't specify a tag.

Ideally, I wish I could do without tag names, as I already have all the IDs. But I can't. What I can do now is either hard-code a table from IDs to names, or look up a table from GetTagTable() on the fly. Both ways, I'm making assumptions about ExifTool internals: after all, tag names may change just as much as GetTagTable().

For this reason, I'm writing an Image::ExifTool::ByID module with a ...ByID() family of wrapper methods that translate ID to names, ensure a group is specified, append :ID-<tag_id> to the group name, and then invoke standard methods such as SetNewValue().


Phil Harvey

Quote from: dae65 on August 04, 2020, 04:19:32 AM
an external app that only knows what IDs a file format uses, still needs to find out somehow what tag name an ID corresponds to according to Image::ExifTool, in order to be able use family 7 group names at all.

Knowing the ID, here is how you get the family 7 group name:

sub GetIDGroup($)
{
    my $id = shift;
    $id =~ s/([^-_A-Za-z0-9])/sprintf('%.2x',ord $1)/ge;
    return "ID-$id";
}


- 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 ($).

dae65

#6
Thanks. I couldn't make myself understood. Knowing the ID (albm), and generating a 7 group name from it (ID-albm), is not enough. We need the ExifTool tag name (Album) also.

This doesn't work:

$ exiftool -ItemList:ID-albm=ABCDEF file.m4a
Warning: Tag 'ItemList:ID-albm' is not defined or has a bad language code
Nothing to do.

It should be:

$ exiftool -ItemList:ID-albm:Album=ABCDEF file.m4a
    1 image files updated


As it seems, family 7 names may well disambiguate a tag, but they can't specify a tag. That's why I'm looking for a reliable way of getting names (Album) from IDs (albm).

Phil Harvey

Right.  I understand now.  Upon re-reading your post, this should have been clear.

- 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 ($).