exiftool-vendored.pl 12.80.0 → 12.84.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 (43) hide show
  1. package/bin/Changes +81 -0
  2. package/bin/MANIFEST +6 -18
  3. package/bin/META.json +1 -1
  4. package/bin/META.yml +1 -1
  5. package/bin/README +4 -2
  6. package/bin/build_geolocation +872 -0
  7. package/bin/config_files/example.config +2 -2
  8. package/bin/exiftool +61 -17
  9. package/bin/fmt_files/gpx.fmt +2 -1
  10. package/bin/fmt_files/gpx_wpt.fmt +2 -1
  11. package/bin/lib/Image/ExifTool/Apple.pm +51 -7
  12. package/bin/lib/Image/ExifTool/BuildTagLookup.pm +47 -31
  13. package/bin/lib/Image/ExifTool/CanonVRD.pm +19 -6
  14. package/bin/lib/Image/ExifTool/DJI.pm +29 -0
  15. package/bin/lib/Image/ExifTool/Exif.pm +19 -2
  16. package/bin/lib/Image/ExifTool/FujiFilm.pm +20 -7
  17. package/bin/lib/Image/ExifTool/GM.pm +552 -0
  18. package/bin/lib/Image/ExifTool/Geolocation.dat +0 -0
  19. package/bin/lib/Image/ExifTool/Geolocation.pm +423 -178
  20. package/bin/lib/Image/ExifTool/Geotag.pm +26 -13
  21. package/bin/lib/Image/ExifTool/M2TS.pm +32 -4
  22. package/bin/lib/Image/ExifTool/MakerNotes.pm +2 -2
  23. package/bin/lib/Image/ExifTool/Microsoft.pm +1 -1
  24. package/bin/lib/Image/ExifTool/Nikon.pm +337 -27
  25. package/bin/lib/Image/ExifTool/NikonCustom.pm +55 -1
  26. package/bin/lib/Image/ExifTool/Olympus.pm +1 -0
  27. package/bin/lib/Image/ExifTool/OpenEXR.pm +21 -3
  28. package/bin/lib/Image/ExifTool/PNG.pm +3 -3
  29. package/bin/lib/Image/ExifTool/QuickTime.pm +45 -24
  30. package/bin/lib/Image/ExifTool/QuickTimeStream.pl +66 -30
  31. package/bin/lib/Image/ExifTool/README +2 -0
  32. package/bin/lib/Image/ExifTool/Sony.pm +16 -7
  33. package/bin/lib/Image/ExifTool/TagLookup.pm +4827 -4778
  34. package/bin/lib/Image/ExifTool/TagNames.pod +953 -620
  35. package/bin/lib/Image/ExifTool/WriteQuickTime.pl +32 -9
  36. package/bin/lib/Image/ExifTool/Writer.pl +169 -130
  37. package/bin/lib/Image/ExifTool/XMP.pm +4 -2
  38. package/bin/lib/Image/ExifTool/XMP2.pl +3 -0
  39. package/bin/lib/Image/ExifTool.pm +106 -48
  40. package/bin/lib/Image/ExifTool.pod +47 -25
  41. package/bin/perl-Image-ExifTool.spec +1 -1
  42. package/bin/pp_build_exe.args +4 -4
  43. package/package.json +3 -3
@@ -15,6 +15,7 @@
15
15
  # 2019/11/10 - PH Also write pitch to CameraElevationAngle
16
16
  # 2020/12/01 - PH Added ability to read DJI CSV log files
17
17
  # 2022/06/21 - PH Added ability to read Google Takeout JSON files
18
+ # 2024/04/23 - PH Added ability to read more OpenTracks GPS tags
18
19
  #
19
20
  # References: 1) http://www.topografix.com/GPX/1/1/
20
21
  # 2) http://www.gpsinformation.org/dale/nmea.htm#GSA
@@ -29,7 +30,7 @@ use vars qw($VERSION);
29
30
  use Image::ExifTool qw(:Public);
30
31
  use Image::ExifTool::GPS;
31
32
 
32
- $VERSION = '1.74';
33
+ $VERSION = '1.76';
33
34
 
