exiftool-vendored.pl 12.42.0 → 12.43.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.
package/bin/Changes CHANGED
@@ -7,6 +7,28 @@ RSS feed: https://exiftool.org/rss.xml
7
7
  Note: The most recent production release is Version 12.42. (Other versions are
8
8
  considered development releases, and are not uploaded to MetaCPAN.)
9
9
 
10
+ July 6, 2022 - Version 12.43
11
+
12
+ - Added the ability to geotag from Google Takeout JSON files
13
+ - Added a few new Canon RF LensType values and a couple of new CanonModelID's
14
+ (thanks Norbert Wasser)
15
+ - Added new values to a couple of FujiFilm tags (thanks Greybeard)
16
+ - Added a new Nikon LensID (thanks BertJan Bakker)
17
+ - Recognize Autodesk Revit files (but don't yet support reading metadata)
18
+ - Decode DriveSerialNumber from LNK files (github #145)
19
+ - Decode Apple FocusDistanceRange (thanks Neal Krawetz)
20
+ - Made a number of Sony SR2SubIFD tags writable
21
+ - Tolerate dashes instead of colons as date separators in -geotag CSV files
22
+ - Patched to read new format accelerometer data from Insta360 files
23
+ - Patched to avoid outputting some Unknown tags when the -validate option is
24
+ used after a previously -execute'd command used the -u option
25
+ - Fixed names of Canon G9 WB levels tags (changed from GRGB to GRBG) (thanks
26
+ Christoph)
27
+ - Fixed typo in new Olympus AISubjectTrackingMode value
28
+ - Fixed "use of undefined value" warning when reading DJI metadata
29
+ - API Changes:
30
+ - Added IgnoreTags option
31
+
10
32
  June 1, 2022 - Version 12.42 (production release)
11
33
 
12
34
  - Added support for reading maker notes from Panasonic DC-GH6 videos
package/bin/META.json CHANGED
@@ -47,6 +47,6 @@
47
47
  }
48
48
  },
49
49
  "release_status" : "stable",
50
- "version" : "12.42",
50
+ "version" : "12.43",
51
51
  "x_serialization_backend" : "JSON::PP version 4.02"
52
52
  }
package/bin/META.yml CHANGED
@@ -28,5 +28,5 @@ recommends:
28
28
  Time::HiRes: 0
29
29
  requires:
30
30
  perl: 5.004
31
- version: 12.42
31
+ version: 12.43
32
32
  x_serialization_backend: 'JSON::PP version 4.02'
package/bin/README CHANGED
@@ -107,8 +107,8 @@ your home directory, then you would type the following commands in a
107
107
  terminal window to extract and run ExifTool:
108
108
 
109
109
  cd ~/Desktop
110
- gzip -dc Image-ExifTool-12.42.tar.gz | tar -xf -
111
- cd Image-ExifTool-12.42
110
+ gzip -dc Image-ExifTool-12.43.tar.gz | tar -xf -
111
+ cd Image-ExifTool-12.43
112
112
  ./exiftool t/images/ExifTool.jpg
113
113
 
114
114
  Note: These commands extract meta information from one of the test images.
package/bin/exiftool CHANGED
@@ -11,7 +11,7 @@ use strict;
11
11
  use warnings;
12
12
  require 5.004;
13
13
 
14
- my $version = '12.42';
14
+ my $version = '12.43';
15
15
 
16
16
  # add our 'lib' directory to the include list BEFORE 'use Image::ExifTool'
17
17
  BEGIN {
@@ -5467,7 +5467,7 @@ with this command:
5467
5467
 
5468
5468
  produces output like this:
5469
5469
 
5470
- -- Generated by ExifTool 12.42 --
5470
+ -- Generated by ExifTool 12.43 --
5471
5471
  File: a.jpg - 2003:10:31 15:44:19
5472
5472
  (f/5.6, 1/60s, ISO 100)
5473
5473
  File: b.jpg - 2006:05:23 11:57:38
@@ -15,7 +15,7 @@ use vars qw($VERSION);
15
15
  use Image::ExifTool::Exif;
16
16
  use Image::ExifTool::PLIST;
17
17
 
18
- $VERSION = '1.05';
18
+ $VERSION = '1.06';
19
19
 
20
20
  # Apple iPhone metadata (ref PH)
21
21
  %Image::ExifTool::Apple::Main = (
@@ -66,7 +66,16 @@ $VERSION = '1.05';
66
66
  Writable => 'string',
67
67
  Notes => 'unique ID for all images in a burst',
68
68
  },
69
- # 0x000c - rational64s[2]: eg) "0.1640625 0.19921875"
69
+ 0x000c => { # ref forum13710 (Neal Krawetz)
70
+ Name => 'FocusDistanceRange',
71
+ Writable => 'rational64s',
72
+ Count => 2,
73
+ PrintConv => q{
74
+ my @a = split ' ', $val;
75
+ sprintf('%.2f - %.2f m', $a[0] <= $a[1] ? @a : reverse @a);
76
+ },
77
+ PrintConvInv => '$val =~ s/ - //; $val =~ s/ ?m$//; $val',
78
+ },
70
79
  # 0x000d - int32s: 0,1,6,20,24,32,40
71
80
  # 0x000e - int32s: 0,1,4,12 (Orientation? 0=landscape? 4=portrait? ref 1)
72
81
  # 0x000f - int32s: 2,3
@@ -88,7 +88,7 @@ sub ProcessCTMD($$$);
88
88
  sub ProcessExifInfo($$$);
89
89
  sub SwapWords($);
90
90
 
91
- $VERSION = '4.58';
91
+ $VERSION = '4.59';
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)
@@ -597,21 +597,23 @@ $VERSION = '4.58';
597
597
  '61182.19' => 'Canon RF 100-500mm F4.5-7.1L IS USM + RF1.4x',
