exiftool_vendored 13.10.0 → 13.14.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 (216) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +82 -19
  3. data/bin/MANIFEST +6 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +3 -3
  7. data/bin/arg_files/exif2xmp.args +4 -0
  8. data/bin/arg_files/xmp2exif.args +2 -1
  9. data/bin/build_geolocation +1 -1
  10. data/bin/exiftool +208 -150
  11. data/bin/lib/File/RandomAccess.pm +1 -1
  12. data/bin/lib/File/RandomAccess.pod +2 -2
  13. data/bin/lib/Image/ExifTool/AAC.pm +1 -1
  14. data/bin/lib/Image/ExifTool/AES.pm +1 -1
  15. data/bin/lib/Image/ExifTool/AFCP.pm +6 -6
  16. data/bin/lib/Image/ExifTool/AIFF.pm +1 -1
  17. data/bin/lib/Image/ExifTool/APE.pm +1 -1
  18. data/bin/lib/Image/ExifTool/APP12.pm +1 -1
  19. data/bin/lib/Image/ExifTool/ASF.pm +1 -1
  20. data/bin/lib/Image/ExifTool/Apple.pm +1 -1
  21. data/bin/lib/Image/ExifTool/Audible.pm +1 -1
  22. data/bin/lib/Image/ExifTool/BMP.pm +1 -1
  23. data/bin/lib/Image/ExifTool/BPG.pm +1 -1
  24. data/bin/lib/Image/ExifTool/BZZ.pm +1 -1
  25. data/bin/lib/Image/ExifTool/BigTIFF.pm +1 -1
  26. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +29 -18
  27. data/bin/lib/Image/ExifTool/CBOR.pm +1 -1
  28. data/bin/lib/Image/ExifTool/Canon.pm +8 -4
  29. data/bin/lib/Image/ExifTool/CanonCustom.pm +1 -1
  30. data/bin/lib/Image/ExifTool/CanonRaw.pm +1 -1
  31. data/bin/lib/Image/ExifTool/CanonVRD.pm +1 -1
  32. data/bin/lib/Image/ExifTool/CaptureOne.pm +1 -1
  33. data/bin/lib/Image/ExifTool/Casio.pm +1 -1
  34. data/bin/lib/Image/ExifTool/Charset.pm +1 -1
  35. data/bin/lib/Image/ExifTool/DICOM.pm +1 -1
  36. data/bin/lib/Image/ExifTool/DJI.pm +150 -46
  37. data/bin/lib/Image/ExifTool/DNG.pm +1 -1
  38. data/bin/lib/Image/ExifTool/DPX.pm +1 -1
  39. data/bin/lib/Image/ExifTool/DV.pm +1 -1
  40. data/bin/lib/Image/ExifTool/DarwinCore.pm +1 -1
  41. data/bin/lib/Image/ExifTool/DjVu.pm +1 -1
  42. data/bin/lib/Image/ExifTool/EXE.pm +123 -32
  43. data/bin/lib/Image/ExifTool/Exif.pm +7 -4
  44. data/bin/lib/Image/ExifTool/FITS.pm +1 -1
  45. data/bin/lib/Image/ExifTool/FLAC.pm +1 -1
  46. data/bin/lib/Image/ExifTool/FLIF.pm +1 -1
  47. data/bin/lib/Image/ExifTool/FLIR.pm +1 -1
  48. data/bin/lib/Image/ExifTool/Fixup.pm +1 -1
  49. data/bin/lib/Image/ExifTool/Flash.pm +1 -1
  50. data/bin/lib/Image/ExifTool/FlashPix.pm +1 -1
  51. data/bin/lib/Image/ExifTool/Font.pm +1 -1
  52. data/bin/lib/Image/ExifTool/FotoStation.pm +1 -1
  53. data/bin/lib/Image/ExifTool/FujiFilm.pm +1 -1
  54. data/bin/lib/Image/ExifTool/GE.pm +1 -1
  55. data/bin/lib/Image/ExifTool/GIF.pm +1 -1
  56. data/bin/lib/Image/ExifTool/GIMP.pm +1 -1
  57. data/bin/lib/Image/ExifTool/GM.pm +1 -1
  58. data/bin/lib/Image/ExifTool/GPS.pm +1 -1
  59. data/bin/lib/Image/ExifTool/GeoTiff.pm +1 -1
  60. data/bin/lib/Image/ExifTool/Geolocation.pm +17 -8
  61. data/bin/lib/Image/ExifTool/Geotag.pm +1 -1
  62. data/bin/lib/Image/ExifTool/GoPro.pm +1 -1
  63. data/bin/lib/Image/ExifTool/H264.pm +1 -1
  64. data/bin/lib/Image/ExifTool/HP.pm +1 -1
  65. data/bin/lib/Image/ExifTool/HTML.pm +1 -1
  66. data/bin/lib/Image/ExifTool/HtmlDump.pm +1 -1
  67. data/bin/lib/Image/ExifTool/ICC_Profile.pm +1 -1
  68. data/bin/lib/Image/ExifTool/ICO.pm +1 -1
  69. data/bin/lib/Image/ExifTool/ID3.pm +1 -1
  70. data/bin/lib/Image/ExifTool/IPTC.pm +8 -5
  71. data/bin/lib/Image/ExifTool/ISO.pm +1 -1
  72. data/bin/lib/Image/ExifTool/ITC.pm +1 -1
  73. data/bin/lib/Image/ExifTool/Import.pm +5 -4
  74. data/bin/lib/Image/ExifTool/InDesign.pm +1 -1
  75. data/bin/lib/Image/ExifTool/InfiRay.pm +1 -1
  76. data/bin/lib/Image/ExifTool/JPEG.pm +6 -2
  77. data/bin/lib/Image/ExifTool/JPEGDigest.pm +1 -1
  78. data/bin/lib/Image/ExifTool/JSON.pm +1 -1
  79. data/bin/lib/Image/ExifTool/JVC.pm +1 -1
  80. data/bin/lib/Image/ExifTool/Jpeg2000.pm +1 -1
  81. data/bin/lib/Image/ExifTool/Kodak.pm +1 -1
  82. data/bin/lib/Image/ExifTool/KyoceraRaw.pm +1 -1
  83. data/bin/lib/Image/ExifTool/LIF.pm +1 -1
  84. data/bin/lib/Image/ExifTool/LNK.pm +1 -1
  85. data/bin/lib/Image/ExifTool/Lang/cs.pm +1 -1
  86. data/bin/lib/Image/ExifTool/Lang/de.pm +1 -1
  87. data/bin/lib/Image/ExifTool/Lang/en_ca.pm +1 -1
  88. data/bin/lib/Image/ExifTool/Lang/en_gb.pm +1 -1
  89. data/bin/lib/Image/ExifTool/Lang/es.pm +1 -1
  90. data/bin/lib/Image/ExifTool/Lang/fi.pm +1 -1
  91. data/bin/lib/Image/ExifTool/Lang/fr.pm +1 -1
  92. data/bin/lib/Image/ExifTool/Lang/it.pm +1 -1
  93. data/bin/lib/Image/ExifTool/Lang/ja.pm +1 -1
  94. data/bin/lib/Image/ExifTool/Lang/ko.pm +1 -1
  95. data/bin/lib/Image/ExifTool/Lang/nl.pm +1 -1
  96. data/bin/lib/Image/ExifTool/Lang/pl.pm +1 -1
  97. data/bin/lib/Image/ExifTool/Lang/ru.pm +1 -1
  98. data/bin/lib/Image/ExifTool/Lang/sk.pm +1 -1
  99. data/bin/lib/Image/ExifTool/Lang/sv.pm +1 -1
  100. data/bin/lib/Image/ExifTool/Lang/tr.pm +1 -1
  101. data/bin/lib/Image/ExifTool/Lang/zh_cn.pm +1 -1
  102. data/bin/lib/Image/ExifTool/Lang/zh_tw.pm +1 -1
  103. data/bin/lib/Image/ExifTool/Leaf.pm +1 -1
  104. data/bin/lib/Image/ExifTool/LigoGPS.pm +409 -0
  105. data/bin/lib/Image/ExifTool/Lytro.pm +1 -1
  106. data/bin/lib/Image/ExifTool/M2TS.pm +22 -13
  107. data/bin/lib/Image/ExifTool/MIE.pm +1 -1
  108. data/bin/lib/Image/ExifTool/MIEUnits.pod +1 -1
  109. data/bin/lib/Image/ExifTool/MIFF.pm +1 -1
  110. data/bin/lib/Image/ExifTool/MISB.pm +1 -1
  111. data/bin/lib/Image/ExifTool/MNG.pm +1 -1
  112. data/bin/lib/Image/ExifTool/MOI.pm +1 -1
  113. data/bin/lib/Image/ExifTool/MPC.pm +1 -1
  114. data/bin/lib/Image/ExifTool/MPEG.pm +1 -1
  115. data/bin/lib/Image/ExifTool/MPF.pm +1 -1
  116. data/bin/lib/Image/ExifTool/MRC.pm +1 -1
  117. data/bin/lib/Image/ExifTool/MWG.pm +1 -1
  118. data/bin/lib/Image/ExifTool/MXF.pm +1 -1
  119. data/bin/lib/Image/ExifTool/MacOS.pm +1 -1
  120. data/bin/lib/Image/ExifTool/MakerNotes.pm +1 -1
  121. data/bin/lib/Image/ExifTool/Matroska.pm +12 -4
  122. data/bin/lib/Image/ExifTool/Microsoft.pm +1 -1
  123. data/bin/lib/Image/ExifTool/Minolta.pm +1 -1
  124. data/bin/lib/Image/ExifTool/MinoltaRaw.pm +1 -1
  125. data/bin/lib/Image/ExifTool/Motorola.pm +1 -1
  126. data/bin/lib/Image/ExifTool/Nikon.pm +166 -35
  127. data/bin/lib/Image/ExifTool/NikonCapture.pm +1 -1
  128. data/bin/lib/Image/ExifTool/NikonCustom.pm +1 -1
  129. data/bin/lib/Image/ExifTool/NikonSettings.pm +1 -1
  130. data/bin/lib/Image/ExifTool/Nintendo.pm +1 -1
  131. data/bin/lib/Image/ExifTool/OOXML.pm +1 -1
  132. data/bin/lib/Image/ExifTool/Ogg.pm +1 -1
  133. data/bin/lib/Image/ExifTool/Olympus.pm +1 -1
  134. data/bin/lib/Image/ExifTool/OpenEXR.pm +1 -1
  135. data/bin/lib/Image/ExifTool/Opus.pm +1 -1
  136. data/bin/lib/Image/ExifTool/Other.pm +1 -1
  137. data/bin/lib/Image/ExifTool/PCX.pm +1 -1
  138. data/bin/lib/Image/ExifTool/PDF.pm +1 -1
  139. data/bin/lib/Image/ExifTool/PGF.pm +1 -1
  140. data/bin/lib/Image/ExifTool/PICT.pm +1 -1
  141. data/bin/lib/Image/ExifTool/PLIST.pm +1 -1
  142. data/bin/lib/Image/ExifTool/PLUS.pm +1 -1
  143. data/bin/lib/Image/ExifTool/PNG.pm +1 -1
  144. data/bin/lib/Image/ExifTool/PPM.pm +1 -1
  145. data/bin/lib/Image/ExifTool/PSP.pm +1 -1
  146. data/bin/lib/Image/ExifTool/Palm.pm +1 -1
  147. data/bin/lib/Image/ExifTool/Panasonic.pm +20 -2
  148. data/bin/lib/Image/ExifTool/PanasonicRaw.pm +1 -1
  149. data/bin/lib/Image/ExifTool/Parrot.pm +1 -1
  150. data/bin/lib/Image/ExifTool/Pentax.pm +1 -1
  151. data/bin/lib/Image/ExifTool/PhaseOne.pm +1 -1
  152. data/bin/lib/Image/ExifTool/PhotoCD.pm +1 -1
  153. data/bin/lib/Image/ExifTool/PhotoMechanic.pm +1 -1
  154. data/bin/lib/Image/ExifTool/Photoshop.pm +1 -1
  155. data/bin/lib/Image/ExifTool/PostScript.pm +1 -1
  156. data/bin/lib/Image/ExifTool/PrintIM.pm +1 -1
  157. data/bin/lib/Image/ExifTool/Protobuf.pm +48 -20
  158. data/bin/lib/Image/ExifTool/Qualcomm.pm +1 -1
  159. data/bin/lib/Image/ExifTool/QuickTime.pm +206 -66
  160. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +21 -303
  161. data/bin/lib/Image/ExifTool/README +4 -0
  162. data/bin/lib/Image/ExifTool/RIFF.pm +1 -1
  163. data/bin/lib/Image/ExifTool/RSRC.pm +1 -1
  164. data/bin/lib/Image/ExifTool/RTF.pm +1 -1
  165. data/bin/lib/Image/ExifTool/Radiance.pm +1 -1
  166. data/bin/lib/Image/ExifTool/Rawzor.pm +1 -1
  167. data/bin/lib/Image/ExifTool/Real.pm +1 -1
  168. data/bin/lib/Image/ExifTool/Reconyx.pm +1 -1
  169. data/bin/lib/Image/ExifTool/Red.pm +1 -1
  170. data/bin/lib/Image/ExifTool/Ricoh.pm +1 -1
  171. data/bin/lib/Image/ExifTool/Samsung.pm +2 -2
  172. data/bin/lib/Image/ExifTool/Sanyo.pm +1 -1
  173. data/bin/lib/Image/ExifTool/Scalado.pm +1 -1
  174. data/bin/lib/Image/ExifTool/Shift.pl +1 -1
  175. data/bin/lib/Image/ExifTool/Shortcuts.pm +1 -1
  176. data/bin/lib/Image/ExifTool/Sigma.pm +1 -1
  177. data/bin/lib/Image/ExifTool/SigmaRaw.pm +1 -1
  178. data/bin/lib/Image/ExifTool/Sony.pm +1 -1
  179. data/bin/lib/Image/ExifTool/SonyIDC.pm +1 -1
  180. data/bin/lib/Image/ExifTool/Stim.pm +1 -1
  181. data/bin/lib/Image/ExifTool/TagInfoXML.pm +2 -2
  182. data/bin/lib/Image/ExifTool/TagLookup.pm +3449 -3435
  183. data/bin/lib/Image/ExifTool/TagNames.pod +164 -47
  184. data/bin/lib/Image/ExifTool/Text.pm +1 -1
  185. data/bin/lib/Image/ExifTool/Theora.pm +1 -1
  186. data/bin/lib/Image/ExifTool/Torrent.pm +3 -3
  187. data/bin/lib/Image/ExifTool/Unknown.pm +1 -1
  188. data/bin/lib/Image/ExifTool/VCard.pm +1 -1
  189. data/bin/lib/Image/ExifTool/Validate.pm +1 -1
  190. data/bin/lib/Image/ExifTool/Vivo.pm +124 -0
  191. data/bin/lib/Image/ExifTool/Vorbis.pm +1 -1
  192. data/bin/lib/Image/ExifTool/WPG.pm +1 -1
  193. data/bin/lib/Image/ExifTool/WTV.pm +1 -1
  194. data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +1 -1
  195. data/bin/lib/Image/ExifTool/WriteExif.pl +1 -1
  196. data/bin/lib/Image/ExifTool/WriteIPTC.pl +1 -1
  197. data/bin/lib/Image/ExifTool/WritePDF.pl +1 -1
  198. data/bin/lib/Image/ExifTool/WritePNG.pl +1 -1
  199. data/bin/lib/Image/ExifTool/WritePhotoshop.pl +1 -1
  200. data/bin/lib/Image/ExifTool/WritePostScript.pl +1 -1
  201. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +74 -43
  202. data/bin/lib/Image/ExifTool/WriteRIFF.pl +1 -1
  203. data/bin/lib/Image/ExifTool/WriteXMP.pl +1 -1
  204. data/bin/lib/Image/ExifTool/Writer.pl +21 -16
  205. data/bin/lib/Image/ExifTool/XISF.pm +1 -1
  206. data/bin/lib/Image/ExifTool/XMP.pm +1 -1
  207. data/bin/lib/Image/ExifTool/XMP2.pl +1 -1
  208. data/bin/lib/Image/ExifTool/XMPStruct.pl +1 -1
  209. data/bin/lib/Image/ExifTool/ZIP.pm +1 -1
  210. data/bin/lib/Image/ExifTool/ZISRAW.pm +1 -1
  211. data/bin/lib/Image/ExifTool/iWork.pm +1 -1
  212. data/bin/lib/Image/ExifTool.pm +34 -12
  213. data/bin/lib/Image/ExifTool.pod +57 -46
  214. data/bin/perl-Image-ExifTool.spec +1 -1
  215. data/lib/exiftool_vendored/version.rb +1 -1
  216. metadata +4 -2
