exiftool-vendored.pl 13.0.0 → 13.16.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. package/bin/Changes +254 -20
  2. package/bin/MANIFEST +10 -0
  3. package/bin/META.json +1 -1
  4. package/bin/META.yml +1 -1
  5. package/bin/README +3 -3
  6. package/bin/arg_files/exif2xmp.args +4 -0
  7. package/bin/arg_files/xmp2exif.args +2 -1
  8. package/bin/build_geolocation +1 -1
  9. package/bin/exiftool +356 -213
  10. package/bin/lib/File/RandomAccess.pm +1 -1
  11. package/bin/lib/File/RandomAccess.pod +2 -2
  12. package/bin/lib/Image/ExifTool/AAC.pm +1 -1
  13. package/bin/lib/Image/ExifTool/AES.pm +1 -1
  14. package/bin/lib/Image/ExifTool/AFCP.pm +6 -6
  15. package/bin/lib/Image/ExifTool/AIFF.pm +2 -2
  16. package/bin/lib/Image/ExifTool/APE.pm +2 -2
  17. package/bin/lib/Image/ExifTool/APP12.pm +1 -1
  18. package/bin/lib/Image/ExifTool/ASF.pm +2 -2
  19. package/bin/lib/Image/ExifTool/Apple.pm +11 -9
  20. package/bin/lib/Image/ExifTool/Audible.pm +1 -1
  21. package/bin/lib/Image/ExifTool/BMP.pm +1 -1
  22. package/bin/lib/Image/ExifTool/BPG.pm +1 -1
  23. package/bin/lib/Image/ExifTool/BZZ.pm +1 -1
  24. package/bin/lib/Image/ExifTool/BigTIFF.pm +1 -1
  25. package/bin/lib/Image/ExifTool/BuildTagLookup.pm +36 -22
  26. package/bin/lib/Image/ExifTool/CBOR.pm +5 -2
  27. package/bin/lib/Image/ExifTool/Canon.pm +66 -27
  28. package/bin/lib/Image/ExifTool/CanonCustom.pm +1 -1
  29. package/bin/lib/Image/ExifTool/CanonRaw.pm +1 -1
  30. package/bin/lib/Image/ExifTool/CanonVRD.pm +1 -1
  31. package/bin/lib/Image/ExifTool/CaptureOne.pm +1 -1
  32. package/bin/lib/Image/ExifTool/Casio.pm +1 -1
  33. package/bin/lib/Image/ExifTool/Charset.pm +1 -1
  34. package/bin/lib/Image/ExifTool/DICOM.pm +1 -1
  35. package/bin/lib/Image/ExifTool/DJI.pm +196 -30
  36. package/bin/lib/Image/ExifTool/DNG.pm +1 -1
  37. package/bin/lib/Image/ExifTool/DPX.pm +1 -1
  38. package/bin/lib/Image/ExifTool/DV.pm +1 -1
  39. package/bin/lib/Image/ExifTool/DarwinCore.pm +1 -1
  40. package/bin/lib/Image/ExifTool/DjVu.pm +1 -1
  41. package/bin/lib/Image/ExifTool/EXE.pm +138 -33
  42. package/bin/lib/Image/ExifTool/Exif.pm +29 -16
  43. package/bin/lib/Image/ExifTool/FITS.pm +3 -3
  44. package/bin/lib/Image/ExifTool/FLAC.pm +1 -1
  45. package/bin/lib/Image/ExifTool/FLIF.pm +3 -3
  46. package/bin/lib/Image/ExifTool/FLIR.pm +1 -1
  47. package/bin/lib/Image/ExifTool/Fixup.pm +1 -1
  48. package/bin/lib/Image/ExifTool/Flash.pm +1 -1
  49. package/bin/lib/Image/ExifTool/FlashPix.pm +17 -21
  50. package/bin/lib/Image/ExifTool/Font.pm +2 -2
  51. package/bin/lib/Image/ExifTool/FotoStation.pm +1 -1
  52. package/bin/lib/Image/ExifTool/FujiFilm.pm +1 -1
  53. package/bin/lib/Image/ExifTool/GE.pm +1 -1
  54. package/bin/lib/Image/ExifTool/GIF.pm +144 -93
  55. package/bin/lib/Image/ExifTool/GIMP.pm +1 -1
  56. package/bin/lib/Image/ExifTool/GM.pm +1 -1
  57. package/bin/lib/Image/ExifTool/GPS.pm +34 -30
  58. package/bin/lib/Image/ExifTool/GeoTiff.pm +1 -1
  59. package/bin/lib/Image/ExifTool/Geolocation.dat +0 -0
  60. package/bin/lib/Image/ExifTool/Geolocation.pm +19 -9
  61. package/bin/lib/Image/ExifTool/Geotag.pm +46 -12
  62. package/bin/lib/Image/ExifTool/GoPro.pm +120 -8
  63. package/bin/lib/Image/ExifTool/H264.pm +1 -1
  64. package/bin/lib/Image/ExifTool/HP.pm +2 -2
  65. package/bin/lib/Image/ExifTool/HTML.pm +1 -1
  66. package/bin/lib/Image/ExifTool/HtmlDump.pm +1 -1
  67. package/bin/lib/Image/ExifTool/ICC_Profile.pm +81 -2
  68. package/bin/lib/Image/ExifTool/ICO.pm +1 -1
  69. package/bin/lib/Image/ExifTool/ID3.pm +8 -8
  70. package/bin/lib/Image/ExifTool/IPTC.pm +10 -7
  71. package/bin/lib/Image/ExifTool/ISO.pm +1 -1
  72. package/bin/lib/Image/ExifTool/ITC.pm +1 -1
  73. package/bin/lib/Image/ExifTool/Import.pm +5 -4
  74. package/bin/lib/Image/ExifTool/InDesign.pm +2 -2
  75. package/bin/lib/Image/ExifTool/InfiRay.pm +1 -1
  76. package/bin/lib/Image/ExifTool/JPEG.pm +32 -5
  77. package/bin/lib/Image/ExifTool/JPEGDigest.pm +1 -1
  78. package/bin/lib/Image/ExifTool/JSON.pm +1 -1
  79. package/bin/lib/Image/ExifTool/JVC.pm +1 -1
  80. package/bin/lib/Image/ExifTool/Jpeg2000.pm +10 -9
  81. package/bin/lib/Image/ExifTool/Kodak.pm +1 -1
  82. package/bin/lib/Image/ExifTool/KyoceraRaw.pm +1 -1
  83. package/bin/lib/Image/ExifTool/LIF.pm +1 -1
  84. package/bin/lib/Image/ExifTool/LNK.pm +2 -2
  85. package/bin/lib/Image/ExifTool/Lang/cs.pm +1 -1
  86. package/bin/lib/Image/ExifTool/Lang/de.pm +1 -1
  87. package/bin/lib/Image/ExifTool/Lang/en_ca.pm +1 -1
  88. package/bin/lib/Image/ExifTool/Lang/en_gb.pm +1 -1
  89. package/bin/lib/Image/ExifTool/Lang/es.pm +1 -1
  90. package/bin/lib/Image/ExifTool/Lang/fi.pm +1 -1
  91. package/bin/lib/Image/ExifTool/Lang/fr.pm +1 -1
  92. package/bin/lib/Image/ExifTool/Lang/it.pm +1 -1
  93. package/bin/lib/Image/ExifTool/Lang/ja.pm +1 -1
  94. package/bin/lib/Image/ExifTool/Lang/ko.pm +1 -1
  95. package/bin/lib/Image/ExifTool/Lang/nl.pm +1 -1
  96. package/bin/lib/Image/ExifTool/Lang/pl.pm +1 -1
  97. package/bin/lib/Image/ExifTool/Lang/ru.pm +1 -1
  98. package/bin/lib/Image/ExifTool/Lang/sk.pm +1 -1
  99. package/bin/lib/Image/ExifTool/Lang/sv.pm +1 -1
  100. package/bin/lib/Image/ExifTool/Lang/tr.pm +1 -1
  101. package/bin/lib/Image/ExifTool/Lang/zh_cn.pm +1 -1
  102. package/bin/lib/Image/ExifTool/Lang/zh_tw.pm +1 -1
  103. package/bin/lib/Image/ExifTool/Leaf.pm +1 -1
  104. package/bin/lib/Image/ExifTool/LigoGPS.pm +409 -0
  105. package/bin/lib/Image/ExifTool/Lytro.pm +1 -1
  106. package/bin/lib/Image/ExifTool/M2TS.pm +57 -18
  107. package/bin/lib/Image/ExifTool/MIE.pm +15 -6
  108. package/bin/lib/Image/ExifTool/MIEUnits.pod +1 -1
  109. package/bin/lib/Image/ExifTool/MIFF.pm +1 -1
  110. package/bin/lib/Image/ExifTool/MISB.pm +1 -1
  111. package/bin/lib/Image/ExifTool/MNG.pm +1 -1
  112. package/bin/lib/Image/ExifTool/MOI.pm +1 -1
  113. package/bin/lib/Image/ExifTool/MPC.pm +1 -1
  114. package/bin/lib/Image/ExifTool/MPEG.pm +1 -1
  115. package/bin/lib/Image/ExifTool/MPF.pm +1 -1
  116. package/bin/lib/Image/ExifTool/MRC.pm +1 -1
  117. package/bin/lib/Image/ExifTool/MWG.pm +1 -1
  118. package/bin/lib/Image/ExifTool/MXF.pm +3 -3
  119. package/bin/lib/Image/ExifTool/MacOS.pm +3 -2
  120. package/bin/lib/Image/ExifTool/MakerNotes.pm +1 -1
  121. package/bin/lib/Image/ExifTool/Matroska.pm +22 -6
  122. package/bin/lib/Image/ExifTool/Microsoft.pm +2 -2
  123. package/bin/lib/Image/ExifTool/Minolta.pm +1 -1
  124. package/bin/lib/Image/ExifTool/MinoltaRaw.pm +1 -1
  125. package/bin/lib/Image/ExifTool/Motorola.pm +1 -1
  126. package/bin/lib/Image/ExifTool/Nikon.pm +495 -39
  127. package/bin/lib/Image/ExifTool/NikonCapture.pm +1 -1
  128. package/bin/lib/Image/ExifTool/NikonCustom.pm +2 -2
  129. package/bin/lib/Image/ExifTool/NikonSettings.pm +1 -1
  130. package/bin/lib/Image/ExifTool/Nintendo.pm +1 -1
  131. package/bin/lib/Image/ExifTool/OOXML.pm +8 -8
  132. package/bin/lib/Image/ExifTool/Ogg.pm +1 -1
  133. package/bin/lib/Image/ExifTool/Olympus.pm +1 -1
  134. package/bin/lib/Image/ExifTool/OpenEXR.pm +1 -1
  135. package/bin/lib/Image/ExifTool/Opus.pm +1 -1
  136. package/bin/lib/Image/ExifTool/Other.pm +1 -1
  137. package/bin/lib/Image/ExifTool/PCX.pm +1 -1
  138. package/bin/lib/Image/ExifTool/PDF.pm +49 -18
  139. package/bin/lib/Image/ExifTool/PGF.pm +1 -1
  140. package/bin/lib/Image/ExifTool/PICT.pm +1 -1
  141. package/bin/lib/Image/ExifTool/PLIST.pm +4 -4
  142. package/bin/lib/Image/ExifTool/PLUS.pm +1 -1
  143. package/bin/lib/Image/ExifTool/PNG.pm +20 -8
  144. package/bin/lib/Image/ExifTool/PPM.pm +12 -3
  145. package/bin/lib/Image/ExifTool/PSP.pm +1 -1
  146. package/bin/lib/Image/ExifTool/Palm.pm +1 -1
  147. package/bin/lib/Image/ExifTool/Panasonic.pm +27 -3
  148. package/bin/lib/Image/ExifTool/PanasonicRaw.pm +1 -1
  149. package/bin/lib/Image/ExifTool/Parrot.pm +1 -1
  150. package/bin/lib/Image/ExifTool/Pentax.pm +1 -1
  151. package/bin/lib/Image/ExifTool/PhaseOne.pm +4 -4
  152. package/bin/lib/Image/ExifTool/PhotoCD.pm +1 -1
  153. package/bin/lib/Image/ExifTool/PhotoMechanic.pm +1 -1
  154. package/bin/lib/Image/ExifTool/Photoshop.pm +65 -4
  155. package/bin/lib/Image/ExifTool/PostScript.pm +1 -1
  156. package/bin/lib/Image/ExifTool/PrintIM.pm +1 -1
  157. package/bin/lib/Image/ExifTool/Protobuf.pm +270 -0
  158. package/bin/lib/Image/ExifTool/Qualcomm.pm +1 -1
  159. package/bin/lib/Image/ExifTool/QuickTime.pm +326 -88
  160. package/bin/lib/Image/ExifTool/QuickTimeStream.pl +199 -195
  161. package/bin/lib/Image/ExifTool/README +12 -2
  162. package/bin/lib/Image/ExifTool/RIFF.pm +21 -6
  163. package/bin/lib/Image/ExifTool/RSRC.pm +1 -1
  164. package/bin/lib/Image/ExifTool/RTF.pm +2 -2
  165. package/bin/lib/Image/ExifTool/Radiance.pm +1 -1
  166. package/bin/lib/Image/ExifTool/Rawzor.pm +1 -1
  167. package/bin/lib/Image/ExifTool/Real.pm +1 -1
  168. package/bin/lib/Image/ExifTool/Reconyx.pm +1 -1
  169. package/bin/lib/Image/ExifTool/Red.pm +1 -1
  170. package/bin/lib/Image/ExifTool/Ricoh.pm +4 -4
  171. package/bin/lib/Image/ExifTool/Samsung.pm +2 -2
  172. package/bin/lib/Image/ExifTool/Sanyo.pm +1 -1
  173. package/bin/lib/Image/ExifTool/Scalado.pm +1 -1
  174. package/bin/lib/Image/ExifTool/Shift.pl +1 -1
  175. package/bin/lib/Image/ExifTool/Shortcuts.pm +1 -1
  176. package/bin/lib/Image/ExifTool/Sigma.pm +1 -1
  177. package/bin/lib/Image/ExifTool/SigmaRaw.pm +1 -1
  178. package/bin/lib/Image/ExifTool/Sony.pm +5 -4
  179. package/bin/lib/Image/ExifTool/SonyIDC.pm +1 -1
  180. package/bin/lib/Image/ExifTool/Stim.pm +1 -1
  181. package/bin/lib/Image/ExifTool/TagInfoXML.pm +6 -5
  182. package/bin/lib/Image/ExifTool/TagLookup.pm +7023 -6968
  183. package/bin/lib/Image/ExifTool/TagNames.pod +445 -29
  184. package/bin/lib/Image/ExifTool/Text.pm +4 -3
  185. package/bin/lib/Image/ExifTool/Theora.pm +1 -1
  186. package/bin/lib/Image/ExifTool/Torrent.pm +3 -3
  187. package/bin/lib/Image/ExifTool/Unknown.pm +1 -1
  188. package/bin/lib/Image/ExifTool/VCard.pm +3 -3
  189. package/bin/lib/Image/ExifTool/Validate.pm +6 -6
  190. package/bin/lib/Image/ExifTool/Vivo.pm +124 -0
  191. package/bin/lib/Image/ExifTool/Vorbis.pm +1 -1
  192. package/bin/lib/Image/ExifTool/WPG.pm +1 -1
  193. package/bin/lib/Image/ExifTool/WTV.pm +1 -1
  194. package/bin/lib/Image/ExifTool/WriteCanonRaw.pl +1 -1
  195. package/bin/lib/Image/ExifTool/WriteExif.pl +3 -3
  196. package/bin/lib/Image/ExifTool/WriteIPTC.pl +1 -1
  197. package/bin/lib/Image/ExifTool/WritePDF.pl +1 -1
  198. package/bin/lib/Image/ExifTool/WritePNG.pl +1 -1
  199. package/bin/lib/Image/ExifTool/WritePhotoshop.pl +1 -1
  200. package/bin/lib/Image/ExifTool/WritePostScript.pl +1 -1
  201. package/bin/lib/Image/ExifTool/WriteQuickTime.pl +166 -79
  202. package/bin/lib/Image/ExifTool/WriteRIFF.pl +17 -6
  203. package/bin/lib/Image/ExifTool/WriteXMP.pl +3 -3
  204. package/bin/lib/Image/ExifTool/Writer.pl +89 -96
  205. package/bin/lib/Image/ExifTool/XISF.pm +1 -1
  206. package/bin/lib/Image/ExifTool/XMP.pm +28 -13
  207. package/bin/lib/Image/ExifTool/XMP2.pl +103 -1
  208. package/bin/lib/Image/ExifTool/XMPStruct.pl +2 -3
  209. package/bin/lib/Image/ExifTool/ZIP.pm +2 -2
  210. package/bin/lib/Image/ExifTool/ZISRAW.pm +1 -1
  211. package/bin/lib/Image/ExifTool/iWork.pm +1 -1
  212. package/bin/lib/Image/ExifTool.pm +335 -163
  213. package/bin/lib/Image/ExifTool.pod +119 -73
  214. package/bin/perl-Image-ExifTool.spec +1 -1
  215. package/bin/windows_exiftool.txt +96 -51
  216. package/package.json +9 -9