598
598
  '61182.20' => 'Canon RF 100-500mm F4.5-7.1L IS USM + RF2x',
599
599
  '61182.21' => 'Canon RF 70-200mm F4L IS USM', #42
600
- '61182.22' => 'Canon RF 50mm F1.8 STM', #42
601
- '61182.23' => 'Canon RF 14-35mm F4L IS USM', #IB
602
- '61182.24' => 'Canon RF 100-400mm F5.6-8 IS USM', #42
603
- '61182.25' => 'Canon RF 100-400mm F5.6-8 IS USM + RF1.4x', #42 (NC)
604
- '61182.26' => 'Canon RF 100-400mm F5.6-8 IS USM + RF2x', #42 (NC)
605
- '61182.27' => 'Canon RF 16mm F2.8 STM', #42
606
- '61182.28' => 'Canon RF 400mm F2.8L IS USM', #IB
607
- '61182.29' => 'Canon RF 400mm F2.8L IS USM + RF1.4x', #IB
608
- '61182.30' => 'Canon RF 400mm F2.8L IS USM + RF2x', #IB
609
- '61182.31' => 'Canon RF 600mm F4L IS USM', #GiaZopatti
600
+ '61182.22' => 'Canon RF 100mm F2.8L MACRO IS USM', #42
601
+ '61182.23' => 'Canon RF 50mm F1.8 STM', #42
602
+ '61182.24' => 'Canon RF 14-35mm F4L IS USM', #IB
603
+ '61182.25' => 'Canon RF-S 18-45mm F4.5-6.3 IS STM', #42
604
+ '61182.26' => 'Canon RF 100-400mm F5.6-8 IS USM', #42
605
+ '61182.27' => 'Canon RF 100-400mm F5.6-8 IS USM + RF1.4x', #42 (NC)
606
+ '61182.28' => 'Canon RF 100-400mm F5.6-8 IS USM + RF2x', #42 (NC)
607
+ '61182.29' => 'Canon RF-S 18-150mm F3.5-6.3 IS STM', #42
608
+ '61182.30' => 'Canon RF 16mm F2.8 STM', #42
609
+ '61182.31' => 'Canon RF 400mm F2.8L IS USM', #IB
610
+ '61182.32' => 'Canon RF 400mm F2.8L IS USM + RF1.4x', #IB
611
+ '61182.33' => 'Canon RF 400mm F2.8L IS USM + RF2x', #IB
612
+ '61182.34' => 'Canon RF 600mm F4L IS USM', #GiaZopatti
610
613
  # we need the RFLensType values for the following...
611
- '61182.32' => 'Canon RF 800mm F5.6L IS USM', #PH (NC)
612
- '61182.33' => 'Canon RF 1200mm F8L IS USM', #PH (NC)
613
- '61182.34' => 'Canon RF 5.2mm F2.8L Dual Fisheye 3D VR', #PH (NC)
614
- '61182.35' => 'Canon RF 100mm F2.8L MACRO IS USM', #(NC)
614
+ '61182.35' => 'Canon RF 800mm F5.6L IS USM', #PH (NC)
615
+ '61182.36' => 'Canon RF 1200mm F8L IS USM', #PH (NC)
616
+ '61182.37' => 'Canon RF 5.2mm F2.8L Dual Fisheye 3D VR', #PH (NC)
615
617
  65535 => 'n/a',
616
618
  );
617
619
 
@@ -968,6 +970,8 @@ $VERSION = '4.58';
968
970
  0x80000437 => 'EOS 90D', #IB
969
971
  0x80000450 => 'EOS R3', #42
970
972
  0x80000453 => 'EOS R6', #PH
973
+ 0x80000464 => 'EOS R7', #42
974
+ 0x80000465 => 'EOS R10', #42
971
975
  0x80000467 => 'PowerShot ZOOM',
972
976
  0x80000468 => 'EOS M50 Mark II / Kiss M2', #IB
973
977
  0x80000520 => 'EOS D2000C', #IB