34
35
  sub JITTER() { return 2 } # maximum time jitter
35
36
 
@@ -66,6 +67,8 @@ my %xmlTag = (
66
67
  course => 'dir', # (written by Arduino)
67
68
  pitch => 'pitch', # (written by Arduino)
68
69
  roll => 'roll', # (written by Arduino)
70
+ speed => 'speed', # (OpenTrack gpx)
71
+ accuracy_horizontal => 'err',#(OpenTrack gpx)
69
72
  # XML containers (fix is reset at the opening tag of these properties)
70
73
  wpt => '', # GPX
71
74
  trkpt => '', # GPX
@@ -85,6 +88,7 @@ my %fixInfoKeys = (
85
88
  alt => [ 'alt' ],
86
89
  orient => [ 'dir', 'pitch', 'roll' ],
87
90
  atemp => [ 'atemp' ],
91
+ err => [ 'err' ],
88
92
  );
89
93
 
90
94
  my %isOrient = ( dir => 1, pitch => 1, roll => 1 ); # test for orientation key
@@ -346,8 +350,8 @@ sub LoadTrackLog($$;$)
346
350
  # validate altitude
347
351
  undef $$fix{alt} if defined $$fix{alt} and $$fix{alt} !~ /^[+-]?\d+\.?\d*/;
348
352
  $$has{alt} = 1 if $$fix{alt}; # set "has altitude" flag if appropriate
349
- } elsif ($tag eq 'atemp') {
350
- $$has{atemp} = 1;
353
+ } elsif ($tag eq 'atemp' or $tag eq 'speed' or $tag eq 'err') {
354
+ $$has{$tag} = 1;
351
355
  }
352
356
  }
353
357
  }
@@ -392,8 +396,8 @@ sub LoadTrackLog($$;$)
392
396
  # validate altitude
393
397
  undef $$fix{alt} if defined $$fix{alt} and $$fix{alt} !~ /^[+-]?\d+\.?\d*/;
394
398
  $$has{alt} = 1 if $$fix{alt}; # set "has altitude" flag if appropriate
395
- } elsif ($tag eq 'atemp') {
396
- $$has{atemp} = 1;
399
+ } elsif ($tag eq 'atemp' or $tag eq 'speed' or $tag eq 'err') {
400
+ $$has{$tag} = 1;
397
401
  }
398
402
  }
399
403
  }
@@ -1126,7 +1130,7 @@ sub SetGeoValues($$;$)
1126
1130
  # loop through available fix information categories
1127
1131
  # (pos, track, alt, orient)
1128
1132
  my ($category, $key);
