exiftool-vendored.pl 13.0.1 → 13.17.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 +269 -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 +46 -26
  26. package/bin/lib/Image/ExifTool/CBOR.pm +5 -2
  27. package/bin/lib/Image/ExifTool/Canon.pm +68 -28
  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 +38 -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 +457 -103
  127. package/bin/lib/Image/ExifTool/NikonCapture.pm +1 -1
  128. package/bin/lib/Image/ExifTool/NikonCustom.pm +6 -6
  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 +327 -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 +6 -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 +6 -5
  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 +7028 -6968
  183. package/bin/lib/Image/ExifTool/TagNames.pod +12079 -11630
  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/Trailer.pm +318 -0
  188. package/bin/lib/Image/ExifTool/Unknown.pm +1 -1
  189. package/bin/lib/Image/ExifTool/VCard.pm +3 -3
  190. package/bin/lib/Image/ExifTool/Validate.pm +6 -6
  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 +170 -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 +106 -3
  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 +467 -228
  213. package/bin/lib/Image/ExifTool.pod +118 -72
  214. package/bin/perl-Image-ExifTool.spec +1 -1
  215. package/bin/windows_exiftool.txt +96 -51
  216. package/package.json +6 -6
@@ -12,7 +12,7 @@ use strict;
12
12
  use vars qw($VERSION);
13
13
  use Image::ExifTool::Exif;
14
14
 
15
- $VERSION = '1.56';
15
+ $VERSION = '1.57';
16
16
 
17
17
  my %coordConv = (
18
18
  ValueConv => 'Image::ExifTool::GPS::ToDegrees($val)',
@@ -20,6 +20,34 @@ my %coordConv = (
20
20
  PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1)',
21
21
  );
22
22
 
23
+ my %printConvLatRef = (
24
+ # extract N/S if written from Composite:GPSLatitude
25
+ # (also allow writing from a signed number)
26
+ OTHER => sub {
27
+ my ($val, $inv) = @_;
28
+ return undef unless $inv;
29
+ return uc $2 if $val =~ /(^|[^A-Z])([NS])(orth|outh)?\b/i;
30
+ return $1 eq '-' ? 'S' : 'N' if $val =~ /([-+]?)\d+/;
31
+ return undef;
32
+ },
33
+ N => 'North',
34
+ S => 'South',
35
+ );
36
+
37
+ my %printConvLonRef = (
38
+ # extract E/W if written from Composite:GPSLongitude
39
+ # (also allow writing from a signed number)
40
+ OTHER => sub {
41
+ my ($val, $inv) = @_;
42
+ return undef unless $inv;
43
+ return uc $2 if $val =~ /(^|[^A-Z])([EW])(ast|est)?\b/i;
44
+ return $1 eq '-' ? 'W' : 'E' if $val =~ /([-+]?)\d+/;
45
+ return undef;
46
+ },
47
+ E => 'East',
48
+ W => 'West',
49
+ );
50
+
23
51
  %Image::ExifTool::GPS::Main = (
24
52
  GROUPS => { 0 => 'EXIF', 1 => 'GPS', 2 => 'Location' },
25
53
  WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
@@ -43,19 +71,7 @@ my %coordConv = (
43
71
  latitudes or negative for south, or a string containing N, North, S or South
44
72
  },
45
73
  Count => 2,
46
- PrintConv => {
47
- # extract N/S if written from Composite:GPSLatitude
48
- # (also allow writing from a signed number)
49
- OTHER => sub {
50
- my ($val, $inv) = @_;
51
- return undef unless $inv;
52
- return uc $2 if $val =~ /(^|[^A-Z])([NS])(orth|outh)?\b/i;
53
- return $1 eq '-' ? 'S' : 'N' if $val =~ /([-+]?)\d+/;
54
- return undef;
55
- },
56
- N => 'North',
57
- S => 'South',
58
- },
74
+ PrintConv => \%printConvLatRef,
59
75
  },
60
76
  0x0002 => {
61
77
  Name => 'GPSLatitude',
@@ -72,19 +88,7 @@ my %coordConv = (
72
88
  ExifTool will also accept a number when writing this tag, positive for east
73
89
  longitudes or negative for west, or a string containing E, East, W or West
74
90
  },
75
- PrintConv => {
76
- # extract E/W if written from Composite:GPSLongitude
77
- # (also allow writing from a signed number)
78
- OTHER => sub {
79
- my ($val, $inv) = @_;
80
- return undef unless $inv;
81
- return uc $2 if $val =~ /(^|[^A-Z])([EW])(ast|est)?\b/i;
82
- return $1 eq '-' ? 'W' : 'E' if $val =~ /([-+]?)\d+/;
83
- return undef;
84
- },
85
- E => 'East',
86
- W => 'West',
87
- },
91
+ PrintConv => \%printConvLonRef,
88
92
  },
