exiftool_vendored 13.36.0 → 13.38.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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +39 -1
  3. data/bin/MANIFEST +9 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +47 -47
  7. data/bin/build_geolocation +7 -3
  8. data/bin/exiftool +65 -63
  9. data/bin/lib/Image/ExifTool/Audible.pm +1 -1
  10. data/bin/lib/Image/ExifTool/BMP.pm +2 -2
  11. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +16 -9
  12. data/bin/lib/Image/ExifTool/CBOR.pm +1 -1
  13. data/bin/lib/Image/ExifTool/Canon.pm +59 -5
  14. data/bin/lib/Image/ExifTool/CanonVRD.pm +1 -1
  15. data/bin/lib/Image/ExifTool/CaptureOne.pm +1 -1
  16. data/bin/lib/Image/ExifTool/DJI.pm +5 -5
  17. data/bin/lib/Image/ExifTool/DSF.pm +138 -0
  18. data/bin/lib/Image/ExifTool/DV.pm +1 -1
  19. data/bin/lib/Image/ExifTool/EXE.pm +5 -2
  20. data/bin/lib/Image/ExifTool/FLIF.pm +1 -1
  21. data/bin/lib/Image/ExifTool/FLIR.pm +3 -3
  22. data/bin/lib/Image/ExifTool/FlashPix.pm +1 -1
  23. data/bin/lib/Image/ExifTool/FujiFilm.pm +5 -4
  24. data/bin/lib/Image/ExifTool/GIF.pm +1 -1
  25. data/bin/lib/Image/ExifTool/GM.pm +1 -1
  26. data/bin/lib/Image/ExifTool/Geolocation.pm +3 -1
  27. data/bin/lib/Image/ExifTool/Geotag.pm +13 -3
  28. data/bin/lib/Image/ExifTool/GoPro.pm +11 -8
  29. data/bin/lib/Image/ExifTool/Google.pm +814 -0
  30. data/bin/lib/Image/ExifTool/H264.pm +1 -1
  31. data/bin/lib/Image/ExifTool/ICC_Profile.pm +1 -1
  32. data/bin/lib/Image/ExifTool/ID3.pm +14 -13
  33. data/bin/lib/Image/ExifTool/JPEG.pm +1 -1
  34. data/bin/lib/Image/ExifTool/JSON.pm +1 -1
  35. data/bin/lib/Image/ExifTool/LIF.pm +1 -1
  36. data/bin/lib/Image/ExifTool/LNK.pm +2 -2
  37. data/bin/lib/Image/ExifTool/Lytro.pm +1 -1
  38. data/bin/lib/Image/ExifTool/M2TS.pm +34 -25
  39. data/bin/lib/Image/ExifTool/MIEUnits.pod +1 -1
  40. data/bin/lib/Image/ExifTool/MPEG.pm +1 -1
  41. data/bin/lib/Image/ExifTool/MWG.pm +1 -1
  42. data/bin/lib/Image/ExifTool/MXF.pm +1 -1
  43. data/bin/lib/Image/ExifTool/MacOS.pm +2 -2
  44. data/bin/lib/Image/ExifTool/MakerNotes.pm +30 -7
  45. data/bin/lib/Image/ExifTool/Microsoft.pm +4 -4
  46. data/bin/lib/Image/ExifTool/Nikon.pm +4 -4
  47. data/bin/lib/Image/ExifTool/OOXML.pm +1 -1
  48. data/bin/lib/Image/ExifTool/Ogg.pm +1 -1
  49. data/bin/lib/Image/ExifTool/Olympus.pm +2 -1
  50. data/bin/lib/Image/ExifTool/Other.pm +1 -1
  51. data/bin/lib/Image/ExifTool/Panasonic.pm +1 -1
  52. data/bin/lib/Image/ExifTool/Pentax.pm +18 -7
  53. data/bin/lib/Image/ExifTool/Protobuf.pm +12 -6
  54. data/bin/lib/Image/ExifTool/Qualcomm.pm +2 -2
  55. data/bin/lib/Image/ExifTool/QuickTime.pm +30 -8
  56. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +2 -0
  57. data/bin/lib/Image/ExifTool/README +7 -6
  58. data/bin/lib/Image/ExifTool/Rawzor.pm +1 -1
  59. data/bin/lib/Image/ExifTool/Reconyx.pm +375 -91
  60. data/bin/lib/Image/ExifTool/Samsung.pm +1 -1
  61. data/bin/lib/Image/ExifTool/Shortcuts.pm +8 -5
  62. data/bin/lib/Image/ExifTool/Sony.pm +22 -7
  63. data/bin/lib/Image/ExifTool/TagInfoXML.pm +3 -2
  64. data/bin/lib/Image/ExifTool/TagLookup.pm +5753 -5696
  65. data/bin/lib/Image/ExifTool/TagNames.pod +707 -518
  66. data/bin/lib/Image/ExifTool/Text.pm +1 -1
  67. data/bin/lib/Image/ExifTool/Trailer.pm +1 -1
  68. data/bin/lib/Image/ExifTool/WPG.pm +1 -1
  69. data/bin/lib/Image/ExifTool/WTV.pm +1 -1
  70. data/bin/lib/Image/ExifTool/WavPack.pm +144 -0
  71. data/bin/lib/Image/ExifTool/XMP.pm +43 -37
  72. data/bin/lib/Image/ExifTool/XMP2.pl +0 -482
  73. data/bin/lib/Image/ExifTool/ZIP.pm +1 -1
  74. data/bin/lib/Image/ExifTool/iWork.pm +1 -1
  75. data/bin/lib/Image/ExifTool.pm +42 -27
  76. data/bin/lib/Image/ExifTool.pod +60 -59
  77. data/bin/perl-Image-ExifTool.spec +46 -46
  78. data/lib/exiftool_vendored/version.rb +1 -1
  79. metadata +6 -6