@@ -6530,23 +6534,23 @@ my %ciMaxFocal = (
6530
6534
  0x02 => 'FacesDetected',
6531
6535
  );
6532
6536
 
6533
- # G9 white balance information (MakerNotes tag 0x29) (ref IB)
6537
+ # G9 white balance information (MakerNotes tag 0x29) (ref IB, changed ref forum13640)
6534
6538
  %Image::ExifTool::Canon::WBInfo = (
6535
6539
  %binaryDataAttrs,
6536
6540
  NOTES => 'WB tags for the Canon G9.',
6537
6541
  FORMAT => 'int32u',
6538
6542
  FIRST_ENTRY => 1,
6539
6543
  GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
6540
- 0x02 => { Name => 'WB_GRGBLevelsAuto', Format => 'int32s[4]' },
6541
- 0x0a => { Name => 'WB_GRGBLevelsDaylight', Format => 'int32s[4]' },
6542
- 0x12 => { Name => 'WB_GRGBLevelsCloudy', Format => 'int32s[4]' },
6543
- 0x1a => { Name => 'WB_GRGBLevelsTungsten', Format => 'int32s[4]' },
6544
- 0x22 => { Name => 'WB_GRGBLevelsFluorescent', Format => 'int32s[4]' },
6545
- 0x2a => { Name => 'WB_GRGBLevelsFluorHigh', Format => 'int32s[4]' },
6546
- 0x32 => { Name => 'WB_GRGBLevelsFlash', Format => 'int32s[4]' },
6547
- 0x3a => { Name => 'WB_GRGBLevelsUnderwater', Format => 'int32s[4]' },
6548
- 0x42 => { Name => 'WB_GRGBLevelsCustom1', Format => 'int32s[4]' },
6549
- 0x4a => { Name => 'WB_GRGBLevelsCustom2', Format => 'int32s[4]' },
6544
+ 0x02 => { Name => 'WB_GRBGLevelsAuto', Format => 'int32s[4]' },
6545
+ 0x0a => { Name => 'WB_GRBGLevelsDaylight', Format => 'int32s[4]' },
6546
+ 0x12 => { Name => 'WB_GRBGLevelsCloudy', Format => 'int32s[4]' },
6547
+ 0x1a => { Name => 'WB_GRBGLevelsTungsten', Format => 'int32s[4]' },
6548
+ 0x22 => { Name => 'WB_GRBGLevelsFluorescent', Format => 'int32s[4]' },
6549
+ 0x2a => { Name => 'WB_GRBGLevelsFluorHigh', Format => 'int32s[4]' },
6550
+ 0x32 => { Name => 'WB_GRBGLevelsFlash', Format => 'int32s[4]' },
6551
+ 0x3a => { Name => 'WB_GRBGLevelsUnderwater', Format => 'int32s[4]' },
6552
+ 0x42 => { Name => 'WB_GRBGLevelsCustom1', Format => 'int32s[4]' },
6553
+ 0x4a => { Name => 'WB_GRBGLevelsCustom2', Format => 'int32s[4]' },
6550
6554
  );
6551
6555
 
6552
6556
  # yet more face detect information (MakerNotes tag 0x2f) - PH (G12)
@@ -6803,17 +6807,19 @@ my %ciMaxFocal = (
6803
6807
  276 => 'Canon RF 100-500mm F4.5-7.1L IS USM + RF1.4x',
6804
6808
  277 => 'Canon RF 100-500mm F4.5-7.1L IS USM + RF2x',
6805
6809
  278 => 'Canon RF 70-200mm F4L IS USM', #42
6810
+ 279 => 'Canon RF 100mm F2.8L MACRO IS USM', #42
6806
6811
  280 => 'Canon RF 50mm F1.8 STM', #42
6807
6812
  281 => 'Canon RF 14-35mm F4L IS USM', #42/IB
6813
+ 282 => 'Canon RF-S 18-45mm F4.5-6.3 IS STM', #42
6808
6814
  283 => 'Canon RF 100-400mm F5.6-8 IS USM', #42
6809
6815
  284 => 'Canon RF 100-400mm F5.6-8 IS USM + RF1.4x', #42 (NC)
6810
6816
  285 => 'Canon RF 100-400mm F5.6-8 IS USM + RF2x', #42 (NC)
6817
+ 286 => 'Canon RF-S 18-150mm F3.5-6.3 IS STM', #42
6811
6818
  288 => 'Canon RF 16mm F2.8 STM', #42
6812
6819
  289 => 'Canon RF 400mm F2.8L IS USM', #IB
6813
6820
  290 => 'Canon RF 400mm F2.8L IS USM + RF1.4x', #IB
6814
6821
  291 => 'Canon RF 400mm F2.8L IS USM + RF2x', #IB
6815
6822
  292 => 'Canon RF 600mm F4L IS USM', #GiaZopatti
6816
- #xxx => 'Canon RF 100mm F2.8L MACRO IS USM',
6817
6823
  # Note: add new RF lenses to %canonLensTypes with ID 61182
6818
6824
  },
