exiftool_vendored 12.81.0 → 12.83.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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +39 -1
  3. data/bin/MANIFEST +4 -18
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +3 -2
  7. data/bin/build_geolocation +867 -0
  8. data/bin/exiftool +37 -9
  9. data/bin/fmt_files/gpx.fmt +2 -1
  10. data/bin/fmt_files/gpx_wpt.fmt +2 -1
  11. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +47 -31
  12. data/bin/lib/Image/ExifTool/CanonVRD.pm +6 -5
  13. data/bin/lib/Image/ExifTool/DJI.pm +29 -0
  14. data/bin/lib/Image/ExifTool/Exif.pm +19 -2
  15. data/bin/lib/Image/ExifTool/FujiFilm.pm +9 -2
  16. data/bin/lib/Image/ExifTool/GM.pm +552 -0
  17. data/bin/lib/Image/ExifTool/Geolocation.dat +0 -0
  18. data/bin/lib/Image/ExifTool/Geolocation.pm +90 -54
  19. data/bin/lib/Image/ExifTool/Nikon.pm +9 -7
  20. data/bin/lib/Image/ExifTool/QuickTime.pm +31 -23
  21. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +66 -30
  22. data/bin/lib/Image/ExifTool/README +2 -0
  23. data/bin/lib/Image/ExifTool/Sony.pm +15 -6
  24. data/bin/lib/Image/ExifTool/TagLookup.pm +37 -6
  25. data/bin/lib/Image/ExifTool/TagNames.pod +407 -239
  26. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +5 -2
  27. data/bin/lib/Image/ExifTool/Writer.pl +165 -133
  28. data/bin/lib/Image/ExifTool/XMP.pm +3 -2
  29. data/bin/lib/Image/ExifTool/XMP2.pl +3 -0
  30. data/bin/lib/Image/ExifTool.pm +38 -9
  31. data/bin/lib/Image/ExifTool.pod +31 -18
  32. data/bin/perl-Image-ExifTool.spec +1 -1
  33. data/lib/exiftool_vendored/version.rb +1 -1
  34. metadata +4 -20
  35. data/bin/lib/Image/ExifTool/GeoLang/cs.pm +0 -978
  36. data/bin/lib/Image/ExifTool/GeoLang/de.pm +0 -1975
  37. data/bin/lib/Image/ExifTool/GeoLang/en_ca.pm +0 -44
  38. data/bin/lib/Image/ExifTool/GeoLang/en_gb.pm +0 -124
  39. data/bin/lib/Image/ExifTool/GeoLang/es.pm +0 -2921
  40. data/bin/lib/Image/ExifTool/GeoLang/fi.pm +0 -1116
  41. data/bin/lib/Image/ExifTool/GeoLang/fr.pm +0 -3171
  42. data/bin/lib/Image/ExifTool/GeoLang/it.pm +0 -2750
  43. data/bin/lib/Image/ExifTool/GeoLang/ja.pm +0 -10256
  44. data/bin/lib/Image/ExifTool/GeoLang/ko.pm +0 -4499
  45. data/bin/lib/Image/ExifTool/GeoLang/nl.pm +0 -1270
  46. data/bin/lib/Image/ExifTool/GeoLang/pl.pm +0 -3019
  47. data/bin/lib/Image/ExifTool/GeoLang/ru.pm +0 -18220
  48. data/bin/lib/Image/ExifTool/GeoLang/sk.pm +0 -441
  49. data/bin/lib/Image/ExifTool/GeoLang/sv.pm +0 -714
  50. data/bin/lib/Image/ExifTool/GeoLang/tr.pm +0 -452
  51. data/bin/lib/Image/ExifTool/GeoLang/zh_cn.pm +0 -2225
  52. data/bin/lib/Image/ExifTool/GeoLang/zh_tw.pm +0 -72
@@ -168,7 +168,8 @@ sub ConvInvISO6709($)
168
168
  # requires at least 3 digits after the decimal point
169
169
  # (and as of Apr 2021, Google Photos doesn't accept coordinats
170
170
  # with more than 5 digits after the decimal place:
171
- # https://exiftool.org/forum/index.php?topic=11055.msg67171#msg67171 )
171
+ # https://exiftool.org/forum/index.php?topic=11055.msg67171#msg67171
172
+ # still a problem Apr 2024: https://exiftool.org/forum/index.php?msg=85761)
172
173
  my @fmt = ('%s%02d.%s%s','%s%03d.%s%s','%s%d.%s%s');
173
174
  my @limit = (90,180);
174
175
  foreach (@a) {
@@ -1452,7 +1453,9 @@ sub WriteQuickTime($$$)
1452
1453
  }
1453
1454
  # ($errStr is set if there was an error that could possibly be due to an unknown trailer)