@@ -22,7 +22,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
22
22
  use Image::ExifTool::Exif;
23
23
  use Image::ExifTool::ASF; # for GetGUID()
24
24
 
25
- $VERSION = '1.48';
25
+ $VERSION = '1.49';
26
26
 
27
27
  sub ProcessFPX($$);
28
28
  sub ProcessFPXR($$$);
@@ -1449,7 +1449,7 @@ sub ReadFPXValue($$$$$;$$)
1449
1449
  $noPad = 1; # values sometimes aren't padded inside vectors!!
1450
1450
  my $size = $oleFormatSize{VT_VECTOR};
1451
1451
  if ($valPos + $size > $dirEnd) {
1452
- $et->WarnOnce('Incorrect FPX VT_VECTOR size');
1452
+ $et->Warn('Incorrect FPX VT_VECTOR size');
1453
1453
  last;
1454
1454
  }
1455
1455
  $count = Get32u($dataPt, $valPos);
@@ -1457,14 +1457,14 @@ sub ReadFPXValue($$$$$;$$)
1457
1457
  $valPos += 4;
1458
1458
  } else {
1459
1459
  # can't yet handle this property flag
1460
- $et->WarnOnce('Unknown FPX property');
1460
+ $et->Warn('Unknown FPX property');
1461
1461
  last;
1462
1462
  }