1129
- Category: foreach $category (qw{pos track alt orient atemp}) {
1133
+ Category: foreach $category (qw{pos track alt orient atemp err}) {
1130
1134
  next unless $$has{$category};
1131
1135
  my ($f, $p0b, $p1b, $f0b);
1132
1136
  # loop through specific fix information keys
@@ -1221,9 +1225,14 @@ Category: foreach $category (qw{pos track alt orient atemp}) {
1221
1225
  # also Geolocate if specified
1222
1226
  my $nvHash;
1223
1227
  my $geoloc = $et->GetNewValue('Geolocate', \$nvHash);
1224
- if ($geoloc and lc($geoloc) eq 'geotag') {
1225
- $geoloc = ($$nvHash{WantGroup} ? "$$nvHash{WantGroup}:" : '') . 'Geolocate';
1226
- $et->SetNewValue($geoloc => "$$fix{lat},$$fix{lon}");
1228
+ if ($geoloc and $geoloc =~ /\bgeotag\b/i) {
1229
+ my $tag = ($$nvHash{WantGroup} ? "$$nvHash{WantGroup}:" : '') . 'Geolocate';
1230
+ # pass along any regular expressions to qualify geolocation search
1231
+ my $parms = join ',', grep m(/), split /\s*,\s*/, $geoloc;
1232
+ $parms and $parms = ",$parms,both";
1233
+ $et->SetNewValue($tag => "$$fix{lat},$$fix{lon}$parms");
1234
+ # (the Geolocate tag will be restored to its original value
1235
+ # by RestoreNewValues before the next file in batch processing)
1227
1236
  }
1228
1237
  return $err if $qt; # all done if writing to QuickTime only
1229
1238
  # (capture error messages by calling SetNewValue in list context)
@@ -1231,10 +1240,11 @@ Category: foreach $category (qw{pos track alt orient atemp}) {
1231
1240
  @r = $et->SetNewValue(GPSLongitude => $$fix{lon}, %opts);
1232
1241
  @r = $et->SetNewValue(GPSAltitude => $gpsAlt, %opts);
1233
1242
  @r = $et->SetNewValue(GPSAltitudeRef => $gpsAltRef, %opts);
1234
- if ($$has{track}) {
1243
+ if ($$has{track} or $$has{speed}) {
1244
+ my $type = $$has{track} ? 'track' : 'speed';
1235
1245
  my $tFix = $fix;
1236
- if (not defined $$fix{track} and defined $iExt) {
1237
- my $p = FindFix($et,'track',$times,$points,$iExt,$iDir,$geoMaxExtSecs);
1246
+ if (not defined $$fix{$type} and defined $iExt) {
1247
+ my $p = FindFix($et,$type,$times,$points,$iExt,$iDir,$geoMaxExtSecs);
1238
1248
  $tFix = $p if $p;
1239
1249
  }
1240
1250
  @r = $et->SetNewValue(GPSTrack => $$tFix{track}, %opts);
@@ -1275,6 +1285,9 @@ Category: foreach $category (qw{pos track alt orient atemp}) {
1275
1285
  }
1276
1286
  @r = $et->SetNewValue(AmbientTemperature => $$tFix{atemp}, %opts);
1277
1287
  }
1288
+ if ($$has{err}) {
1289
+ @r = $et->SetNewValue(GPSHPositioningError => $$fix{err}, %opts);
1290
+ }
1278
1291
  unless ($xmp) {
1279
1292
  my ($latRef, $lonRef);
1280
1293
  $latRef = ($$fix{lat} > 0 ? 'N' : 'S') if defined $$fix{lat};
@@ -1300,7 +1313,7 @@ Category: foreach $category (qw{pos track alt orient atemp}) {
1300
1313
  GPSAltitude GPSAltitudeRef GPSDateStamp GPSTimeStamp GPSDateTime
1301
1314
  GPSTrack GPSTrackRef GPSSpeed GPSSpeedRef GPSImgDirection
1302
1315
  GPSImgDirectionRef GPSPitch GPSRoll CameraElevationAngle
1303
- AmbientTemperature GPSCoordinates))
1316
+ AmbientTemperature GPSHPositioningError GPSCoordinates))
1304
1317
  {
1305
1318
  my @r = $et->SetNewValue($_, undef, %opts);
1306
1319
  }
@@ -32,7 +32,7 @@ use strict;
32
32
  use vars qw($VERSION);
33
33
  use Image::ExifTool qw(:DataAccess :Utils);
34
34
 
35
- $VERSION = '1.24';
35
+ $VERSION = '1.25';
36
36
 
37
37
  # program map table "stream_type" lookup (ref 6/1/9)
38
38
  my %streamType = (
@@ -379,7 +379,7 @@ sub ParsePID($$$$$)
379
379
  $et->HandleTag($tagTbl, Accelerometer => "@acc");
380
380
  }
381
381
  SetByteOrder('MM');
382
- $$et{HasINNOV} = 1; # (necessary to skip over empty/unknown INNOV records)
382
+ $$et{FoundGoodGPS} = 1; # (necessary to skip over empty/unknown INNOV records)
383
383
  $more = 1;
384
384
  } elsif ($$dataPt =~ /^\$(GPSINFO|GSNRINFO),/) {
385
385
  # $GPSINFO,0x0004,2021.08.09 13:27:36,2341.54561,12031.70135,8.0,51,153,0,0,\x0d
@@ -481,7 +481,35 @@ sub ParsePID($$$$$)
481
481
  $et->HandleTag($tagTbl, GPSTrackRef => 'T');
482
482
  SetByteOrder('MM');
483
483
  $more = 1;
484
- } elsif ($$et{HasINNOV}) {
484
+ } elsif (length($$dataPt) >= 64 and substr($$dataPt, 32, 2) eq '$S') {
485
+ # DOD_LS600W.TS
486
+ my $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
487
+ # find the earliest sample time in the cyclical list
488
+ my ($n, $last) = (32, "\0");
489
+ for (my $i=32; $i<length($$dataPt)-32; $i+=32) {
490
+ last unless substr($$dataPt, $n, 2) eq '$S';
491
+ my $dateTime = substr($$dataPt, $i+6, 8);
492
+ $last gt $dateTime and $n = $i, last; # earliest sample if time goes backwards
493
+ $last = $dateTime;
494
+ }
495
+ for (my $i=32; $i<length($$dataPt)-32; $i+=32, $n+=32) {
496
+ $n = 32 if $n > length($$dataPt)-32;
497
+ last unless substr($$dataPt, $n, 2) eq '$S';
498
+ my @a = unpack("x${n}nnnnCCCCnCNNC", $$dataPt);
499
+ $a[8] /= 10; # 1/10 sec
500
+ $a[2] += (36000 - 65536) if $a[2] & 0x8000; # convert signed integer into range 0-36000
501
+ $$et{DOC_NUM} = ++$$et{DOC_COUNT};
502
+ $et->HandleTag($tagTbl, GPSDateTime => sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%04.1fZ', @a[3..8]));
503
+ $et->HandleTag($tagTbl, GPSLatitude => $a[10] * 1e-7);
504
+ $et->HandleTag($tagTbl, GPSLongitude => $a[11] * 1e-7);
505
+ $et->HandleTag($tagTbl, GPSSpeed => $a[1] * 0.036); # convert from metres per 100 s
506
+ $et->HandleTag($tagTbl, GPSTrack => $a[2] / 100);
507
+ }
508
+ # Note: 10 bytes after last GPS record look like a single 3-axis accelerometer reading:
509
+ # eg. fd ff 00 00 ff ff 00 00 01 00
510
+ $$et{FoundGoodGPS} = 1; # so we skip over unrecognized packets
511
+ $more = 1;
512
+ } elsif ($$et{FoundGoodGPS}) {
485
513
  $more = 1;
486
514
  }
487
515
  delete $$et{DOC_NUM};
@@ -538,7 +566,7 @@ sub ProcessM2TS($$)
538
566
  my %needPID = ( 0 => 1 ); # lookup for stream PID's that we still need to parse
539
567
  # PID's that may contain GPS info
540
568
  my %gpsPID = (
541
- 0x0300 => 1, # Novatek INNOVV
569
+ 0x0300 => 1, # Novatek INNOVV, DOD_LS600W
542
570
  0x01e4 => 1, # vsys a6l dashcam
543
571
  0x0e1b => 1, # Jomise T860S-GM dashcam
544
572
  );
@@ -21,7 +21,7 @@ sub ProcessKodakPatch($$$);
21
21
  sub WriteUnknownOrPreview($$$);
22
22
  sub FixLeicaBase($$;$);
23
23
 
24
- $VERSION = '2.15';
24
+ $VERSION = '2.16';
25
25
 
26
26
  my $debug; # set to 1 to enable debugging code
27
27
 
@@ -195,7 +195,7 @@ my $debug; # set to 1 to enable debugging code
195
195
  },
196
196
  {
197
197
  Name => 'MakerNoteHP4', # PhotoSmart M627
198
- Condition => '$$valPt =~ /^IIII\x04\0/',
198
+ Condition => '$$valPt =~ /^IIII[\x04|\x05]\0/',
199
199
  NotIFD => 1,
200
200
  SubDirectory => {
201
201
  TagTable => 'Image::ExifTool::HP::Type4',
@@ -245,7 +245,7 @@ my %sRegions = (
245
245
  Copyright => { Groups => { 2 => 'Author' } },
246
246
  Count => { },
247
247
  CurrentBitrate => { },
248
- Description => { },
248
+ Description => { Writable => 'Unicode', Avoid => 1 },
249
249
  DisplayArtist => { },
250
250
  DLNAServerUDN => { },
251
251
  DLNASourceURI => { },