@@ -15,6 +15,8 @@ my %movMap = (
15
15
  QuickTime => 'ItemList', # (default location for QuickTime tags)
16
16
  ItemList => 'Meta', # MOV-Movie-UserData-Meta-ItemList
17
17
  Keys => 'Movie', # MOV-Movie-Meta-Keys !! (hack due to different Meta location)
18
+ AudioKeys => 'Track', # MOV-Movie-Track-Meta-Keys !!
19
+ VideoKeys => 'Track', # MOV-Movie-Track-Meta-Keys !!
18
20
  Meta => 'UserData',
19
21
  XMP => 'UserData', # MOV-Movie-UserData-XMP
20
22
  Microsoft => 'UserData', # MOV-Movie-UserData-Microsoft
@@ -29,6 +31,8 @@ my %mp4Map = (
29
31
  QuickTime => 'ItemList', # (default location for QuickTime tags)
30
32
  ItemList => 'Meta', # MOV-Movie-UserData-Meta-ItemList
31
33
  Keys => 'Movie', # MOV-Movie-Meta-Keys !! (hack due to different Meta location)
34
+ AudioKeys => 'Track', # MOV-Movie-Track-Meta-Keys !!
35
+ VideoKeys => 'Track', # MOV-Movie-Track-Meta-Keys !!
32
36
  Meta => 'UserData',
33
37
  UserData => 'Movie', # MOV-Movie-UserData
34
38
  Microsoft => 'UserData', # MOV-Movie-UserData-Microsoft
@@ -383,13 +387,14 @@ sub WriteKeys($$$)
383
387
  my $outfile = $$dirInfo{OutFile};
384
388
  my ($tag, %done, %remap, %info, %add, $i);
385
389
 
390
+ my $keysGrp = $avType{$$et{MediaType}} ? "$avType{$$et{MediaType}}Keys" : 'Keys';
386
391
  $dirLen < 8 and $et->Warn('Short Keys box'), $dirLen = 8, $$dataPt = "\0" x 8;
387
- if ($$et{DEL_GROUP}{Keys}) {
392
+ if ($$et{DEL_GROUP}{$keysGrp}) {
388
393
  $dirLen = 8; # delete all existing keys
389
394
  # deleted keys are identified by a zero entry in the Remap lookup
390
395
  my $n = Get32u($dataPt, 4);
391
396
  for ($i=1; $i<=$n; ++$i) { $remap{$i} = 0; }
392
- $et->VPrint(0, " [deleting $n Keys entr".($n==1 ? 'y' : 'ies')."]\n");
397
+ $et->VPrint(0, " [deleting $n $keysGrp entr".($n==1 ? 'y' : 'ies')."]\n");
393
398
  ++$$et{CHANGED};
394
399
  }
395
400
  my $pos = 8;
@@ -425,7 +430,7 @@ sub WriteKeys($$$)
425
430
  }
426
431
  unless ($dontDelete) {
427
432
  # delete this key
428
- $et->VPrint(1, "$$et{INDENT}\[deleting Keys entry $index '${tag}']\n");
433
+ $et->VPrint(1, "$$et{INDENT}\[deleting $keysGrp entry $index '${tag}']\n");
429
434
  $pos += $len;
430
435
  $remap{$index++} = 0;
431
436
  ++$$et{CHANGED};
@@ -455,7 +460,7 @@ sub WriteKeys($$$)
455
460
  # add new entry to 'keys' data
456
461
  my $val = $id =~ /^com\./ ? $id : "com.apple.quicktime.$id";
457
462
  $newData .= Set32u(8 + length($val)) . 'mdta' . $val;
458
- $et->VPrint(1, "$$et{INDENT}\[adding Keys entry $newIndex '${id}']\n");
463
+ $et->VPrint(1, "$$et{INDENT}\[adding $keysGrp entry $newIndex '${id}']\n");
459
464
  $add{$newIndex++} = $tagInfo;
460
465
  ++$$et{CHANGED};
461
466
  }
@@ -470,7 +475,7 @@ sub WriteKeys($$$)
470
475
  # Info - Keys tag information, based on old index value
471
476
  # Add - Keys items deleted, based on old index value
472
477
  # Num - Number of items in edited Keys box
473
- $$et{Keys} = { Remap => \%remap, Info => \%info, Add => \%add, Num => $num };
478
+ $$et{$keysGrp} = { Remap => \%remap, Info => \%info, Add => \%add, Num => $num };
474
479
 
475
480
  return $newData; # return updated Keys box
476
481
  }
@@ -556,6 +561,7 @@ sub WriteItemInfo($$$)
556
561
  }
