exiftool-vendored.exe 13.38.0 → 13.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/exiftool.exe CHANGED
Binary file
@@ -11,7 +11,7 @@ use strict;
11
11
  use warnings;
12
12
  require 5.004;
13
13
 
14
- my $version = '13.38';
14
+ my $version = '13.41';
15
15
 
16
16
  $^W = 1; # enable global warnings
17
17
 
@@ -89,6 +89,7 @@ END {
89
89
  # declare all static file-scope variables
90
90
  my @commonArgs; # arguments common to all commands
91
91
  my @condition; # conditional processing of files
92
+ my @csvExclude; # list of tags excluded from CSV import
92
93
  my @csvFiles; # list of files when reading with CSV option (in ExifTool Charset)
93
94
  my @csvTags; # order of tags for first file with CSV option (lower case)
94
95
  my @delFiles; # list of files to delete
@@ -454,6 +455,7 @@ if ($stayOpen >= 2) {
454
455
  # (not done: @commonArgs, @moreArgs, $critical, $binaryStdout, $helped,
455
456
  # $interrupted, $mt, $pause, $rtnValApp, $rtnValPrev, $stayOpen, $stayOpenBuff, $stayOpenFile)
456
457
  undef @condition;
458
+ undef @csvExclude;
457
459
  undef @csvFiles;
458
460
  undef @csvTags;
459
461
  undef @delFiles;
@@ -591,6 +593,7 @@ my $escapeXML; # flag to escape printed values for xml
591
593
  my $setTagsFile; # filename for last TagsFromFile option
592
594
  my $sortOpt; # sort option is used
593
595
  my $srcStdin; # one of the source files is STDIN
596
+ my $tagsFrom = ''; # tags on command line come from 'csv' or 'file'
594
597
  my $useMWG; # flag set if we are using any MWG tag
595
598
 
596
599
  my ($argsLeft, @nextPass, $badCmd);
@@ -825,6 +828,7 @@ for (;;) {
825
828
  }
826
829
  # create necessary lists, etc for this new -tagsFromFile file
827
830
  AddSetTagsFile($setTagsFile, { Replace => ($1 and lc($1) eq 'add') ? 0 : 1 } );
831
+ $tagsFrom = 'file';
828
832
  next;
829
833
  }
830
834
  if ($a eq '@') {
@@ -940,6 +944,7 @@ for (;;) {
940
944
  if ($csvFile) {
941
945
  push @newValues, { SaveCount => ++$saveCount }; # marker to save new values now
942
946
  $csvSaveCount = $saveCount;
947
+ $tagsFrom = 'csv';
943
948
  }
944
949
  next;
945
950
  }
@@ -1130,6 +1135,7 @@ for (;;) {
1130
1135
  push @nextPass, "-$_";
1131
1136
  push @newValues, { SaveCount => ++$saveCount }; # marker to save new values now
1132
1137
  $csvSaveCount = $saveCount;
1138
+ $tagsFrom = 'csv';
1133
1139
  next;
1134
1140
  }
1135
1141
  my $jsonFile = $2;
@@ -1378,10 +1384,12 @@ for (;;) {
1378
1384
  my $tag = shift;
1379
1385
  defined $tag or Error("Expecting tag name for -x option\n"), $badCmd=1, next;
1380
1386
  $tag =~ s/\ball\b/\*/ig; # replace 'all' with '*' in tag names
1381
- if ($setTagsFile) {
1382
- push @{$setTags{$setTagsFile}}, "-$tag";
1383
- } else {
1387
+ if (not $tagsFrom) {
1384
1388
  push @exclude, $tag;
1389
+ } elsif ($tagsFrom eq 'csv') {
1390
+ push @csvExclude, $tag;
1391
+ } else {
1392
+ push @{$setTags{$setTagsFile}}, "-$tag";
1385
1393
  }
1386
1394
  next;
1387
1395
  }
@@ -1424,9 +1432,15 @@ for (;;) {
1424
1432
  }
1425
1433
  } else {
1426
1434
  # assume '-tagsFromFile @' if tags are being redirected
1427
- # and -tagsFromFile hasn't already been specified
1428
- AddSetTagsFile($setTagsFile = '@') if not $setTagsFile and /(<|>)/;
1429
- if ($setTagsFile) {
1435
+ # and not from CSV and -tagsFromFile hasn't already been specified
1436
+ if (not $setTagsFile and $tagsFrom ne 'csv' and /(<|>)/) {
1437
+ AddSetTagsFile($setTagsFile = '@');
1438
+ $tagsFrom = 'file';
1439
+ }
1440
+ if ($tagsFrom eq 'csv') {
1441
+ my $lst = s/^-// ? \@csvExclude : \@tags;
1442
+ push @$lst, $_;
1443
+ } elsif ($setTagsFile) {
1430
1444
  push @{$setTags{$setTagsFile}}, $_;
1431
1445
  if ($1 eq '>') {
1432
1446
  $useMWG = 1 if /^(.*>\s*)?([-_0-9A-Z]+:)*1?mwg:/si;
@@ -1795,11 +1809,9 @@ if (@newValues) {
1795
1809
  $wrn and Warning($mt, $wrn);
1796
1810
  }
1797
1811
  # exclude specified tags
1798
- unless ($csv) {
1799
- foreach (@exclude) {
1800
- $mt->SetNewValue($_, undef, Replace => 2);
1801
- $needSave = 1;
1802
- }
1812
+ foreach (@exclude) {
1813
+ $mt->SetNewValue($_, undef, Replace => 2);
1814
+ $needSave = 1;
1803
1815
  }
1804
1816
  unless ($isWriting or $outOpt or @tags) {
1805
1817
  Error "Nothing to do.\n";
@@ -1936,7 +1948,7 @@ if (@fileOrder) {
1936
1948
  # set file count for progress message
1937
1949
  $progressMax = scalar @files if defined $progress;
1938
1950
 
1939
- # store duplicate database information under absolute path
1951
+ # store duplicate database information under absolute path and with standardized case
1940
1952
  my @dbKeys = keys %database;
1941
1953
  if (@dbKeys) {
1942
1954
  if (eval { require Cwd }) {
@@ -1945,6 +1957,7 @@ if (@dbKeys) {
1945
1957
  foreach (@dbKeys) {
1946
1958
  my $db = $database{$_};
1947
1959
  tr/\\/\// and $database{$_} = $db; # allow for backslashes in SourceFile
1960
+ $database{lc} = $db unless $database{lc}; # duplicate entry with lower case
1948
1961
  # (punt on using ConvertFileName here, so $absPath may be a mix of encodings)
1949
1962
  my $absPath = AbsPath($_);
1950
1963
  if (defined $absPath) {
@@ -1952,6 +1965,7 @@ if (@dbKeys) {
1952
1965
  if ($verbose and $verbose > 1) {
1953
1966
  print $vout "Imported entry for '${_}' (full path: '${absPath}')\n";
1954
1967
  }
1968
+ $database{lc $absPath} = $db unless $database{lc $absPath};
1955
1969
  } elsif ($verbose and $verbose > 1) {
1956
1970
  print $vout "Imported entry for '${_}' (no full path)\n";
1957
1971
  }
@@ -3249,7 +3263,7 @@ sub SetImageInfo($$$)
3249
3263
  next;
3250
3264
  } elsif (ref $dyFile eq 'SCALAR') {
3251
3265
  # set new values from CSV or JSON database
3252
- my ($f, $found, $csvTag, $tryTag, $tg);
3266
+ my ($f, $found, $csvTag, $tg, $csvExifTool);
3253
3267
  undef $evalWarning;
3254
3268
  local $SIG{'__WARN__'} = sub { $evalWarning = $_[0] };
3255
3269
  # force UTF-8 if the database was JSON
@@ -3260,48 +3274,68 @@ sub SetImageInfo($$$)
3260
3274
  my $csvInfo = $database{$f};
3261
3275
  unless ($csvInfo) {
3262
3276
  next if $f eq '*';
3263
- # check absolute path
3277
+ # check absolute path and case-insensitive name
3264
3278
  # (punt on using ConvertFileName here, so $absPath may be a mix of encodings)
3265
3279
  my $absPath = AbsPath($f);
3266
- next unless defined $absPath and $csvInfo = $database{$absPath};
3280
+ if (defined $absPath and $database{$absPath}) {
3281
+ $csvInfo = $database{$absPath};
3282
+ } elsif ($database{lc $f}) {
3283
+ $csvInfo = $database{lc $f};
3284
+ } elsif (defined $absPath and $database{lc $absPath}) {
3285
+ $csvInfo = $database{lc $absPath};
3286
+ } else {
3287
+ next;
3288
+ }
3267
3289
  }
3268
3290
  $found = 1;
3269
3291
  if ($verbose) {
3270
3292
  print $vout "Setting new values from $csv database\n";
3271
3293
  print $vout 'Including tags: ',join(' ',@tags),"\n" if @tags;
3272
- print $vout 'Excluding tags: ',join(' ',@exclude),"\n" if @exclude;
3294
+ print $vout 'Excluding tags: ',join(' ',@csvExclude),"\n" if @csvExclude;
3273
3295
  }
3274
- my @tryTags = (@exclude, @tags); # (exclude first because it takes priority)
3275
- foreach (@tryTags) {
3296
+ if (@tags) {
3297
+ # prepare a dummy ExifTool object to hold appropriate tags from the database
3298
+ $csvExifTool = Image::ExifTool->new unless $csvExifTool;
3299
+ foreach $csvTag (OrderedKeys($csvInfo)) {
3300
+ next if $csvTag =~ /^([-_0-9A-Z]+:)*(SourceFile|Directory|FileName)$/i;
3301
+ my @grps = split /:/, $csvTag;
3302
+ my $name = pop @grps;
3303
+ unshift @grps, 'Unknown' while @grps < 2;
3304
+ $csvExifTool->FoundTag($name, $$csvInfo{$csvTag}, @grps);
3305
+ }
3306
+ next;
3307
+ }
3308
+ my @exclTags = @csvExclude;
3309
+ foreach (@exclTags) {
3276
3310
  tr/-0-9a-zA-Z_:#?*//dc; # remove illegal characters
3277
3311
  s/(^|:)(all:)+/$1/ig; # remove 'all' group names
3278
3312
  s/(^|:)all(#?)$/$1*$2/i; # convert 'all' tag name to '*'
3279
3313
  tr/?/./; s/\*/.*/g; # convert wildcards for regex
3280
3314
  }
3315
+ # run through tags in database order
3281
3316
  foreach $csvTag (OrderedKeys($csvInfo)) {
3282
3317
  # don't write SourceFile, Directory or FileName
3283
3318
  next if $csvTag =~ /^([-_0-9A-Z]+:)*(SourceFile|Directory|FileName)$/i;
3284
- if (@tryTags) {
3285
- my ($i, $tryGrp, $matched);
3286
- TryMatch: for ($i=0; $i<@tryTags; ++$i) {
3287
- $tryTag = $tryTags[$i];
3288
- if ($tryTag =~ /:/) {
3319
+ if (@exclTags) {
3320
+ my ($exclTag, $exclGrp, $excluded);
3321
+ ExclMatch: foreach $exclTag (@exclTags) {
3322
+ if ($exclTag =~ /:/) {
3289
3323
  next unless $csvTag =~ /:/; # db entry must also specify group
3290
3324
  my @csvGrps = split /:/, $csvTag;
3291
- my @tryGrps = split /:/, $tryTag;
3292
- my $tryName = pop @tryGrps;
3293
- next unless pop(@csvGrps) =~ /^$tryName$/i; # tag name must match
3294
- foreach $tryGrp (@tryGrps) {
3325
+ my @exclGrps = split /:/, $exclTag;
3326
+ my $exclName = pop @exclGrps;
3327
+ next unless pop(@csvGrps) =~ /^$exclName$/i; # tag name must match
3328
+ foreach $exclGrp (@exclGrps) {
3295
3329
  # each specified group name must match db entry
3296
- next TryMatch unless grep /^$tryGrp$/i, @csvGrps;
3330
+ next ExclMatch unless grep /^$exclGrp$/i, @csvGrps;
3297
3331
  }
3298
- $matched = 1;
3332
+ $excluded = 1;
3299
3333
  last;
3300
3334
  }
3301
3335
  # no group specified, so match by tag name only
3302
- $csvTag =~ /^([-_0-9A-Z]+:)*$tryTag$/i and $matched = 1, last;
3336
+ $csvTag =~ /^([-_0-9A-Z]+:)*$exclTag$/i and $excluded = 1, last;
3303
3337
  }
3304
- next if $matched ? $i < @exclude : @tags;
3338
+ next if $excluded;
3305
3339
  }
3306
3340
  my ($rtn, $wrn) = $et->SetNewValue($csvTag, $$csvInfo{$csvTag},
3307
3341
  Protected => 1, AddValue => $csvAdd,
@@ -3309,6 +3343,11 @@ TryMatch: for ($i=0; $i<@tryTags; ++$i) {
3309
3343
  $wrn and Warn "$wrn\n" if $verbose;
3310
3344
  }
3311
3345
  }
3346
+ # set specified tags now
3347
+ if ($csvExifTool) {
3348
+ my @excl = map "-$_", @csvExclude; # add back leading dashes
3349
+ $et->SetNewValuesFromFile($csvExifTool, @tags, @excl);
3350
+ }
3312
3351
  $et->Options(Charset => $old) if $csv eq 'JSON';
3313
3352
  unless ($found) {
3314
3353
  Warn("No SourceFile '${file}' in imported $csv database\n");
@@ -88,7 +88,7 @@ sub ProcessCTMD($$$);
88
88
  sub ProcessExifInfo($$$);
89
89
  sub SwapWords($);
90
90
 
91
- $VERSION = '4.97';
91
+ $VERSION = '4.98';
92
92
 
93
93
  # Note: Removed 'USM' from 'L' lenses since it is redundant - PH
94
94
  # (or is it? Ref 32 shows 5 non-USM L-type lenses)
@@ -562,6 +562,7 @@ $VERSION = '4.97';
562
562
  4160 => 'Canon EF-S 35mm f/2.8 Macro IS STM', #42
563
563
  4208 => 'Sigma 56mm f/1.4 DC DN | C or other Sigma Lens', #forum10603
564
564
  4208.1 => 'Sigma 30mm F1.4 DC DN | C', #github#83 (016)
565
+ 4976 => 'Sigma 16-300mm F3.5-6.7 DC OS | C (025)', #50
565
566
  6512 => 'Sigma 12mm F1.4 DC | C', #github#352 (025)
566
567
  # (Nano USM lenses - 0x90xx)
567
568
  36910 => 'Canon EF 70-300mm f/4-5.6 IS II USM', #42
@@ -1995,12 +1996,12 @@ my %offOn = ( 0 => 'Off', 1 => 'On' );
1995
1996
  SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorData10' },
1996
1997
  },
1997
1998
  { # (int16u[3973]) - R3 ref IB
1998
- Condition => '$count == 3973 or $count == 3778',
1999
+ Condition => '($count == 3973 or $count == 3778) and $$valPt !~ /^\x41\0/',
1999
2000
  Name => 'ColorData11',
2000
2001
  SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorData11' },
2001
2002
  },
2002
- { # (int16u[4528]) - R1/R5mkII ref forum16406
2003
- Condition => '$count == 4528',
2003
+ { # (int16u[4528]) - R1/R5mkII (4528) ref forum16406, R50V (3778) ref PH
2004
+ Condition => '$count == 4528 or $count == 3778',
2004
2005
  Name => 'ColorData12',
2005
2006
  SubDirectory => { TagTable => 'Image::ExifTool::Canon::ColorData12' },
2006
2007
  },
@@ -8321,8 +8322,8 @@ my %ciMaxFocal = (
8321
8322
  RawConv => '$$self{ColorDataVersion} = $val',
8322
8323
  PrintConv => {
8323
8324
  16 => '16 (M50)',
8324
- 17 => '17 (EOS R)', # (and PowerShot SX740HS)
8325
- 18 => '18 (EOS RP/250D)', # (and PowerShot SX70HS)
8325
+ 17 => '17 (R)', # (and PowerShot SX740HS)
8326
+ 18 => '18 (RP/250D)', # (and PowerShot SX70HS)
8326
8327
  19 => '19 (90D/850D/M6mkII/M200)',# (and PowerShot G7XmkIII)
8327
8328
  },
8328
8329
  },
@@ -8553,10 +8554,10 @@ my %ciMaxFocal = (
8553
8554
  },
8554
8555
  );
8555
8556
 
8556
- # Color data (MakerNotes tag 0x4001, count=3973, ref IB)
8557
+ # Color data (MakerNotes tag 0x4001, count=3973/3778, ref IB)
8557
8558
  %Image::ExifTool::Canon::ColorData11 = (
8558
8559
  %binaryDataAttrs,
8559
- NOTES => 'These tags are used by the EOS R3, R7 and R6mkII',
8560
+ NOTES => 'These tags are used by the EOS R3, R7, R50 and R6mkII',
8560
8561
  FORMAT => 'int16s',
8561
8562
  FIRST_ENTRY => 0,
8562
8563
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
@@ -8568,7 +8569,7 @@ my %ciMaxFocal = (
8568
8569
  RawConv => '$$self{ColorDataVersion} = $val',
8569
8570
  PrintConv => {
8570
8571
  34 => '34 (R3)', #IB
8571
- 48 => '48 (R7, R10, R6 Mark II)', #IB
8572
+ 48 => '48 (R7/R10/R50/R6mkII)', #IB
8572
8573
  },
8573
8574
  },
8574
8575
  0x69 => { Name => 'WB_RGGBLevelsAsShot', Format => 'int16s[4]' },
@@ -8673,10 +8674,10 @@ my %ciMaxFocal = (
8673
8674
  },
8674
8675
  );
8675
8676
 
8676
- # Color data (MakerNotes tag 0x4001, count=4528, ref PH)
8677
+ # Color data (MakerNotes tag 0x4001, count=4528/3778, ref PH)
8677
8678
  %Image::ExifTool::Canon::ColorData12 = (
8678
8679
  %binaryDataAttrs,
8679
- NOTES => 'These tags are used by the EOS R1 and R5mkII',
8680
+ NOTES => 'These tags are used by the EOS R1, R5mkII and R50V',
8680
8681
  FORMAT => 'int16s',
8681
8682
  FIRST_ENTRY => 0,
8682
8683
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
@@ -8687,7 +8688,8 @@ my %ciMaxFocal = (
8687
8688
  DataMember => 'ColorDataVersion',
8688
8689
  RawConv => '$$self{ColorDataVersion} = $val',
8689
8690
  PrintConv => {
8690
- 64 => '64 (R1, R5 Mark II)',
8691
+ 64 => '64 (R1/R5mkII)',
8692
+ 65 => '65 (R50V)',
8691
8693
  },
8692
8694
  },
8693
8695
  0x69 => { Name => 'WB_RGGBLevelsAsShot', Format => 'int16s[4]' }, # (NC)
@@ -8778,6 +8780,7 @@ my %ciMaxFocal = (
8778
8780
  Name => 'PerChannelBlackLevel',
8779
8781
  Format => 'int16u[4]',
8780
8782
  },
8783
+ # 0x290 - PerChannelBlackLevel again
8781
8784
  0x294 => {
8782
8785
  Name => 'NormalWhiteLevel',
8783
8786
  Format => 'int16u',