6819
6825
  },
@@ -16,7 +16,7 @@ use Image::ExifTool::Exif;
16
16
  use Image::ExifTool::XMP;
17
17
  use Image::ExifTool::GPS;
18
18
 
19
- $VERSION = '1.05';
19
+ $VERSION = '1.06';
20
20
 
21
21
  sub ProcessDJIInfo($$$);
22
22
 
@@ -176,6 +176,7 @@ sub ProcessDJIInfo($$$)
176
176
  }
177
177
  while ($$dataPt =~ /\G\[(.*?)\](?=(\[|$))/sg) {
178
178
  my ($tag, $val) = split /:/, $1, 2;
179
+ next unless defined $tag and defined $val;
179
180
  if ($val =~ /^([\x20-\x7f]+)\0*$/) {
180
181
  $val = $1;
181
182
  } else {
@@ -15,7 +15,7 @@ use strict;
15
15
  use vars qw($VERSION);
16
16
  use Image::ExifTool::XMP;
17
17
 
18
- $VERSION = '1.06';
18
+ $VERSION = '1.07';
19
19
 
20
20
  my %dateTimeInfo = (
21
21
  # NOTE: Do NOT put "Groups" here because Groups hash must not be common!
@@ -138,6 +138,9 @@ my %event = (
138
138
  identificationVerificationStatus => { },
139
139
  identifiedBy => { },
140
140
  typeStatus => { },
141
+ # new, ref forum13707
142
+ identifiedByID => { },
143
+ verbatimIdentification => { },
141
144
  },
142
145
  },
143
146
  LivingSpecimen => { Struct => \%materialSample },
@@ -189,6 +192,10 @@ my %event = (
189
192
  recordNumber => { },
190
193
  reproductiveCondition => { },
191
194
  sex => { },
195
+ # new, ref forum13707
196
+ degreeOfEstablishment => { },
197
+ georeferenceVerificationStatus => { },
198
+ recordedByID => { },
192
199
  },
193
200
  },
194
201
  OccurrenceOccurrenceDetails => { Name => 'OccurrenceDetails', Flat => 1 },
@@ -242,6 +249,7 @@ my %event = (
242
249
  relationshipRemarks => { },
243
250
  resourceID => { },
244
251
  resourceRelationshipID => { },
252
+ relationshipOfResourceID => { }, # new, ref forum13707
245
253
  },
246
254
  },
247
255
  Taxon => {
@@ -255,6 +263,7 @@ my %event = (
255
263
  genus => { },
256
264
  higherClassification => { },
257
265
  infraspecificEpithet => { },
266
+ cultivarEpithet => { }, # new, ref forum13707
258
267
  kingdom => { },
259
268
  nameAccordingTo => { },
260
269
  nameAccordingToID => { },
@@ -338,6 +347,8 @@ my %event = (
338
347
  verbatimLongitude => { },
339
348
  verbatimSRS => { },
340
349
  waterBody => { },
350
+ # new, ref forum13707
351
+ verticalDatum => { },
341
352
  },
342
353
  },
343
354
  );
@@ -21,7 +21,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
21
21
  use Image::ExifTool::Exif;
22
22
  use Image::ExifTool::ASF; # for GetGUID()
23
23
 
24
- $VERSION = '1.39';
24
+ $VERSION = '1.40';
25
25
 
26
26
  sub ProcessFPX($$);
27
27
  sub ProcessFPXR($$$);
@@ -467,6 +467,19 @@ my %fpxFileType = (
467
467
  ByteOrder => 'BigEndian',
468
468
  },
469
469
  },
470
+ # recognize Autodesk Revit files by looking at BasicFileInfo
471
+ # (but don't yet support reading their metatdata)
472
+ BasicFileInfo => {
473
+ Name => 'BasicFileInfo',
474
+ Binary => 1,
475
+ RawConv => q{
476
+ $val =~ tr/\0//d; # brute force conversion to ASCII
477
+ if ($val =~ /\.(rfa|rft|rte|rvt)/) {
478
+ $self->OverrideFileType(uc($1), "application/$1", $1);
479
+ }
480
+ return $val;
481
+ },
482
+ },
470
483
  );
471
484
 
472
485
  # Summary Information properties
@@ -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.80';
34
+ $VERSION = '1.81';
35
35
 
36
36
  sub ProcessFujiDir($$$);
37
37
  sub ProcessFaceRec($$$);
