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
@@ -112,7 +112,7 @@ sub ValidateProperty($$;$)
112
112
  my $valLang = $$et{XmpValidateLangAlt} || ($$et{XmpValidateLangAlt} = { });
113
113
  $$valLang{$langPath} or $$valLang{$langPath} = { };
114
114
  if ($$valLang{$langPath}{$lang}) {
115
- $et->WarnOnce("Duplicate language ($lang) in lang-alt list: $langPath");
115
+ $et->Warn("Duplicate language ($lang) in lang-alt list: $langPath");
116
116
  } else {
117
117
  $$valLang{$langPath}{$lang} = 1;
118
118
  }
@@ -984,7 +984,7 @@ sub WriteXMP($$;$)
984
984
  (not @fixInfo or $fixInfo[0] ne $info);
985
985
  pop @props;
986
986
  }
987
- $et->WarnOnce("Error finding parent structure for $$tagInfo{Name}") unless @fixInfo;
987
+ $et->Warn("Error finding parent structure for $$tagInfo{Name}") unless @fixInfo;
988
988
  }
989
989
  # fix property path for this tag (last in the @fixInfo list)
990
990
  push @fixInfo, $tagInfo unless @fixInfo and $isStruct;
@@ -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.
@@ -43,6 +43,7 @@ my %tiffMap = (
43
43
  PrintIM => 'IFD0',
44
44
  IPTC => 'IFD0',
45
45
  Photoshop => 'IFD0',
46
+ SEAL => 'IFD0',
46
47
  InteropIFD => 'ExifIFD',
47
48
  MakerNotes => 'ExifIFD',
48
49
  CanonVRD => 'MakerNotes', # (so VRDOffset will get updated)
@@ -74,6 +75,7 @@ my %jpegMap = (
74
75
  Meta => 'APP3',
75
76
  MetaIFD => 'Meta',
76
77
  RMETA => 'APP5',
78
+ SEAL => ['APP8','APP9'], # (note: add 'IFD0' if this is a possibility)
77
79
  Ducky => 'APP12',
78
80
  Photoshop => 'APP13',
79
81
  Adobe => 'APP14',
@@ -136,11 +138,12 @@ my %rawType = (
136
138
  # 2) any dependencies must be added to %excludeGroups
137
139
  my @delGroups = qw(
138
140
  Adobe AFCP APP0 APP1 APP2 APP3 APP4 APP5 APP6 APP7 APP8 APP9 APP10 APP11 APP12
139
- APP13 APP14 APP15 CanonVRD CIFF Ducky EXIF ExifIFD File FlashPix FotoStation
140
- GlobParamIFD GPS ICC_Profile IFD0 IFD1 Insta360 InteropIFD IPTC ItemList JFIF
141
- Jpeg2000 JUMBF Keys MakerNotes Meta MetaIFD Microsoft MIE MPF Nextbase NikonApp
142
- NikonCapture PDF PDF-update PhotoMechanic Photoshop PNG PNG-pHYs PrintIM
143
- QuickTime RMETA RSRC 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 iTunes JFIF Jpeg2000 JUMBF Keys MakerNotes Meta MetaIFD Microsoft
144
+ MIE MPF Nextbase NikonApp NikonCapture PDF PDF-update PhotoMechanic
145
+ Photoshop PNG PNG-pHYs PrintIM QuickTime RMETA RSRC SEAL SubIFD Trailer
146
+ UserData VideoKeys Vivo XML XML-* XMP XMP-*
144
147
  );
145
148
  # family 2 group names that we can delete
146
149
  my @delGroup2 = qw(
@@ -152,6 +155,7 @@ my %delMore = (
152
155
  QuickTime => [ qw(ItemList UserData Keys) ],
153
156
  XMP => [ 'XMP-*' ],
154
157
  XML => [ 'XML-*' ],
158
+ SEAL => [ 'XMP-SEAL' ],
155
159
  );
156
160
 
157
161
  # family 0 groups where directories should never be deleted
@@ -1291,67 +1295,30 @@ sub SetNewValuesFromFile($$;@)
1291
1295
  # ! DON'T FORGET!! Must consider each new !
1292
1296
  # ! option to decide how it is handled here. !
1293
1297
  # +------------------------------------------+
1298
+ foreach (qw(ByteUnit Charset CharsetEXIF CharsetFileName CharsetID3 CharsetIPTC
1299
+ CharsetPhotoshop Composite DateFormat Debug EncodeHangs Escape ExtendedXMP
1300
+ ExtractEmbedded FastScan Filter FixBase Geolocation GeolocAltNames
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))
1308
+ {
1309
+ $srcExifTool->Options($_ => $$options{$_});
1310
+ }
1294
1311
  $srcExifTool->Options(
1295
1312
  Binary => 1,
1296
- ByteUnit => $$options{ByteUnit},
1297
- Charset => $$options{Charset},
1298
- CharsetEXIF => $$options{CharsetEXIF},
1299
- CharsetFileName => $$options{CharsetFileName},
1300
- CharsetID3 => $$options{CharsetID3},
1301
- CharsetIPTC => $$options{CharsetIPTC},
1302
- CharsetPhotoshop=> $$options{CharsetPhotoshop},
1303
- Composite => $$options{Composite},
1304
1313
  CoordFormat => $$options{CoordFormat} || '%d %d %.8f', # copy coordinates at high resolution unless otherwise specified
1305
- DateFormat => $$options{DateFormat},
1306
1314
  Duplicates => 1,
1307
- Escape => $$options{Escape},
1308
1315
  # Exclude (set below)
1309
- ExtendedXMP => $$options{ExtendedXMP},
1310
- ExtractEmbedded => $$options{ExtractEmbedded},
1311
- FastScan => $$options{FastScan},
1312
- Filter => $$options{Filter},
1313
- FixBase => $$options{FixBase},
1314
- Geolocation => $$options{Geolocation},
1315
- GeolocAltNames => $$options{GeolocAltNames},
1316
- GeolocFeature => $$options{GeolocFeature},
1317
- GeolocMinPop => $$options{GeolocMinPop},
1318
- GeolocMaxDist => $$options{GeolocMaxDist},
1319
- GlobalTimeShift => $$options{GlobalTimeShift},
1320
- HexTagIDs => $$options{HexTagIDs},
1321
- IgnoreGroups => $$options{IgnoreGroups},
1322
- IgnoreMinorErrors=>$$options{IgnoreMinorErrors},
1323
- IgnoreTags => $$options{IgnoreTags},
1324
- ImageHashType => $$options{ImageHashType},
1325
- Lang => $$options{Lang},
1326
- LargeFileSupport=> $$options{LargeFileSupport},
1327
1316
  LimitLongValues => 10000000, # (10 MB)
1328
1317
  List => 1,
1329
- ListItem => $$options{ListItem},
1330
- ListSep => $$options{ListSep},
1331
1318
  MakerNotes => $$options{FastScan} && $$options{FastScan} > 1 ? undef : 1,
1332
- MDItemTags => $$options{MDItemTags},
1333
- MissingTagValue => $$options{MissingTagValue},
1334
- NoPDFList => $$options{NoPDFList},
1335
- NoWarning => $$options{NoWarning},
1336
- Password => $$options{Password},
1337
- PrintConv => $$options{PrintConv},
1338
- QuickTimeUTC => $$options{QuickTimeUTC},
1339
- RequestAll => $$options{RequestAll} || 1, # (is this still necessary now that RequestTags are being set?)
1340
- RequestTags => $$options{RequestTags},
1341
- SaveFormat => $$options{SaveFormat},
1342
- SavePath => $$options{SavePath},
1343
- ScanForXMP => $$options{ScanForXMP},
1319
+ RequestAll => $$options{RequestAll} || 1, # (must request all because reqTags doesn't cover wildcards)
1344
1320
  StrictDate => defined $$options{StrictDate} ? $$options{StrictDate} : 1,
1345
1321
  Struct => $structOpt,
1346
- StructFormat => $$options{StructFormat},
1347
- SystemTags => $$options{SystemTags},
1348
- TimeZone => $$options{TimeZone},
1349
- Unknown => $$options{Unknown},
1350
- UserParam => $$options{UserParam},
1351
- Validate => $$options{Validate},
1352
- WindowsWideFile => $$options{WindowsWideFile},
1353
- XAttrTags => $$options{XAttrTags},
1354
- XMPAutoConv => $$options{XMPAutoConv},
1355
1322
  );
1356
1323
  # reset Geolocation option if we aren't copying any geolocation tags
1357
1324
  if ($$options{Geolocation} and not grep /\bGeolocation/i, @setTags) {
@@ -1362,11 +1329,8 @@ sub SetNewValuesFromFile($$;@)
1362
1329
  $$srcExifTool{ALT_EXIFTOOL} = $$self{ALT_EXIFTOOL};
1363
1330
  foreach $tag (@setTags) {
1364
1331
  next if ref $tag;
1365
- if ($tag =~ /^-(.*)/) {
1366
- # avoid extracting tags that are excluded
1367
- push @exclude, $1;
1368
- next;
1369
- }
1332
+ # avoid extracting tags that are excluded
1333
+ $tag =~ /^-(.*)/ and push(@exclude, $1), next;
1370
1334
  # add specified tags to list of requested tags
1371
1335
  $_ = $tag;
1372
1336
  if (/(.+?)\s*(>|<)\s*(.+)/) {
@@ -1787,7 +1751,7 @@ GNV_TagInfo: foreach $tagInfo (@tagInfoList) {
1787
1751
  my $err = &$checkProc($self, $tagInfo, \$val);
1788
1752
  if ($err or not defined $val) {
1789
1753
  $err or $err = 'Error generating raw value';
1790
- $self->WarnOnce("$err for $$tagInfo{Name}");
1754
+ $self->Warn("$err for $$tagInfo{Name}");
1791
1755
  @$vals = ();
1792
1756
  last;
1793
1757
  }
@@ -1807,7 +1771,7 @@ GNV_TagInfo: foreach $tagInfo (@tagInfoList) {
1807
1771
  # an empty warning ("\n") ignores tag with no error
1808
1772
  if ($evalWarning ne "\n") {
1809
1773
  my $err = CleanWarning() . " in $$tagInfo{Name} (RawConvInv)";
1810
- $self->WarnOnce($err);
1774
+ $self->Warn($err);
1811
1775
  }
1812
1776
  @$vals = ();
1813
1777
  last;
@@ -1991,8 +1955,8 @@ sub SetFileModifyDate($$;$$$)
1991
1955
  }
1992
1956
  my ($aTime, $mTime, $cTime);
1993
1957
  if ($tag eq 'FileCreateDate') {
1994
- eval { require Win32::API } or $self->WarnOnce("Install Win32::API to set $tag"), return -1;
1995
- eval { require Win32API::File } or $self->WarnOnce("Install Win32API::File to set $tag"), return -1;
1958
+ eval { require Win32::API } or $self->Warn("Install Win32::API to set $tag"), return -1;
1959
+ eval { require Win32API::File } or $self->Warn("Install Win32API::File to set $tag"), return -1;
1996
1960
  $cTime = $val;
1997
1961
  } else {
1998
1962
  $aTime = $mTime = $val;
@@ -2189,7 +2153,7 @@ sub SetSystemTags($$)
2189
2153
  $self->VerboseValue('+ FilePermissions', $perm);
2190
2154
  $result = 1;
2191
2155
  } else {
2192
- $self->WarnOnce('Error setting FilePermissions');
2156
+ $self->Warn('Error setting FilePermissions');
2193
2157
  $result = -1;
2194
2158
  }
2195
2159
  }
@@ -2203,7 +2167,7 @@ sub SetSystemTags($$)
2203
2167
  $self->VerboseValue('+ FileGroupID', $gid) if $gid >= 0;
2204
2168
  $result = 1;
2205
2169
  } else {
2206
- $self->WarnOnce('Error setting FileGroup/UserID');
2170
+ $self->Warn('Error setting FileGroup/UserID');
2207
2171
  $result = -1 unless $result;
2208
2172
  }
2209
2173
  }
@@ -2219,7 +2183,7 @@ sub SetSystemTags($$)
2219
2183
  $result = $res if $res == 1 or not $result;
2220
2184
  last;
2221
2185
  } elsif ($tag ne 'FileCreateDate') {
2222
- $self->WarnOnce('Can only set MDItem tags on MacOS');
2186
+ $self->Warn('Can only set MDItem tags on MacOS');
2223
2187
  last;
2224
2188
  }
2225
2189
  }
@@ -2232,7 +2196,7 @@ sub SetSystemTags($$)
2232
2196
  } elsif (ref $file) {
2233
2197
  $self->Warn('Writing ZoneIdentifer requires a file name');
2234
2198
  } elsif (defined $self->GetNewValue('ZoneIdentifier', \$zhash)) {
2235
- $self->Warn('ZoneIndentifier may only be delted');
2199
+ $self->Warn('ZoneIndentifier may only be deleted');
2236
2200
  } elsif (not eval { require Win32API::File }) {
2237
2201
  $self->Warn('Install Win32API::File to write ZoneIdentifier');
2238
2202
  } else {
@@ -2376,9 +2340,13 @@ sub WriteInfo($$;$$)
2376
2340
  } elsif (UNIVERSAL::isa($inRef,'File::RandomAccess')) {
2377
2341
  $inRef->Seek(0);
2378
2342
  $raf = $inRef;
2379
- } elsif ($] >= 5.006 and (eval { require Encode; Encode::is_utf8($$inRef) } or $@)) {
2343
+ } elsif ($] >= 5.006 and ($$self{OPTIONS}{EncodeHangs} or
2344
+ eval { require Encode; Encode::is_utf8($$inRef) } or $@))
2345
+ {
2346
+ local $SIG{'__WARN__'} = \&SetWarning;
2380
2347
  # convert image data from UTF-8 to character stream if necessary
2381
- my $buff = $@ ? pack('C*',unpack($] < 5.010000 ? 'U0C*' : 'C0C*',$$inRef)) : Encode::encode('utf8',$$inRef);
2348
+ my $buff = ($$self{OPTIONS}{EncodeHangs} or $@) ? pack('C*', unpack($] < 5.010000 ?
2349
+ 'U0C*' : 'C0C*', $$inRef)) : Encode::encode('utf8', $$inRef);
2382
2350
  if (defined $outfile) {
2383
2351
  $inRef = \$buff;
2384
2352
  } else {
@@ -2856,7 +2824,10 @@ sub GetAllGroups($;$)
2856
2824
 
2857
2825
  my %allGroups;
2858
2826
  # add family 1 groups not in tables
2859
- $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;
2860
2831
  # loop through all tag tables and get all group names
2861
2832
  while (@tableNames) {
2862
2833
  my $table = GetTagTable(pop @tableNames);
@@ -2885,7 +2856,7 @@ sub GetAllGroups($;$)
2885
2856
  }
2886
2857
  }