@@ -88,7 +88,7 @@ sub ProcessCTMD($$$);
88
88
  sub ProcessExifInfo($$$);
89
89
  sub SwapWords($);
90
90
 
91
- $VERSION = '4.96';
91
+ $VERSION = '4.97';
92
92
 
93
93
  # Note: Removed 'USM' from 'L' lenses since it is redundant - PH
94
94
  # (or is it? Ref 32 shows 5 non-USM L-type lenses)
@@ -561,7 +561,8 @@ $VERSION = '4.96';
561
561
  4159 => 'Canon EF-M 32mm f/1.4 STM', #42
562
562
  4160 => 'Canon EF-S 35mm f/2.8 Macro IS STM', #42
563
563
  4208 => 'Sigma 56mm f/1.4 DC DN | C or other Sigma Lens', #forum10603
564
- 4208.1 => 'Sigma 30mm F1.4 DC DN | C', #git issue#83 (016)
564
+ 4208.1 => 'Sigma 30mm F1.4 DC DN | C', #github#83 (016)
565
+ 6512 => 'Sigma 12mm F1.4 DC | C', #github#352 (025)
565
566
  # (Nano USM lenses - 0x90xx)
566
567
  36910 => 'Canon EF 70-300mm f/4-5.6 IS II USM', #42
567
568
  36912 => 'Canon EF-S 18-135mm f/3.5-5.6 IS USM', #42
@@ -640,6 +641,7 @@ $VERSION = '4.96';
640
641
  '61182.62' => 'Canon RF 50mm F1.4 L VCM', #42
641
642
  '61182.63' => 'Canon RF 24mm F1.4 L VCM', #42
642
643
  '61182.64' => 'Canon RF 20mm F1.4 L VCM', #42
644
+ '61182.65' => 'Canon RF 85mm F1.4 L VCM', #github350
643
645
  65535 => 'n/a',
644
646
  );
645
647
 
@@ -892,6 +894,7 @@ $VERSION = '4.96';
892
894
 
893
895
  # (see http://cweb.canon.jp/e-support/faq/answer/digitalcamera/10447-1.html for PowerShot/IXUS/IXY names)
894
896
 
897
+ 0x40000227 => 'EOS C50', #github350
895
898
  0x4007d673 => 'DC19/DC21/DC22',
896
899
  0x4007d674 => 'XH A1',
897
900
  0x4007d675 => 'HV10',
@@ -7048,6 +7051,7 @@ my %ciMaxFocal = (
7048
7051
  325 => 'Canon RF 50mm F1.4 L VCM', #42
7049
7052
  326 => 'Canon RF 24mm F1.4 L VCM', #42
7050
7053
  327 => 'Canon RF 20mm F1.4 L VCM', #42
7054
+ 328 => 'Canon RF 85mm F1.4 L VCM', #42/github350
7051
7055
  # Note: add new RF lenses to %canonLensTypes with ID 61182
7052
7056
  },
7053
7057
  },
@@ -9125,7 +9129,7 @@ my %filterConv = (
9125
9129
  RawConv => '$val == 0x7fffffff ? undef : $val',
9126
9130
  },
9127
9131
  7 => { # -4 to 4
9128
- Name => 'Saturation',
9132
+ Name => 'Saturation',
9129
9133
  RawConv => '$val == 0x7fffffff ? undef : $val',
9130
9134
  %Image::ExifTool::Exif::printParameter,
9131
9135
  },