89
93
  0x0004 => {
90
94
  Name => 'GPSLongitude',
@@ -238,7 +242,7 @@ my %coordConv = (
238
242
  Writable => 'string',
239
243
  Notes => 'tags 0x0013-0x001a used for subject location according to MWG 2.0',
240
244
  Count => 2,
241
- PrintConv => { N => 'North', S => 'South' },
245
+ PrintConv => \%printConvLatRef,
242
246
  },
243
247
  0x0014 => {
244
248
  Name => 'GPSDestLatitude',
@@ -251,7 +255,7 @@ my %coordConv = (
251
255
  Name => 'GPSDestLongitudeRef',
252
256
  Writable => 'string',
253
257
  Count => 2,
254
- PrintConv => { E => 'East', W => 'West' },
258
+ PrintConv => \%printConvLonRef,
255
259
  },
256
260
  0x0016 => {
257
261
  Name => 'GPSDestLongitude',
@@ -615,7 +619,7 @@ GPS (Global Positioning System) meta information in EXIF data.
615
619
 
616
620
  =head1 AUTHOR
617
621
 
618
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
622
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
619
623
 
620
624
  This library is free software; you can redistribute it and/or modify it
621
625
  under the same terms as Perl itself.
@@ -2242,7 +2242,7 @@ coordinates.
2242
2242
 
2243
2243
  =head1 AUTHOR
2244
2244
 
2245
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
2245
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
2246
2246
 
2247
2247
  This library is free software; you can redistribute it and/or modify it
2248
2248
  under the same terms as Perl itself.
@@ -18,7 +18,8 @@
18
18
  # specifying $Image::ExifTool::Geolocation::altDir. This
19
19
  # database and has entries in the same order as Geolocation.dat,
20
20
  # and each entry is a newline-separated list of alternate names
21
- # terminated by a null byte.
21
+ # terminated by a null byte. These alternate names are used
22
+ # only when searching for a city by name (eg. "Big Apple").
22
23
  #
23
24
  # Databases are based on data from geonames.org with a
24
25
  # Creative Commons license, reformatted as follows in the
@@ -70,7 +71,7 @@ package Image::ExifTool::Geolocation;
70
71
  use strict;
71
72
  use vars qw($VERSION $geoDir $altDir $dbInfo);
72
73
 
73
- $VERSION = '1.08'; # (this is the module version number, not the database version)
74
+ $VERSION = '1.09'; # (this is the module version number, not the database version)
74
75
 
75
76
  my $debug; # set to output processing time for testing
76
77
 
@@ -462,7 +463,7 @@ sub GetAltNames($;$)
462
463
  sub Geolocate($;$)
463
464
  {
464
465
  my ($arg, $opts) = @_;
465
- my ($city, @exact, %regex, @multiCity, $other, $idx, @cargs, $useLastFound);
466
+ my ($city, @exact, %regex, @multiCity, $other, $idx, @cargs);
466
467
  my ($minPop, $minDistU, $minDistC, @matchParms, @coords, %fcOK, $both);
467
468
  my ($pop, $maxDist, $multi, $fcodes, $altNames, @startTime);
468
469
 
@@ -593,8 +594,16 @@ Entry: for (; $i<@cityList; ++$i) {
593
594
  }
594
595
  @startTime and printf("= Processing time: %.3f sec\n", Time::HiRes::tv_interval(\@startTime));
595
596
  if (%lastFound) {
596
- @coords == 2 and $useLastFound = 1, last; # continue to use coords with last city matches
597
+ last if @coords == 2; # continue to use coords with last city matches
597
598
  scalar(keys %lastFound) > 200 and warn("Too many matching cities\n"), return();
599
+ # return nearby cities if "num=" is used and only one match found
600
+ if ($num > 1 and scalar(keys %lastFound) == 1) {
601
+ my ($i) = keys %lastFound;
602
+ my @entry = GetEntry($i);
603
+ @coords = @entry[8,9];
604
+ SortDatabase('Latitude'); # (make sure we are sorted by latitude)
605
+ last;
606
+ }
598
607
  unless (@lastByPop) {
599
608
  @lastByPop = sort { $lastFound{$b} cmp $lastFound{$a} or $cityList[$a] cmp $cityList[$b] } keys %lastFound;
600
609
  }
@@ -776,7 +785,7 @@ on the first call.
776
785
 
777
786
  Sort database in specified order.
778
787
 
779
- Image::ExifTool::Geolocation::ReadDatabase('City');
788
+ Image::ExifTool::Geolocation::SortDatabase('City');
780
789
 
781
790
  =over 4
782
791
 
@@ -923,9 +932,10 @@ to the argument list:
923
932
  both to determine the closest city matching the specified
924
933
  name(s) instead of using GPS only.
925
934
 
926
- 'num=##' - When the search includes GPS coordinates, return the nearest
927
- ## cities instead of just the closest one. Returned cities
928
- are in the order from nearest to farthest.
935
+ 'num=##' - When the search includes GPS coordinates, or when a single
936
+ city is matched by name, return the nearest ## cities instead
937
+ of just the closest or named one. Returned cities are in the
938
+ order from nearest to farthest.
929
939
 
930
940
  See L<https://exiftool.org/geolocation.html#Read> for more details.
931
941
 
@@ -1005,7 +1015,7 @@ the input arguments of the AddEntry method.
1005
1015
 
1006
1016
  =head1 AUTHOR
1007
1017
 
1008
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
1018
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
1009
1019
 
1010
1020
  This library is free software; you can redistribute it and/or modify it
1011
1021
  under the same terms as Perl itself. The associated database files are
@@ -17,6 +17,7 @@
17
17
  # 2022/06/21 - PH Added ability to read Google Takeout JSON files
18
18
  # 2024/04/23 - PH Added ability to read more OpenTracks GPS tags
19
19
  # 2024/08/28 - PH Added support for new Google Takeout JSON format
20
+ # 2024/11/26 - PH Also write GPSMeasureMode and GPSDOP
20
21
  #
21
22
  # References: 1) http://www.topografix.com/GPX/1/1/
22
23
  # 2) http://www.gpsinformation.org/dale/nmea.htm#GSA
@@ -31,7 +32,7 @@ use vars qw($VERSION);
31
32
  use Image::ExifTool qw(:Public);
32
33
  use Image::ExifTool::GPS;
33
34
 
34
- $VERSION = '1.79';
35
+ $VERSION = '1.81';
35
36
 
36
37
  sub JITTER() { return 2 } # maximum time jitter
37
38
 
@@ -90,12 +91,25 @@ my %fixInfoKeys = (
90
91
  orient => [ 'dir', 'pitch', 'roll' ],
91
92
  atemp => [ 'atemp' ],
92
93
  err => [ 'err' ],
94
+ dop => [ 'hdop', 'vdop', 'pdop' ],
93
95
  );
94
96
 
95
- my %isOrient = ( dir => 1, pitch => 1, roll => 1 ); # test for orientation key
97
+ # category for select keys
98
+ my %keyCategory = (
99
+ dir => 'orient',
100
+ pitch => 'orient',
101
+ roll => 'orient',
102
+ hdop => 'dop',
103
+ pdop => 'dop',
104
+ vdop => 'dop',
105
+ );
96
106
 
97
107
  # tags which may exist separately in some formats (eg. CSV)
98
- my %sepTags = ( dir => 1, pitch => 1, roll => 1, track => 1, speed => 1 );
108
+ my %sepTags = (
109
+ dir => 1, pitch => 1, roll => 1, track => 1, speed => 1,
110
+ # (plus other tags we don't want to scan outwards for)
111
+ hdop => 1, pdop => 1, vdop => 1,
112
+ );
99
113
 
100
114
  # conversion factors for GPSSpeed (standard EXIF units only)
101
115
  my %speedConv = (
@@ -348,8 +362,8 @@ sub LoadTrackLog($$;$)
348
362
  my $tag = $xmlTag{lc $2};
349
363
  if ($tag) {
350
364
  $$fix{$tag} = $4;
351
- if ($isOrient{$tag}) {
352
- $$has{orient} = 1;
365
+ if ($keyCategory{$tag}) {
366
+ $$has{$keyCategory{$tag}} = 1;
353
367
  } elsif ($tag eq 'alt') {
354
368
  # validate altitude
355
369
  undef $$fix{alt} if defined $$fix{alt} and $$fix{alt} !~ /^[+-]?\d+\.?\d*/;
@@ -394,8 +408,8 @@ sub LoadTrackLog($$;$)
394
408
  } else {
395
409
  $$fix{$tag} = $1;
396
410
  }
397
- if ($isOrient{$tag}) {
398
- $$has{orient} = 1;
411
+ if ($keyCategory{$tag}) {
412
+ $$has{$keyCategory{$tag}} = 1;
399
413
  } elsif ($tag eq 'alt') {
400
414
  # validate altitude
401
415
  undef $$fix{alt} if defined $$fix{alt} and $$fix{alt} !~ /^[+-]?\d+\.?\d*/;
@@ -562,8 +576,8 @@ DoneFix: $isDate = 1;
562
576
  next;
563
577
  } elsif ($format eq 'JSON') {
564
578
  # Google Takeout JSON format
565
- if (/"(latitudeE7|longitudeE7|latE7|lngE7|timestamp|startTime|point|durationMinutesOffsetFromStartTime)"\s*:\s*"?(.*?)"?,?\s*[\x0d\x0a]/) {
566
- if ($1 eq 'timestamp') {
579
+ if (/"(latitudeE7|longitudeE7|latE7|lngE7|timestamp|startTime|point|durationMinutesOffsetFromStartTime|time)"\s*:\s*"?(.*?)"?,?\s*[\x0d\x0a]/) {
580
+ if ($1 eq 'timestamp' or $1 eq 'time') {
567
581
  $time = GetTime($2);
568
582
  goto DoneFix if $time and $$fix{lat} and $$fix{lon};
569
583
  } elsif ($1 eq 'startTime') { # (new format)
@@ -1145,7 +1159,7 @@ sub SetGeoValues($$;$)
1145
1159
  # loop through available fix information categories
1146
1160
  # (pos, track, alt, orient)
1147
1161
  my ($category, $key);
1148
- Category: foreach $category (qw{pos track alt orient atemp err}) {
1162
+ Category: foreach $category (qw{pos track alt orient atemp err dop}) {
1149
1163
  next unless $$has{$category};
1150
1164
  my ($f, $p0b, $p1b, $f0b);
1151
1165
  # loop through specific fix information keys
@@ -1303,6 +1317,25 @@ Category: foreach $category (qw{pos track alt orient atemp err}) {
1303
1317
  if ($$has{err}) {
1304
1318
  @r = $et->SetNewValue(GPSHPositioningError => $$fix{err}, %opts);
1305
1319
  }
1320
+ if ($$has{dop}) {
1321
+ my ($dop, $mm);
1322
+ if (defined $$fix{pdop}) {
1323
+ $dop = $$fix{pdop};
1324
+ $mm = 3;
1325
+ } elsif (defined $$fix{hdop}) {
1326
+ if (defined $$fix{vdop}) {
1327
+ $dop = sqrt($$fix{hdop} * $$fix{hdop} + $$fix{vdop} * $$fix{vdop});
1328
+ $mm = 3;
1329
+ } else {
1330
+ $dop = $$fix{hdop};
1331
+ $mm = 2;
1332
+ }
1333
+ }
1334
+ if (defined $dop) {
1335
+ $et->SetNewValue(GPSMeasureMode => $mm, %opts);
1336
+ $et->SetNewValue(GPSDOP => $dop, %opts);
1337
+ }
1338
+ }
1306
1339
  unless ($xmp) {
1307
1340
  my ($latRef, $lonRef);
1308
1341
  $latRef = ($$fix{lat} > 0 ? 'N' : 'S') if defined $$fix{lat};
@@ -1328,7 +1361,8 @@ Category: foreach $category (qw{pos track alt orient atemp err}) {
1328
1361
  GPSAltitude GPSAltitudeRef GPSDateStamp GPSTimeStamp GPSDateTime
1329
1362
  GPSTrack GPSTrackRef GPSSpeed GPSSpeedRef GPSImgDirection
1330
1363
  GPSImgDirectionRef GPSPitch GPSRoll CameraElevationAngle
1331
- AmbientTemperature GPSHPositioningError GPSCoordinates))
1364
+ AmbientTemperature GPSHPositioningError GPSCoordinates
1365
+ GPSMeasureMode GPSDOP))
1332
1366
  {
1333
1367
  my @r = $et->SetNewValue($_, undef, %opts);
1334
1368
  }
@@ -1527,7 +1561,7 @@ user-defined tag GPSRoll, must be active.
1527
1561
 
1528
1562
  =head1 AUTHOR
1529
1563
 
1530
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
1564
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
1531
1565
 
1532
1566
  This library is free software; you can redistribute it and/or modify it
1533
1567
  under the same terms as Perl itself.
@@ -16,7 +16,7 @@ use vars qw($VERSION);
16
16
  use Image::ExifTool qw(:DataAccess :Utils);
17
17
  use Image::ExifTool::QuickTime;
18
18
 
19
- $VERSION = '1.08';
19
+ $VERSION = '1.11';
20
20
 
21
21
  sub ProcessGoPro($$$);
22
22
  sub ProcessString($$$);
@@ -72,6 +72,7 @@ my %addUnits = (
72
72
  let me know if you discover the meaning of any of these unknown tags. See
73
73
  L<https://github.com/gopro/gpmf-parser> for details about this format.
74
74
  },
75
+ # ABSC (GPMF) - seen: 0 (fmt f)
75
76
  ACCL => { #2 (gpmd)
76
77
  Name => 'Accelerometer',
77
78
  Notes => 'accelerator readings in m/s2',
@@ -81,7 +82,9 @@ my %addUnits = (
81
82
  # ANGY (GPMF-GEOC) - seen 179.9 (fmt d, Max)
82
83
  # ANGZ (GPMF-GEOC) - seen 0.152 (fmt d, Max)
83
84
  ALLD => 'AutoLowLightDuration', #1 (gpmd) (untested)
84
- # APTO (GPMF) - seen: 'RAW', 'DYNM' (fmt c)
85
+ # APTO (GPMF) - seen: 'OFF', 'RAW', 'DYNM' (fmt c)
86
+ # ARUW (GPMF) - seen: 1.14285719394684 (fmt f)
87
+ # ARWA (GPMF) - seen: 1.14285719394684 (fmt f)
85
88
  ATTD => { #PH (Karma)
86
89
  Name => 'Attitude',
87
90
  # UNIT=s,rad,rad,rad,rad/s,rad/s,rad/s,
@@ -96,8 +99,10 @@ my %addUnits = (
96
99
  # SCAL=1000 1 1 1 1
97
100
  Binary => 1,
98
101
  },
102
+ # AUBT (GPMF) - seen: ''N' (type c)
99
103
  AUDO => 'AudioSetting', #PH (GPMF - seen: 'WIND', fmt c)
100
104
  # AUPT (GPMF) - seen: 'N','Y' (fmt c)
105
+ # BITR (GPMF) - seen: 'STANDARD' (fmt c)
101
106
  BPOS => { #PH (Karma)
102
107
  Name => 'Controller',
103
108
  Unknown => 1,
@@ -111,9 +116,16 @@ my %addUnits = (
111
116
  # CALH (GPMF-GEOC) - seen 3040 (fmt L, Max)
112
117
  # CALW (GPMF-GEOC) - seen 4056 (fmt L, Max)
113
118
  CASN => 'CameraSerialNumber', #PH (GPMF - seen: 'C3221324545448', fmt c)
119
+ # CDAT (GPMF) - seen: 1732152823 (fmt J)
120
+ # CDTM (GPMF) - seen: 0 (fmt L)
114
121
  # CINF (GPMF) - seen: 0x67376be7709bc8876a8baf3940908618, 0xe230988539b30cf5f016627ae8fc5395,
115
122
  # 0x8bcbe424acc5b37d7d77001635198b3b (fmt B) (Camera INFormation?)
123
+ # CLDP (GPMF) - seen: 'Y' (fmt c)
124
+ # CLKC (GPMF) - seen: 0 (fmt L)
125
+ # CLKS (GPMF) - seen: 2 (fmt B)
116
126
  # CMOD (GPMF) - seen: 12,13,17 [12 360 video, 13 time-laps video, 17 JPEG] (fmt B)
127
+ # CPID (GPMF) - seen: '1194885996 3387225026 733916448 2433577768' (fmt L)
128
+ # CPIN (GPMF) - seen: 1
117
129
  # CRTX (GPMF-BACK/FRNT) - double[1]
118
130
  # CRTY (GPMF-BACK/FRNT) - double[1]
119
131
  CSEN => { #PH (Karma)
@@ -123,6 +135,7 @@ my %addUnits = (
123
135
  # SCAL=1000 1 1 1 1 1 1 1 1 1 1
124
136
  Binary => 1,
125
137
  },
138
+ # CTRL (GPMF) - seen: 'Pro' (fmt c)
126
139
  CYTS => { #PH (Karma)
127
140
  Name => 'CoyoteStatus',
128
141
  # UNIT=s,,,,,rad,rad,rad,,
@@ -141,6 +154,8 @@ my %addUnits = (
141
154
  # (Max) DVID='FRNT',DVNM='Front Lens',KLNS,CTRX,CTRY,MFOV,SFTR
142
155
  # (Max) DVID='HLMT',DVNM='Highlights'
143
156
  },
157
+ # DNSC (GPMF) - seen: 'HIGH' (fmt c)
158
+ # DUST (GPMF) - seen: 'NO_LIMIT' (fmt c)
144
159
  # DVID (GPMF) - DeviceID; seen: 1 (fmt L), HLMT (fmt F), GEOC (fmt F), 'BACK' (fmt F, Max)
145
160
  DVID => { Name => 'DeviceID', Unknown => 1 }, #2 (gpmd)
146
161
  # DVNM (GPMF) seen: 'Video Global Settings' (fmt c), 'Highlights' (fmt c), 'Geometry Calibrations' (Max)
@@ -150,6 +165,7 @@ my %addUnits = (
150
165
  Name => 'DigitalZoom',
151
166
  PrintConv => { N => 'No', Y => 'Yes' },
152
167
  },
168
+ # DZMX (GPMF) - seen: 1.39999997615814 (fmt f)
153
169
  # DZST (GPMF) - seen: 0 (fmt L) (something to do with digital zoom maybe?)
154
170
  EISA => { #PH (GPMF) - seen: 'Y','N','HS EIS','N/A' (fmt c) [N was for a time-lapse video]
155
171
  Name => 'ElectronicImageStabilization',
@@ -188,10 +204,20 @@ my %addUnits = (
188
204
  },
189
205
  GPS5 => { #2 (gpmd)
190
206
  Name => 'GPSInfo',
207
+ # UNIT=deg,deg,m,m/s,m/s
208
+ # TYPE=l
191
209
  # SCAL=10000000,10000000,1000,1000,100
192
210
  RawConv => '$val', # necessary to use scaled value instead of raw data as subdir data
193
211
  SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPS5' },
194
212
  },
213
+ GPS9 => { #PH (gpmd, Hero 13)
214
+ Name => 'GPSInfo9',
215
+ # UNIT=deg,deg,m,m/s,m/s,,s,,
216
+ # TYPE=lllllllSS
217
+ # SCAL=10000000 10000000 1000 1000 100 1 1000 100 1
218
+ RawConv => '$val', # necessary to use scaled value instead of raw data as subdir data
219
+ SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPS9' },
220
+ },
195
221
  GPSF => { #2 (gpmd)
196
222
  Name => 'GPSMeasureMode',
197
223
  PrintConv => {
@@ -216,7 +242,10 @@ my %addUnits = (
216
242
  Notes => 'gyroscope readings in rad/s',
217
243
  Binary => 1,
218
244
  },
245
+ # HCTL (GPMF) - seen: "Off" (fmt c)
246
+ # HDRV (GPMF) - seen: "N" (fmt c)
219
247
  # HFLG (APP6) - seen: 0
248
+ # HSGT (GPMF) - seen: 'OFF' (fmt c)
220
249
  ISOE => 'ISOSpeeds', #PH (gpmd)
221
250
  ISOG => { #2 (gpmd)
222
251
  Name => 'ImageSensorGain',
@@ -232,6 +261,7 @@ my %addUnits = (
232
261
  },
233
262
  # KLNS (GPMF-BACK/FRNT) - double[5] (fmt d, Max)
234
263
  # LINF (GPMF) - seen: LAJ7061916601668,C3341326002180,C33632245450981 (fmt c) (Lens INFormation?)
264
+ # LMOD (GPMF) - seen: 'NONE' (fmt F)
235
265
  LNED => { #PH (Karma)
236
266
  Name => 'LocalPositionNED',
237
267
  # UNIT=s,m,m,m,m/s,m/s,m/s
@@ -240,14 +270,20 @@ my %addUnits = (
240
270
  Binary => 1,
241
271
  },
242
272
  MAGN => 'Magnetometer', #1 (gpmd) (units of uT)
273
+ # MAPX (GPMF) - seen: 1 (fmt f)
274
+ # MAPY (GPMF) - seen: 1 (fmt f)
243
275
  # MFOV (GPMF-BACK/FRNT) - seen: 100 (fmt d, Max)
244
276
  MINF => { #PH (GPMF - seen: HERO6 Black, fmt c)
245
277
  Name => 'Model',
246
278
  Groups => { 2 => 'Camera' },
247
279
  Description => 'Camera Model Name',
248
280
  },
281
+ # MMOD (GPMF) - seen: 'STEREO' (fmt c)
249
282
  # MTYP (GPMF) - seen: 0,1,5,11 [1 for time-lapse video, 5 for 360 video, 11 for JPEG] (fmt B)
250
283
  # MUID (GPMF) - seen: 3882563431 2278071152 967805802 411471936 0 0 0 0 (fmt L)
284
+ # MXCF (GPMF) - seen: 'x1' (fmt c)
285
+ # MYCF (GPMF) - seen: 'y1' (fmt c)
286
+ # ORDP (GPMF) - seen: 'Y' (fmt c)
251
287
  OREN => { #PH (GPMF - seen: 'U', fmt c)
252
288
  Name => 'AutoRotation',
253
289
  PrintConv => {
@@ -258,11 +294,16 @@ my %addUnits = (
258
294
  },
259
295
  # (most of the "P" tags are ProTune settings - PH)
260
296
  PHDR => 'HDRSetting', #PH (APP6 - seen: 0)
297
+ # PIMD (GPMF) - seen: 'AUTO' (fmt c)
261
298
  PIMN => 'AutoISOMin', #PH (GPMF - seen: 100, fmt L)
262
299
  PIMX => 'AutoISOMax', #PH (GPMF - seen: 1600, fmt L)
300
+ # POLY (GPMF) - seen: '0 2.11120247840881 0.14325800538063 -1.030...' (fmt f)
263
301
  # PRAW (APP6) - seen: 0, 'N', 'Y' (fmt c)
302
+ # PRCN (GPMF) - seen: 65 zeros (fmt B)
264
303
  PRES => 'PhotoResolution', #PH (APP6 - seen: '12MP_W')
265
304
  # PRJT (APP6) - seen: 'GPRO','EACO' (fmt F, Hero8, Max)
305
+ # PRNA (GPMF) - seen 10 (fmt B)
306
+ # PRNU (GPMF) - seen 0 (fmt B)
266
307
  PRTN => { #PH (GPMF - seen: 'N', fmt c)
267
308
  Name => 'ProTune',
268
309
  PrintConv => {
@@ -275,6 +316,9 @@ my %addUnits = (
275
316
  PTSH => 'Sharpness', #PH (GPMF - seen: 'HIGH', fmt c)
276
317
  PTWB => 'WhiteBalance', #PH (GPMF - seen: 'AUTO', fmt c)
277
318
  # PVUL (APP6) - seen: 'F' (fmt c, Hero8, Max)
319
+ # PWPR (GPMF) - seen: 'PERFORMANCE' (fmt c)
320
+ # PYCF (GPMF) - seen: '[r0,r1,r2,r3,r4,r5,r6]' (fmt c)
321
+ # RAMP (GPMF) - seen: empty string (fmt c)
278
322
  RATE => 'Rate', #PH (GPMF - seen: '0_5SEC', fmt c; APP6 - seen: '4_1SEC')
279
323
  RMRK => { #2 (gpmd)
280
324
  Name => 'Comments',
@@ -284,6 +328,7 @@ my %addUnits = (
284
328
  Name => 'ScaleFactor',
285
329
  Unknown => 1,
286
330
  },
331
+ # SCAP (GPMF) - seen: 'N' (fmt c)
287
332
  SCPR => { #PH (Karma) [stream was empty]
288
333
  Name => 'ScaledPressure',
289
334
  # UNIT=s,Pa,Pa,degC
@@ -291,6 +336,7 @@ my %addUnits = (
291
336
  # SCAL=1000 0.00999999977648258 0.00999999977648258 100
292
337
  %addUnits,
293
338
  },
339
+ # SCTM (GPMF) - seen 0 (fmt L)
294
340
  # SFTR (GPMF-BACK/FRNT) - seen 0.999,1.00004 (fmt d, Max)
295
341
  # SHFX (GPMF-GEOC) - seen 22.92 (fmt d, Max)
296
342
  # SHFY (GPMF-GEOC) - seen 0.123 (fmt d, Max)
@@ -355,6 +401,10 @@ my %addUnits = (
355
401
  # TOCK => { Name => 'OutTime', Unknown => 1, ValueConv => '$val/1000' }, #1 (gpmd)
356
402
  TSMP => { Name => 'TotalSamples', Unknown => 1 }, #2 (gpmd)
357
403
  TYPE => { Name => 'StructureType', Unknown => 1 }, #2 (gpmd,GPMF - eg 'LLLllfFff', fmt c)
404
+ TZON => { # (GPMF) - seen: 60 (fmt s)
405
+ Name => 'TimeZone',
406
+ PrintConv => 'Image::ExifTool::TimeZoneString($val)',
407
+ },
358
408
  UNIT => { #2 (gpmd) alternative units
359
409
  Name => 'Units',
360
410
  Unknown => 1,
@@ -373,6 +423,7 @@ my %addUnits = (
373
423
  },
374
424
  },
375
425
  # VLTA (GPMF) - seen: 78 ('N') (fmt B -- wrong format?)
426
+ VFPS => { Name => 'VideoFrameRate', PrintConv => '$val=~s( )(/);$val' }, #PH (GPMF, fmt L)
376
427
  VFRH => { #PH (Karma)
377
428
  Name => 'VisualFlightRulesHUD',
378
429
  BinaryData => 1,
@@ -380,13 +431,17 @@ my %addUnits = (
380
431
  # TYPE=ffffsS
381
432
  },
382
433
  # VLTE (GPMF) - seen: 'Y','N' (fmt c)
434
+ VRES => { Name => 'VideoFrameSize', PrintConv => '$val=~s/ /x/;$val' }, #PH (GPMF, fmt L)
383
435
  WBAL => 'ColorTemperatures', #PH (gpmd)
384
436
  WRGB => { #PH (gpmd)
385
437
  Name => 'WhiteBalanceRGB',
386
438
  Binary => 1,
387
439
  },
388
440
  # ZFOV (APP6,GPMF) - seen: 148.34, 0 (fmt f, Hero8, Max)
389
- # the following ref forum12825
441
+ # ZMPL (GPMF) - seen: 0.652929663658142 (fmt f)
442
+ #
443
+ # the following ref forum12825
444
+ #
390
445
  MUID => {
391
446
  Name => 'MediaUniqueID',
392
447
  PrintConv => q{
@@ -418,7 +473,7 @@ my %addUnits = (
418
473
  YAVG => 'LumaAverage',
419
474
  );
420
475
 
421
- # GoPro GPS5 tags (ref 2) (Hero5,Hero6)
476
+ # GoPro GPS5 tags (ref 2) (Hero5,Hero6,Hero9)
422
477
  %Image::ExifTool::GoPro::GPS5 = (
423
478
  PROCESS_PROC => \&ProcessString,
424
479
  GROUPS => { 1 => 'GoPro', 2 => 'Location' },
@@ -435,8 +490,65 @@ my %addUnits = (
435
490
  Name => 'GPSAltitude',
436
491
  PrintConv => '"$val m"',
437
492
  },
438
- 3 => 'GPSSpeed', # (unit='m/s')
439
- 4 => 'GPSSpeed3D', # (unit='m/s')
493
+ 3 => {
494
+ Name => 'GPSSpeed',
495
+ Notes => 'stored as m/s but converted to km/h when extracted',
496
+ ValueConv => '$val * 3.6',
497
+ },
498
+ 4 => {
499
+ Name => 'GPSSpeed3D',
500
+ Notes => 'stored as m/s but converted to km/h when extracted',
501
+ ValueConv => '$val * 3.6',
502
+ },
503
+ );
504
+
505
+ # GoPro GPS9 tags (Hero13)
506
+ %Image::ExifTool::GoPro::GPS9 = (
507
+ PROCESS_PROC => \&ProcessString,
508
+ GROUPS => { 1 => 'GoPro', 2 => 'Location' },
509
+ VARS => { HEX_ID => 0, ID_LABEL => 'Index' },
510
+ 0 => { # (unit='deg')
511
+ Name => 'GPSLatitude',
512
+ PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
513
+ },
514
+ 1 => { # (unit='deg')
515
+ Name => 'GPSLongitude',
516
+ PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
517
+ },
518
+ 2 => { # (unit='m')
519
+ Name => 'GPSAltitude',
520
+ PrintConv => '"$val m"',
521
+ },
522
+ 3 => {
523
+ Name => 'GPSSpeed',
524
+ Notes => 'stored as m/s but converted to km/h when extracted',
525
+ ValueConv => '$val * 3.6',
526
+ },
527
+ 4 => {
528
+ Name => 'GPSSpeed3D',
529
+ Notes => 'stored as m/s but converted to km/h when extracted',
530
+ ValueConv => '$val * 3.6',
531
+ },
532
+ 5 => { # days since 2000
533
+ Name => 'GPSDays',
534
+ RawConv => '$$self{GPSDays} = $val; undef',
535
+ Hidden => 1,
536
+ },
537
+ 6 => { # seconds of date/time
538
+ Name => 'GPSDateTime',
539
+ Groups => { 2 => 'Time' },
540
+ # (10957 days from Jan 1 1970 to Jan 1 2000)
541
+ RawConv => 'ConvertUnixTime(($$self{GPSDays} + 10957) * 24 * 3600 + $val, undef, 3)',
542
+ PrintConv => '$self->ConvertDateTime($val)',
543
+ },
544
+ 7 => 'GPSDOP',
545
+ 8 => {
546
+ Name => 'GPSMeasureMode', #PH (NC)
547
+ PrintConv => {
548
+ 2 => '2-Dimensional Measurement',
549
+ 3 => '3-Dimensional Measurement',
550
+ },
551
+ },
440
552
  );
441
553
 
442
554
  # GoPro GPRI tags (ref PH) (Karma)
@@ -604,7 +716,7 @@ sub ScaleValues($$)
604
716
  sub AddUnits($$$)
605
717
  {
606
718
  my ($et, $val, $tag) = @_;
607
- if ($et and $$et{TAG_EXTRA}{$tag} and $$et{TAG_EXTRA}{$tag}{Units}) {
719
+ if ($et and $$et{TAG_EXTRA}{$tag}{Units}) {
608
720
  my $u = $$et{TAG_EXTRA}{$tag}{Units};
609
721
  $u = [ $u ] unless ref $u eq 'ARRAY';
610
722
  my @a = split ' ', $val;
@@ -748,7 +860,7 @@ metadata from GoPro MP4 videos.
748
860
 
749
861
  =head1 AUTHOR
750
862
 
751
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
863
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
752
864
 
753
865
  This library is free software; you can redistribute it and/or modify it
754
866
  under the same terms as Perl itself.
@@ -1123,7 +1123,7 @@ information from H.264 video streams.
1123
1123
 
1124
1124
  =head1 AUTHOR
1125
1125
 
1126
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
1126
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
1127
1127
 
1128
1128
  This library is free software; you can redistribute it and/or modify it
1129
1129
  under the same terms as Perl itself.
@@ -225,7 +225,7 @@ sub ProcessHP($$$)
225
225
  # scan for other tag ID's
226
226
  foreach $tagID (sort(TagTableKeys($tagTablePtr))) {
227
227
  next if $tagID eq 'PreviewImage';
228
- next unless $$dataPt =~ /$tagID:\s*([\x20-\x7f]+)/i;
228
+ next unless $$dataPt =~ /$tagID:\s*([\x20-\x7e]+)/i;
229
229
  $et->HandleTag($tagTablePtr, $tagID, $1);
230
230
  }
231
231
  return 1;
@@ -250,7 +250,7 @@ Hewlett-Packard maker notes.
250
250
 
251
251
  =head1 AUTHOR
252
252
 
253
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
253
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
254
254
 
255
255
  This library is free software; you can redistribute it and/or modify it
256
256
  under the same terms as Perl itself.
@@ -555,7 +555,7 @@ meta information from HTML documents.
555
555
 
556
556
  =head1 AUTHOR
557
557
 
558
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
558
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
559
559
 
560
560
  This library is free software; you can redistribute it and/or modify it
561
561
  under the same terms as Perl itself.