2887
2858
  delete $allGroups{'*'}; # (not a real group)
2888
- return sort keys %allGroups;
2859
+ return sort { lc $a cmp lc $b } keys %allGroups;
2889
2860
  }
2890
2861
 
2891
2862
  #------------------------------------------------------------------------------
@@ -2903,7 +2874,7 @@ sub GetNewGroups($)
2903
2874
  # Returns: List of group names (sorted alphabetically)
2904
2875
  sub GetDeleteGroups()
2905
2876
  {
2906
- return sort @delGroups, @delGroup2;
2877
+ return sort { lc $a cmp lc $b } @delGroups, @delGroup2;
2907
2878
  }
2908
2879
 
2909
2880
  #------------------------------------------------------------------------------
@@ -2951,10 +2922,15 @@ sub Sanitize($$)
2951
2922
  $$valPt = $$$valPt if ref $$valPt eq 'SCALAR';
2952
2923
  # make sure the Perl UTF-8 flag is OFF for the value if perl 5.6 or greater
2953
2924
  # (otherwise our byte manipulations get corrupted!!)
2954
- if ($] >= 5.006 and (eval { require Encode; Encode::is_utf8($$valPt) } or $@)) {
2925
+ # NOTE: Don't use Encode on Windows becase "require Encode" on Windows hangs if cwd is a long path name!!
2926
+ if ($] >= 5.006 and ($$self{OPTIONS}{EncodeHangs} or
2927
+ eval { require Encode; Encode::is_utf8($$valPt) } or $@))
2928
+ {
2929
+ # (SIG handling was added in 10.39. Not sure why, but I've added this to other similar code for 13.02)
2955
2930
  local $SIG{'__WARN__'} = \&SetWarning;
2956
2931
  # repack by hand if Encode isn't available
2957
- $$valPt = $@ ? pack('C*',unpack($] < 5.010000 ? 'U0C*' : 'C0C*',$$valPt)) : Encode::encode('utf8',$$valPt);
2932
+ $$valPt = ($$self{OPTIONS}{EncodeHangs} or $@) ? pack('C*', unpack($] < 5.010000 ?
2933
+ 'U0C*' : 'C0C*', $$valPt)) : Encode::encode('utf8', $$valPt);
2958
2934
  }