1463
1463
  }
1464
1464
  unless ($format =~ /^VT_/) {
1465
1465
  my $size = Image::ExifTool::FormatSize($format) * $count;
1466
1466
  if ($valPos + $size > $dirEnd) {
1467
- $et->WarnOnce("Incorrect FPX $format size");
1467
+ $et->Warn("Incorrect FPX $format size");
1468
1468
  last;
1469
1469
  }
1470
1470
  @vals = ReadValue($dataPt, $valPos, $format, $count, $size);
@@ -1476,7 +1476,7 @@ sub ReadFPXValue($$$$$;$$)
1476
1476
  my ($item, $val, $len);
1477
1477
  for ($item=0; $item<$count; ++$item) {
1478
1478
  if ($valPos + $size > $dirEnd) {
1479
- $et->WarnOnce("Truncated FPX $format value");
1479
+ $et->Warn("Truncated FPX $format value");
1480
1480
  last;
1481
1481
  }
1482
1482
  # sometimes VT_VECTOR items are padded to even 4-byte boundaries, and sometimes they aren't
@@ -1528,7 +1528,7 @@ sub ReadFPXValue($$$$$;$$)
1528
1528
  $len = Get32u($dataPt, $valPos);
1529
1529
  $len *= 2 if $format eq 'VT_LPWSTR'; # convert to byte count
1530
1530
  if ($valPos + $len + 4 > $dirEnd) {
1531
- $et->WarnOnce("Truncated $format value");
1531
+ $et->Warn("Truncated $format value");
1532
1532
  last;
1533
1533
  }
1534
1534
  $val = substr($$dataPt, $valPos + 4, $len);
@@ -1551,7 +1551,7 @@ sub ReadFPXValue($$$$$;$$)
1551
1551
  } elsif ($format eq 'VT_BLOB' or $format eq 'VT_CF') {
1552
1552
  my $len = Get32u($dataPt, $valPos); # (use local $len because we always expect padding)
1553
1553
  if ($valPos + $len + 4 > $dirEnd) {
1554
- $et->WarnOnce("Truncated $format value");
1554
+ $et->Warn("Truncated $format value");
1555
1555
  last;
1556
1556
  }
1557
1557
  $val = substr($$dataPt, $valPos + 4, $len);
@@ -1627,7 +1627,7 @@ sub ProcessContents($$$)
1627
1627
  while ($$dataPt =~ /\x0bTargetRole1(?:.\x80|\xff\xff.\0.\0Vn(\w+))\0\0\x01.{4}(.{24})/sg) {
1628
1628
  my ($index, @coords) = unpack('Vx4V4', $2);
1629
1629
  next if $index == 0xffffffff;
1630
- $$et{IeImg_lkup}{$index} and $et->WarnOnce('Duplicate image index');
1630
+ $$et{IeImg_lkup}{$index} and $et->Warn('Duplicate image index');
1631
1631
  $$et{IeImg_lkup}{$index} = "@coords";
1632
1632
  $$et{IeImg_class}{$index} = $1 if $1;
1633
1633
  }
@@ -1661,7 +1661,7 @@ sub ProcessWordDocument($$$)
1661
1661
  my $dirLen = length $$dataPt;
1662
1662
  # validate the FIB signature
1663
1663
  unless ($dirLen > 2 and Get16u($dataPt,0) == 0xa5ec) {
1664
- $et->WarnOnce('Invalid FIB signature', 1);
1664
+ $et->Warn('Invalid FIB signature', 1);
1665
1665
  return 0;
1666
1666
  }
1667
1667
  $et->ProcessBinaryData($dirInfo, $tagTablePtr); # process FIB
@@ -1717,16 +1717,14 @@ sub ProcessDocumentTable($)
1717
1717
  my $offsets = $$value{$key};
1718
1718
  last unless defined $offsets;
1719
1719
  my $doc;
1720
- $doc = $$extra{$key}{G3} if $$extra{$key};
1721
- $doc = '' unless $doc;
1720
+ $doc = $$extra{$key}{G3} || '';
1722
1721
  # get DocFlags for this sub-document
1723
1722
  my ($docFlags, $docTable);
1724
1723
  for ($j=0; ; ++$j) {
1725
1724
  my $key = 'DocFlags' . ($j ? " ($j)" : '');
1726
1725
  last unless defined $$value{$key};
1727
1726
  my $tmp;
1728
- $tmp = $$extra{$key}{G3} if $$extra{$key};
1729
- $tmp = '' unless $tmp;
1727
+ $tmp = $$extra{$key}{G3} || '';
1730
1728
  if ($tmp eq $doc) {
1731
1729
  $docFlags = $$value{$key};
1732
1730
  last;
@@ -1739,8 +1737,7 @@ sub ProcessDocumentTable($)
1739
1737
  my $key = $tag . ($j ? " ($j)" : '');
1740
1738
  last unless defined $$value{$key};
1741
1739
  my $tmp;
1742
- $tmp = $$extra{$key}{G3} if $$extra{$key};
1743
- $tmp = '' unless $tmp;
1740
+ $tmp = $$extra{$key}{G3} || '';
1744
1741
  if ($tmp eq $doc) {
1745
1742
  $docTable = \$$value{$key};
1746
1743
  last;
@@ -2101,7 +2098,7 @@ sub ProcessFPXR($$$)
2101
2098
  my $overlap = length($$obj{Stream}) - $offset;
2102
2099
  my $start = $dirStart + 13;
2103
2100
  if ($overlap < 0 or $dirLen - $overlap < 13) {
2104
- $et->WarnOnce("Bad FPXR stream $index offset",1);
2101
+ $et->Warn("Bad FPXR stream $index offset",1);
2105
2102
  } else {
2106
2103
  # ignore any overlapping data in this segment
2107
2104
  # (this seems to be the convention)
@@ -2341,7 +2338,7 @@ sub ProcessFPX($$)
2341
2338
  $tag =~ s/\0.*//s; # truncate at null (in case length was wrong)
2342
2339
 
2343
2340
  if ($tag eq '0' and not defined $ee) {
2344
- $et->WarnOnce('Use the ExtractEmbedded option to extract embedded information', 3);
2341
+ $et->Warn('Use the ExtractEmbedded option to extract embedded information', 3);
2345
2342
  }
2346
2343
  my $sect = Get32u(\$dir, $pos + 0x74); # start sector number
2347
2344
  my $size = Get32u(\$dir, $pos + 0x78); # stream length
@@ -2444,7 +2441,7 @@ sub ProcessFPX($$)
2444
2441
  my $subTablePtr = GetTagTable($$subdir{TagTable});
2445
2442
  $et->ProcessDirectory(\%dirInfo, $subTablePtr, $$subdir{ProcessProc});
2446
2443
  } elsif (defined $size and $size > length($buff)) {
2447
- $et->WarnOnce('Truncated object');
2444
+ $et->Warn('Truncated object');
2448
2445
  } else {
2449
2446
  $buff = substr($buff, 0, $size) if defined $size and $size < length($buff);
2450
2447
  if ($tag =~ /^IeImg_0*(\d+)$/) {
@@ -2505,8 +2502,7 @@ sub ProcessFPX($$)
2505
2502
  for ($copy=1; ;++$copy) {
2506
2503
  my $key = "$tag ($copy)";
2507
2504
  last unless defined $$et{VALUE}{$key};
2508
- my $extra = $$et{TAG_EXTRA}{$key};
2509
- next if $extra and $$extra{G3}; # not Main if family 3 group is set
2505
+ next if $$et{TAG_EXTRA}{$key}{G3}; # not Main if family 3 group is set
2510
2506
  foreach $member ('PRIORITY','VALUE','FILE_ORDER','TAG_INFO','TAG_EXTRA') {
2511
2507
  my $pHash = $$et{$member};
2512
2508
  my $t = $$pHash{$tag};
@@ -2561,7 +2557,7 @@ JPEG images.
2561
2557
 
2562
2558
  =head1 AUTHOR
2563
2559
 
2564
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
2560
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
2565
2561
 
2566
2562
  This library is free software; you can redistribute it and/or modify it
2567
2563
  under the same terms as Perl itself.
@@ -405,7 +405,7 @@ sub ProcessOTF($$)
405
405
  next;
406
406
  }
407
407
  if ($verbose) {
408
- $tag =~ s/([\0-\x1f\x80-\xff])/sprintf('\x%.2x',ord $1)/ge;
408
+ $tag =~ s/([\0-\x1f\x7f-\xff])/sprintf('\x%.2x',ord $1)/ge;
409
409
  my $str = sprintf("%s%d) Tag '%s' (offset 0x%.4x, %d bytes)\n",
410
410
  $$et{INDENT}, $pos/16, $tag, $offset, $size);
411
411
  $et->VPrint(0, $str);
@@ -633,7 +633,7 @@ extracted from these formats.
633
633
 
634
634
  =head1 AUTHOR
635
635
 
636
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
636
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
637
637
 
638
638
  This library is free software; you can redistribute it and/or modify it
639
639
  under the same terms as Perl itself.
@@ -243,7 +243,7 @@ write information from the FotoWare FotoStation trailer.
243
243
 
244
244
  =head1 AUTHOR
245
245
 
246
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
246
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
247
247
 
248
248
  This library is free software; you can redistribute it and/or modify it
249
249
  under the same terms as Perl itself.
@@ -1959,7 +1959,7 @@ FujiFilm maker notes in EXIF information, and to read/write FujiFilm RAW
1959
1959
 
1960
1960
  =head1 AUTHOR
1961
1961
 
1962
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
1962
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
1963
1963
 
1964
1964
  This library is free software; you can redistribute it and/or modify it
1965
1965
  under the same terms as Perl itself.
@@ -68,7 +68,7 @@ General Imaging maker notes.
68
68
 
69
69
  =head1 AUTHOR
70
70
 
71
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
71
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
72
72
 
73
73
  This library is free software; you can redistribute it and/or modify it
74
74
  under the same terms as Perl itself.
@@ -20,7 +20,7 @@ use strict;
20
20
  use vars qw($VERSION);
21
21
  use Image::ExifTool qw(:DataAccess :Utils);
22
22
 
23
- $VERSION = '1.20';
23
+ $VERSION = '1.21';
24
24
 
25
25
  # road map of directory locations in GIF images
26
26
  my %gifMap = (
@@ -28,6 +28,9 @@ my %gifMap = (
28
28
  ICC_Profile => 'GIF',
29
29
  );
30
30
 
31
+ # application extensions that we can write, and the order they are written
32
+ my @appExtensions = ( 'XMP Data/XMP', 'ICCRGBG1/012' );
33
+
31
34
  %Image::ExifTool::GIF::Main = (
32
35
  GROUPS => { 2 => 'Image' },
33
36
  VARS => { NO_ID => 1 },
@@ -61,19 +64,26 @@ my %gifMap = (
61
64
  %Image::ExifTool::GIF::Extensions = (
62
65
  GROUPS => { 2 => 'Image' },
63
66
  NOTES => 'Tags extracted from GIF89a application extensions.',
67
+ WRITE_PROC => sub { return 1 }, # (dummy proc to facilitate writable directories)
64
68
  'NETSCAPE/2.0' => { #3
65
69
  Name => 'Animation',
66
70
  SubDirectory => { TagTable => 'Image::ExifTool::GIF::Animation' },
67
71
  },
68
72
  'XMP Data/XMP' => { #2
69
73
  Name => 'XMP',
70
- IncludeLengthBytes => 1, # length bytes are included in the data
71
- Writable => 2,
74
+ # IncludeLengthBytes indicates the length bytes are part of the data value...
75
+ # undef = data may contain nulls and is split into 255-byte blocks
76
+ # 1 = data may not contain nulls and is not split; NULL padding is added as necessary
77
+ # 2 = data is not split and may be edited in place; 257-byte landing zone is added
78
+ # (Terminator may be specified for a value of 1 above, but must be specified for 2)
79
+ IncludeLengthBytes => 2,
80
+ Terminator => q(<\\?xpacket end=['"][wr]['"]\\?>), # (regex to match end of valid data)
81
+ Writable => 2, # (writable directory!)
72
82
  SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' },
73
83
  },
74
84
  'ICCRGBG1/012' => { #4
75
85
  Name => 'ICC_Profile',
76
- Writable => 2,
86
+ Writable => 2, # (writable directory!)
77
87
  SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' },
78
88
  },
79
89
  'MIDICTRL/Jon' => { #5
@@ -162,7 +172,7 @@ my %gifMap = (
162
172
  );
163
173
 
164
174
  #------------------------------------------------------------------------------
165
- # Process meta information in GIF image
175
+ # Read/write meta information in GIF image
166
176
  # Inputs: 0) ExifTool object reference, 1) Directory information ref
167
177
  # Returns: 1 on success, 0 if this wasn't a valid GIF file, or -1 if
168
178
  # an output file was specified and a write error occurred
@@ -174,7 +184,7 @@ sub ProcessGIF($$)
174
184
  my $verbose = $et->Options('Verbose');
175
185
  my $out = $et->Options('TextOut');
176
186
  my ($a, $s, $ch, $length, $buff);
177
- my ($err, $newComment, $setComment, $nvComment);
187
+ my ($err, $newComment, $setComment, $nvComment, $newExt);
178
188
  my ($addDirs, %doneDir);
179
189
  my ($frameCount, $delayTime) = (0, 0);
180
190
 
@@ -186,9 +196,19 @@ sub ProcessGIF($$)
186
196
  my $ver = $1;
187
197
  my $rtnVal = 0;
188
198
  my $tagTablePtr = GetTagTable('Image::ExifTool::GIF::Main');
199
+ my $extTable = GetTagTable('Image::ExifTool::GIF::Extensions');
189
200
  SetByteOrder('II');
190
201
 
191
202
  if ($outfile) {
203
+ # add any user-defined writable app extensions to the list
204
+ my $ext;
205
+ foreach $ext (sort keys %$extTable) {
206
+ next unless ref $$extTable{$ext} eq 'HASH';
207
+ my $extInfo = $$extTable{$ext};
208
+ next unless $$extInfo{SubDirectory} and $$extInfo{Writable} and not $gifMap{$$extInfo{Name}};
209
+ $gifMap{$$extInfo{Name}} = 'GIF';
210
+ push @appExtensions, $ext;
211
+ }
192
212
  $et->InitWriteDirs(\%gifMap, 'XMP'); # make XMP the preferred group for GIF
193
213
  $addDirs = $$et{ADD_DIRS};
194
214
  # determine if we are editing the File:Comment tag
@@ -196,8 +216,9 @@ sub ProcessGIF($$)
196
216
  $newComment = $et->GetNewValue('Comment', \$nvComment);
197
217
  $setComment = 1 if $nvComment or $$delGroup{File};
198
218
  # change to GIF 89a if adding comment, XMP or ICC_Profile
199
- $buff = 'GIF89a' if $$addDirs{XMP} or $$addDirs{ICC_Profile} or defined $newComment;
219
+ $buff = 'GIF89a' if %$addDirs or defined $newComment;
200
220
  Write($outfile, $buff, $s) or $err = 1;
221
+ $newExt = $et->GetNewTagInfoHash($extTable);
201
222
  } else {
202
223
  $et->SetFileType(); # set file type
203
224
  $et->HandleTag($tagTablePtr, 'GIFVersion', $ver);
@@ -238,45 +259,50 @@ Block:
238
259
  undef $nvComment; # delete any other extraneous comments
239
260
  ++$$et{CHANGED}; # increment file changed flag
240
261
  }
241
- # add application extension containing XMP block if necessary
242
- # (this will place XMP before the first non-extension block)
243
- if (exists $$addDirs{XMP} and not defined $doneDir{XMP}) {
244
- $doneDir{XMP} = 1;
245
- # write new XMP data
246
- my $xmpTable = GetTagTable('Image::ExifTool::XMP::Main');
247
- my %dirInfo = ( Parent => 'GIF' );
248
- $verbose and print $out "Creating XMP application extension block:\n";
249
- $buff = $et->WriteDirectory(\%dirInfo, $xmpTable);
250
- if (defined $buff and length $buff) {
251
- my $lz = pack('C*',1,reverse(0..255),0);
252
- Write($outfile, "\x21\xff\x0bXMP DataXMP", $buff, $lz) or $err = 1;
253
- ++$doneDir{XMP}; # set to 2 to indicate we added XMP
262
+ # add application extensions if necessary
263
+ my $ext;
264
+ my @new = sort keys %$newExt;
265
+ foreach $ext (@appExtensions, @new) {
266
+ my $extInfo = $$extTable{$ext};
267
+ my $name = $$extInfo{Name};
268
+ if ($$newExt{$ext}) {
269
+ delete $$newExt{$ext};
270
+ $doneDir{$name} = 1; # (we wrote this as a block instead)
271
+ $buff = $et->GetNewValue($extInfo);
272
+ $et->VerboseValue("+ GIF:$name", $buff);
273
+ } elsif (exists $$addDirs{$name} and not defined $doneDir{$name}) {
274
+ $doneDir{$name} = 1;
275
+ my $tbl = GetTagTable($$extInfo{SubDirectory}{TagTable});
276
+ my %dirInfo = ( Parent => 'GIF' );
277
+ $verbose and print $out "Creating $name application extension block:\n";
278
+ $buff = $et->WriteDirectory(\%dirInfo, $tbl);
254
279
  } else {
255
- $verbose and print $out " -> no XMP to add\n";
280
+ next;
256
281
  }
257
- }
258
- # add application extension containing ICC_Profile if necessary
259
- if (exists $$addDirs{ICC_Profile} and not defined $doneDir{ICC_Profile}) {
260
- $doneDir{ICC_Profile} = 1;
261
- # write new ICC_Profile
262
- my $iccTable = GetTagTable('Image::ExifTool::ICC_Profile::Main');
263
- my %dirInfo = ( Parent => 'GIF' );
264
- $verbose and print $out "Creating ICC_Profile application extension block:\n";
265
- $buff = $et->WriteDirectory(\%dirInfo, $iccTable);
266
282
  if (defined $buff and length $buff) {
283
+ ++$$et{CHANGED};
284
+ Write($outfile, "\x21\xff\x0b", substr($ext,0,8), substr($ext,9,3)) or $err = 1;
267
285
  my $pos = 0;
268
- Write($outfile, "\x21\xff\x0bICCRGBG1012") or $err = 1;
269
- my $len = length $buff;
270
- while ($pos < $len) {
271
- my $n = $len - $pos;
272
- $n = 255 if $n > 255;
273
- Write($outfile, chr($n), substr($buff, $pos, $n)) or $err = 1;
274
- $pos += $n;
286
+ if (not $$extTable{$ext}{IncludeLengthBytes}) {
287
+ my $len = length $buff;
288
+ while ($pos < length $buff) {
289
+ my $n = length($buff) - $pos;
290
+ $n = 255 if $n > 255;
291
+ Write($outfile, chr($n), substr($buff, $pos, $n)) or $err = 1;
292
+ $pos += $n;
293
+ }
294
+ Write($outfile, "\0") or $err = 1; # write null terminator
295
+ } elsif ($$extTable{$ext}{IncludeLengthBytes} < 2) {
296
+ $pos += ord(substr($buff,$pos,1)) + 1 while $pos < length $buff;
297
+ # write data, null padding and terminator
298
+ Write($outfile, $buff, "\0" x ($pos - length($buff) + 1)) or $err = 1;
299
+ } else {
300
+ # write data, landing zone and null terminator
301
+ Write($outfile, $buff, pack('C*',1,reverse(0..255),0)) or $err = 1;
275
302
  }
276
- Write($outfile, "\0") or $err = 1; # write null terminator
277
- ++$doneDir{ICC_Profile}; # set to 2 to indicate we added a new profile
303
+ ++$doneDir{$name}; # set to 2 to indicate we added it
278
304
  } else {
279
- $verbose and print $out " -> no ICC_Profile to add\n";
305
+ $verbose and print $out " -> no $name to add\n";
280
306
  }
281
307
  }
282
308
  }
@@ -286,7 +312,7 @@ Block:
286
312
  # image descriptor
287
313
  last unless $raf->Read($buff, 8) == 8 and $raf->Read($ch, 1);
288
314
  Write($outfile, $buff, $ch) or $err = 1 if $outfile;
289
- if ($verbose) {
315
+ if ($verbose and not $outfile) {
290
316
  my ($left, $top, $w, $h) = unpack('v*', $buff);
291
317
  print $out "Image: left=$left top=$top width=$w height=$h\n";
292
318
  }
@@ -352,9 +378,9 @@ Block:
352
378
  }
353
379
  if ($isOverwriting) {
354
380
  ++$$et{CHANGED}; # increment file changed flag
355
- $et->VerboseValue('- Comment', $comment);
381
+ $et->VerboseValue('- GIF:Comment', $comment);
356
382
  $comment = $newComment;
357
- $et->VerboseValue('+ Comment', $comment) if defined $comment;
383
+ $et->VerboseValue('+ GIF:Comment', $comment) if defined $comment;
358
384
  undef $nvComment; # just delete remaining comments
359
385
  } else {
360
386
  undef $setComment; # leave remaining comments alone
@@ -393,14 +419,19 @@ Block:
393
419
  $tag =~ tr/\0-\x1f//d; # remove nulls and control characters
394
420
  $verbose and print $out "Application Extension: $tag\n";
395
421
 
396
- my $extTable = GetTagTable('Image::ExifTool::GIF::Extensions');
397
422
  my $extInfo = $$extTable{$tag};
398
- my ($subdir, $inclLen, $justCopy);
423
+ my ($subdir, $inclLen, $justCopy, $name);
399
424
  if ($extInfo) {
400
- $subdir = $$extInfo{SubDirectory};
425
+ if ($outfile and $$newExt{$$extInfo{TagID}}) {
426
+ delete $$newExt{$$extInfo{TagID}}; # don't create again
427
+ # (write as a block -- don't define $subdir)
428
+ } else {
429
+ $subdir = $$extInfo{SubDirectory};
430
+ }
401
431
  $inclLen = $$extInfo{IncludeLengthBytes};
402
- # rewrite as-is unless this is a writable subdirectory
403
- $justCopy = 1 if $outfile and (not $subdir or not $$extInfo{Writable});
432
+ $name = $$extInfo{Name};
433
+ # rewrite as-is unless this is a writable
434
+ $justCopy = 1 if $outfile and not $$extInfo{Writable};
404
435
  } else {
405
436
  $justCopy = 1 if $outfile;
406
437
  }
@@ -415,62 +446,82 @@ Block:
415
446
  Write($outfile, $ch, $buff) or $err = 1 if $justCopy;
416
447
  $dat .= $inclLen ? $ch . $buff : $buff;
417
448
  }
418
- Write($outfile, "\0") if $justCopy;
419
-
420
- if ($subdir) {
421
- my $dirLen = length $dat;
422
- my $name = $$extInfo{Name};
423
- if ($name eq 'XMP') {
424
- # get length of XMP without landing zone data
425
- # (note that LZ data may not be exactly the same as what we use)
426
- $dirLen = pos($dat) if $dat =~ /<\?xpacket end=['"][wr]['"]\?>/g;
449
+ if ($justCopy) {
450
+ Write($outfile, "\0") or $err = 1;
451
+ next;
452
+ } elsif ($inclLen) {
453
+ # remove landing zone or padding
454
+ if ($$extInfo{Terminator} and $dat =~ /$$extInfo{Terminator}/g) {
455
+ $dat = substr($dat, 0, pos($dat));
456
+ } elsif ($dat =~ /\0/g) {
457
+ $dat = substr($dat, 0, pos($dat) - 1);
427
458
  }
459
+ }
460
+ if ($subdir) {
428
461
  my %dirInfo = (
429
462
  DataPt => \$dat,
430
463
  DataLen => length $dat,
431
- DirLen => $dirLen,
464
+ DirLen => length $dat,
432
465
  DirName => $name,
433
466
  Parent => 'GIF',
434
467
  );
435
468
  my $subTable = GetTagTable($$subdir{TagTable});
436
- if (not $outfile) {
469
+ unless ($outfile) {
437
470
  $et->ProcessDirectory(\%dirInfo, $subTable);
438
- } elsif ($$extInfo{Writable}) {
439
- if ($doneDir{$name} and $doneDir{$name} > 1) {
440
- $et->Warn("Duplicate $name block created");
441
- }
442
- $buff = $et->WriteDirectory(\%dirInfo, $subTable);
443
- if (defined $buff) {
444
- next unless length $buff; # delete this extension if length is zero
445
- # check for null just to be safe
446
- $et->Error("$name contained NULL character") if $buff =~ /\0/;
447
- $dat = $buff;
448
- # add landing zone (without terminator, which will be added later)
449
- $dat .= pack('C*',1,reverse(0..255)) if $$extInfo{IncludeLengthBytes};
450
- } # (else rewrite original data)
451
-
452
- $doneDir{$name} = 1;
453
-
454
- if ($$extInfo{IncludeLengthBytes}) {
455
- # write data and landing zone
456
- Write($outfile, $hdr, $dat) or $err = 1;
457
- } else {
458
- # write as sub-blocks
459
- Write($outfile, $hdr) or $err = 1;
460
- my $pos = 0;
461
- my $len = length $dat;
462
- while ($pos < $len) {
463
- my $n = $len - $pos;
464
- $n = 255 if $n > 255;
465
- Write($outfile, chr($n), substr($dat, $pos, $n)) or $err = 1;
466
- $pos += $n;
467
- }
468
- }
469
- Write($outfile, "\0") or $err = 1; # write null terminator
471
+ next;
472
+ }
473
+ next if $justCopy;
474
+ if ($doneDir{$name} and $doneDir{$name} > 1) {
475
+ $et->Warn("Duplicate $name block created");
476
+ }
477
+ $buff = $et->WriteDirectory(\%dirInfo, $subTable);
478
+ if (defined $buff) {
479
+ next unless length $buff; # delete this extension if length is zero
480
+ $dat = $buff;
481
+ }
482
+ $doneDir{$name} = 1;
483
+ } elsif ($outfile and not $justCopy) {
484
+ my $nvHash = $et->GetNewValueHash($extInfo);
485
+ if ($nvHash and $et->IsOverwriting($nvHash, $dat)) {
486
+ ++$$et{CHANGED};
487
+ my $val = $et->GetNewValue($extInfo);
488
+ $et->VerboseValue("- GIF:$name", $dat);
489
+ next unless defined $val and length $val;
490
+ $dat = $val;
491
+ $et->VerboseValue("+ GIF:$name", $dat);
492
+ $doneDir{$name} = 1; # (possibly wrote dir as a block)
470
493
  }
471
494
  } elsif (not $outfile) {
472
495
  $et->HandleTag($extTable, $tag, $dat);
496
+ next;
497
+ }
498
+ Write($outfile, $hdr) or $err = 1; # write extension header
499
+ if ($inclLen) {
500
+ # check for null just to be safe
501
+ $et->Error("$name contained NULL character") if $inclLen and $dat =~ /\0/;
502
+ if ($inclLen > 1) {
503
+ # add landing zone (without terminator, which will be added later)
504
+ $dat .= pack('C*',1,reverse(0..255)) if $inclLen;
505
+ } else {
506
+ # pad with nulls as required
507
+ my $pos = 0;
508
+ $pos += ord(substr($dat,$pos,1)) + 1 while $pos < length $dat;
509
+ $dat .= "\0" x ($pos - length($dat));
510
+ }
511
+ # write data and landing zone
512
+ Write($outfile, $dat) or $err = 1;
513
+ } else {
514
+ # write as sub-blocks
515
+ my $pos = 0;
516
+ my $len = length $dat;
517
+ while ($pos < $len) {
518
+ my $n = $len - $pos;
519
+ $n = 255 if $n > 255;
520
+ Write($outfile, chr($n), substr($dat, $pos, $n)) or $err = 1;
521
+ $pos += $n;
522
+ }
473
523
  }
524
+ Write($outfile, "\0") or $err = 1; # write null terminator
474
525
  next;
475
526
 
476
527
  } elsif ($a == 0xf9 and $length == 4) { # graphic control extension
@@ -489,7 +540,7 @@ Block:
489
540
 
490
541
  last unless $raf->Read($buff, $length) == $length;
491
542
  Write($outfile, $ch, $s, $buff) or $err = 1 if $outfile;
492
- if ($verbose) {
543
+ if ($verbose and not $outfile) {
493
544
  my ($left, $top, $w, $h) = unpack('v4', $buff);
494
545
  print $out "Text: left=$left top=$top width=$w height=$h\n";
495
546
  }
@@ -545,7 +596,7 @@ write GIF meta information.
545
596
 
546
597
  =head1 AUTHOR
547
598
 
548
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
599
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
549
600
 
550
601
  This library is free software; you can redistribute it and/or modify it
551
602
  under the same terms as Perl itself.
@@ -270,7 +270,7 @@ GIMP software.
270
270
 
271
271
  =head1 AUTHOR
272
272
 
273
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
273
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
274
274
 
275
275
  This library is free software; you can redistribute it and/or modify it
276
276
  under the same terms as Perl itself.
@@ -531,7 +531,7 @@ metadata from videos written by some GM models such as Corvette and Camero.
531
531
 
532
532
  =head1 AUTHOR
533
533
 
534
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
534
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
535
535
 
536
536
  This library is free software; you can redistribute it and/or modify it
537
537
  under the same terms as Perl itself.