@@ -689,8 +689,9 @@ my %faceCategories = (
689
689
  PrintConv => [{
690
690
  0 => 'None',
691
691
  1 => 'Optical', #PH
692
- 2 => 'Sensor-shift', #PH
692
+ 2 => 'Sensor-shift', #PH (now IBIS/OIS, ref forum13708)
693
693
  3 => 'OIS Lens', #forum9815 (optical+sensor?)
694
+ 258 => 'IBIS/OIS + DIS', #forum13708 (digital on top of IBIS/OIS)
694
695
  512 => 'Digital', #PH
695
696
  },{
696
697
  0 => 'Off',
@@ -841,6 +842,24 @@ my %faceCategories = (
841
842
  1 => 'Face',
842
843
  2 => 'Left Eye',
843
844
  3 => 'Right Eye',
845
+ 7 => 'Body',
846
+ 8 => 'Head',
847
+ 11 => 'Bike',
848
+ 12 => 'Body of Car',
849
+ 13 => 'Front of Car',
850
+ 14 => 'Animal Body',
851
+ 15 => 'Animal Head',
852
+ 16 => 'Animal Face',
853
+ 17 => 'Animal Left Eye',
854
+ 18 => 'Animal Right Eye',
855
+ 19 => 'Bird Body',
856
+ 20 => 'Bird Head',
857
+ 21 => 'Bird Left Eye',
858
+ 22 => 'Bird Right Eye',
859
+ 23 => 'Aircraft Body',
860
+ 25 => 'Aircraft Cockpit',
861
+ 26 => 'Train Front',
862
+ 27 => 'Train Cockpit',
844
863
  },'REPEAT'],
845
864
  },
846
865
  # 0x4202 int8u[-1] - number of cooredinates in each rectangle? (ref 11)
@@ -14,6 +14,7 @@
14
14
  # 2019/07/02 - PH Added ability to read IMU CSV files
15
15
  # 2019/11/10 - PH Also write pitch to CameraElevationAngle
16
16
  # 2020/12/01 - PH Added ability to read DJI CSV log files
17
+ # 2022/06/21 - PH Added ability to read Google Takeout JSON files
17
18
  #
18
19
  # References: 1) http://www.topografix.com/GPX/1/1/
19
20
  # 2) http://www.gpsinformation.org/dale/nmea.htm#GSA
@@ -28,7 +29,7 @@ use vars qw($VERSION);
28
29
  use Image::ExifTool qw(:Public);
29
30
  use Image::ExifTool::GPS;
30
31
 
31
- $VERSION = '1.66';
32
+ $VERSION = '1.68';
32
33
 
33
34
  sub JITTER() { return 2 } # maximum time jitter
34
35
 
@@ -133,7 +134,7 @@ sub LoadTrackLog($$;$)
133
134
  local ($_, $/, *EXIFTOOL_TRKFILE);
134
135
  my ($et, $val) = @_;
135
136
  my ($raf, $from, $time, $isDate, $noDate, $noDateChanged, $lastDate, $dateFlarm);
136
- my ($nmeaStart, $fixSecs, @fixTimes, $lastFix, %nmea, @csvHeadings);
137
+ my ($nmeaStart, $fixSecs, @fixTimes, $lastFix, %nmea, @csvHeadings, $sortFixes);
137
138
  my ($canCut, $cutPDOP, $cutHDOP, $cutSats, $e0, $e1, @tmp, $trackFile, $trackTime);
138
139
 
139
140
  unless (eval { require Time::Local }) {
@@ -285,6 +286,10 @@ sub LoadTrackLog($$;$)
285
286
  }
286
287
  }
287
288
  next;
289
+ } elsif (/"(timelineObjects|placeVisit|activitySegment|latitudeE7)":/) {
290
+ # Google Takeout JSON format
291
+ $format = 'JSON';
292
+ $sortFixes = 1; # (fixes are not all in order for this format)
288
293
  } else {
289
294
  # search only first 50 lines of file for a valid fix
290
295
  last if ++$skipped > 50;
@@ -506,6 +511,19 @@ DoneFix: $isDate = 1;
506
511
  goto DoneFix;
507
512
  }
508
513
  next;
514
+ } elsif ($format eq 'JSON') {
515
+ # Google Takeout JSON format
516
+ if (/"(latitudeE7|longitudeE7|latE7|lngE7|timestamp)":\s*"?(.*?)"?,?\s*[\x0d\x0a]/) {
517
+ if ($1 eq 'timestamp') {
518
+ $time = GetTime($2);
519
+ goto DoneFix if $time and $$fix{lat} and $$fix{lon};
520
+ } elsif ($1 eq 'latitudeE7' or $1 eq 'latE7') {
521
+ $$fix{lat} = $2 * 1e-7;
522
+ } else {
523
+ $$fix{lon} = $2 * 1e-7;
524
+ }
525
+ }
526
+ next;
509
527
  }
510
528
  my (%fix, $secs, $date, $nmea);
511
529
  if ($format eq 'NMEA') {
@@ -751,6 +769,8 @@ DoneFix: $isDate = 1;
751
769
  $numPoints -= $cutHDOP;
752
770
  $numPoints -= $cutSats;
753
771
  }
772
+ # sort fixes if necessary
773
+ @fixTimes = sort { $a <=> $b } @fixTimes if $sortFixes;
754
774
  # mark first fix of the track
