exiftool_vendored 12.68.0 → 12.72.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +98 -15
  3. data/bin/MANIFEST +5 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +10 -10
  7. data/bin/exiftool +32 -25
  8. data/bin/lib/Image/ExifTool/AAC.pm +175 -0
  9. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +2 -1
  10. data/bin/lib/Image/ExifTool/CBOR.pm +18 -2
  11. data/bin/lib/Image/ExifTool/Canon.pm +87 -20
  12. data/bin/lib/Image/ExifTool/DJI.pm +3 -2
  13. data/bin/lib/Image/ExifTool/DNG.pm +25 -2
  14. data/bin/lib/Image/ExifTool/EXE.pm +54 -6
  15. data/bin/lib/Image/ExifTool/Exif.pm +204 -22
  16. data/bin/lib/Image/ExifTool/FujiFilm.pm +145 -20
  17. data/bin/lib/Image/ExifTool/GIF.pm +5 -1
  18. data/bin/lib/Image/ExifTool/GoPro.pm +16 -1
  19. data/bin/lib/Image/ExifTool/ID3.pm +76 -10
  20. data/bin/lib/Image/ExifTool/InDesign.pm +1 -1
  21. data/bin/lib/Image/ExifTool/JPEG.pm +1 -1
  22. data/bin/lib/Image/ExifTool/JSON.pm +4 -1
  23. data/bin/lib/Image/ExifTool/Jpeg2000.pm +30 -15
  24. data/bin/lib/Image/ExifTool/M2TS.pm +21 -16
  25. data/bin/lib/Image/ExifTool/MakerNotes.pm +2 -2
  26. data/bin/lib/Image/ExifTool/Nikon.pm +213 -105
  27. data/bin/lib/Image/ExifTool/Olympus.pm +7 -1
  28. data/bin/lib/Image/ExifTool/PNG.pm +8 -13
  29. data/bin/lib/Image/ExifTool/Panasonic.pm +15 -2
  30. data/bin/lib/Image/ExifTool/Pentax.pm +15 -6
  31. data/bin/lib/Image/ExifTool/PhotoMechanic.pm +2 -2
  32. data/bin/lib/Image/ExifTool/QuickTime.pm +60 -14
  33. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +59 -11
  34. data/bin/lib/Image/ExifTool/README +14 -5
  35. data/bin/lib/Image/ExifTool/RIFF.pm +60 -10
  36. data/bin/lib/Image/ExifTool/Ricoh.pm +109 -1
  37. data/bin/lib/Image/ExifTool/Samsung.pm +3 -2
  38. data/bin/lib/Image/ExifTool/Sony.pm +177 -37
  39. data/bin/lib/Image/ExifTool/TagLookup.pm +6971 -6714
  40. data/bin/lib/Image/ExifTool/TagNames.pod +957 -372
  41. data/bin/lib/Image/ExifTool/Text.pm +4 -5
  42. data/bin/lib/Image/ExifTool/Validate.pm +23 -20
  43. data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +2 -2
  44. data/bin/lib/Image/ExifTool/WriteExif.pl +33 -8
  45. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +1 -0
  46. data/bin/lib/Image/ExifTool/WriteRIFF.pl +31 -6
  47. data/bin/lib/Image/ExifTool/Writer.pl +121 -28
  48. data/bin/lib/Image/ExifTool/XMP.pm +67 -2
  49. data/bin/lib/Image/ExifTool/XMP2.pl +35 -0
  50. data/bin/lib/Image/ExifTool.pm +94 -43
  51. data/bin/lib/Image/ExifTool.pod +28 -17
  52. data/bin/perl-Image-ExifTool.spec +9 -9
  53. data/lib/exiftool_vendored/version.rb +1 -1
  54. metadata +3 -2
@@ -18,12 +18,13 @@ use strict;
18
18
  use vars qw($VERSION);
19
19
  use Image::ExifTool qw(:DataAccess :Utils);
20
20
 
21
- $VERSION = '1.58';
21
+ $VERSION = '1.60';
22
22
 
23
23
  sub ProcessID3v2($$$);
