ExifTool Forum

ExifTool => The Image::ExifTool API => Topic started by: yosh on May 17, 2017, 11:19:47 AM

Title: Recognizing list-type fields
Post by: yosh on May 17, 2017, 11:19:47 AM
Hey, I'm trying to make an action that handles all possible IPTC moves (from single record to single, single to list-type, list-type to single (joined) and list-type to list-type). The problem is when I try to move one list-type record into another list-type record that has only one value, i.e. put all keywords into by-line tags. So in fact I want to change all 2:25 (1C 02 19) to 2.80 (1C 02 50).

Is there a fast way to tell if the destination record is of list-type by standard, and not check it's current values?

Currently trying something like this but the destination isn't always of type 'ARRAY'.

if (ref $record_from eq 'ARRAY' && ref $record_to eq 'ARRAY') {
       foreach (@$record_from) {
     $exifTool->SetNewValue($record_too, $_, AddValue => 1);
     $exifTool->SetNewValue($record_from, $_, DelValue => 1);
       }
}


Or maybe there is a better way and I don't have to check the type of source and destination fields? :)

Also, bonus question.... Is it safe to use this solution to get tag names by number?

my $record = 2;
my $number = 80;
my $tagname = Image::ExifTool::GetTagTable( $Image::ExifTool::IPTC::Main{$record}{SubDirectory}{TagTable} )->{$number}{Name}; #= By-line


Thanks in advance!
Title: Re: Recognizing list-type fields
Post by: Phil Harvey on May 17, 2017, 04:07:34 PM
How are you joining the lists?  If you can join them so they can be split again, you can just do this:

$exifTool->Options(List => 0);
$exifTool->Options(ListSep => ', ');
$exifTool->Options(ListSplit => ', ');
# then just do this for all tags:
$exifTool->SetNewValue($tag, $val);


If it is a List-type tag, then the value will be split apart again.

For the bonus:  It really isn't safe in that you are accessing private ExifTool data structures, but these aren't likely to change so your code should work for the foreseeable future.

You shouldn't, however, use a table without calling GetTagTable() first.  So you should do this:

my $record = 2;
my $number = 80;
my $iptcTable = Image::ExifTool::GetTagTable('Image::ExifTool::IPTC::Main');
my $tagname = Image::ExifTool::GetTagTable( $iptcTable{$record}{SubDirectory}{TagTable} )->{$number}{Name}; #= By-line


- Phil
Title: Re: Recognizing list-type fields
Post by: yosh on May 19, 2017, 04:47:25 AM
Thank you! I am testing it now and it seems to work great.

I have another question though. Is there a method like "commit" or "update" that updates the metadata in memory before writing it to file?

I allow users to define a list of actions to perform. For example:

1) Delete keywords
$exifTool->SetNewValue('Keywords');
2) Set new keyword
$exifTool->SetNewValue('Keywords', 'word1');
3) Add new keyword
$exifTool->SetNewValue('Keywords', 'word2', AddValue=>1);

This results in all the previously deleted keywords being brought back. Is there any sync/update method to call? SaveNewValues() called after each action doesn't seem to do that.

Also fixed the IptcTable to include calling that method, thanks!
Title: Re: Recognizing list-type fields
Post by: Phil Harvey on May 19, 2017, 07:20:04 AM
I think you are confused about the function of AddValue.  This is only used to preserve existing entries in the file.

If you want to replace existing keywords with "word1", "word2", just do this:

$exifTool->SetNewValue(Keywords => 'word1');
$exifTool->SetNewValue(Keywords => 'word2');


- Phil
Title: Re: Recognizing list-type fields
Post by: yosh on May 22, 2017, 04:06:25 AM
No, I understand how AddValue works.
Just hoped I could do something to use it without bringing back previously deleted content of that record.

This is great, thank you!
Title: Re: Recognizing list-type fields
Post by: Phil Harvey on May 22, 2017, 05:30:07 PM
If you want to delete a specific value, then use DelValue.  If you want to replace all existing list values from a file, then you don't use either DelValue or AddValue.

- Phil