1454
1455
  if ($errStr) {
1455
- if ($lastTag eq 'mdat' and not $dataPt and not $$tagTablePtr{$tag}) {
1456
+ if (($lastTag eq 'mdat' or $lastTag eq 'moov') and not $dataPt and (not $$tagTablePtr{$tag} or
1457
+ ref $$tagTablePtr{$tag} eq 'HASH' and $$tagTablePtr{$tag}{Unknown}))
1458
+ {
1456
1459
  my $nvTrail = $et->GetNewValueHash($Image::ExifTool::Extra{Trailer});
1457
1460
  if ($$et{DEL_GROUP}{Trailer} or ($nvTrail and not ($$nvTrail{Value} and $$nvTrail{Value}[0]))) {
1458
1461
  $errStr =~ s/ is too large.*//;
@@ -1234,7 +1234,8 @@ WriteAlso:
1234
1234
 
1235
1235
  #------------------------------------------------------------------------------
1236
1236
  # set new values from information in specified file
1237
- # Inputs: 0) ExifTool object reference, 1) source file name or reference, etc
1237
+ # Inputs: 0) ExifTool object reference, 1) source file name or reference, etc,
1238
+ # or ExifTool ref to use already-extracted tags from an ExifTool object,
1238
1239
  # 2-N) List of tags to set (or all if none specified), or reference(s) to
1239
1240
  # hash for options to pass to SetNewValue. The Replace option defaults
1240
1241
  # to 1 for SetNewValuesFromFile -- set this to 0 to allow multiple tags
@@ -1245,11 +1246,12 @@ WriteAlso:
1245
1246
  # be used to represent all tags in a group. An optional destination tag
1246
1247
  # may be specified with '>DSTTAG' ('DSTTAG<TAG' also works, but in this
1247
1248
  # case the source tag may also be an expression involving tag names).
1249
+ # Simple assignments are also allowed: 'DSTTAG[#][+-][^]=[string]'
1248
1250
  sub SetNewValuesFromFile($$;@)
1249
1251
  {
1250
1252
  local $_;
1251
1253
  my ($self, $srcFile, @setTags) = @_;
1252
- my ($key, $tag, @exclude, @reqTags);
1254
+ my ($srcExifTool, $key, $tag, @exclude, @reqTags, $info);
1253
1255
 
1254
1256
  # get initial SetNewValuesFromFile options
1255
1257
  my %opts = ( Replace => 1 ); # replace existing list items by default
@@ -1261,113 +1263,8 @@ sub SetNewValuesFromFile($$;@)
1261
1263
  }
1262
1264
  # expand shortcuts
1263
1265
  @setTags and ExpandShortcuts(\@setTags);
1264
- my $srcExifTool = Image::ExifTool->new;
1265
- # set flag to indicate we are being called from inside SetNewValuesFromFile()
1266
- $$srcExifTool{TAGS_FROM_FILE} = 1;
1267
- # synchronize and increment the file sequence number
1268
- $$srcExifTool{FILE_SEQUENCE} = $$self{FILE_SEQUENCE}++;
1269
1266
  # set options for our extraction tool
1270
1267
  my $options = $$self{OPTIONS};
1271
- # copy both structured and flattened tags by default (but flattened tags are "unsafe")
1272
- my $structOpt = defined $$options{Struct} ? $$options{Struct} : 2;
1273
- # copy structures only if no tags specified (since flattened tags are "unsafe")
1274
- $structOpt = 1 if $structOpt eq '2' and not @setTags;
1275
- # +------------------------------------------+
1276
- # ! DON'T FORGET!! Must consider each new !
1277
- # ! option to decide how it is handled here. !
1278
- # +------------------------------------------+
1279
- $srcExifTool->Options(
1280
- Binary => 1,
1281
- ByteUnit => $$options{ByteUnit},
1282
- Charset => $$options{Charset},
1283
- CharsetEXIF => $$options{CharsetEXIF},
1284
- CharsetFileName => $$options{CharsetFileName},
1285
- CharsetID3 => $$options{CharsetID3},
1286
- CharsetIPTC => $$options{CharsetIPTC},
1287
- CharsetPhotoshop=> $$options{CharsetPhotoshop},
1288
- Composite => $$options{Composite},
1289
- CoordFormat => $$options{CoordFormat} || '%d %d %.8f', # copy coordinates at high resolution unless otherwise specified
1290
- DateFormat => $$options{DateFormat},
1291
- Duplicates => 1,
1292
- Escape => $$options{Escape},
1293
- # Exclude (set below)
1294
- ExtendedXMP => $$options{ExtendedXMP},
1295
- ExtractEmbedded => $$options{ExtractEmbedded},
1296
- FastScan => $$options{FastScan},
1297
- Filter => $$options{Filter},
1298
- FixBase => $$options{FixBase},
1299
- Geolocation => $$options{Geolocation},
1300
- GeolocAltNames => $$options{GeolocAltNames},
1301
- GeolocFeature => $$options{GeolocFeature},
1302
- GeolocMinPop => $$options{GeolocMinPop},
1303
- GeolocMaxDist => $$options{GeolocMaxDist},
1304
- GlobalTimeShift => $$options{GlobalTimeShift},
1305
- HexTagIDs => $$options{HexTagIDs},
1306
- IgnoreMinorErrors=>$$options{IgnoreMinorErrors},
1307
- IgnoreTags => $$options{IgnoreTags},
1308
- ImageHashType => $$options{ImageHashType},
1309
- Lang => $$options{Lang},
1310
- LargeFileSupport=> $$options{LargeFileSupport},
1311
- LimitLongValues => 10000000, # (10 MB)
1312
- List => 1,
1313
- ListItem => $$options{ListItem},
1314
- ListSep => $$options{ListSep},
1315
- MakerNotes => $$options{FastScan} && $$options{FastScan} > 1 ? undef : 1,
1316
- MDItemTags => $$options{MDItemTags},
1317
- MissingTagValue => $$options{MissingTagValue},
1318
- NoPDFList => $$options{NoPDFList},
1319
- NoWarning => $$options{NoWarning},
1320
- Password => $$options{Password},
1321
- PrintConv => $$options{PrintConv},
1322
- QuickTimeUTC => $$options{QuickTimeUTC},
1323
- RequestAll => $$options{RequestAll} || 1, # (is this still necessary now that RequestTags are being set?)
1324
- RequestTags => $$options{RequestTags},
1325
- SaveFormat => $$options{SaveFormat},
1326
- SavePath => $$options{SavePath},
1327
- ScanForXMP => $$options{ScanForXMP},
1328
- StrictDate => defined $$options{StrictDate} ? $$options{StrictDate} : 1,
1329
- Struct => $structOpt,
1330
- StructFormat => $$options{StructFormat},
1331
- SystemTags => $$options{SystemTags},
1332
- TimeZone => $$options{TimeZone},
1333
- Unknown => $$options{Unknown},
1334
- UserParam => $$options{UserParam},
1335
- Validate => $$options{Validate},
1336
- WindowsWideFile => $$options{WindowsWideFile},
1337
- XAttrTags => $$options{XAttrTags},
1338
- XMPAutoConv => $$options{XMPAutoConv},
1339
- );
1340
- # reset Geolocation option if we aren't copying any geolocation tags
1341
- if ($$options{Geolocation} and not grep /\bGeolocation/i, @setTags) {
1342
- $self->VPrint(0, '(resetting unnecessary Geolocation option)');
1343
- $$srcExifTool{OPTIONS}{Geolocation} = undef;
1344
- }
1345
- $$srcExifTool{GLOBAL_TIME_OFFSET} = $$self{GLOBAL_TIME_OFFSET};
1346
- $$srcExifTool{ALT_EXIFTOOL} = $$self{ALT_EXIFTOOL};
1347
- foreach $tag (@setTags) {
1348
- next if ref $tag;
1349
- if ($tag =~ /^-(.*)/) {
1350
- # avoid extracting tags that are excluded
1351
- push @exclude, $1;
1352
- next;
1353
- }
1354
- # add specified tags to list of requested tags
1355
- $_ = $tag;
1356
- if (/(.+?)\s*(>|<)\s*(.+)/) {
1357
- if ($2 eq '>') {
1358
- $_ = $1;
1359
- } else {
1360
- $_ = $3;
1361
- /\$/ and push(@reqTags, /\$\{?(?:[-\w]+:)*([-\w?*]+)/g), next;
1362
- }
1363
- }
1364
- push @reqTags, $2 if /(^|:)([-\w?*]+)#?$/;
1365
- }
1366
- if (@exclude) {
1367
- ExpandShortcuts(\@exclude, 1);
1368
- $srcExifTool->Options(Exclude => \@exclude);
1369
- }
1370
- $srcExifTool->Options(RequestTags => \@reqTags) if @reqTags;
1371
1268
  my $printConv = $$options{PrintConv};
1372
1269
  if ($opts{Type}) {
1373
1270
  # save source type separately because it may be different than dst Type
@@ -1377,9 +1274,120 @@ sub SetNewValuesFromFile($$;@)
1377
1274
  $srcExifTool->Options(PrintConv => $printConv);
1378
1275
  }
1379
1276
  my $srcType = $printConv ? 'PrintConv' : 'ValueConv';
1277
+ my $structOpt = defined $$options{Struct} ? $$options{Struct} : 2;
1380
1278
 
1381
- # get all tags from source file (including MakerNotes block)
1382
- my $info = $srcExifTool->ImageInfo($srcFile);
1279
+ if (ref $srcFile and UNIVERSAL::isa($srcFile,'Image::ExifTool')) {
1280
+ $srcExifTool = $srcFile;
1281
+ $info = $srcExifTool->GetInfo();
1282
+ } else {
1283
+ $srcExifTool = Image::ExifTool->new;
1284
+ # set flag to indicate we are being called from inside SetNewValuesFromFile()
1285
+ $$srcExifTool{TAGS_FROM_FILE} = 1;
1286
+ # synchronize and increment the file sequence number
1287
+ $$srcExifTool{FILE_SEQUENCE} = $$self{FILE_SEQUENCE}++;
1288
+ # copy both structured and flattened tags by default (but flattened tags are "unsafe")
1289
+ # copy structures only if no tags specified (since flattened tags are "unsafe")
1290
+ $structOpt = 1 if $structOpt eq '2' and not @setTags;
1291
+ # +------------------------------------------+
1292
+ # ! DON'T FORGET!! Must consider each new !
1293
+ # ! option to decide how it is handled here. !
1294
+ # +------------------------------------------+
1295
+ $srcExifTool->Options(
1296
+ Binary => 1,
1297
+ ByteUnit => $$options{ByteUnit},
1298
+ Charset => $$options{Charset},
1299
+ CharsetEXIF => $$options{CharsetEXIF},
1300
+ CharsetFileName => $$options{CharsetFileName},
1301
+ CharsetID3 => $$options{CharsetID3},
1302
+ CharsetIPTC => $$options{CharsetIPTC},
1303
+ CharsetPhotoshop=> $$options{CharsetPhotoshop},
1304
+ Composite => $$options{Composite},
1305
+ CoordFormat => $$options{CoordFormat} || '%d %d %.8f', # copy coordinates at high resolution unless otherwise specified
1306
+ DateFormat => $$options{DateFormat},
1307
+ Duplicates => 1,
1308
+ Escape => $$options{Escape},
1309
+ # Exclude (set below)
1310
+ ExtendedXMP => $$options{ExtendedXMP},
1311
+ ExtractEmbedded => $$options{ExtractEmbedded},
1312
+ FastScan => $$options{FastScan},
1313
+ Filter => $$options{Filter},
1314
+ FixBase => $$options{FixBase},
1315
+ Geolocation => $$options{Geolocation},
1316
+ GeolocAltNames => $$options{GeolocAltNames},
1317
+ GeolocFeature => $$options{GeolocFeature},
1318
+ GeolocMinPop => $$options{GeolocMinPop},
1319
+ GeolocMaxDist => $$options{GeolocMaxDist},
1320
+ GlobalTimeShift => $$options{GlobalTimeShift},
1321
+ HexTagIDs => $$options{HexTagIDs},
1322
+ IgnoreGroups => $$options{IgnoreGroups},
1323
+ IgnoreMinorErrors=>$$options{IgnoreMinorErrors},
1324
+ IgnoreTags => $$options{IgnoreTags},
1325
+ ImageHashType => $$options{ImageHashType},
1326
+ Lang => $$options{Lang},
1327
+ LargeFileSupport=> $$options{LargeFileSupport},
1328
+ LimitLongValues => 10000000, # (10 MB)
1329
+ List => 1,
1330
+ ListItem => $$options{ListItem},
1331
+ ListSep => $$options{ListSep},
1332
+ MakerNotes => $$options{FastScan} && $$options{FastScan} > 1 ? undef : 1,
1333
+ MDItemTags => $$options{MDItemTags},
1334
+ MissingTagValue => $$options{MissingTagValue},
1335
+ NoPDFList => $$options{NoPDFList},
1336
+ NoWarning => $$options{NoWarning},
1337
+ Password => $$options{Password},
1338
+ PrintConv => $$options{PrintConv},
1339
+ QuickTimeUTC => $$options{QuickTimeUTC},
1340
+ RequestAll => $$options{RequestAll} || 1, # (is this still necessary now that RequestTags are being set?)
1341
+ RequestTags => $$options{RequestTags},
1342
+ SaveFormat => $$options{SaveFormat},
1343
+ SavePath => $$options{SavePath},
1344
+ ScanForXMP => $$options{ScanForXMP},
1345
+ StrictDate => defined $$options{StrictDate} ? $$options{StrictDate} : 1,
1346
+ Struct => $structOpt,
1347
+ StructFormat => $$options{StructFormat},
1348
+ SystemTags => $$options{SystemTags},
1349
+ TimeZone => $$options{TimeZone},
1350
+ Unknown => $$options{Unknown},
1351
+ UserParam => $$options{UserParam},
1352
+ Validate => $$options{Validate},
1353
+ WindowsWideFile => $$options{WindowsWideFile},
1354
+ XAttrTags => $$options{XAttrTags},
1355
+ XMPAutoConv => $$options{XMPAutoConv},
1356
+ );
1357
+ # reset Geolocation option if we aren't copying any geolocation tags
1358
+ if ($$options{Geolocation} and not grep /\bGeolocation/i, @setTags) {
1359
+ $self->VPrint(0, '(resetting unnecessary Geolocation option)');
1360
+ $$srcExifTool{OPTIONS}{Geolocation} = undef;
1361
+ }
1362
+ $$srcExifTool{GLOBAL_TIME_OFFSET} = $$self{GLOBAL_TIME_OFFSET};
1363
+ $$srcExifTool{ALT_EXIFTOOL} = $$self{ALT_EXIFTOOL};
1364
+ foreach $tag (@setTags) {
1365
+ next if ref $tag;
1366
+ if ($tag =~ /^-(.*)/) {
1367
+ # avoid extracting tags that are excluded
1368
+ push @exclude, $1;
1369
+ next;
1370
+ }
1371
+ # add specified tags to list of requested tags
1372
+ $_ = $tag;
1373
+ if (/(.+?)\s*(>|<)\s*(.+)/) {
1374
+ if ($2 eq '>') {
1375
+ $_ = $1;
1376
+ } else {
1377
+ $_ = $3;
1378
+ /\$/ and push(@reqTags, /\$\{?(?:[-\w]+:)*([-\w?*]+)/g), next;
1379
+ }
1380
+ }
1381
+ push @reqTags, $2 if /(^|:)([-\w?*]+)#?$/;
1382
+ }
1383
+ if (@exclude) {
1384
+ ExpandShortcuts(\@exclude, 1);
1385
+ $srcExifTool->Options(Exclude => \@exclude);
1386
+ }
1387
+ $srcExifTool->Options(RequestTags => \@reqTags) if @reqTags;
1388
+ # get all tags from source file (including MakerNotes block)
1389
+ $info = $srcExifTool->ImageInfo($srcFile);
1390
+ }
1383
1391
  return $info if $$info{Error} and $$info{Error} eq 'Error opening file';
1384
1392
  delete $$srcExifTool{VALUE}{Error}; # delete so we can check this later
1385
1393
 
@@ -1414,6 +1422,7 @@ sub SetNewValuesFromFile($$;@)
1414
1422
  #
1415
1423
  # 1) loop through input list of tags to set, and build @setList
1416
1424
  my (@setList, $set, %setMatches, $t, %altFiles);
1425
+ my $assign = 0;
1417
1426
  foreach $t (@setTags) {
1418
1427
  if (ref $t eq 'HASH') {
1419
1428
  # update current options
@@ -1428,18 +1437,22 @@ sub SetNewValuesFromFile($$;@)
1428
1437
  $tag = lc $t; # change tag/group names to all lower case
1429
1438
  my (@fg, $grp, $dst, $dstGrp, $dstTag, $isExclude);
1430
1439
  # handle redirection to another tag
1431
- if ($tag =~ /(.+?)\s*(>|<)\s*(.+)/) {
1440
+ if ($tag =~ /(.+?)\s*(>|<|=)(\s*)(.*)/) {
1432
1441
  $dstGrp = '';
1433
- my $opt;
1442
+ my ($opt, $op, $spc);
1434
1443
  if ($2 eq '>') {
1435
- ($tag, $dstTag) = ($1, $3);
1444
+ ($tag, $dstTag) = ($1, $4);
1436
1445
  # flag add and delete (eg. '+<' and '-<') redirections
1437
1446
  $opt = $1 if $tag =~ s/\s*([-+])$// or $dstTag =~ s/^([-+])\s*//;
1438
1447
  } else {
1439
- ($tag, $dstTag) = ($3, $1);
1448
+ ($dstTag, $op, $spc, $tag) = ($1, $2, $3, $4);
1440
1449
  $opt = $1 if $dstTag =~ s/\s*([-+])$//;
1441
- # handle expressions
1442
- if ($tag =~ /\$/) {
1450
+ if ($op eq '=') {
1451
+ # simple assignment ($tag will be the new value)
1452
+ $tag = $spc . $tag;
1453
+ undef $tag unless $dstTag =~ s/\^$// or length $tag;
1454
+ $$opts{ASSIGN} = ++$assign;
1455
+ } elsif ($tag =~ /\$/) { # handle expressions
1443
1456
  $tag = $t; # restore original case
1444
1457
  # recover leading whitespace (except for initial single space)
1445
1458
  $tag =~ s/(.+?)\s*(>|<) ?//;
@@ -1452,7 +1465,7 @@ sub SetNewValuesFromFile($$;@)
1452
1465
  }
1453
1466
  $$opts{Replace} = 0 if $dstTag =~ s/^\+//;
1454
1467
  # validate tag name(s)
1455
- unless ($$opts{EXPR} or ValidTagName($tag)) {
1468
+ unless ($$opts{EXPR} or $$opts{ASSIGN} or ValidTagName($tag)) {
1456
1469
  $self->Warn("Invalid tag name '${tag}'. Use '=' not '<' to assign a tag value");
1457
1470
  next;
1458
1471
  }
@@ -1470,7 +1483,7 @@ sub SetNewValuesFromFile($$;@)
1470
1483
  } else {
1471
1484
  $$opts{Replace} = 0 if $tag =~ s/^\+//;
1472
1485
  }
1473
- unless ($$opts{EXPR}) {
1486
+ unless ($$opts{EXPR} or $$opts{ASSIGN}) {
1474
1487
  $isExclude = ($tag =~ s/^-//);
1475
1488
  if ($tag =~ /(.*):(.+)/) {
1476
1489
  ($grp, $tag) = ($1, $2);
@@ -1540,6 +1553,8 @@ sub SetNewValuesFromFile($$;@)
1540
1553
  foreach $set (@setList) {
1541
1554
  $$set[2] and $setMatches{$set} = [ ];
1542
1555
  }
1556
+ # no need to search source tags if doing only assignments
1557
+ undef @tags if $assign == @setList;
1543
1558
  # 3) loop through all tags in source image and save tags matching each setTag
1544
1559
  my (%rtnInfo, $isAlt);
1545
1560
  foreach $tag (@tags) {
@@ -1592,21 +1607,26 @@ SET: foreach $set (@setList) {
1592
1607
  # get options for SetNewValue
1593
1608
  my $opts = $$set[3];
1594
1609
  # handle expressions
1595
- if ($$opts{EXPR}) {
1596
- my $val = $srcExifTool->InsertTagValues($$set[1], \@tags, 'Error');
1597
- my $err = $$srcExifTool{VALUE}{Error};
1598
- if ($err) {
1599
- # pass on any error as a warning unless it is suppressed
1600
- my $noWarn = $$srcExifTool{OPTIONS}{NoWarning};
1601
- unless ($noWarn and (eval { $err =~ /$noWarn/ } or
1602
- # (also apply expression to warning without "[minor] " prefix)
1603
- ($err =~ s/^\[minor\] //i and eval { $err =~ /$noWarn/ })))
1604
- {
1605
- $tag = NextFreeTagKey(\%rtnInfo, 'Warning');
1606
- $rtnInfo{$tag} = $$srcExifTool{VALUE}{Error};
1610
+ if ($$opts{EXPR} or $$opts{ASSIGN}) {
1611
+ my $val;
1612
+ if ($$opts{EXPR}) {
1613
+ $val = $srcExifTool->InsertTagValues($$set[1], \@tags, 'Error');
1614
+ my $err = $$srcExifTool{VALUE}{Error};
1615
+ if ($err) {
1616
+ # pass on any error as a warning unless it is suppressed
1617
+ my $noWarn = $$srcExifTool{OPTIONS}{NoWarning};
1618
+ unless ($noWarn and (eval { $err =~ /$noWarn/ } or
1619
+ # (also apply expression to warning without "[minor] " prefix)
1620
+ ($err =~ s/^\[minor\] //i and eval { $err =~ /$noWarn/ })))
1621
+ {
1622
+ $tag = NextFreeTagKey(\%rtnInfo, 'Warning');
1623
+ $rtnInfo{$tag} = $$srcExifTool{VALUE}{Error};
1624
+ }
1625
+ delete $$srcExifTool{VALUE}{Error};
1626
+ next unless defined $val;
1607
1627
  }
1608
- delete $$srcExifTool{VALUE}{Error};
1609
- next unless defined $val;
1628
+ } else {
1629
+ $val = $$set[1];
1610
1630
  }
1611
1631
  my ($dstGrp, $dstTag) = @{$$set[2]};
1612
1632
  $$opts{Protected} = 1 unless $dstTag =~ /[?*]/ and $dstTag ne '*';
@@ -3167,8 +3187,8 @@ sub PushValue($$$;$)
3167
3187
  # Inputs: 0) ExifTool object ref, 1) string with embedded tag names,
3168
3188
  # 2) reference to list of found tags or undef to use FOUND_TAGS, 3) Options:
3169
3189
  # undef - set missing tags to ''
3170
- # 'Error' - issue minor error on missing tag (and return undef)
3171
- # 'Warn' - issue minor warning on missing tag (and return undef)
3190
+ # 'Error' - issue minor error on missing tag (and return undef if error sent)
3191
+ # 'Warn' - issue minor warning on missing tag (and return undef if warning sent)
3172
3192
  # 'Silent' - just return undef on missing tag (no errors/warnings)
3173
3193
  # Hash ref - defined to interpolate as variables in string instead of values
3174
3194
  # --> receives tag/value pairs for interpolation of the variables
@@ -3454,6 +3474,18 @@ sub NoDups
3454
3474
  $_ = ($_[0] and $new eq $_) ? undef : $new;
3455
3475
  }
3456
3476
 
3477
+ #------------------------------------------------------------------------------
3478
+ # Utility routine to set in $_ image from current object
3479
+ # Inputs: 0-N) list of tags to copy
3480
+ # Notes: - for use only in advanced formatting expressions
3481
+ sub SetTags(@)
3482
+ {
3483
+ my $self = $advFmtSelf;
3484
+ my $et = Image::ExifTool->new;
3485
+ $et->SetNewValuesFromFile($self, @_);
3486
+ $et->WriteInfo(\$_);
3487
+ }
3488
+
3457
3489
  #------------------------------------------------------------------------------
3458
3490
  # Is specified tag writable
3459
3491
  # Inputs: 0) tag name, case insensitive (optional group name currently ignored)
@@ -50,7 +50,7 @@ use Image::ExifTool::Exif;
50
50
  use Image::ExifTool::GPS;
51
51
  require Exporter;
52
52
 
53
- $VERSION = '3.64';
53
+ $VERSION = '3.65';
54
54
  @ISA = qw(Exporter);
55
55
  @EXPORT_OK = qw(EscapeXML UnescapeXML);
56
56
 
@@ -283,11 +283,12 @@ my %recognizedAttrs = (
283
283
  # NOTE: this lookup is duplicated in TagLookup.pm!!
284
284
  %specialStruct = (
285
285
  STRUCT_NAME => 1, # [optional] name of structure
286
- NAMESPACE => 1, # [mandatory] namespace prefix used for fields of this structure
286
+ NAMESPACE => 1, # [mandatory for XMP] namespace prefix used for fields of this structure
287
287
  NOTES => 1, # [optional] notes for documentation about this structure
288
288
  TYPE => 1, # [optional] rdf:type resource for struct (if used, the StructType flag
289
289
  # will be set automatically for all derived flattened tags when writing)
290
290
  GROUPS => 1, # [optional] specifies family group 2 name for the structure
291
+ SORT_ORDER => 1, # [optional] order for sorting fields in documentation
291
292
  );
292
293
  # XMP structures (each structure is similar to a tag table so we can
293
294
  # recurse through them in SetPropertyPath() as if they were tag tables)
@@ -1941,6 +1941,9 @@ my %sACDSeeRegionStruct = (
1941
1941
  ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)',
1942
1942
  ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)',
1943
1943
  },
1944
+ MotionPhoto => { Writable => 'integer' },
1945
+ MotionPhotoVersion => { Writable => 'integer' },
1946
+ MotionPhotoPresentationTimestampUs => { Writable => 'integer' },
1944
1947
  );
1945
1948
 
1946
1949
  # Google creations namespace (ref PH)
@@ -29,7 +29,7 @@ use vars qw($VERSION $RELEASE @ISA @EXPORT_OK %EXPORT_TAGS $AUTOLOAD @fileTypes
29
29
  %jpegMarker %specialTags %fileTypeLookup $testLen $exeDir
30
30
  %static_vars);
31
31
 
32
- $VERSION = '12.81';
32
+ $VERSION = '12.83';
33
33
  $RELEASE = '';
34
34
  @ISA = qw(Exporter);
35
35
  %EXPORT_TAGS = (
@@ -1118,6 +1118,7 @@ my @availableOptions = (
1118
1118
  [ 'HexTagIDs', 0, 'use hex tag ID\'s in family 7 group names' ],
1119
1119
  [ 'HtmlDump', 0, 'HTML dump (0-3, higher # = bigger limit)' ],
1120
1120
  [ 'HtmlDumpBase', undef, 'base address for HTML dump' ],
1121
+ [ 'IgnoreGroups', undef, 'list of groups to ignore when extracting' ],
1121
1122
  [ 'IgnoreMinorErrors',undef, 'ignore minor errors when reading/writing' ],
1122
1123
  [ 'IgnoreTags', undef, 'list of tags to ignore when extracting' ],
1123
1124
  [ 'ImageHashType', 'MD5', 'image hash algorithm' ],
@@ -1137,6 +1138,7 @@ my @availableOptions = (
1137
1138
  [ 'NoPDFList', undef, 'flag to avoid splitting PDF List-type tag values' ],
1138
1139
  [ 'NoWarning', undef, 'regular expression for warnings to suppress' ],
1139
1140
  [ 'Password', undef, 'password for password-protected PDF documents' ],
1141
+ [ 'PrintCSV', undef, 'flag to print CSV directly (selected metadata types only)' ],
1140
1142
  [ 'PrintConv', 1, 'flag to enable print conversion' ],
1141
1143
  [ 'QuickTimeHandler', 1, 'flag to add mdir Handler to newly created Meta box' ],
1142
1144
  [ 'QuickTimePad', undef, 'flag to preserve padding of QuickTime CR3 tags' ],
@@ -2035,8 +2037,8 @@ my %systemTagsNotes = (
2035
2037
  }
2036
2038
  return join(',', @args);
2037
2039
  },
2038
- },
2039
- GeolocationBearing => { %geoInfo,
2040
+ },
2041
+ GeolocationBearing => { %geoInfo,
2040
2042
  Notes => q{
2041
2043
  compass bearing to GeolocationCity center. Geolocation tags are
2042
2044
  generated only if API L<Geolocation|../ExifTool.html#Geolocation> option is set
@@ -2469,12 +2471,12 @@ sub Options($$;@)
2469
2471
  } else {
2470
2472
  $$options{$param} = undef; # clear the list
2471
2473
  }
2472
- } elsif ($param eq 'IgnoreTags') {
2474
+ } elsif ($param =~ /^(IgnoreTags|IgnoreGroups)$/) {
2473
2475
  if (defined $newVal) {
2474
2476
  # parse list from delimited string if necessary
2475
- my @ignoreList = (ref $newVal eq 'ARRAY') ? @$newVal : ($newVal =~ /[-\w?*:]+/g);
2476
- ExpandShortcuts(\@ignoreList);
2477
- # add to existing tags to ignore
2477
+ my @ignoreList = (ref $newVal eq 'ARRAY') ? @$newVal : ($newVal =~ /[-\w?*:#]+/g);
2478
+ ExpandShortcuts(\@ignoreList) if $param eq 'IgnoreTags';
2479
+ # add to existing tags/groups to ignore
2478
2480
  $$options{$param} or $$options{$param} = { };
2479
2481
  foreach (@ignoreList) {
2480
2482
  /^(.*:)?([-\w?*]+)#?$/ or next;
@@ -2650,7 +2652,6 @@ sub ExtractInfo($;@)
2650
2652
  $self->Options(Duplicates => 1) if $$options{HtmlDump};
2651
2653
  # enable Validate option if Validate tag is requested
2652
2654
  $self->Options(Validate => 1) if $$req{validate};
2653
-
2654
2655
  if (defined $_[0]) {
2655
2656
  # only initialize filename if called with arguments
2656
2657
  $$self{FILENAME} = undef; # name of file (or '' if we didn't open it)
@@ -2659,6 +2660,11 @@ sub ExtractInfo($;@)
2659
2660
  $self->ParseArguments(@_); # initialize from our arguments
2660
2661
  }
2661
2662
  }
2663
+ # ignore all tags and set ExtractEmbedded if outputting CSV directly
2664
+ if ($self->Options('PrintCSV')) {
2665
+ $$self{OPTIONS}{IgnoreTags} = { all => 1 };
2666
+ $self->Options(ExtractEmbedded => 1);
2667
+ }
2662
2668
  # initialize ExifTool object members
2663
2669
  $self->Init();
2664
2670
  $$self{InExtract} = 1; # set flag indicating we are inside ExtractInfo
@@ -2839,6 +2845,7 @@ sub ExtractInfo($;@)
2839
2845
  $self->FoundTag('FileTypeExtension', '');
2840
2846
  $self->DoneExtract();
2841
2847
  $raf->Close() if $raf;
2848
+ %saveOptions and $$self{OPTIONS} = \%saveOptions;
2842
2849
  delete $$self{InExtract} unless $reEntry;
2843
2850
  return 1;
2844
2851
  }
@@ -3070,8 +3077,14 @@ sub ExtractInfo($;@)
3070
3077
  # restore necessary members when exiting re-entrant code
3071
3078
  $$self{$_} = $$reEntry{$_} foreach keys %$reEntry;
3072
3079
  SetByteOrder($saveOrder);
3080
+ } else {
3081
+ # call cleanup routines if necessary
3082
+ if ($$self{Cleanup}) {
3083
+ &$_($self) foreach @{$$self{Cleanup}};
3084
+ delete $$self{Cleanup};
3085
+ }
3086
+ delete $$self{InExtract};
3073
3087
  }
3074
- delete $$self{InExtract} unless $reEntry;
3075
3088
 
3076
3089
  # ($type may be undef without an Error when processing sub-documents)
3077
3090
  return 0 if not defined $type or exists $$self{VALUE}{Error};
@@ -5273,6 +5286,16 @@ sub AUTOLOAD
5273
5286
  return DoAutoLoad($AUTOLOAD, @_);
5274
5287
  }
5275
5288
 
5289
+ #------------------------------------------------------------------------------
5290
+ # Add cleanup routine to call before returning from Extract
5291
+ # Inputs: 0) ExifTool ref, 1) code ref to routine with ExifTool ref as an argument
5292
+ sub AddCleanup($)
5293
+ {
5294
+ my ($self, $sub) = @_;
5295
+ $$self{Cleanup} or $$self{Cleanup} = [ ];
5296
+ push @{$$self{Cleanup}}, $sub;
5297
+ }
5298
+
5276
5299
  #------------------------------------------------------------------------------
5277
5300
  # Add warning tag
5278
5301
  # Inputs: 0) ExifTool object reference, 1) warning message
@@ -8914,6 +8937,12 @@ sub FoundTag($$$;@)
8914
8937
  }
8915
8938
  $grps[0] or $grps[0] = $$self{SET_GROUP0};
8916
8939
  $grps[1] or $grps[1] = $$self{SET_GROUP1};
8940
+ if ($$options{IgnoreGroups}) {
8941
+ foreach (0..1) {
8942
+ my $g = lc($grps[$_] || $$tagInfo{Groups}{$_} || $$tagInfo{Table}{GROUPS}{$_});
8943
+ return undef if $$options{IgnoreGroups}{$g} or $$options{IgnoreGroups}{"$_$g"};
8944
+ }
8945
+ }
8917
8946
  my $valueHash = $$self{VALUE};
8918
8947
 
8919
8948
  if ($$tagInfo{RawConv}) {