24
24
  sub ProcessPrivate($$$);
25
25
  sub ProcessSynText($$$);
26
26
  sub ProcessID3Dir($$$);
27
+ sub ProcessGEOB($$$);
27
28
  sub ConvertID3v1Text($$);
28
29
  sub ConvertTimeStamp($);
29
30
 
@@ -419,7 +420,7 @@ my %genre = (
419
420
 
420
421
  # Tags for ID2v2.2
421
422
  %Image::ExifTool::ID3::v2_2 = (
422
- PROCESS_PROC => \&Image::ExifTool::ID3::ProcessID3v2,
423
+ PROCESS_PROC => \&ProcessID3v2,
423
424
  GROUPS => { 1 => 'ID3v2_2', 2 => 'Audio' },
424
425
  NOTES => q{
425
426
  ExifTool extracts mainly text-based tags from ID3v2 information. The tags
@@ -511,6 +512,9 @@ my %genre = (
511
512
  TSC => 'ComposerSortOrder',
512
513
  ITU => { Name => 'iTunesU', Description => 'iTunes U', Binary => 1, Unknown => 1 },
513
514
  PCS => { Name => 'Podcast', Binary => 1, Unknown => 1 },
515
+ GP1 => 'Grouping', #github142 (NC)
516
+ MVN => 'MovementName', #github142 (NC)
517
+ MVI => 'MovementNumber', #github142 (NC)
514
518
  );
515
519
 
516
520
  # tags common to ID3v2.3 and ID3v2.4
@@ -534,7 +538,10 @@ my %id3v2_common = (
534
538
  # COMR => 'Commercial',
535
539
  # ENCR => 'EncryptionMethod',
536
540
  # ETCO => 'EventTimingCodes',
537
- # GEOB => 'GeneralEncapsulatedObject',
541
+ GEOB => {
542
+ Name => 'GeneralEncapsulatedObject',
543
+ SubDirectory => { TagTable => 'Image::ExifTool::ID3::GEOB' },
544
+ },
538
545
  # GRID => 'GroupIdentification',
539
546
  # LINK => 'LinkedInformation',
540
547
  MCDI => { Name => 'MusicCDIdentifier', Binary => 1 },
@@ -640,9 +647,25 @@ my %id3v2_common = (
640
647
  MVIN => 'MovementNumber', # (NC)
641
648
  );
642
649
 
650
+ %Image::ExifTool::ID3::GEOB = (
651
+ GROUPS => { 1 => 'ID3v2_3', 2 => 'Other' },
652
+ PROCESS_PROC => \&ProcessGEOB,
653
+ 'application/x-c2pa-manifest-store' => {
654
+ Name => 'JUMBF',
655
+ SubDirectory => {
656
+ TagTable => 'Image::ExifTool::Jpeg2000::Main',
657
+ ByteOrder => 'BigEndian',
658
+ },
659
+ },
660
+ 'GEOB-Mime' => { },
661
+ 'GEOB-File' => { },
662
+ 'GEOB-Desc' => { },
663
+ 'GEOB-Data' => { },
664
+ );
665
+
643
666
  # Tags for ID3v2.3 (http://www.id3.org/id3v2.3.0)
644
667
  %Image::ExifTool::ID3::v2_3 = (
645
- PROCESS_PROC => \&Image::ExifTool::ID3::ProcessID3v2,
668
+ PROCESS_PROC => \&ProcessID3v2,
646
669
  GROUPS => { 1 => 'ID3v2_3', 2 => 'Audio' },
647
670
  NOTES => q{
648
671
  ID3 version 2.3 tags. Includes some non-standard tags written by other
@@ -662,7 +685,7 @@ my %id3v2_common = (
662
685
 
663
686
  # Tags for ID3v2.4 (http://www.id3.org/id3v2.4.0-frames)
664
687
  %Image::ExifTool::ID3::v2_4 = (
665
- PROCESS_PROC => \&Image::ExifTool::ID3::ProcessID3v2,
688
+ PROCESS_PROC => \&ProcessID3v2,
666
689
  GROUPS => { 1 => 'ID3v2_4', 2 => 'Audio' },
667
690
  NOTES => q{
668
691
  ID3 version 2.4 tags. Includes some non-standard tags written by other
@@ -802,8 +825,8 @@ my %id3v2_common = (
802
825
 
803
826
  # lookup to check for existence of tags in other ID3 versions
804
827
  my %otherTable = (
805
- \%Image::ExifTool::ID3::v2_4 => \%Image::ExifTool::ID3::v2_3,
806
- \%Image::ExifTool::ID3::v2_3 => \%Image::ExifTool::ID3::v2_4,
828
+ \%Image::ExifTool::ID3::v2_4 => 'Image::ExifTool::ID3::v2_3',
829
+ \%Image::ExifTool::ID3::v2_3 => 'Image::ExifTool::ID3::v2_4',
807
830
  );
808
831
 
809
832
  # ID3 Composite tags
@@ -1075,6 +1098,7 @@ sub ProcessID3v2($$$)
1075
1098
  my $vers = $$dirInfo{Version};
1076
1099
  my $verbose = $et->Options('Verbose');
1077
1100
  my $len; # frame data length
1101
+ my $otherTable;
1078
1102
 
1079
1103
  $et->VerboseDir($tagTablePtr->{GROUPS}->{1}, 0, $size);
1080
1104
  $et->VerboseDump($dataPt, Len => $size, Start => $offset);
@@ -1101,7 +1125,11 @@ sub ProcessID3v2($$$)
1101
1125
  my $oldLen = $len;
1102
1126
  $len = UnSyncSafe($len);
1103
1127
  if (not defined $len or $offset + $len + 10 > $size) {
1104
- $et->Warn('Invalid ID3 frame size');
1128
+ if ($offset + $len == $size) {
1129
+ $et->Warn('Missing ID3 terminating frame', 1);
1130
+ } else {
1131
+ $et->Warn('Invalid ID3 frame size');
1132
+ }
1105
1133
  last;
1106
1134
  }
1107
1135
  # check next ID to see if it makes sense
@@ -1117,7 +1145,9 @@ sub ProcessID3v2($$$)
1117
1145
  last if $offset + $len > $size;
1118
1146
  my $tagInfo = $et->GetTagInfo($tagTablePtr, $id);
1119
1147
  unless ($tagInfo) {
1120
- my $otherTable = $otherTable{$tagTablePtr};
1148
+ if (not $otherTable and $otherTable{$tagTablePtr}) {
1149
+ $otherTable = GetTagTable($otherTable{$tagTablePtr});
1150
+ }
1121
1151
  $tagInfo = $et->GetTagInfo($otherTable, $id) if $otherTable;
1122
1152
  if ($tagInfo) {
1123
1153
  $et->WarnOnce("Frame '${id}' is not valid for this ID3 version", 1);
@@ -1218,7 +1248,7 @@ sub ProcessID3v2($$$)
1218
1248
  my @vals = DecodeString($et, $val);
1219
1249
  foreach (0..1) { $vals[$_] = '' unless defined $vals[$_]; }
1220
1250
  ($val = "($vals[0]) $vals[1]") =~ s/^\(\) //;
1221
- } elsif ($id =~ /^T/ or $id =~ /^(IPL|IPLS)$/) {
1251
+ } elsif ($id =~ /^T/ or $id =~ /^(IPL|IPLS|GP1|MVI|MVN)$/) {
1222
1252
  $val = DecodeString($et, $val);
1223
1253
  } elsif ($id =~ /^(WXX|WXXX)$/) {
1224
1254
  # one encoded string and one Latin string separated by a null
@@ -1582,6 +1612,42 @@ sub ProcessID3Dir($$$)
1582
1612
  return ProcessID3($et, $dirInfo);
1583
1613
  }
1584
1614
 
1615
+ #------------------------------------------------------------------------------
1616
+ # Process ID3 General Encapsulated Object
1617
+ # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
1618
+ # Returns: 1 on success
1619
+ sub ProcessGEOB($$$)
1620
+ {
1621
+ my ($et, $dirInfo, $tagTablePtr) = @_;
1622
+ $et->VerboseDir('GEOB', undef, length ${$$dirInfo{DataPt}});
1623
+ my $dataPt = $$dirInfo{DataPt};
1624
+ my $len = length $$dataPt;
1625
+ $len >= 4 or $et->Warn("Short GEOB frame"), return 0;
1626
+ my ($hdr, $attr);
1627
+ my $enc = unpack('C', $$dataPt);
1628
+ if ($enc == 1 or $enc == 2) {
1629
+ $hdr = ".(.*?)\0((?:..)*?)\0\0((?:..)*?)\0\0";
1630
+ } else {
1631
+ $hdr = ".(.*?)\0(.*?)\0(.*?)\0";
1632
+ }
1633
+ # remove header (encoding, mime, filename, description)
1634
+ $$dataPt =~ s/^$hdr//s or $et->Warn("Invalid GEOB frame"), return 0;
1635
+ my ($mime, $file, $desc) = ($1, DecodeString($et, $2, $enc), DecodeString($et, $3, $enc));
1636
+ $et->HandleTag($tagTablePtr, 'GEOB-Mime', $mime) if length $mime;
1637
+ $et->HandleTag($tagTablePtr, 'GEOB-File', $file) if length $file;
1638
+ $et->HandleTag($tagTablePtr, 'GEOB-Desc', $desc) if length $desc;
1639
+ if ($$tagTablePtr{$mime}) {
1640
+ $et->HandleTag($tagTablePtr, $mime, undef,
1641
+ DataPt => $dataPt,
1642
+ Start => 0,
1643
+ Size => length($$dataPt),
1644
+ );
1645
+ } else {
1646
+ $et->HandleTag($tagTablePtr, 'GEOB-Data', $dataPt);
1647
+ }
1648
+ return 1;
1649
+ }
1650
+
1585
1651
  #------------------------------------------------------------------------------
1586
1652
  # Extract ID3 information from an MP3 audio file
1587
1653
  # Inputs: 0) ExifTool object reference, 1) dirInfo reference
@@ -122,7 +122,7 @@ sub ProcessIND($$)
122
122
  # memory troubles (with its apparent 1 GB limit) if the XMP is larger
123
123
  # than about 400 MB, so guard against this
124
124
  if ($len > 300 * 1024 * 1024) {
125
- my $msg = sprintf('Insanely large XMP (%.0f MB)', $len / (1024 * 1024));
125
+ my $msg = sprintf('Insanely large XMP (%.0f MiB)', $len / (1024 * 1024));
126
126
  if ($outfile) {
127
127
  $et->Error($msg, 2) and $err = 1, last;
128
128
  } elsif ($et->Options('IgnoreMinorErrors')) {
@@ -251,7 +251,7 @@ sub ProcessJPEG_HDR($$$);
251
251
  Name => 'JUMBF',
252
252
  Condition => '$$valPt =~ /^JP/',
253
253
  SubDirectory => { TagTable => 'Image::ExifTool::Jpeg2000::Main' },
254
- # Note: The recommended options for reading C2PA JUMBF metadata are "-G3 -b -j -u"
254
+ # Note: The suggested options for reading C2PA CAI JUMBF metadata are "-G3 -b -j -u"
255
255
  }],
256
256
  APP12 => [{
257
257
  Name => 'PictureInfo',
@@ -14,7 +14,7 @@ use vars qw($VERSION);
14
14
  use Image::ExifTool qw(:DataAccess :Utils);
15
15
  use Image::ExifTool::Import;
16
16
 
17
- $VERSION = '1.05';
17
+ $VERSION = '1.06';
18
18
 
19
19
  sub ProcessJSON($$);
20
20
  sub ProcessTag($$$$%);
@@ -60,6 +60,9 @@ sub FoundTag($$$$%)
60
60
  # avoid conflict with special table entries
61
61
  $tag .= '!' if $Image::ExifTool::specialTags{$tag};
62
62
 
63
+ # use underline instead of colon if necessary in tag name
64
+ $tag =~ s/([A-Z]):([A-Z]{2})/${1}_$2/g;
65
+
63
66
  AddTagToTable($tagTablePtr, $tag, {
64
67
  Name => Image::ExifTool::MakeTagName($tag),
65
68
  %flags,
@@ -89,12 +89,14 @@ my %uuid = (
89
89
  # JPEG2000 codestream markers (ref ISO/IEC FCD15444-1/2)
90
90
  my %j2cMarker = (
91
91
  0x4f => 'SOC', # start of codestream
92
+ # 0x50 - seen in JPH codestream
92
93
  0x51 => 'SIZ', # image and tile size
93
94
  0x52 => 'COD', # coding style default
94
95
  0x53 => 'COC', # coding style component
95
96
  0x55 => 'TLM', # tile-part lengths
96
97
  0x57 => 'PLM', # packet length, main header
97
98
  0x58 => 'PLT', # packet length, tile-part header
99
+ # 0x59 - seen in JPH codestream
98
100
  0x5c => 'QCD', # quantization default
99
101
  0x5d => 'QCC', # quantization component
100
102
  0x5e => 'RGN', # region of interest
@@ -128,12 +130,21 @@ my %j2cMarker = (
128
130
  WRITE_PROC => \&ProcessJpeg2000Box,
129
131
  PREFERRED => 1, # always add these tags when writing
130
132
  NOTES => q{
131
- The tags below are found in JPEG 2000 images and the JUMBF metadata in JPEG
132
- images, but not all of these are extracted. Note that ExifTool currently
133
- writes only EXIF, IPTC and XMP tags in Jpeg2000 images, and EXIF and XMP in
134
- JXL images. ExifTool will read/write Brotli-compressed EXIF and XMP in JXL
135
- images, but the API L<Compress|../ExifTool.html#Compress> option must be set to create new EXIF and XMP
136
- in compressed format.
133
+ The tags below are found in JPEG 2000 images and the C2PA CAI JUMBF metadata
134
+ in various file types (see below). Note that ExifTool currently writes only
135
+ EXIF, IPTC and XMP tags in Jpeg2000 images, and EXIF and XMP in JXL images.
136
+ ExifTool will read/write Brotli-compressed EXIF and XMP in JXL images, but
137
+ the API L<Compress|../ExifTool.html#Compress> option must be set to create new EXIF and XMP in compressed
138
+ format.
139
+
140
+ C2PA (Coalition for Content Provenance and Authenticity) CAI (Content
141
+ Authenticity Initiative) JUMBF (JPEG Universal Metadata Box Format) metdata
142
+ is currently extracted from JPEG, PNG, TIFF-based (eg. TIFF, DNG),
143
+ QuickTime-based (eg. MP4, MOV, HEIF, AVIF), RIFF-based (eg. WAV, AVI, WebP),
144
+ GIF files and ID3v2 metadata. The suggested ExifTool command-line arguments
145
+ for reading C2PA metadata are C<-jumbf:all -G3 -b -j -u -struct>. This
146
+ metadata may be deleted from writable JPEG, PNG, WebP, TIFF-based, and
147
+ QuickTime-based files by deleting the JUMBF group with C<-jumbf:all=>.
137
148
  },
138
149
  #
139
150
  # NOTE: ONLY TAGS WITH "Format" DEFINED ARE EXTRACTED!
@@ -345,13 +356,6 @@ my %j2cMarker = (
345
356
  Start => '$valuePtr + 16',
346
357
  },
347
358
  },
348
- {
349
- Name => 'UUID-Signature', # (seen in JUMB data of JPEG images)
350
- # (may be able to remove this when JUMBF specification is finalized)
351
- Condition => '$$valPt=~/^casg\x00\x11\x00\x10\x80\x00\x00\xaa\x00\x38\x9b\x71/',
352
- Format => 'undef',
353
- ValueConv => 'substr($val,16)',
354
- },
355
359
  {
356
360
  Name => 'UUID-C2PAClaimSignature', # (seen in incorrectly-formatted JUMB data of JPEG images)
357
361
  # (may be able to remove this when JUMBF specification is finalized)
@@ -361,6 +365,13 @@ my %j2cMarker = (
361
365
  Start => '$valuePtr + 16',
362
366
  },
363
367
  },
368
+ {
369
+ Name => 'UUID-Signature', # (seen in JUMB data of JPEG images)
370
+ # (may be able to remove this when JUMBF specification is finalized)
371
+ Condition => '$$valPt=~/^casg\x00\x11\x00\x10\x80\x00\x00\xaa\x00\x38\x9b\x71/',
372
+ Format => 'undef',
373
+ ValueConv => 'substr($val,16)',
374
+ },
364
375
  {
365
376
  Name => 'UUID-Unknown',
366
377
  },
@@ -549,6 +560,7 @@ my %j2cMarker = (
549
560
  'jpm ' => 'JPEG 2000 Compound Image (.JPM)', # image/jpm
550
561
  'jpx ' => 'JPEG 2000 with extensions (.JPX)', # image/jpx
551
562
  'jxl ' => 'JPEG XL Image (.JXL)', # image/jxl
563
+ 'jph ' => 'High-throughput JPEG 2000 (.JPH)', # image/jph
552
564
  },
553
565
  },
554
566
  1 => {
@@ -993,10 +1005,12 @@ sub ProcessJpeg2000Box($$$)
993
1005
  my $dirLen = $$dirInfo{DirLen} || 0;
994
1006
  my $dirStart = $$dirInfo{DirStart} || 0;
995
1007
  my $base = $$dirInfo{Base} || 0;
996
- my $raf = $$dirInfo{RAF};
997
1008
  my $outfile = $$dirInfo{OutFile};
998
1009
  my $dirEnd = $dirStart + $dirLen;
999
- my ($err, $outBuff, $verbose, $doColour, $hash);
1010
+ my ($err, $outBuff, $verbose, $doColour, $hash, $raf);
1011
+
1012
+ # read from RAF unless reading from buffer
1013
+ $raf = $$dirInfo{RAF} unless $dataPt;
1000
1014
 
1001
1015
  if ($outfile) {
1002
1016
  unless ($raf) {
@@ -1516,6 +1530,7 @@ sub ProcessJP2($$)
1516
1530
  $fileType = 'JPX' if $1 eq 'jpx ';
1517
1531
  $fileType = 'JPM' if $1 eq 'jpm ';
1518
1532
  $fileType = 'JXL' if $1 eq 'jxl ';
1533
+ $fileType = 'JPH' if $1 eq 'jph ';
1519
1534
  }
1520
1535
  $raf->Seek(-length($buff), 1) if defined $buff;
1521
1536
  $et->SetFileType($fileType);
@@ -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.23';
35
+ $VERSION = '1.24';
36
36
 
37
37
  # program map table "stream_type" lookup (ref 6/1/9)
38
38
  my %streamType = (
@@ -354,29 +354,32 @@ sub ParsePID($$$$$)
354
354
  my $tbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
355
355
  Image::ExifTool::QuickTime::ProcessFreeGPS($et, { DataPt => \$dat }, $tbl);
356
356
  $more = 1;
357
- } elsif ($$dataPt =~ /^A([NS])([EW])\0/s) {
358
- # INNOVV TS video (same format is INNOVV MP4)
357
+ } elsif ($$dataPt =~ /^(V00|A([NS])([EW]))\0/s) {
358
+ # INNOVV TS video (same format as INNOVV MP4)
359
359
  SetByteOrder('II');
360
360
  my $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
361
- while ($$dataPt =~ /(A[NS][EW]\0.{28})/g) {
361
+ while ($$dataPt =~ /((V00|A[NS][EW])\0.{28})/g) {
362
362
  my $dat = $1;
363
- my $lat = abs(GetFloat(\$dat, 4)); # (abs just to be safe)
364
- my $lon = abs(GetFloat(\$dat, 8)); # (abs just to be safe)
365
- my $spd = GetFloat(\$dat, 12) * $knotsToKph;
366
- my $trk = GetFloat(\$dat, 16);
363
+ $$et{DOC_NUM} = ++$$et{DOC_COUNT};
364
+ if ($2 ne 'V00') {
365
+ my $lat = abs(GetFloat(\$dat, 4)); # (abs just to be safe)
366
+ my $lon = abs(GetFloat(\$dat, 8)); # (abs just to be safe)
367
+ my $spd = GetFloat(\$dat, 12) * $knotsToKph;
368
+ my $trk = GetFloat(\$dat, 16);
369
+ Image::ExifTool::QuickTime::ConvertLatLon($lat, $lon);
370
+ $et->HandleTag($tagTbl, GPSLatitude => abs($lat) * (substr($dat,1,1) eq 'S' ? -1 : 1));
371
+ $et->HandleTag($tagTbl, GPSLongitude => abs($lon) * (substr($dat,2,1) eq 'W' ? -1 : 1));
372
+ $et->HandleTag($tagTbl, GPSSpeed => $spd);
373
+ $et->HandleTag($tagTbl, GPSSpeedRef => 'K');
374
+ $et->HandleTag($tagTbl, GPSTrack => $trk);
375
+ $et->HandleTag($tagTbl, GPSTrackRef => 'T');
376
+ }
367
377
  my @acc = unpack('x20V3', $dat);
368
378
  map { $_ = $_ - 4294967296 if $_ >= 0x80000000 } @acc;
369
- Image::ExifTool::QuickTime::ConvertLatLon($lat, $lon);
370
- $$et{DOC_NUM} = ++$$et{DOC_COUNT};
371
- $et->HandleTag($tagTbl, GPSLatitude => abs($lat) * (substr($dat,1,1) eq 'S' ? -1 : 1));
372
- $et->HandleTag($tagTbl, GPSLongitude => abs($lon) * (substr($dat,2,1) eq 'W' ? -1 : 1));
373
- $et->HandleTag($tagTbl, GPSSpeed => $spd);
374
- $et->HandleTag($tagTbl, GPSSpeedRef => 'K');
375
- $et->HandleTag($tagTbl, GPSTrack => $trk);
376
- $et->HandleTag($tagTbl, GPSTrackRef => 'T');
377
379
  $et->HandleTag($tagTbl, Accelerometer => "@acc");
378
380
  }
379
381
  SetByteOrder('MM');
382
+ $$et{HasINNOV} = 1; # (necessary to skip over empty/unknown INNOV records)
380
383
  $more = 1;
381
384
  } elsif ($$dataPt =~ /^\$(GPSINFO|GSNRINFO),/) {
382
385
  # $GPSINFO,0x0004,2021.08.09 13:27:36,2341.54561,12031.70135,8.0,51,153,0,0,\x0d
@@ -478,6 +481,8 @@ sub ParsePID($$$$$)
478
481
  $et->HandleTag($tagTbl, GPSTrackRef => 'T');
479
482
  SetByteOrder('MM');
480
483
  $more = 1;
484
+ } elsif ($$et{HasINNOV}) {
485
+ $more = 1;
481
486
  }
482
487
  delete $$et{DOC_NUM};
483
488
  }
@@ -21,7 +21,7 @@ sub ProcessKodakPatch($$$);
21
21
  sub WriteUnknownOrPreview($$$);
22
22
  sub FixLeicaBase($$;$);
23
23
 
24
- $VERSION = '2.14';
24
+ $VERSION = '2.15';
25
25
 
26
26
  my $debug; # set to 1 to enable debugging code
27
27
 
@@ -694,7 +694,7 @@ my $debug; # set to 1 to enable debugging code
694
694
  Name => 'MakerNoteLeica8', # used by the Q (Type 116)
695
695
  # (Q (Typ 116) starts with "LEICA\0\x08\0", Make is "LEICA CAMERA AG")
696
696
  # (SL (Typ 601) and CL start with "LEICA\0\x09\0", Make is "LEICA CAMERA AG")
697
- Condition => '$$valPt =~ /^LEICA\0[\x08\x09]\0/',
697
+ Condition => '$$valPt =~ /^LEICA\0[\x08\x09\x0a]\0/',
698
698
  SubDirectory => {
699
699
  TagTable => 'Image::ExifTool::Panasonic::Leica5',
700
700
  Start => '$valuePtr + 8',