2959
2935
  # un-escape value if necessary
2960
2936
  if ($$self{OPTIONS}{Escape}) {
@@ -3012,7 +2988,7 @@ Conv: for (;;) {
3012
2988
  $err2 = eval $$tagInfo{WriteCheck};
3013
2989
  $@ and warn($@), $err2 = 'Error evaluating WriteCheck';
3014
2990
  }
3015
- unless ($err2) {
2991
+ unless (defined $err2) {
3016
2992
  my $table = $$tagInfo{Table};
3017
2993
  if ($table and $$table{CHECK_PROC} and not $$tagInfo{RawConvInv}) {
3018
2994
  my $checkProc = $$table{CHECK_PROC};
@@ -3295,7 +3271,7 @@ sub InsertTagValues($$;$$$$)
3295
3271
  my @matches = grep /^$tag(\s|$)/i, @$foundTags;
3296
3272
  @matches = $self->GroupMatches($group, \@matches) if defined $group;
3297
3273
  foreach (@matches) {
3298
- my $doc = $$ex{$_} ? $$ex{$_}{G3} || 0 : 0;
3274
+ my $doc = $$ex{$_}{G3} || 0;
3299
3275
  if (defined $$cacheTag[$doc]) {
3300
3276
  next unless $$cacheTag[$doc] =~ / \((\d+)\)$/;
3301
3277
  my $cur = $1;
@@ -3364,7 +3340,8 @@ sub InsertTagValues($$;$$$$)
3364
3340
  } elsif ($tag eq 'self') {
3365
3341
  $val = $et; # ("$self{var}" or "$file1:self{var}" in string)
3366
3342
  } else {
3367
- # get the tag value
3343
+ # get the tag value (note: this direct access allows excluded tags
3344
+ # to be accessed if the case is correct and a group name is not used)
3368
3345
  $val = $et->GetValue($tag, $type);
3369
3346
  unless (defined $val) {
3370
3347
  # check for tag name with different case
@@ -4295,7 +4272,7 @@ sub WriteDirectory($$$;$)
4295
4272
  # allow MakerNotes to be deleted from ExifIFD of CR3 file
4296
4273
  not ($self->IsRawType() == 2 and $parent eq 'ExifIFD'))
4297
4274
  {
4298
- $self->WarnOnce("Can't delete $1 from $$self{FileType}",1);
4275
+ $self->Warn("Can't delete $1 from $$self{FileType}",1);
4299
4276
  undef $grp1;
4300
4277
  } elsif (not $blockExifTypes{$$self{FILE_TYPE}}) {
4301
4278
  # restrict delete logic to prevent entire tiff image from being killed
@@ -5022,7 +4999,7 @@ my $strptimeLib; # strptime library name if available
5022
4999
  sub InverseDateTime($$;$$)
5023
5000
  {
5024
5001
  my ($self, $val, $tzFlag, $dateOnly) = @_;
5025
- my ($rtnVal, $tz);
5002
+ my ($rtnVal, $tz, $fs);
5026
5003
  my $fmt = $$self{OPTIONS}{DateFormat};
5027
5004
  # strip off timezone first if it exists
5028
5005
  if (not $fmt and $val =~ s/([-+])(\d{1,2}):?(\d{2})\s*(DST)?$//i) {
@@ -5048,8 +5025,17 @@ sub InverseDateTime($$;$$)
5048
5025
  $strptimeLib = '';
5049
5026
  }
5050
5027
  }
5051
- # handle factional seconds (%f), but only at the end of the string
5052
- my $fs = ($fmt =~ s/%f$// and $val =~ s/(\.\d+)\s*$//) ? $1 : '';
5028
+ # handle fractional seconds (%f) and time zone (%z)
5029
+ ($fs, $tz) = ('', '');
5030
+ if ($fmt =~ /%(f|:?z)/) {
5031
+ if ($fmt =~ s/(.*[^%])%f/$1/) {
5032
+ $fs = $2 if $val =~ s/(.*)(\.\d+)/$1/; # (take last .### as fractional seconds)
5033
+ }
5034
+ if ($fmt =~ s/(.*[^%])%(:?)z/$1/) {
5035
+ my $colon = $2;
5036
+ $tz = "$2:$3" if $val =~ s/(.*)([-+]\d{2})$colon(\d{2})/$1/;
5037
+ }
5038
+ }
5053
5039
  my ($lib, $wrn, @a);
5054
5040
  TryLib: for ($lib=$strptimeLib; ; $lib='') {
5055
5041
  # handle %s format ourself (not supported in Fedora, see forum15032)
@@ -5094,7 +5080,7 @@ TryLib: for ($lib=$strptimeLib; ; $lib='') {
5094
5080
  $a[$i] = "0$a[$i]"; # pad to 2 digits if necessary
5095
5081
  }
5096
5082
  }
5097
- $val = join(':', @a[5,4,3]) . ' ' . join(':', @a[2,1,0]) . $fs;
5083
+ $val = join(':', @a[5,4,3]) . ' ' . join(':', @a[2,1,0]) . $fs . $tz;
5098
5084
  last;
5099
5085
  }
5100
5086
  }
@@ -5106,7 +5092,9 @@ TryLib: for ($lib=$strptimeLib; ; $lib='') {
5106
5092
  my $ss = $a[4]; # get SS
5107
5093
  push @a, '00' while @a < 5; # add MM, SS if not given
5108
5094
  # get sub-seconds if they exist (must be after SS, and have leading ".")
5109
- my $fs = (@a > 5 and $val =~ /(\.\d+)\s*$/) ? $1 : '';
5095
+ unless ($fmt) {
5096
+ $fs = (@a > 5 and $val =~ /(\.\d+)\s*$/) ? $1 : '';
5097
+ }
5110
5098
  # add/remove timezone if necessary
5111
5099
  if ($tzFlag) {
5112
5100
  if (not $tz) {
@@ -5246,7 +5234,7 @@ sub Set64u(@)
5246
5234
  {
5247
5235
  my $val = $_[0];
5248
5236
  my $hi = int($val / 4294967296);
5249
- my $lo = Set32u($val - $hi * 4294967296);
5237
+ my $lo = Set32u($val - $hi * 4294967296); # NOTE: subject to round-off errors!
5250
5238
  $hi = Set32u($hi);
5251
5239
  $val = GetByteOrder() eq 'MM' ? $hi . $lo : $lo . $hi;
5252
5240
  $_[1] and substr(${$_[1]}, $_[2], length($val)) = $val;
@@ -6120,7 +6108,7 @@ sub WriteJPEG($$)
6120
6108
  my $tbuf = '';
6121
6109
  $raf->Seek(-length($buff), 1); # seek back to just after EOI
6122
6110
  $$trailInfo{OutFile} = \$tbuf; # rewrite the trailer
6123
- $$trailInfo{ScanForAFCP} = 1; # scan if necessary
6111
+ $$trailInfo{ScanForTrailer} = 1;# scan if necessary
6124
6112
  $self->ProcessTrailers($trailInfo) or undef $trailInfo;
6125
6113
  }
6126
6114
  if (not $oldOutfile) {
@@ -6459,7 +6447,7 @@ sub WriteJPEG($$)
6459
6447
  # warn of subsequent XMP blocks specifying a different
6460
6448
  # HasExtendedXMP (have never seen this)
6461
6449
  if ($goodGuid and $goodGuid ne $2) {
6462
- $self->WarnOnce('Multiple XMP segments specifying different extended XMP GUID');
6450
+ $self->Warn('Multiple XMP segments specifying different extended XMP GUID');
6463
6451
  }
6464
6452
  $goodGuid = $2; # GUID for the standard extended XMP
6465
6453
  }
@@ -6607,7 +6595,7 @@ sub WriteJPEG($$)
6607
6595
  undef $$segDataPt;
6608
6596
  next Marker;
6609
6597
  } elsif (defined $chunkNum) {
6610
- $self->WarnOnce('Invalid or extraneous ICC_Profile chunk(s)');
6598
+ $self->Warn('Invalid or extraneous ICC_Profile chunk(s)');
6611
6599
  # fall through to preserve this extra profile...
6612
6600
  }
6613
6601
  } elsif ($$segDataPt =~ /^FPXR\0/) {
@@ -6650,6 +6638,11 @@ sub WriteJPEG($$)
6650
6638
  $segType = 'Ricoh RMETA';
6651
6639
  $$delGroup{RMETA} and $del = 1;
6652
6640
  }
6641
+ } elsif ($marker == 0xe8 or $marker == 0xe9) { # APP8/9 (SEAL)
6642
+ if ($$segDataPt =~ /^SEAL\0/) {
6643
+ $segType = 'SEAL';
6644
+ $$delGroup{SEAL} and $del = 1;
6645
+ }
6653
6646
  } elsif ($marker == 0xeb) { # APP10 (JUMBF)
6654
6647
  if ($$segDataPt =~ /^JP/) {
6655
6648
  $segType = 'JUMBF';
@@ -7000,7 +6993,7 @@ sub SetFileTime($$;$$$$)
7000
6993
  $mtime = $m unless defined $mtime;
7001
6994
  $success = eval { utime($atime, $mtime, $file) } if defined $atime and defined $mtime;
7002
6995
  }
7003
- $self->Warn('Error opening file for update') unless $success;
6996
+ $self->Warn('Error updating file time') unless $success;
7004
6997
  return $success;
7005
6998
  }
7006
6999
  $saveFile = $file;
@@ -7009,14 +7002,14 @@ sub SetFileTime($$;$$$$)
7009
7002
  # on Windows, try to work around incorrect file times when daylight saving time is in effect
7010
7003
  if ($^O eq 'MSWin32') {
7011
7004
  if (not eval { require Win32::API }) {
7012
- $self->WarnOnce('Install Win32::API for proper handling of Windows file times');
7005
+ $self->Warn('Install Win32::API for proper handling of Windows file times');
7013
7006
  } elsif (not eval { require Win32API::File }) {
7014
- $self->WarnOnce('Install Win32API::File for proper handling of Windows file times');
7007
+ $self->Warn('Install Win32API::File for proper handling of Windows file times');
7015
7008
  } else {
7016
7009
  # get Win32 handle, needed for SetFileTime
7017
7010
  my $win32Handle = eval { Win32API::File::GetOsFHandle($file) };
7018
7011
  unless ($win32Handle) {
7019
- $self->Warn('Win32API::File::GetOsFHandle returned invalid handle');
7012
+ $self->Warn('Win32API::File GetOsFHandle returned invalid handle');
7020
7013
  return 0;
7021
7014
  }
7022
7015
  # convert Unix seconds to FILETIME structs
@@ -7034,13 +7027,13 @@ sub SetFileTime($$;$$$$)
7034
7027
  return 0 if defined $k32SetFileTime;
7035
7028
  $k32SetFileTime = Win32::API->new('KERNEL32', 'SetFileTime', 'NPPP', 'I');
7036
7029
  unless ($k32SetFileTime) {
7037
- $self->Warn('Error calling Win32::API::SetFileTime');
7030
+ $self->Warn('Error loading Win32::API SetFileTime');
7038
7031
  $k32SetFileTime = 0;
7039
7032
  return 0;
7040
7033
  }
7041
7034
  }
7042
7035
  unless ($k32SetFileTime->Call($win32Handle, $ctime, $atime, $mtime)) {
7043
- $self->Warn('Win32::API::SetFileTime returned ' . Win32::GetLastError());
7036
+ $self->Warn('Win32::API SetFileTime returned ' . Win32::GetLastError());
7044
7037
  return 0;
7045
7038
  }
7046
7039
  return 1;
@@ -7389,7 +7382,7 @@ used routines.
7389
7382
 
7390
7383
  =head1 AUTHOR
7391
7384
 
7392
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
7385
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
7393
7386
 
7394
7387
  This library is free software; you can redistribute it and/or modify it
7395
7388
  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.
@@ -50,7 +50,7 @@ use Image::ExifTool::Exif;
50
50
  use Image::ExifTool::GPS;
51
51
  require Exporter;
52
52
 
53
- $VERSION = '3.67';
53
+ $VERSION = '3.70';
54
54
  @ISA = qw(Exporter);
55
55
  @EXPORT_OK = qw(EscapeXML UnescapeXML);
56
56
 
@@ -203,9 +203,12 @@ my %xmpNS = (
203
203
  hdr_metadata => 'http://ns.adobe.com/hdr-metadata/1.0/',
204
204
  hdrgm => 'http://ns.adobe.com/hdr-gain-map/1.0/',
205
205
  xmpDSA => 'http://leica-camera.com/digital-shift-assistant/1.0/',
206
+ seal => 'http://ns.seal/2024/1.0/',
206
207
  # Note: Google uses a prefix of 'Container', but this conflicts with the
207
208
  # Device Container namespace, also by Google. So call this one GContainer
208
209
  GContainer=> 'http://ns.google.com/photos/1.0/container/',
210
+ HDRGainMap=> 'http://ns.apple.com/HDRGainMap/1.0/',
211
+ apdi => 'http://ns.apple.com/pixeldatainfo/1.0/',
209
212
  );
210
213
 
211
214
  # build reverse namespace lookup
@@ -933,6 +936,18 @@ my %sRangeMask = (
933
936
  Name => 'xmpDSA',
934
937
  SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::DSA' },
935
938
  },
939
+ HDRGainMap => {
940
+ Name => 'HDRGainMap',
941
+ SubDirectory => { TagTable => 'Image::ExifTool::XMP::HDRGainMap' },
942
+ },
943
+ apdi => {
944
+ Name => 'apdi',
945
+ SubDirectory => { TagTable => 'Image::ExifTool::XMP::apdi' },
946
+ },
947
+ seal => {
948
+ Name => 'seal',
949
+ SubDirectory => { TagTable => 'Image::ExifTool::XMP::seal' },
950
+ },
936
951
  GContainer => {
937
952
  Name => 'GContainer',
938
953
  SubDirectory => { TagTable => 'Image::ExifTool::XMP::GContainer' },
@@ -2834,7 +2849,7 @@ sub FullEscapeXML($)
2834
2849
  $str =~ s/\\/&#92;/sg; # escape backslashes too
2835
2850
  # then use C-escape sequences for invalid characters
2836
2851
  if ($str =~ /[\0-\x1f]/ or Image::ExifTool::IsUTF8(\$str) < 0) {
2837
- $str =~ s/([\0-\x1f\x80-\xff])/sprintf("\\x%.2x",ord $1)/sge;
2852
+ $str =~ s/([\0-\x1f\x7f-\xff])/sprintf("\\x%.2x",ord $1)/sge;
2838
2853
  }
2839
2854
  return $str;
2840
2855
  }
@@ -3615,9 +3630,9 @@ NoLoop:
3615
3630
  }
3616
3631
  if ($$et{XmpValidate} and $fmt and $fmt eq 'boolean' and $val!~/^True|False$/) {
3617
3632
  if ($val =~ /^true|false$/) {
3618
- $et->WarnOnce("Boolean value for XMP-$ns:$$tagInfo{Name} should be capitalized",1);
3633
+ $et->Warn("Boolean value for XMP-$ns:$$tagInfo{Name} should be capitalized",1);
3619
3634
  } else {
3620
- $et->WarnOnce(qq(Boolean value for XMP-$ns:$$tagInfo{Name} should be "True" or "False"),1);
3635
+ $et->Warn(qq(Boolean value for XMP-$ns:$$tagInfo{Name} should be "True" or "False"),1);
3621
3636
  }
3622
3637
  }
3623
3638
  # protect against large binary data in unknown tags
@@ -3626,7 +3641,7 @@ NoLoop:
3626
3641
  # store the value for this tag
3627
3642
  my $key = $et->FoundTag($tagInfo, $val) or return 0;
3628
3643
  # save original components of rational numbers (used when copying)
3629
- $$et{RATIONAL}{$key} = $rational if defined $rational;
3644
+ $$et{TAG_EXTRA}{$key}{Rational} = $rational if defined $rational;
3630
3645
  # save structure/list information if necessary
3631
3646
  if (@structProps and (@structProps > 1 or defined $structProps[0][1]) and
3632
3647
  not $$et{NO_STRUCT})
@@ -3808,7 +3823,7 @@ sub ParseXMPElement($$$;$$$$)
3808
3823
  $stdNS = $uri2ns{$try};
3809
3824
  if ($stdNS) {
3810
3825
  $val = $try;
3811
- $et->WarnOnce("Fixed incorrect URI for xmlns:$ns", 1);
3826
+ $et->Warn("Fixed incorrect URI for xmlns:$ns", 1);
3812
3827
  } elsif ($val =~ m(^http://ns.nikon.com/BASIC_PARAM)) {
3813
3828
  $et->OverrideFileType('NXD','application/x-nikon-nxd');
3814
3829
  } else {
@@ -3889,9 +3904,9 @@ sub ParseXMPElement($$$;$$$$)
3889
3904
  if ($nItems == 1000) {
3890
3905
  my ($tg,$ns) = GetXMPTagID($propList);
3891
3906
  if ($isWriting) {
3892
- $et->WarnOnce("Excessive number of items for $ns:$tg. Processing may be slow", 1);
3907
+ $et->Warn("Excessive number of items for $ns:$tg. Processing may be slow", 1);
3893
3908
  } elsif (not $$et{OPTIONS}{IgnoreMinorErrors}) {
3894
- $et->WarnOnce("Extracted only 1000 $ns:$tg items. Ignore minor errors to extract all", 2);
3909
+ $et->Warn("Extracted only 1000 $ns:$tg items. Ignore minor errors to extract all", 2);
3895
3910
  last;
3896
3911
  }
3897
3912
  }
@@ -3991,12 +4006,12 @@ sub ParseXMPElement($$$;$$$$)
3991
4006
  } elsif ($$et{XmpAbout} ne $attrs{$shortName}) {
3992
4007
  if ($isWriting) {
3993
4008
  my $str = "Different 'rdf:about' attributes not handled";
3994
- unless ($$et{WARNED_ONCE}{$str}) {
4009
+ unless ($$et{WAS_WARNED}{$str}) {
3995
4010
  $et->Error($str, 1);
3996
- $$et{WARNED_ONCE}{$str} = 1;
4011
+ $$et{WAS_WARNED}{$str} = 1;
3997
4012
  }
3998
4013
  } elsif ($$et{XmpValidate}) {
3999
- $et->WarnOnce("Different 'rdf:about' attributes");
4014
+ $et->Warn("Different 'rdf:about' attributes");
4000
4015
  }
4001
4016
  }
4002
4017
  }
@@ -4142,7 +4157,7 @@ sub ParseXMPElement($$$;$$$$)
4142
4157
 
4143
4158
  #------------------------------------------------------------------------------
4144
4159
  # Process XMP data
4145
- # Inputs: 0) ExifTool object reference, 1) DirInfo reference, 2) Pointer to tag table
4160
+ # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
4146
4161
  # Returns: 1 on success
4147
4162
  # Notes: The following flavours of XMP files are currently recognized:
4148
4163
  # - standard XMP with xpacket, x:xmpmeta and rdf:RDF elements
@@ -4567,7 +4582,7 @@ information.
4567
4582
 
4568
4583
  =head1 AUTHOR
4569
4584
 
4570
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
4585
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
4571
4586
 
4572
4587
  This library is free software; you can redistribute it and/or modify it
4573
4588
  under the same terms as Perl itself.