@@ -9175,6 +9179,7 @@ my %filterConv = (
9175
9179
  ValueConvInv => '$val - 1',
9176
9180
  PrintHex => 1,
9177
9181
  PrintConv => {
9182
+ 11 => 'Case A', #KG instead of 'Case 11'. Canon use A for Auto
9178
9183
  0x80000000 => 'n/a',
9179
9184
  OTHER => sub { 'Case ' . shift },
9180
9185
  },
@@ -9184,6 +9189,7 @@ my %filterConv = (
9184
9189
  Name => 'AFTrackingSensitivity',
9185
9190
  PrintHex => 1,
9186
9191
  PrintConv => {
9192
+ 127 => 'Auto', #KG
9187
9193
  0x7fffffff => 'n/a',
9188
9194
  OTHER => sub { shift },
9189
9195
  },
@@ -9193,6 +9199,7 @@ my %filterConv = (
9193
9199
  Description => 'AF Accel/Decel Tracking',
9194
9200
  PrintHex => 1,
9195
9201
  PrintConv => {
9202
+ 127 => 'Auto', #KG
9196
9203
  0x7fffffff => 'n/a',
9197
9204
  OTHER => sub { shift },
9198
9205
  },
@@ -9353,6 +9360,7 @@ my %filterConv = (
9353
9360
  1 => 'People',
9354
9361
  2 => 'Animals',
9355
9362
  3 => 'Vehicles',
9363
+ 4 => 'Auto', #KG (R1, R5m2)
9356
9364
  },
9357
9365
  },
9358
9366
  21 => { #github344 (R6)
@@ -9363,9 +9371,55 @@ my %filterConv = (
9363
9371
  2 => 'Switch Subject',
9364
9372
  },
9365
9373
  },
9366
- 24 => { #forum16068
9374
+ 24 => { #forum16068 #KG extensions for 'left' and 'right'
9367
9375
  Name => 'EyeDetection',
9368
- PrintConv => \%offOn,
9376
+ PrintConv => {
9377
+ 0 => 'Off',
9378
+ 1 => 'Auto',
9379
+ 2 => 'Left Eye',
9380
+ 3 => 'Right Eye',
9381
+ },
9382
+ },
9383
+ # ---------------
9384
+ # Entries 25..31 exist for recent models only (R1, R5m2, ...)
9385
+ # ---------------
9386
+ 26 => { #KG
9387
+ Name => 'WholeAreaTracking',
9388
+ PrintConv => {
9389
+ 0 => 'Off',
9390
+ 1 => 'On',
9391
+ },
9392
+ },
9393
+ 27 => { #KG
9394
+ Name => 'ServoAFCharacteristics',
9395
+ PrintConv => {
9396
+ 0 => 'Case Auto',
9397
+ 1 => 'Case Manual',
9398
+ },
9399
+ },
9400
+ 28 => { #KG
9401
+ Name => 'CaseAutoSetting',
9402
+ PrintConv => {
9403
+ -1 => 'Locked On',
9404
+ 0 => 'Standard',
9405
+ 1 => 'Responsive',
9406
+ 0x7fffffff => 'n/a',
9407
+ },
9408
+ },
9409
+ 29 => { #KG
9410
+ Name => 'ActionPriority',
9411
+ PrintConv => {
9412
+ 0 => 'Off',
9413
+ 1 => 'On',
9414
+ },
9415
+ },
9416
+ 30 => { #KG
9417
+ Name => 'SportEvents',
9418
+ PrintConv => {
9419
+ 0 => 'Soccer',
9420
+ 1 => 'Basketball',
9421
+ 2 => 'Volleyball',
9422
+ }
9369
9423
  },
9370
9424
  );
9371
9425
 
@@ -1004,7 +1004,7 @@ my $blankFooter = "CANON OPTIONAL DATA\0" . ("\0" x 42) . "\xff\xd9";
1004
1004
  WRITABLE => 1,
1005
1005
  PERMANENT => 1, # (can't add/delete these individually)
1006
1006
  GROUPS => { 1 => 'CanonDR4', 2 => 'Image' },
1007
- VARS => { HEX_ID => 1, SORT_PROC => \&SortDR4 },
1007
+ VARS => { ID_FMT => 'hex', SORT_PROC => \&SortDR4 },
1008
1008
  NOTES => q{
1009
1009
  Tags written by Canon DPP version 4 in CanonVRD trailers and DR4 files. Each
1010
1010
  tag has three associated flag words which are stored with the directory
@@ -25,7 +25,7 @@ $VERSION = '1.04';
25
25
  %Image::ExifTool::CaptureOne::Main = (
26
26
  GROUPS => { 0 => 'XML', 1 => 'XML', 2 => 'Image' },
27
27
  PROCESS_PROC => \&Image::ExifTool::XMP::ProcessXMP,
28
- VARS => { NO_ID => 1 },
28
+ VARS => { ID_FMT => 'none' },
29
29
  ColorCorrections => { ValueConv => '\$val' }, # (long list of floating point numbers)
30
30
  );
31
31
 
@@ -140,7 +140,7 @@ my %convFloat2 = (
140
140
  GROUPS => { 0 => 'XMP', 1 => 'XMP-drone-dji', 2 => 'Location' },
141
141
  NAMESPACE => 'drone-dji',
142
142
  TABLE_DESC => 'XMP DJI',
143
- VARS => { NO_ID => 1 },
143
+ VARS => { ID_FMT => 'none' },
144
144
  NOTES => 'XMP tags used by DJI for images from drones.',
145
145
  AbsoluteAltitude => { Writable => 'real' },
146
146
  RelativeAltitude => { Writable => 'real' },
@@ -530,7 +530,7 @@ my %convFloat2 = (
530
530
  %Image::ExifTool::DJI::DroneInfo = (
531
531
  GROUPS => { 0 => 'Protobuf', 1 => 'DJI', 2 => 'Camera' },
532
532
  PROCESS_PROC => \&Image::ExifTool::Protobuf::ProcessProtobuf,
533
- VARS => { HEX_ID => 0, ID_LABEL => 'Field #' },
533
+ VARS => { ID_FMT => 'dec', ID_LABEL => 'Field #' },
534
534
  1 => { Name => 'DroneRoll', Format => 'int64s', ValueConv => '$val / 10' },
535
535
  2 => { Name => 'DronePitch', Format => 'int64s', ValueConv => '$val / 10' },
536
536
  3 => { Name => 'DroneYaw', Format => 'int64s', ValueConv => '$val / 10' },
@@ -539,7 +539,7 @@ my %convFloat2 = (
539
539
  %Image::ExifTool::DJI::GimbalInfo = (
540
540
  GROUPS => { 0 => 'Protobuf', 1 => 'DJI', 2 => 'Camera' },
541
541
  PROCESS_PROC => \&Image::ExifTool::Protobuf::ProcessProtobuf,
542
- VARS => { HEX_ID => 0, ID_LABEL => 'Field #' },
542
+ VARS => { ID_FMT => 'dec', ID_LABEL => 'Field #' },
543
543
  1 => { Name => 'GimbalPitch',Format => 'int64s', ValueConv => '$val / 10' },
544
544
  2 => { Name => 'GimbalRoll', Format => 'int64s', ValueConv => '$val / 10' }, # usually 0, so missing
545
545
  3 => { Name => 'GimbalYaw', Format => 'int64s', ValueConv => '$val / 10' },
@@ -548,7 +548,7 @@ my %convFloat2 = (
548
548
  %Image::ExifTool::DJI::FrameInfo = (
549
549
  GROUPS => { 0 => 'Protobuf', 1 => 'DJI', 2 => 'Video' },
550
550
  PROCESS_PROC => \&Image::ExifTool::Protobuf::ProcessProtobuf,
551
- VARS => { HEX_ID => 0, ID_LABEL => 'Field #' },
551
+ VARS => { ID_FMT => 'dec', ID_LABEL => 'Field #' },
552
552
  1 => { Name => 'FrameWidth', Format => 'unsigned' },
553
553
  2 => { Name => 'FrameHeight', Format => 'unsigned' },
554
554
  3 => { Name => 'FrameRate', Format => 'float' },
@@ -558,7 +558,7 @@ my %convFloat2 = (
558
558
  %Image::ExifTool::DJI::GPSInfo = (
559
559
  GROUPS => { 0 => 'Protobuf', 1 => 'DJI', 2 => 'Location' },
560
560
  PROCESS_PROC => \&Image::ExifTool::Protobuf::ProcessProtobuf,
561
- VARS => { HEX_ID => 0, ID_LABEL => 'Field #' },
561
+ VARS => { ID_FMT => 'dec', ID_LABEL => 'Field #' },
562
562
  1 => {
563
563
  Name => 'CoordinateUnits',
564
564
  Format => 'unsigned',
@@ -0,0 +1,138 @@
1
+ #------------------------------------------------------------------------------
2
+ # File: DSF.pm
3
+ #
4
+ # Description: Read DSF meta information
5
+ #
6
+ # Revisions: 2025-09-24 - P. Harvey Created
7
+ #
8
+ # References: 1) https://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
9
+ #------------------------------------------------------------------------------
10
+
11
+ package Image::ExifTool::DSF;
12
+
13
+ use strict;
14
+ use vars qw($VERSION);
15
+ use Image::ExifTool qw(:DataAccess :Utils);
16
+
17
+ $VERSION = '1.00';
18
+
19
+ # DSF header format
20
+ %Image::ExifTool::DSF::Main = (
21
+ PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
22
+ GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Audio' },
23
+ FORMAT => 'int32u',
24
+ NOTES => q{
25
+ Tags read from the 'fmt ' header of a DSF (DSD Stream File) audio files. As
26
+ well, ID3 metadata may also exist in these files. See
27
+ L<https://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf>
28
+ for the specification.
29
+ },
30
+ 3 => 'FormatVersion',
31
+ 4 => { Name => 'FormatID', PrintConv => { 0 => 'DSD Raw' }},
32
+ 5 => {
33
+ Name => 'ChannelType',
34
+ PrintConv => {
35
+ 1 => 'Mono',
36
+ 2 => 'Stereo (Left, Right)',
37
+ 3 => '3 Channels (Left, Right, Center)',
38
+ 4 => 'Quad (Left, Right, Back L, Back R)',
39
+ 5 => '4 Channels (Left, Right, Center, Bass)',
40
+ 6 => '5 Channels (Left, Right, Center, Back L, Back R)',
41
+ 7 => '5.1 Channels (Left, Right, Center, Bass, Back L, Back R)',
42
+ },
43
+ },
44
+ 6 => 'ChannelCount',
45
+ 7 => 'SampleRate',
46
+ 8 => 'BitsPerSample',
47
+ 9 => { Name => 'SampleCount', Format => 'int64u' },
48
+ 11 => 'BlockSize',
49
+ );
50
+
51
+ #------------------------------------------------------------------------------
52
+ # Extract metadata from a DSF file
53
+ # Inputs: 0) ExifTool object reference, 1) dirInfo reference
54
+ # Returns: 1 on success, 0 if this wasn't a valid DSF file
55
+ sub ProcessDSF($$)
56
+ {
57
+ my ($et, $dirInfo) = @_;
58
+ my $raf = $$dirInfo{RAF};
59
+ my ($buff, $buf2, $tagTablePtr);
60
+
61
+ # verify this is a valid DSF file
62
+ return 0 unless $raf->Read($buff, 40) == 40;
63
+ return 0 unless $buff =~ /^DSD \x1c\0{7}.{16}fmt /s;
64
+ $et->SetFileType(); # set the FileType tag
65
+ my $tagTbl = GetTagTable('Image::ExifTool::DSF::Main');
66
+ SetByteOrder('II');
67
+ my $fmtLen = Get64u(\$buff,32);
68
+ unless ($fmtLen > 12 and $fmtLen < 1000 and
69
+ $raf->Read($buf2, $fmtLen - 12) == $fmtLen - 12)
70
+ {
71
+ $et->Warn('Error reading DSF fmt chunk');
72
+ return 1;
73
+ }
74
+ my $fileSize = Get64u(\$buff, 12);
75
+ my $metaPos = Get64u(\$buff, 20);
76
+ $buff = substr($buff, 28) . $buf2;
77
+ #
78
+ # process the DSF 'fmt ' chunk
79
+ #
80
+ my %dirInfo = (
81
+ DataPt => \$buff,
82
+ DirStart => 0,
83
+ DirLen => length($buff),
84
+ );
85
+ $et->ProcessBinaryData(\%dirInfo, $tagTbl);
86
+ #
87
+ # process ID3v2 if it exists
88
+ #
89
+ my $metaLen = $fileSize - $metaPos;
90
+ if ($metaPos and $metaLen > 0 and $metaLen < 20000000 and
91
+ $raf->Seek($metaPos, 0) and $raf->Read($buff, $metaLen) == $metaLen)
92
+ {
93
+ $dirInfo{DataPos} = $metaPos;
94
+ $dirInfo{DirLen} = $metaLen;
95
+ my $id3Tbl = GetTagTable('Image::ExifTool::ID3::Main');
96
+ $et->ProcessDirectory(\%dirInfo, $id3Tbl);
97
+ }
98
+ return 1;
99
+ }
100
+
101
+ 1; # end
102
+
103
+ __END__
104
+
105
+ =head1 NAME
106
+
107
+ Image::ExifTool::DSF - Read DSF meta information
108
+
109
+ =head1 SYNOPSIS
110
+
111
+ This module is used by Image::ExifTool
112
+
113
+ =head1 DESCRIPTION
114
+
115
+ This module contains definitions required by Image::ExifTool to read DSF
116
+ (DSD Stream File) audio files.
117
+
118
+ =head1 AUTHOR
119
+
120
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
121
+
122
+ This library is free software; you can redistribute it and/or modify it
123
+ under the same terms as Perl itself.
124
+
125
+ =head1 REFERENCES
126
+
127
+ =over 4
128
+
129
+ =item L<https://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf>
130
+
131
+ =back
132
+
133
+ =head1 SEE ALSO
134
+
135
+ L<Image::ExifTool::TagNames/DSF Tags>,
136
+ L<Image::ExifTool(3pm)|Image::ExifTool>
137
+
138
+ =cut
@@ -123,7 +123,7 @@ my @dvTags = (
123
123
  # DV tags
124
124
  %Image::ExifTool::DV::Main = (
125
125
  GROUPS => { 2 => 'Video' },
126
- VARS => { NO_ID => 1 },
126
+ VARS => { ID_FMT => 'none' },
127
127
  NOTES => 'The following tags are extracted from DV videos.',
128
128
  DateTimeOriginal => {
129
129
  Description => 'Date/Time Original',
@@ -22,7 +22,7 @@ use strict;
22
22
  use vars qw($VERSION);
23
23
  use Image::ExifTool qw(:DataAccess :Utils);
24
24
 
25
- $VERSION = '1.23';
25
+ $VERSION = '1.25';
26
26
 
27
27
  sub ProcessPEResources($$);
28
28
  sub ProcessPEVersion($$);
@@ -450,7 +450,7 @@ my %int32uTime = (
450
450
  # (see http://msdn.microsoft.com/en-us/library/aa381049.aspx)
451
451
  %Image::ExifTool::EXE::PEString = (
452
452
  GROUPS => { 2 => 'Other' },
453
- VARS => { NO_ID => 1 },
453
+ VARS => { ID_FMT => 'none' },
454
454
  NOTES => q{
455
455
  Resource strings found in Windows PE files. The B<TagID>'s are not shown
456
456
  because they are the same as the B<Tag Name>. ExifTool will extract any
@@ -962,6 +962,7 @@ sub ProcessPEVersion($$)
962
962
  $pos = ($pos + 3) & 0xfffffffc; # align on a 4-byte boundary
963
963
  last if $pos + 6 > $end;
964
964
  $len = Get16u($dataPt, $pos);
965
+ return 0 if $pos + $len > $end;
965
966
  $valLen = Get16u($dataPt, $pos + 2);
966
967
  $type = Get16u($dataPt, $pos + 4);
967
968
  return 0 unless $len or $valLen; # prevent possible infinite loop
@@ -985,9 +986,11 @@ sub ProcessPEVersion($$)
985
986
  my $tagTablePtr = GetTagTable('Image::ExifTool::EXE::PEString');
986
987
  for ($index = 0; $pt + 6 < $pos; ++$index) {
987
988
  $len = Get16u($dataPt, $pt);
989
+ $len or $et->Warn('Invalid PEString entry'), last;
988
990
  $valLen = Get16u($dataPt, $pt + 2);
989
991
  # $type = Get16u($dataPt, $pt + 4);
990
992
  my $entryEnd = $pt + $len;
993
+ return 0 if $entryEnd > $end;
991
994
  # get tag ID (converted to UTF8)
992
995
  ($string, $pt) = ReadUnicodeStr($dataPt, $pt + 6, $entryEnd);
993
996
  unless ($index) {
@@ -36,7 +36,7 @@ my %flifMap = (
36
36
  # FLIF tags
37
37
  %Image::ExifTool::FLIF::Main = (
38
38
  GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' },
39
- VARS => { HEX_ID => 0 },
39
+ VARS => { ID_FMT => 'dec' },
40
40
  NOTES => q{
41
41
  Information extracted from Free Lossless Image Format files. See
42
42
  L<http://flif.info/> for more information.
@@ -476,7 +476,7 @@ my %float8g = ( Format => 'float', PrintConv => 'sprintf("%.8g",$val)' );
476
476
  GROUPS => { 0 => 'APP1', 2 => 'Image' },
477
477
  PROCESS_PROC => \&ProcessMeasInfo,
478
478
  FORMAT => 'int16u',
479
- VARS => { NO_ID => 1 },
479
+ VARS => { ID_FMT => 'none' },
480
480
  NOTES => q{
481
481
  Tags listed below are only for the first measurement tool, however multiple
482
482
  measurements may be added, and information is extracted for all of them.
@@ -548,7 +548,7 @@ my %float8g = ( Format => 'float', PrintConv => 'sprintf("%.8g",$val)' );
548
548
  %Image::ExifTool::FLIR::TextInfo = (
549
549
  GROUPS => { 0 => 'APP1', 2 => 'Image' },
550
550
  PROCESS_PROC => \&ProcessFLIRText,
551
- VARS => { NO_ID => 1 },
551
+ VARS => { ID_FMT => 'none' },
552
552
  Label0 => { },
553
553
  Value0 => { },
554
554
  Label1 => { },
@@ -564,7 +564,7 @@ my %float8g = ( Format => 'float', PrintConv => 'sprintf("%.8g",$val)' );
564
564
  %Image::ExifTool::FLIR::ParamInfo = (
565
565
  GROUPS => { 0 => 'APP1', 2 => 'Image' },
566
566
  PROCESS_PROC => \&ProcessFLIRText,
567
- VARS => { NO_ID => 1 },
567
+ VARS => { ID_FMT => 'none' },
568
568
  Generated => {
569
569
  Name => 'DateTimeGenerated',
570
570
  Description => 'Date/Time Generated',
@@ -1093,7 +1093,7 @@ my %fpxFileType = (
1093
1093
  %Image::ExifTool::FlashPix::DocTable = (
1094
1094
  GROUPS => { 1 => 'MS-DOC', 2 => 'Document' },
1095
1095
  NOTES => 'Tags extracted from the Microsoft Word document table.',
1096
- VARS => { NO_ID => 1 },
1096
+ VARS => { ID_FMT => 'none' },
1097
1097
  CommentBy => {
1098
1098
  Groups => { 2 => 'Author' },
1099
1099
  Notes => 'enable L<Duplicates|../ExifTool.html#Duplicates> option to extract all entries',
@@ -31,7 +31,7 @@ use vars qw($VERSION);
31
31
  use Image::ExifTool qw(:DataAccess :Utils);
32
32
  use Image::ExifTool::Exif;
33
33
 
34
- $VERSION = '1.99';
34
+ $VERSION = '2.00';
35
35
 
36
36
  sub ProcessFujiDir($$$);
37
37
  sub ProcessFaceRec($$$);
@@ -643,8 +643,8 @@ my %faceCategories = (
643
643
  Writable => 'int16u',
644
644
  PrintConv => {
645
645
  1 => 'Right',
646
- 2 => 'Up', # (or Left?, forum17591)
647
- 3 => 'Left', # (or Up?, forum17591)
646
+ 2 => 'Left', #forum17591
647
+ 3 => 'Up', #forum17591
648
648
  4 => 'Down',
649
649
  },
650
650
  },
@@ -960,6 +960,7 @@ my %faceCategories = (
960
960
  3 => 'Right Eye',
961
961
  7 => 'Body',
962
962
  8 => 'Head',
963
+ 9 => 'Both Eyes', #forum17635
963
964
  11 => 'Bike',
964
965
  12 => 'Body of Car',
965
966
  13 => 'Front of Car',
@@ -1190,7 +1191,7 @@ my %faceCategories = (
1190
1191
  %Image::ExifTool::FujiFilm::FaceRecInfo = (
1191
1192
  PROCESS_PROC => \&ProcessFaceRec,
1192
1193
  GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
1193
- VARS => { NO_ID => 1 },
1194
+ VARS => { ID_FMT => 'none' },
1194
1195
  NOTES => 'Face recognition information.',
1195
1196
  Face1Name => { },
1196
1197
  Face2Name => { },
@@ -33,7 +33,7 @@ my @appExtensions = ( 'XMP Data/XMP', 'ICCRGBG1/012' );
33
33
 
34
34
  %Image::ExifTool::GIF::Main = (
35
35
  GROUPS => { 2 => 'Image' },
36
- VARS => { NO_ID => 1 },
36
+ VARS => { ID_FMT => 'none' },
37
37
  NOTES => q{
38
38
  This table lists information extracted from GIF images. See
39
39
  L<http://www.w3.org/Graphics/GIF/spec-gif89a.txt> for the official GIF89a
@@ -136,7 +136,7 @@ my %channelStruct = (
136
136
  %Image::ExifTool::GM::marl = (
137
137
  PROCESS_PROC => \&Process_marl,
138
138
  GROUPS => { 2 => 'Other' },
139
- VARS => { NO_ID => 1, NO_LOOKUP => 1 },
139
+ VARS => { ID_FMT => 'none', NO_LOOKUP => 1 },
140
140
  NOTES => q{
141
141
  Tags extracted from the 'ctbx' 'marl' (Marlin) box of timed PDR metadata
142
142
  from GM cars. Use the -ee (L<API ExtractEmbedded|../ExifTool.html#ExtractEmbedded>) option to extract this
@@ -401,11 +401,13 @@ sub GetEntry($;$$)
401
401
  my $xlat = $langLookup{$lang};
402
402
  # load language lookups if not done already
403
403
  if (not defined $xlat) {
404
- if (eval "require '$geoDir/GeoLang/$lang.pm'") {
404
+ unshift @INC, $geoDir; # make sure $geoDir is first in path
405
+ if (eval "require 'GeoLang/$lang.pm'") {
405
406
  my $trans = "Image::ExifTool::GeoLang::${lang}::Translate";
406
407
  no strict 'refs';
407
408
  $xlat = \%$trans if %$trans;
408
409
  }
410
+ shift @INC;
409
411
  # read user-defined language translations
410
412
  if (%Image::ExifTool::Geolocation::geoLang) {
411
413
  my $userLang = $Image::ExifTool::Geolocation::geoLang{$lang};
@@ -20,6 +20,7 @@
20
20
  # 2024/11/26 - PH Also write GPSMeasureMode and GPSDOP
21
21
  # 2024/11/05 - PH Added support for Google Maps "Export timeline data"
22
22
  # JSON format
23
+ # 2025/09/22 - PH Added ability to read Columbus CSV log files
23
24
  #
24
25
  # References: 1) http://www.topografix.com/GPX/1/1/
25
26
  # 2) http://www.gpsinformation.org/dale/nmea.htm#GSA
@@ -34,7 +35,7 @@ use vars qw($VERSION);
34
35
  use Image::ExifTool qw(:Public);
35
36
  use Image::ExifTool::GPS;
36
37
 
37
- $VERSION = '1.81';
38
+ $VERSION = '1.82';
38
39
 
39
40
  sub JITTER() { return 2 } # maximum time jitter
40
41
 
@@ -275,6 +276,7 @@ sub LoadTrackLog($$;$)
275
276
  } elsif (((/\b(GPS)?Date/i and /\b(GPS)?(Date)?Time/i) or /\bTime\(seconds\)/i) and /\Q$csvDelim/) {
276
277
  chomp;
277
278
  @csvHeadings = split /\Q$csvDelim/;
279
+ my $isColumbus = ($csvHeadings[0] and $csvHeadings[0] eq 'INDEX'); # (Columbus GPS logger)
278
280
  $format = 'CSV';
279
281
  # convert recognized headings to our parameter names
280
282
  foreach (@csvHeadings) {
@@ -306,7 +308,7 @@ sub LoadTrackLog($$;$)
306
308
  } elsif (/^(Pos)?Lon/i) {
307
309
  $param = 'lon';
308
310
  /ref$/i and $param .= 'ref';
309
- } elsif (/^(Pos)?Alt/i) {
311
+ } elsif (/^(Pos)?(Alt|Height)/i) {
310
312
  $param = 'alt';
311
313
  } elsif (/^Speed/i) {
312
314
  $param = 'speed';
@@ -314,6 +316,9 @@ sub LoadTrackLog($$;$)
314
316
  if (m{\((mph|km/h|m/s)\)}) {
315
317
  $scaleSpeed = $otherConv{$1};
316
318
  $xtra = " in $1";
319
+ } elsif ($isColumbus) { # (Columbus GPS logger)
320
+ $scaleSpeed = $otherConv{'km/h'};
321
+ $xtra = " in km/h";
317
322
  } else {
318
323
  $xtra = ' in knots';
319
324
  }
@@ -541,12 +546,16 @@ DoneFix: $isDate = 1;
541
546
  $date = Time::Local::timegm(0,0,0,$1,$2-1,$3);
542
547
  } elsif ($val =~ /(\d{4}).*?(\d{2}).*?(\d{2})/) {
543
548
  $date = Time::Local::timegm(0,0,0,$3,$2-1,$1);
549
+ } elsif ($val =~ /^(\d{2})(\d{2})(\d{2})$/) { # (Columbus GPS logger)
550
+ $date = Time::Local::timegm(0,0,0,$3,$2-1,$1+2000);
544
551
  }
545
552
  } elsif ($param eq 'time') {
546
553
  if ($val =~ /^(\d{1,2}):(\d{2}):(\d{2}(\.\d+)?).*?(([-+])(\d{1,2}):?(\d{2}))?/) {
547
554
  $secs = (($1 * 60) + $2) * 60 + $3;
548
555
  # adjust for time zone if specified
549
556
  $secs += ($7 * 60 + $8) * ($6 eq '-' ? 60 : -60) if $5;
557
+ } elsif ($val =~ /^(\d{2})(\d{2})(\d{2})$/) { # (Columbus GPS logger)
558
+ $secs = (($1 * 60) + $2) * 60 + $3;
550
559
  }
551
560
  } elsif ($param eq 'lat' or $param eq 'lon') {
552
561
  $$fix{$param} = Image::ExifTool::GPS::ToDegrees($val, 1);
@@ -1549,7 +1558,8 @@ This module loads GPS track logs, interpolates to determine position based
1549
1558
  on time, and sets new GPS values for geotagging images. Currently supported
1550
1559
  formats are GPX, NMEA RMC/GGA/GLL/GSA/ZDA, KML, IGC, Garmin XML and TCX,
1551
1560
  Magellan PMGNTRK, Honeywell PTNTHPR, Bramor gEO, Winplus Beacon text,
1552
- GPS/IMU CSV, DJI CSV, ExifTool CSV and 3 different Google JSON formats.
1561
+ GPS/IMU CSV, DJI/Columbus/ExifTool CSV format and 3 different Google JSON
1562
+ formats.
1553
1563
 
1554
1564
  Methods in this module should not be called directly. Instead, the Geotag
1555
1565
  feature is accessed by writing the values of the ExifTool Geotag, Geosync
@@ -17,7 +17,7 @@ use vars qw($VERSION);
17
17
  use Image::ExifTool qw(:DataAccess :Utils);
18
18
  use Image::ExifTool::QuickTime;
19
19
 
20
- $VERSION = '1.14';
20
+ $VERSION = '1.15';
21
21
 
22
22
  sub ProcessGoPro($$$);
23
23
  sub ProcessString($$$);
@@ -251,7 +251,8 @@ my %noYes = ( N => 'No', Y => 'Yes' );
251
251
  Notes => 'gyroscope readings in rad/s',
252
252
  Binary => 1,
253
253
  },
254
- HCLT => 'HorizonControl', #3
254
+ LOGS => 'HealthLogs',
255
+ HCTL => 'HorizonControl', #3
255
256
  HDRV => { Name => 'HDRVideo', PrintConv => \%noYes }, #3/PH (NC)
256
257
  # HFLG (APP6) - seen: 0
257
258
  HSGT => 'HindsightSettings', #3
@@ -409,6 +410,7 @@ my %noYes = ( N => 'No', Y => 'Yes' );
409
410
  },
410
411
  # TOCK => { Name => 'OutTime', Unknown => 1, ValueConv => '$val/1000' }, #1 (gpmd)
411
412
  TSMP => { Name => 'TotalSamples', Unknown => 1 }, #2 (gpmd)
413
+ TIMO => 'TimeOffset',
412
414
  TYPE => { Name => 'StructureType', Unknown => 1 }, #2 (gpmd,GPMF - eg 'LLLllfFff', fmt c)
413
415
  TZON => { # (GPMF) - seen: 60 (fmt s)
414
416
  Name => 'TimeZone',
@@ -469,7 +471,8 @@ my %noYes = ( N => 'No', Y => 'Yes' );
469
471
  AALP => { Name => 'AudioLevel', Notes => 'dBFS' },
470
472
  GPSA => 'GPSAltitudeSystem', # (eg. 'MSLV')
471
473
  GRAV => { Name => 'GravityVector', Binary => 1 },
472
- HUES => 'PrediminantHue',
474
+ # DISP - Disparity track
475
+ HUES => 'PredominantHue',
473
476
  IORI => { Name => 'ImageOrientation', Binary => 1, Notes => 'quaternions 0-1' },
474
477
  # LRVO - ? Part of LRV Frame Skip
475
478
  # LRVS - ? Part of LRV Frame Skip
@@ -485,7 +488,7 @@ my %noYes = ( N => 'No', Y => 'Yes' );
485
488
  %Image::ExifTool::GoPro::GPS5 = (
486
489
  PROCESS_PROC => \&ProcessString,
487
490
  GROUPS => { 1 => 'GoPro', 2 => 'Location' },
488
- VARS => { HEX_ID => 0, ID_LABEL => 'Index' },
491
+ VARS => { ID_FMT => 'dec', ID_LABEL => 'Index' },
489
492
  0 => { # (unit='deg')
490
493
  Name => 'GPSLatitude',
491
494
  PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
@@ -514,7 +517,7 @@ my %noYes = ( N => 'No', Y => 'Yes' );
514
517
  %Image::ExifTool::GoPro::GPS9 = (
515
518
  PROCESS_PROC => \&ProcessString,
516
519
  GROUPS => { 1 => 'GoPro', 2 => 'Location' },
517
- VARS => { HEX_ID => 0, ID_LABEL => 'Index' },
520
+ VARS => { ID_FMT => 'dec', ID_LABEL => 'Index' },
518
521
  0 => { # (unit='deg')
519
522
  Name => 'GPSLatitude',
520
523
  PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
@@ -563,7 +566,7 @@ my %noYes = ( N => 'No', Y => 'Yes' );
563
566
  %Image::ExifTool::GoPro::GPRI = (
564
567
  PROCESS_PROC => \&ProcessString,
565
568
  GROUPS => { 1 => 'GoPro', 2 => 'Location' },
566
- VARS => { HEX_ID => 0, ID_LABEL => 'Index' },
569
+ VARS => { ID_FMT => 'dec', ID_LABEL => 'Index' },
567
570
  0 => { # (unit='s')
568
571
  Name => 'GPSDateTimeRaw',
569
572
  Groups => { 2 => 'Time' },
@@ -595,7 +598,7 @@ my %noYes = ( N => 'No', Y => 'Yes' );
595
598
  %Image::ExifTool::GoPro::GLPI = (
596
599
  PROCESS_PROC => \&ProcessString,
597
600
  GROUPS => { 1 => 'GoPro', 2 => 'Location' },
598
- VARS => { HEX_ID => 0, ID_LABEL => 'Index' },
601
+ VARS => { ID_FMT => 'dec', ID_LABEL => 'Index' },
599
602
  0 => { # (unit='s')
600
603
  Name => 'GPSDateTime',
601
604
  Groups => { 2 => 'Time' },
@@ -626,7 +629,7 @@ my %noYes = ( N => 'No', Y => 'Yes' );
626
629
  %Image::ExifTool::GoPro::KBAT = (
627
630
  PROCESS_PROC => \&ProcessString,
628
631
  GROUPS => { 1 => 'GoPro', 2 => 'Camera' },
629
- VARS => { HEX_ID => 0, ID_LABEL => 'Index' },
632
+ VARS => { ID_FMT => 'dec', ID_LABEL => 'Index' },
630
633
  NOTES => 'Battery status information found in GoPro Karma videos.',
631
634
  0 => { Name => 'BatteryCurrent', PrintConv => '"$val A"' },
632
635
  1 => { Name => 'BatteryCapacity', PrintConv => '"$val Ah"' },