557
562
  }
558
563
  my ($hdr, $subTable, $proc);
564
+ my $strt = 0;
559
565
  if ($name eq 'EXIF') {
560
566
  if (not length $buff) {
561
567
  # create EXIF from scratch
@@ -565,6 +571,7 @@ sub WriteItemInfo($$$)
565
571
  $hdr = '';
566
572
  } elsif (length($buff) >= 4 and length($buff) >= 4 + unpack('N',$buff)) {
567
573
  $hdr = substr($buff, 0, 4 + unpack('N',$buff));
574
+ $strt = length $hdr;
568
575
  } else {
569
576
  $et->Warn('Invalid Exif header');
570
577
  next;
@@ -578,8 +585,8 @@ sub WriteItemInfo($$$)
578
585
  my %dirInfo = (
579
586
  DataPt => \$buff,
580
587
  DataLen => length $buff,
581
- DirStart => length $hdr,
582
- DirLen => length($buff) - length $hdr,
588
+ DirStart => $strt,
589
+ DirLen => length($buff) - $strt,
583
590
  );
584
591
  my $changed = $$et{CHANGED};
585
592
  my $newVal = $et->WriteDirectory(\%dirInfo, $subTable, $proc);
@@ -881,7 +888,7 @@ sub WriteQuickTime($$$)
881
888
  $et or return 1; # allow dummy access to autoload this package
882
889
  my ($mdat, @mdat, @mdatEdit, $edit, $track, $outBuff, $co, $term, $delCount);
883
890
  my (%langTags, $canCreate, $delGrp, %boxPos, %didDir, $writeLast, $err, $atomCount);
884
- my ($tag, $lastTag, $lastPos, $errStr, $trailer, $buf2);
891
+ my ($tag, $lastTag, $lastPos, $errStr, $trailer, $buf2, $keysGrp, $keysPath);
885
892
  my $outfile = $$dirInfo{OutFile} || return 0;
886
893
  my $raf = $$dirInfo{RAF}; # (will be null for lower-level atoms)
887
894
  my $dataPt = $$dirInfo{DataPt}; # (will be null for top-level atoms)
@@ -915,15 +922,26 @@ sub WriteQuickTime($$$)
915
922
 
916
923
  $raf->Seek($dirStart, 1) if $dirStart; # skip header if it exists
917
924
 
925
+ if ($avType{$$et{MediaType}}) {
926
+ # (note: these won't be correct now if we haven't yet processed the Media box,
927
+ # but in this case they won't be needed until after we set them properly below)
928
+ ($keysGrp, $keysPath) = ("$avType{$$et{MediaType}}Keys", 'MOV-Movie-Track');
929
+ } else {
930
+ ($keysGrp, $keysPath) = ('Keys', 'MOV-Movie');
931
+ }
918
932
  my $curPath = join '-', @{$$et{PATH}};
919
933
  my ($dir, $writePath) = ($dirName, $dirName);
920
934
  $writePath = "$dir-$writePath" while defined($dir = $$et{DirMap}{$dir});
921
935
  # hack to create Keys directories if necessary (its containing Meta is in a different location)
922
- if ($$addDirs{Keys} and $curPath =~ /^MOV-Movie(-Meta)?$/) {
936
+ if (($$addDirs{Keys} and $curPath =~ /^MOV-Movie(-Meta)?$/)) {
923
937
  $createKeys = 1; # create new Keys directories
924
- } elsif ($curPath eq 'MOV-Movie-Meta-ItemList') {
938
+ } elsif (($$addDirs{AudioKeys} or $$addDirs{VideoKeys}) and $curPath =~ /^MOV-Movie-Track(-Meta)?$/) {
939
+ $createKeys = -1; # (must wait until MediaType is known)
940
+ } elsif (($curPath eq 'MOV-Movie-Meta-ItemList') or
941
+ ($curPath eq 'MOV-Movie-Track-Meta-ItemList' and $avType{$$et{MediaType}}))
942
+ {
925
943
  $createKeys = 2; # create new Keys tags
926
- my $keys = $$et{Keys};
944
+ my $keys = $$et{$keysGrp};
927
945
  if ($keys) {
928
946
  # add new tag entries for existing Keys tags, now that we know their ID's
929
947
  # - first make lookup to convert Keys tagInfo ref to index number
@@ -931,7 +949,7 @@ sub WriteQuickTime($$$)
931
949
  foreach $index (keys %{$$keys{Info}}) {
932
950
  $keysInfo{$$keys{Info}{$index}} = $index if $$keys{Remap}{$index};
933
951
  }
934
- my $keysTable = GetTagTable('Image::ExifTool::QuickTime::Keys');
952
+ my $keysTable = GetTagTable("Image::ExifTool::QuickTime::$keysGrp");
935
953
  my $newKeysTags = $et->GetNewTagInfoHash($keysTable);
936
954
  foreach (keys %$newKeysTags) {
937
955
  my $tagInfo = $$newKeysTags{$_};
@@ -960,7 +978,8 @@ sub WriteQuickTime($$$)
960
978
  }
961
979
  if ($curPath eq $writePath or $createKeys) {
962
980
  $canCreate = 1;
963
- $delGrp = $$et{DEL_GROUP}{$dirName};
981
+ # (must check the appropriate Keys delete flag if this is a Keys ItemList)
982
+ $delGrp = $$et{DEL_GROUP}{$createKeys ? $keysGrp : $dirName};
964
983
  }
965
984
  $atomCount = $$tagTablePtr{VARS}{ATOM_COUNT} if $$tagTablePtr{VARS};
966
985
 
@@ -1078,12 +1097,12 @@ sub WriteQuickTime($$$)
1078
1097
  last;
1079
1098
  }
1080
1099
  }
1081
- # save the handler type for this track
1082
- if ($tag eq 'hdlr' and length $buff >= 12) {
1083
- my $hdlr = substr($buff,8,4);
1084
- $$et{HandlerType} = $hdlr if $hdlr =~ /^(vide|soun)$/;
1100
+ # save the handler type of the track media
1101
+ if ($tag eq 'hdlr' and length $buff >= 12 and
1102
+ @{$$et{PATH}} and $$et{PATH}[-1] eq 'Media')
1103
+ {
1104
+ $$et{MediaType} = substr($buff,8,4);
1085
1105
  }
1086
-
1087
1106
  # if this atom stores offsets, save its location so we can fix up offsets later
1088
1107
  # (are there any other atoms that may store absolute file offsets?)
1089
1108
  if ($tag =~ /^(stco|co64|iloc|mfra|moof|sidx|saio|gps |CTBO|uuid)$/) {
@@ -1128,11 +1147,11 @@ sub WriteQuickTime($$$)
1128
1147
  &{$$tagInfo{WriteHook}}($buff,$et) if $tagInfo and $$tagInfo{WriteHook};
1129
1148
 
1130
1149
  # allow numerical tag ID's (ItemList entries defined by Keys)
1131
- if (not $tagInfo and $dirName eq 'ItemList' and $$et{Keys}) {
1150
+ if (not $tagInfo and $dirName eq 'ItemList' and $$et{$keysGrp}) {
1132
1151
  $keysIndex = unpack('N', $tag);
1133
- my $newIndex = $$et{Keys}{Remap}{$keysIndex};
1152
+ my $newIndex = $$et{$keysGrp}{Remap}{$keysIndex};
1134
1153
  if (defined $newIndex) {
1135
- $tagInfo = $$et{Keys}{Info}{$keysIndex};
1154
+ $tagInfo = $$et{$keysGrp}{Info}{$keysIndex};
1136
1155
  unless ($newIndex) {
1137
1156
  if ($tagInfo) {
1138
1157
  $et->VPrint(1," - Keys:$$tagInfo{Name}");
@@ -1172,7 +1191,7 @@ sub WriteQuickTime($$$)
1172
1191
  if ($subdir) { # process atoms in this container from a buffer in memory
1173
1192
 
1174
1193
  if ($tag eq 'trak') {
1175
- undef $$et{HandlerType}; # init handler type for this track
1194
+ $$et{MediaType} = ''; # init media type for this track
1176
1195
  delete $$et{AssumedDataRef};
1177
1196
  }
1178
1197
  my $subName = $$subdir{DirName} || $$tagInfo{Name};
@@ -1241,10 +1260,13 @@ sub WriteQuickTime($$$)
1241
1260
  $$et{CHANGED} = $oldChanged;
1242
1261
  undef $newData;
1243
1262
  }
1244
- if ($tag eq 'trak' and $$et{AssumedDataRef}) {
1245
- my $grp = $$et{CUR_WRITE_GROUP} || $dirName;
1246
- $et->Error("Can't locate data reference to update offsets for $grp");
1247
- delete $$et{AssumedDataRef};
1263
+ if ($tag eq 'trak') {
1264
+ $$et{MediaType} = ''; # reset media type at end of track
1265
+ if ($$et{AssumedDataRef}) {
1266
+ my $grp = $$et{CUR_WRITE_GROUP} || $dirName;
1267
+ $et->Error("Can't locate data reference to update offsets for $grp");
1268
+ delete $$et{AssumedDataRef};
1269
+ }
1248
1270
  }
1249
1271
  $$et{CUR_WRITE_GROUP} = $oldWriteGroup;
1250
1272
  SetByteOrder('MM');
@@ -1540,7 +1562,7 @@ sub WriteQuickTime($$$)
1540
1562
  }
1541
1563
  if ($msg) {
1542
1564
  # (allow empty sample description for non-audio/video handler types, eg. 'url ', 'meta')
1543
- if ($$et{HandlerType}) {
1565
+ if ($$et{MediaType}) {
1544
1566
  my $grp = $$et{CUR_WRITE_GROUP} || $parent;
1545
1567
  $et->Error("$msg for $grp");
1546
1568
  return $rtnErr;
@@ -1593,7 +1615,16 @@ sub WriteQuickTime($$$)
1593
1615
  }
1594
1616
  $et->VPrint(0, " [deleting $delCount $dirName tag".($delCount==1 ? '' : 's')."]\n") if $delCount;
1595
1617
 
1596
- $createKeys &= ~0x01 unless $$addDirs{Keys}; # (Keys may have been written)
1618
+ # can finally set necessary variables for creating Video/AudioKeys tags
1619
+ if ($createKeys < 0) {
1620
+ if ($avType{$$et{MediaType}}) {
1621
+ $createKeys = 1;
1622
+ ($keysGrp, $keysPath) = ("$avType{$$et{MediaType}}Keys", 'MOV-Movie-Track');
1623
+ } else {
1624
+ $canCreate = 0;
1625
+ }
1626
+ }
1627
+ $createKeys &= ~0x01 unless $$addDirs{$keysGrp}; # (Keys may have been written)
1597
1628
 
1598
1629
  # add new directories/tags at this level if necessary
1599
1630
  if ($canCreate and (exists $$et{EDIT_DIRS}{$dirName} or $createKeys)) {
@@ -1604,13 +1635,13 @@ sub WriteQuickTime($$$)
1604
1635
  my ($tag, $index);
1605
1636
  # add Keys tags if necessary
1606
1637
  if ($createKeys) {
1607
- if ($curPath eq 'MOV-Movie') {
1638
+ if ($curPath eq $keysPath) {
1608
1639
  # add Meta for Keys if necessary
1609
1640
  unless ($didDir{meta}) {
1610
1641
  $$dirs{meta} = $Image::ExifTool::QuickTime::Movie{meta};
1611
1642
  push @addTags, 'meta';
1612
1643
  }
1613
- } elsif ($curPath eq 'MOV-Movie-Meta') {
1644
+ } elsif ($curPath eq "$keysPath-Meta") {
1614
1645
  # special case for Keys Meta -- reset directories and start again
1615
1646
  undef @addTags;
1616
1647
  $dirs = { };
@@ -1619,10 +1650,10 @@ sub WriteQuickTime($$$)
1619
1650
  $$dirs{$_} = $Image::ExifTool::QuickTime::Meta{$_};
1620
1651
  push @addTags, $_;
1621
1652
  }
1622
- } elsif ($curPath eq 'MOV-Movie-Meta-ItemList' and $$et{Keys}) {
1623
- foreach $index (sort { $a <=> $b } keys %{$$et{Keys}{Add}}) {
1653
+ } elsif ($curPath eq "$keysPath-Meta-ItemList" and $$et{$keysGrp}) {
1654
+ foreach $index (sort { $a <=> $b } keys %{$$et{$keysGrp}{Add}}) {
1624
1655
  my $id = Set32u($index);
1625
- $$newTags{$id} = $$et{Keys}{Add}{$index};
1656
+ $$newTags{$id} = $$et{$keysGrp}{Add}{$index};
1626
1657
  push @addTags, $id;
1627
1658
  }
1628
1659
  } else {
@@ -1634,8 +1665,7 @@ sub WriteQuickTime($$$)
1634
1665
  foreach $tag (@addTags) {
1635
1666
  my $tagInfo = $$dirs{$tag} || $$newTags{$tag};
1636
1667
  next if defined $$tagInfo{CanCreate} and not $$tagInfo{CanCreate};
1637
- next if defined $$tagInfo{HandlerType} and
1638
- (not $$et{HandlerType} or $$et{HandlerType} ne $$tagInfo{HandlerType});
1668
+ next if defined $$tagInfo{MediaType} and $$et{MediaType} ne $$tagInfo{MediaType};
1639
1669
  my $subdir = $$tagInfo{SubDirectory};
1640
1670
  unless ($subdir) {
1641
1671
  my $nvHash = $et->GetNewValueHash($tagInfo);
@@ -1697,13 +1727,13 @@ sub WriteQuickTime($$$)
1697
1727
  }
1698
1728
  my $subName = $$subdir{DirName} || $$tagInfo{Name};
1699
1729
  # QuickTime hierarchy is complex, so check full directory path before adding
1700
- if ($createKeys and $curPath eq 'MOV-Movie' and $subName eq 'Meta') {
1730
+ if ($createKeys and $curPath eq $keysPath and $subName eq 'Meta') {
1701
1731
  $et->VPrint(0, " Creating Meta with mdta Handler and Keys\n");
1702
1732
  # init Meta box for Keys tags with mdta Handler and empty Keys+ItemList
1703
1733
  $buf2 = "\0\0\0\x20hdlr\0\0\0\0\0\0\0\0mdta\0\0\0\0\0\0\0\0\0\0\0\0" .
1704
1734
  "\0\0\0\x10keys\0\0\0\0\0\0\0\0" .
1705
1735
  "\0\0\0\x08ilst";
1706
- } elsif ($createKeys and $curPath eq 'MOV-Movie-Meta') {
1736
+ } elsif ($createKeys and $curPath eq "$keysPath-Meta") {
1707
1737
  $buf2 = ($subName eq 'Keys' ? "\0\0\0\0\0\0\0\0" : '');
1708
1738
  } elsif ($subName eq 'Meta' and $$et{OPTIONS}{QuickTimeHandler}) {
1709
1739
  $et->VPrint(0, " Creating Meta with mdir Handler\n");
@@ -1752,8 +1782,8 @@ sub WriteQuickTime($$$)
1752
1782
  }
1753
1783
  }
1754
1784
  # add only once (must delete _after_ call to WriteDirectory())
1755
- # (Keys is a special case, and will be removed after Meta is processed)
1756
- delete $$addDirs{$subName} unless $subName eq 'Keys';
1785
+ # (Keys tags are a special case, and are handled separately)
1786
+ delete $$addDirs{$subName} unless $createKeys;
1757
1787
  }
1758
1788
  }
1759
1789
  # write HEIC metadata after top-level 'meta' box has been processed if editing this information
@@ -1779,9 +1809,9 @@ sub WriteQuickTime($$$)
1779
1809
  # (could report a file if editing nothing when it contained an empty Meta atom)
1780
1810
  # ++$$et{CHANGED};
1781
1811
  }
1782
- if ($curPath eq 'MOV-Movie-Meta') {
1783
- delete $$addDirs{Keys}; # prevent creation of another Meta for Keys tags
1784
- delete $$et{Keys};
1812
+ if ($curPath eq "$keysPath-Meta") {
1813
+ delete $$addDirs{$keysGrp}; # prevent creation of another Meta for Keys tags
1814
+ delete $$et{$keysGrp};
1785
1815
  }
1786
1816
  }
1787
1817
 
@@ -2109,6 +2139,7 @@ sub WriteMOV($$)
2109
2139
  $raf->Seek(0,0);
2110
2140
 
2111
2141
  # write the file
2142
+ $$et{MediaType} = '';
2112
2143
  $$dirInfo{Parent} = '';
2113
2144
  $$dirInfo{DirName} = 'MOV';
2114
2145
  $$dirInfo{ChunkOffset} = [ ]; # (just to be safe)
@@ -2134,7 +2165,7 @@ QuickTime-based file formats like MOV and MP4.
2134
2165
 
2135
2166
  =head1 AUTHOR
2136
2167
 
2137
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
2168
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
2138
2169
 
2139
2170
  This library is free software; you can redistribute it and/or modify it
2140
2171
  under the same terms as Perl itself.
@@ -372,7 +372,7 @@ Currently writes only WebP files.
372
372
 
373
373
  =head1 AUTHOR
374
374
 
375
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
375
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
376
376
 
377
377
  This library is free software; you can redistribute it and/or modify it
378
378
  under the same terms as Perl itself.
@@ -1651,7 +1651,7 @@ This file contains routines to write XMP metadata.
1651
1651
 
1652
1652
  =head1 AUTHOR
1653
1653
 
1654
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
1654
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
1655
1655
 
1656
1656
  This library is free software; you can redistribute it and/or modify it
1657
1657
  under the same terms as Perl itself.
@@ -138,11 +138,12 @@ my %rawType = (
138
138
  # 2) any dependencies must be added to %excludeGroups
139
139
  my @delGroups = qw(
140
140
  Adobe AFCP APP0 APP1 APP2 APP3 APP4 APP5 APP6 APP7 APP8 APP9 APP10 APP11 APP12
141
- APP13 APP14 APP15 CanonVRD CIFF Ducky EXIF ExifIFD File FlashPix FotoStation
142
- GlobParamIFD GPS ICC_Profile IFD0 IFD1 Insta360 InteropIFD IPTC ItemList JFIF
143
- Jpeg2000 JUMBF Keys MakerNotes Meta MetaIFD Microsoft MIE MPF Nextbase NikonApp
144
- NikonCapture PDF PDF-update PhotoMechanic Photoshop PNG PNG-pHYs PrintIM
145
- QuickTime RMETA RSRC SEAL SubIFD Trailer UserData XML XML-* XMP XMP-*
141
+ APP13 APP14 APP15 AudioKeys CanonVRD CIFF Ducky EXIF ExifIFD File FlashPix
142
+ FotoStation GlobParamIFD GPS ICC_Profile IFD0 IFD1 Insta360 InteropIFD IPTC
143
+ ItemList JFIF Jpeg2000 JUMBF Keys MakerNotes Meta MetaIFD Microsoft MIE MPF
144
+ Nextbase NikonApp NikonCapture PDF PDF-update PhotoMechanic Photoshop PNG
145
+ PNG-pHYs PrintIM QuickTime RMETA RSRC SEAL SubIFD Trailer UserData VideoKeys
146
+ Vivo XML XML-* XMP XMP-*
146
147
  );
147
148
  # family 2 group names that we can delete
148
149
  my @delGroup2 = qw(
@@ -1297,12 +1298,13 @@ sub SetNewValuesFromFile($$;@)
1297
1298
  foreach (qw(ByteUnit Charset CharsetEXIF CharsetFileName CharsetID3 CharsetIPTC
1298
1299
  CharsetPhotoshop Composite DateFormat Debug EncodeHangs Escape ExtendedXMP
1299
1300
  ExtractEmbedded FastScan Filter FixBase Geolocation GeolocAltNames
1300
- GeolocFeature GeolocMinPop GeolocMaxDist GlobalTimeShift HexTagIDs
1301
- IgnoreGroups IgnoreMinorErrors IgnoreTags ImageHashType Lang
1302
- LargeFileSupport LigoGPSScale ListItem ListSep MDItemTags MissingTagValue
1303
- NoPDFList NoWarning Password PrintConv QuickTimeUTC RequestTags SaveFormat
1304
- SavePath ScanForXMP StructFormat SystemTags TimeZone Unknown UserParam
1305
- Validate WindowsLongPath WindowsWideFile XAttrTags XMPAutoConv))
1301
+ GeolocFeature GeolocMinPop GeolocMaxDist GlobalTimeShift GPSQuadrant
1302
+ HexTagIDs IgnoreGroups IgnoreMinorErrors IgnoreTags ImageHashType Lang
1303
+ LargeFileSupport LigoGPSScale ListItem ListSep MDItemTags
1304
+ MissingTagValue NoPDFList NoWarning Password PrintConv QuickTimeUTC
1305
+ RequestTags SaveFormat SavePath ScanForXMP StructFormat SystemTags
1306
+ TimeZone Unknown UserParam Validate WindowsLongPath WindowsWideFile
1307
+ XAttrTags XMPAutoConv))
1306
1308
  {
1307
1309
  $srcExifTool->Options($_ => $$options{$_});
1308
1310
  }
@@ -2822,7 +2824,10 @@ sub GetAllGroups($;$)
2822
2824
 
2823
2825
  my %allGroups;
2824
2826
  # add family 1 groups not in tables
2825
- $family == 1 and map { $allGroups{$_} = 1 } qw(Garmin);
2827
+ no warnings; # (avoid "possible attempt to put comments in qw()")
2828
+ $family == 1 and map { $allGroups{$_} = 1 } qw(Garmin AudioItemList AudioUserData
2829
+ VideoItemList VideoUserData Track#Keys Track#ItemList Track#UserData);
2830
+ use warnings;
2826
2831
  # loop through all tag tables and get all group names
2827
2832
  while (@tableNames) {
2828
2833
  my $table = GetTagTable(pop @tableNames);
@@ -5228,7 +5233,7 @@ sub Set64u(@)
5228
5233
  {
5229
5234
  my $val = $_[0];
5230
5235
  my $hi = int($val / 4294967296);
5231
- my $lo = Set32u($val - $hi * 4294967296);
5236
+ my $lo = Set32u($val - $hi * 4294967296); # NOTE: subject to round-off errors!
5232
5237
  $hi = Set32u($hi);
5233
5238
  $val = GetByteOrder() eq 'MM' ? $hi . $lo : $lo . $hi;
5234
5239
  $_[1] and substr(${$_[1]}, $_[2], length($val)) = $val;
@@ -6102,7 +6107,7 @@ sub WriteJPEG($$)
6102
6107
  my $tbuf = '';
6103
6108
  $raf->Seek(-length($buff), 1); # seek back to just after EOI
6104
6109
  $$trailInfo{OutFile} = \$tbuf; # rewrite the trailer
6105
- $$trailInfo{ScanForAFCP} = 1; # scan if necessary
6110
+ $$trailInfo{ScanForTrailer} = 1;# scan if necessary
6106
6111
  $self->ProcessTrailers($trailInfo) or undef $trailInfo;
6107
6112
  }
6108
6113
  if (not $oldOutfile) {
@@ -6987,7 +6992,7 @@ sub SetFileTime($$;$$$$)
6987
6992
  $mtime = $m unless defined $mtime;
6988
6993
  $success = eval { utime($atime, $mtime, $file) } if defined $atime and defined $mtime;
6989
6994
  }
6990
- $self->Warn('Error opening file for update') unless $success;
6995
+ $self->Warn('Error updating file time') unless $success;
6991
6996
  return $success;
6992
6997
  }
6993
6998
  $saveFile = $file;
@@ -7376,7 +7381,7 @@ used routines.
7376
7381
 
7377
7382
  =head1 AUTHOR
7378
7383
 
7379
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
7384
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
7380
7385
 
7381
7386
  This library is free software; you can redistribute it and/or modify it
7382
7387
  under the same terms as Perl itself.
@@ -163,7 +163,7 @@ information from XISF (Extensible Image Serialization Format) images.
163
163
 
164
164
  =head1 AUTHOR
165
165
 
166
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
166
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
167
167
 
168
168
  This library is free software; you can redistribute it and/or modify it
169
169
  under the same terms as Perl itself.
@@ -4582,7 +4582,7 @@ information.
4582
4582
 
4583
4583
  =head1 AUTHOR
4584
4584
 
4585
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
4585
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
4586
4586
 
4587
4587
  This library is free software; you can redistribute it and/or modify it
4588
4588
  under the same terms as Perl itself.
@@ -2427,7 +2427,7 @@ This file contains definitions for less common XMP namespaces.
2427
2427
 
2428
2428
  =head1 AUTHOR
2429
2429
 
2430
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
2430
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
2431
2431
 
2432
2432
  This library is free software; you can redistribute it and/or modify it
2433
2433
  under the same terms as Perl itself.
@@ -944,7 +944,7 @@ information.
944
944
 
945
945
  =head1 AUTHOR
946
946
 
947
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
947
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
948
948
 
949
949
  This library is free software; you can redistribute it and/or modify it
950
950
  under the same terms as Perl itself.
@@ -840,7 +840,7 @@ Electronic Publication (EPUB), and Sketch design files (SKETCH).
840
840
 
841
841
  =head1 AUTHOR
842
842
 
843
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
843
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
844
844
 
845
845
  This library is free software; you can redistribute it and/or modify it
846
846
  under the same terms as Perl itself.
@@ -220,7 +220,7 @@ metadata from Zeiss Integrated Software RAW (ZISRAW) CZI files.
220
220
 
221
221
  =head1 AUTHOR
222
222
 
223
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
223
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
224
224
 
225
225
  This library is free software; you can redistribute it and/or modify it
226
226
  under the same terms as Perl itself.
@@ -215,7 +215,7 @@ information from Apple iWork '09 XML+ZIP files.
215
215
 
216
216
  =head1 AUTHOR
217
217
 
218
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
218
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
219
219
 
220
220
  This library is free software; you can redistribute it and/or modify it
221
221
  under the same terms as Perl itself.
@@ -8,7 +8,7 @@
8
8
  # Revisions: Nov. 12/2003 - P. Harvey Created
9
9
  # (See html/history.html for revision history)
10
10
  #
11
- # Legal: Copyright (c) 2003-2024, Phil Harvey (philharvey66 at gmail.com)
11
+ # Legal: Copyright (c) 2003-2025, Phil Harvey (philharvey66 at gmail.com)
12
12
  # This library is free software; you can redistribute it and/or
13
13
  # modify it under the same terms as Perl itself.
14
14
  #------------------------------------------------------------------------------
@@ -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 $advFmtSelf);
31
31
 
32
- $VERSION = '13.10';
32
+ $VERSION = '13.14';
33
33
  $RELEASE = '';
34
34
  @ISA = qw(Exporter);
35
35
  %EXPORT_TAGS = (
@@ -154,10 +154,10 @@ sub ReadValue($$$;$$$);
154
154
  Matroska::StdTag MOI MXF DV Flash Flash::FLV Real::Media Real::Audio
155
155
  Real::Metafile Red RIFF AIFF ASF WTV DICOM FITS XISF MIE JSON HTML XMP::SVG
156
156
  Palm Palm::MOBI Palm::EXTH Torrent EXE EXE::PEVersion EXE::PEString
157
- EXE::MachO EXE::PEF EXE::ELF EXE::AR EXE::CHM LNK Font VCard Text
158
- VCard::VCalendar VCard::VNote RSRC Rawzor ZIP ZIP::GZIP ZIP::RAR ZIP::RAR5
159
- RTF OOXML iWork ISO FLIR::AFF FLIR::FPF MacOS MacOS::MDItem
160
- FlashPix::DocTable
157
+ EXE::DebugRSDS EXE::DebugNB10 EXE::Misc EXE::MachO EXE::PEF EXE::ELF EXE::AR
158
+ EXE::CHM LNK Font VCard Text VCard::VCalendar VCard::VNote RSRC Rawzor ZIP
159
+ ZIP::GZIP ZIP::RAR ZIP::RAR5 RTF OOXML iWork ISO FLIR::AFF FLIR::FPF MacOS
160
+ MacOS::MDItem FlashPix::DocTable
161
161
  );
162
162
 
163
163
  # alphabetical list of current Lang modules
@@ -1126,6 +1126,7 @@ my @availableOptions = (
1126
1126
  [ 'GeoMinSats', undef, 'geotag minimum satellites' ],
1127
1127
  [ 'GeoSpeedRef', undef, 'geotag GPSSpeedRef' ],
1128
1128
  [ 'GlobalTimeShift', undef, 'apply time shift to all extracted date/time values' ],
1129
+ [ 'GPSQuadrant', undef, 'quadrant for GPS if not otherwise known' ],
1129
1130
  [ 'Group#', undef, 'return tags for specified groups in family #' ],
1130
1131
  [ 'HexTagIDs', 0, 'use hex tag ID\'s in family 7 group names' ],
1131
1132
  [ 'HtmlDump', 0, 'HTML dump (0-3, higher # = bigger limit)' ],
@@ -2500,6 +2501,7 @@ sub Options($$;@)
2500
2501
  }
2501
2502
  } elsif ($param =~ /^(IgnoreTags|IgnoreGroups)$/) {
2502
2503
  if (defined $newVal) {
2504
+ ref $newVal eq 'HASH' and $$options{$param} = $newVal, next;
2503
2505
  # parse list from delimited string if necessary
2504
2506
  my @ignoreList = (ref $newVal eq 'ARRAY') ? @$newVal : ($newVal =~ /[-\w?*:#]+/g);
2505
2507
  ExpandShortcuts(\@ignoreList) if $param eq 'IgnoreTags';
@@ -6894,6 +6896,8 @@ sub IdentifyTrailer($;$)
6894
6896
  $type = 'Insta360';
6895
6897
  } elsif ($buff =~ m(\0{6}/NIKON APP$)) {
6896
6898
  $type = 'NikonApp';
6899
+ } elsif ($buff =~ /\xff{4}\x1b\*9HWfu\x84\x93\xa2\xb1$/) {
6900
+ $type = 'Vivo';
6897
6901
  }
6898
6902
  last;
6899
6903
  }
@@ -6906,7 +6910,8 @@ sub IdentifyTrailer($;$)
6906
6910
  # Inputs: 0) ExifTool object ref, 1) DirInfo ref:
6907
6911
  # - requires RAF and DirName
6908
6912
  # - OutFile is a scalar reference for writing
6909
- # - scans from current file position if ScanForAFCP is set
6913
+ # - scans from current file position for each trailer if ScanForTrailer is set
6914
+ # (current file position is just after JPEG EOF for a JPEG image)
6910
6915
  # Returns: 1 if trailer was processed or couldn't be processed (or written OK)
6911
6916
  # 0 if trailer was recognized but offsets need fixing (or write error)
6912
6917
  # - DirName, DirLen, DataPos, Offset, Fixup and OutFile are updated
@@ -6952,7 +6957,7 @@ sub ProcessTrailers($$)
6952
6957
  # read or write this trailer
6953
6958
  # (proc takes Offset as positive offset from end of trailer to end of file,
6954
6959
  # and returns DataPos and DirLen, and Fixup if applicable, and updates
6955
- # OutFile when writing)
6960
+ # OutFile when writing. Returns < 0 if we must scan for this trailer)
6956
6961
  no strict 'refs';
6957
6962
  my $result = &$proc($self, $dirInfo);
6958
6963
  use strict 'refs';
@@ -7362,7 +7367,7 @@ sub ProcessJPEG($$;$)
7362
7367
  # and scan for AFCP if necessary
7363
7368
  my $fromEnd = 0;
7364
7369
  if ($trailInfo) {
7365
- $$trailInfo{ScanForAFCP} = 1; # scan now if necessary
7370
+ $$trailInfo{ScanForTrailer} = 1; # scan now if necessary
7366
7371
  $self->ProcessTrailers($trailInfo);
7367
7372
  # save offset from end of file to start of first trailer
7368
7373
  $fromEnd = $$trailInfo{Offset};
@@ -7562,6 +7567,19 @@ sub ProcessJPEG($$;$)
7562
7567
  $$self{SkipData} = \@skipData if @skipData;
7563
7568
  # extract the EXIF information (it is in standard TIFF format)
7564
7569
  $self->ProcessTIFF(\%dirInfo) or $self->Warn('Malformed APP1 EXIF segment');
7570
+ # scan for Vivo HiddenData if necessary
7571
+ if ($$self{Make} eq 'vivo' and
7572
+ # (stored as UserComment by some models)
7573
+ not ($$self{VALUE}{UserComment} and $$self{VALUE}{UserComment} =~ /^filter:/) and
7574
+ $$dataPt =~ /(filter: .*?; \n)\0/sg)
7575
+ {
7576
+ if ($htmlDump) {
7577
+ my $n = length($1) + 1;
7578
+ $self->HDump($segPos+pos($$dataPt)-$n, $n, '[Vivo HiddenData]', undef, 0x08);
7579
+ }
7580
+ my $tbl = GetTagTable('Image::ExifTool::Vivo::Main');
7581
+ $self->HandleTag($tbl, HiddenData => $1);
7582
+ }
7565
7583
  # avoid looking for preview unless necessary because it really slows
7566
7584
  # us down -- only look for it if we found pointer, and preview is
7567
7585
  # outside EXIF, and PreviewImage is specifically requested
@@ -8376,7 +8394,11 @@ sub DoProcessTIFF($$;$)
8376
8394
  # save a copy of the EXIF data
8377
8395
  my $dirStart = $$dirInfo{DirStart} || 0;
8378
8396
  my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $dirStart);
8379
- $$self{EXIF_DATA} = substr($$dataPt, $dirStart, $dirLen);
8397
+ if ($dirLen > 0 or not $outfile) {
8398
+ $$self{EXIF_DATA} = substr($$dataPt, $dirStart, $dirLen);
8399
+ } else {
8400
+ delete $$self{EXIF_DATA}; # create from scratch;
8401
+ }
8380
8402
  $self->VerboseDir('TIFF') if $$self{OPTIONS}{Verbose} and length($$self{INDENT}) > 2;
8381
8403
  } elsif ($outfile) {
8382
8404
  delete $$self{EXIF_DATA}; # create from scratch
@@ -8535,7 +8557,7 @@ sub DoProcessTIFF($$;$)
8535
8557
  if ($raf) {
8536
8558
  my $trailInfo = IdentifyTrailer($raf);
8537
8559
  if ($trailInfo) {
8538
- $$trailInfo{ScanForAFCP} = 1; # scan to find AFCP if necessary
8560
+ $$trailInfo{ScanForTrailer} = 1; # scan to find AFCP if necessary
8539
8561
  $self->ProcessTrailers($trailInfo);
8540
8562
  }
8541
8563
  # dump any other known trailer (eg. A100 RAW Data)
@@ -8640,7 +8662,7 @@ sub DoProcessTIFF($$;$)
8640
8662
  last unless $trailInfo;
8641
8663
  my $tbuf = '';
8642
8664
  $$trailInfo{OutFile} = \$tbuf; # rewrite trailer(s)
8643
- $$trailInfo{ScanForAFCP} = 1; # scan for AFCP if necessary
8665
+ $$trailInfo{ScanForTrailer} = 1; # scan for AFCP if necessary
8644
8666
  # rewrite all trailers to buffer
8645
8667
  unless ($self->ProcessTrailers($trailInfo)) {
8646
8668
  undef $trailInfo;