755
775
  while (@fixTimes) {
756
776
  $fix = $$points{$fixTimes[0]} or shift(@fixTimes), next;
@@ -1409,8 +1429,8 @@ This module is used by Image::ExifTool
1409
1429
  This module loads GPS track logs, interpolates to determine position based
1410
1430
  on time, and sets new GPS values for geotagging images. Currently supported
1411
1431
  formats are GPX, NMEA RMC/GGA/GLL, KML, IGC, Garmin XML and TCX, Magellan
1412
- PMGNTRK, Honeywell PTNTHPR, Winplus Beacon text, IMU CSV, DJI CSV, and
1413
- Bramor gEO log files.
1432
+ PMGNTRK, Honeywell PTNTHPR, Bramor gEO, Winplus Beacon text, Google Takeout
1433
+ JSON, GPS/IMU CSV, DJI CSV, ExifTool CSV log files.
1414
1434
 
1415
1435
  Methods in this module should not be called directly. Instead, the Geotag
1416
1436
  feature is accessed by writing the values of the ExifTool Geotag, Geosync
@@ -15,7 +15,7 @@ use strict;
15
15
  use vars qw($VERSION);
16
16
  use Image::ExifTool qw(:DataAccess :Utils);
17
17
 
18
- $VERSION = '1.07';
18
+ $VERSION = '1.08';
19
19
 
20
20
  sub ProcessItemID($$$);
21
21
  sub ProcessLinkInfo($$$);
@@ -273,7 +273,9 @@ sub ProcessLinkInfo($$$);
273
273
  6 => 'Ram Disk',
274
274
  },
275
275
  },
276
- DriveSerialNumber => { },
276
+ DriveSerialNumber => {
277
+ PrintConv => 'join("-", unpack("A4 A4", sprintf("%08X", $val)))',
278
+ },
277
279
  VolumeLabel => { },
278
280
  LocalBasePath => { },
279
281
  CommonNetworkRelLink => { },
@@ -508,6 +510,7 @@ sub ProcessLinkInfo($$$)
508
510
  if ($off + 0x20 <= $dataLen) {
509
511
  # my $len = Get32u($dataPt, $off);
510
512
  $et->HandleTag($tagTablePtr, 'DriveType', undef, %opts, Start=>$off+4);
513
+ $et->HandleTag($tagTablePtr, 'DriveSerialNumber', undef, %opts, Start=>$off+8);
511
514
  $pos = Get32u($dataPt, $off + 0x0c);
512
515
  if ($pos == 0x14) {
513
516
  # use VolumeLabelOffsetUnicode instead
@@ -63,7 +63,7 @@ use Image::ExifTool::Exif;
63
63
  use Image::ExifTool::GPS;
64
64
  use Image::ExifTool::XMP;
65
65
 
66
- $VERSION = '4.06';
66
+ $VERSION = '4.07';
67
67
 
68
68
  sub LensIDConv($$$);
69
69
  sub ProcessNikonAVI($$$);
@@ -606,6 +606,7 @@ sub GetAFPointGrid($$;$);
606
606
  'CC 44 68 98 34 41 DF 0E' => 'Tamron 100-400mm f/4.5-6.3 Di VC USD', #30
607
607
  'EB 40 76 A6 38 40 DF 0E' => 'Tamron SP AF 150-600mm f/5-6.3 VC USD (A011)',
608
608
  'E3 40 76 A6 38 40 DF 4E' => 'Tamron SP 150-600mm f/5-6.3 Di VC USD G2', #30
609
+ 'E3 40 76 A6 38 40 DF 0E' => 'Tamron SP 150-600mm f/5-6.3 Di VC USD G2 (A022)', #forum3833
609
610
  '20 3C 80 98 3D 3D 1E 02' => 'Tamron AF 200-400mm f/5.6 LD IF (75D)',
610
611
  '00 3E 80 A0 38 3F 00 02' => 'Tamron SP AF 200-500mm f/5-6.3 Di LD (IF) (A08)',
611
612
  '00 3F 80 A0 38 3F 00 02' => 'Tamron SP AF 200-500mm f/5-6.3 Di (A08)',
@@ -4026,7 +4027,7 @@ my %base64coord = (
4026
4027
  },
4027
4028
  Format => 'int16u',
4028
4029
  },
4029
- 0x2f => { #28 (Z7) Still photography range 1-17 for the 493 point Z7 (arranged in a 29x17 grid. Center at x=16, y=10).
4030
+ 0x2f => { #28 (Z7) Still photography range 1-17 for the 493 point Z7 (arranged in a 29x17 grid. Center at x=16, y=10).
4030
4031
  Name => 'AFFocusPointXPosition',
4031
4032
  Condition => q{
4032
4033
  $$self{ContrastDetectAF} == 2 and $$self{AFInfo2Version} =~ /^03/ or
@@ -4194,11 +4195,19 @@ my %base64coord = (
4194
4195
  },
4195
4196
  0x43 => {
4196
4197
  Name => 'FocusPositionHorizontal',
4197
- PrintConv => sub { my ($val) = @_; PrintAFPointsLeftRight($val, 29 ); }, #493 focus points for Z9 fall in a 30x18 grid (some coordinates are not accessible)
4198
+ Notes => q{
4199
+ the focus points form a 29x17 grid, but the X,Y coordinate values run from 1,1
4200
+ to 30,19. The horizontal coordinate 11R (5) and the vertical coordinates 6U
4201
+ (4) and 2D (12) are not used for some reason
4202
+ },
4203
+ # 493 focus points for Z9 fall in a 30x19 grid
4204
+ # (the 11R (5) position is not used, for a total of 29 columns, ref AlbertShan email)
4205
+ PrintConv => sub { my ($val) = @_; PrintAFPointsLeftRight($val, 29); },
4198
4206
  },
4199
4207
  0x45 => {
4200
4208
  Name => 'FocusPositionVertical',
4201
- PrintConv => sub { my ($val) = @_; PrintAFPointsUpDown($val, 17 ); },
4209
+ # (the 6U (4) and 2D (12) are not used, for a total of 17 rows, ref AlbertShan email)
4210
+ PrintConv => sub { my ($val) = @_; PrintAFPointsUpDown($val, 17); },
4202
4211
  },
4203
4212
  0x46 => {
4204
4213
  Name => 'AFAreaWidth',
@@ -11316,7 +11325,7 @@ sub PrintAFPointsGridInv($$$)
11316
11325
  #------------------------------------------------------------------------------
11317
11326
  # Print conversion for relative Left/Right AF points (ref 28)
11318
11327
  # Inputs: 0) column, 1) number of columns
11319
- # Returns: AF point data as a string (e.g. '2L' or 'C' or '3R')
11328
+ # Returns: AF point data as a string (e.g. '2L of Center' or 'C' or '3R of Center')
11320
11329
  sub PrintAFPointsLeftRight($$)
11321
11330
  {
11322
11331
  my ($col, $ncol) = @_;
@@ -11329,7 +11338,7 @@ sub PrintAFPointsLeftRight($$)
11329
11338
  #------------------------------------------------------------------------------
11330
11339
  # Print conversion for relative Up/Down AF points (ref 28)
11331
11340
  # Inputs: 0) row, 1) number of rows
11332
- # Returns: AF point data as a string (e.g. '2U' or 'C' or '3D')
11341
+ # Returns: AF point data as a string (e.g. '2U from Center' or 'C' or '3D from Center')
11333
11342
  sub PrintAFPointsUpDown($$)
11334
11343
  {
11335
11344
  my ($row, $nrow) = @_;
@@ -1919,7 +1919,7 @@ my %indexInfo = (
1919
1919
  PrintConv => [{
1920
1920
  0 => 'Off',
1921
1921
  1 => 'Motorsports',
1922
- 2 => 'Airplnes',
1922
+ 2 => 'Airplanes',
1923
1923
  3 => 'Trains',
1924
1924
  4 => 'Birds',
1925
1925
  5 => 'Dogs & Cats',
@@ -6,6 +6,7 @@
6
6
  # Revisions: 2019-10-23 - P. Harvey Created
7
7
  #
8
8
  # References: 1) https://developer.parrot.com/docs/pdraw/metadata.html
9
+ # --> changed to https://developer.parrot.com/docs/pdraw/video-metadata.html
9
10
  #------------------------------------------------------------------------------
10
11
 
11
12
  package Image::ExifTool::Parrot;
@@ -80,7 +80,7 @@ my %processByMetaFormat = (
80
80
 
81
81
  # data lengths for each INSV record type
82
82
  my %insvDataLen = (
83
- 0x300 => 56, # accelerometer
83
+ 0x300 => 0, # accelerometer (could be either 20 or 56 bytes)
84
84
  0x400 => 16, # exposure (ref 6)
85
85
  0x600 => 8, # timestamps (ref 6)
86
86
  0x700 => 53, # GPS
@@ -2621,8 +2621,33 @@ sub ProcessInsta360($;$)
2621
2621
  if ($verbose) {
2622
2622
  $et->VPrint(0, sprintf("Insta360 Record 0x%x (offset 0x%x, %d bytes):\n", $id, $fileEnd + $epos, $len));
2623
2623
  }
2624
+ # there are 2 types of record 0x300:
2625
+ # 1. 56 byte records
2626
+ # 0000: 4a f7 02 00 00 00 00 00 00 00 00 00 00 1e e7 3f [J..............?]
2627
+ # 0010: 00 00 00 00 00 b2 ef bf 00 00 00 00 00 70 c1 bf [.............p..]
2628
+ # 0020: 00 00 00 e0 91 5c 8c bf 00 00 00 20 8f ff 87 bf [.....\..... ....]
2629
+ # 0030: 00 00 00 00 88 7f c9 bf
2630
+ # 2. 20 byte records
2631
+ # 0000: c1 d8 d9 0b 00 00 00 00 f5 83 14 80 df 7f fe 7f [................]
2632
+ # 0010: fe 7f 01 80
2633
+ if ($id == 0x300) {
2634
+ if ($len % 20 and not $len % 56) {
2635
+ $dlen = 56;
2636
+ } elsif ($len % 56 and not $len % 20) {
2637
+ $dlen = 20;
2638
+ } else {
2639
+ if ($raf->Read($buff, 20) == 20) {
2640
+ if (substr($buff, 16, 3) eq "\0\0\0") {
2641
+ $dlen = 56;
2642
+ } else {
2643
+ $dlen = 20;
2644
+ }
2645
+ }
2646
+ $raf->Seek($epos, 2) or last;
2647
+ }
2648
+ }
2624
2649
  # limit the number of records we read if necessary
2625
- if ($insvLimit{$id} and $len > $insvLimit{$id}[1] * $dlen and
2650
+ if ($dlen and $insvLimit{$id} and $len > $insvLimit{$id}[1] * $dlen and
2626
2651
  $et->Warn("Insta360 $insvLimit{$id}[0] data is huge. Processing only the first $insvLimit{$id}[1] records",2))
2627
2652
  {
2628
2653
  $len = $insvLimit{$id}[1] * $dlen;
@@ -2630,11 +2655,18 @@ sub ProcessInsta360($;$)
2630
2655
  $raf->Read($buff, $len) == $len or last;
2631
2656
  $et->VerboseDump(\$buff) if $verbose > 2;
2632
2657
  if ($dlen) {
2633
- $len % $dlen and $et->Warn(sprintf('Unexpected Insta360 record 0x%x length',$id)), last;
2634
- if ($id == 0x300) {
2658
+ if ($len % $dlen) {
2659
+ $et->Warn(sprintf('Unexpected Insta360 record 0x%x length',$id));
2660
+ } elsif ($id == 0x300) {
2635
2661
  for ($p=0; $p<$len; $p+=$dlen) {
2636
2662
  $$et{DOC_NUM} = ++$$et{DOC_COUNT};
2637
- my @a = map { GetDouble(\$buff, $p + 8 * $_) } 1..6;
2663
+ my @a;
2664
+ if ($dlen == 56) {
2665
+ @a = map { GetDouble(\$buff, $p + 8 * $_) } 1..6;
2666
+ } else {
2667
+ @a = unpack("x${p}x8v6", $buff);
2668
+ map { $_ = ($_ - 0x8000) / 1000 } @a;
2669
+ }
2638
2670
  $et->HandleTag($tagTbl, TimeCode => sprintf('%.3f', Get64u(\$buff, $p) / 1000));
2639
2671
  $et->HandleTag($tagTbl, Accelerometer => "@a[0..2]"); # (NC)
2640
2672
  $et->HandleTag($tagTbl, AngularVelocity => "@a[3..5]"); # (NC)
@@ -2668,7 +2700,7 @@ sub ProcessInsta360($;$)
2668
2700
  $a[$_] = GetDouble(\$a[$_], 0) foreach 4,6,8,9,10;
2669
2701
  $a[4] = -abs($a[4]) if $a[5] eq 'S'; # (abs just in case it was already signed)
2670
2702
  $a[6] = -abs($a[6]) if $a[7] ne 'E';
2671
- $et->HandleTag($tagTbl, GPSDateTime => Image::ExifTool::ConvertUnixTime($a[0]) . 'Z');
2703
+ $et->HandleTag($tagTbl, GPSDateTifme => Image::ExifTool::ConvertUnixTime($a[0]) . 'Z');
2672
2704
  $et->HandleTag($tagTbl, GPSLatitude => $a[4]);
2673
2705
  $et->HandleTag($tagTbl, GPSLongitude => $a[6]);
2674
2706
  $et->HandleTag($tagTbl, GPSSpeed => $a[8] * $mpsToKph);
@@ -531,7 +531,8 @@ numerical, and generated automatically otherwise.
531
531
  SubIFD's where the PutFirst flag is valid.
532
532
 
533
533
  'Unknown' - this is an unknown tag (only extracted when the
534
- Unknown option is set).
534
+ Unknown option is set). This is set to 2 for Unknown tags in
535
+ binary tables (extracted when Unknown is 2).
535
536
 
536
537
  'WriteNothing' - flag indicating that nothing is actually
537
538
  written when this tag is set. It is a fake writable tag that
@@ -975,6 +976,9 @@ numerical, and generated automatically otherwise.
975
976
  alternate language tags (eg. 'fr'). Only used with formats
976
977
  which support alternate languages (eg. XMP, MIE, etc).
977
978
 
979
+ AddedUnknown : [reserved] Used internally to mark Unknown tags that were
980
+ added to the table at run time.
981
+
978
982
  SubDirectory { If it exists, this specifies the start of a new subdirectory.
979
983
  It contains a collection of variables which specify the type
980
984
  and location of the subdirectory. Note that ValueConv and