exiftool_vendored 13.38.0 → 13.41.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.
@@ -35,7 +35,7 @@ use vars qw($VERSION);
35
35
  use Image::ExifTool qw(:Public);
36
36
  use Image::ExifTool::GPS;
37
37
 
38
- $VERSION = '1.82';
38
+ $VERSION = '1.83';
39
39
 
40
40
  sub JITTER() { return 2 } # maximum time jitter
41
41
 
@@ -1345,6 +1345,23 @@ Category: foreach $category (qw{pos track alt orient atemp err dop}) {
1345
1345
  if (defined $dop) {
1346
1346
  $et->SetNewValue(GPSMeasureMode => $mm, %opts);
1347
1347
  $et->SetNewValue(GPSDOP => $dop, %opts);
1348
+ # also set GPSHPositioningError if specified
1349
+ my $hposErr = $$et{OPTIONS}{GeoHPosErr};
1350
+ if ($hposErr) {
1351
+ $hposErr =~ s/gpsdop/GPSDOP/i;
1352
+ my $GPSDOP = $dop;
1353
+ local $SIG{'__WARN__'} = \&Image::ExifTool::SetWarning;
1354
+ undef $Image::ExifTool::evalWarning;
1355
+ #### eval GeoHPosErr ($GPSDOP)
1356
+ $hposErr = eval $hposErr;
1357
+ my $err = Image::ExifTool::GetWarning() || $@;
1358
+ if ($err) {
1359
+ $err = Image::ExifTool::CleanWarning($err);
1360
+ $et->Warn("Error calculating GPSHPositioningError: $err", 1);
1361
+ } else {
1362
+ $et->SetNewValue(GPSHPositioningError => $hposErr, %opts);
1363
+ }
1364
+ }
1348
1365
  }
1349
1366
  }
1350
1367
  unless ($xmp) {
@@ -26,7 +26,7 @@ use strict;
26
26
  use vars qw($VERSION);
27
27
  use Image::ExifTool qw(:DataAccess :Utils);
28
28
 
29
- $VERSION = '1.41';
29
+ $VERSION = '1.42';
30
30
 
31
31
  sub ProcessICC($$);
32
32
  sub ProcessICC_Profile($$$);
@@ -330,6 +330,7 @@ my %manuSig = ( #6
330
330
  'WTG2' => 'Ware To Go',
331
331
  'WYSE' => 'WYSE Technology',
332
332
  'XERX' => 'Xerox Corporation',
333
+ 'XM ' => 'Xiaomi',
333
334
  'XRIT' => 'X-Rite',
334
335
  'yxym' => 'YxyMaster GmbH',
335
336
  'Z123' => "Lavanya's test Company",
@@ -4,6 +4,7 @@
4
4
  # Description: Read meta information from MS Shell Link files
5
5
  #
6
6
  # Revisions: 2009/09/19 - P. Harvey Created
7
+ # 2025/10/20 - PH Added .URL file support
7
8
  #
8
9
  # References: 1) http://msdn.microsoft.com/en-us/library/dd871305(PROT.10).aspx
9
10
  # 2) http://www.i2s-lab.com/Papers/The_Windows_Shortcut_File_Format.pdf
@@ -17,7 +18,7 @@ use vars qw($VERSION);
17
18
  use Image::ExifTool qw(:DataAccess :Utils);
18
19
  use Image::ExifTool::Microsoft;
19
20
 
20
- $VERSION = '1.11';
21
+ $VERSION = '1.13';
21
22
 
22
23
  sub ProcessItemID($$$);
23
24
  sub ProcessLinkInfo($$$);
@@ -190,7 +191,7 @@ sub ProcessLinkInfo($$$);
190
191
  },
191
192
  0xa0000001 => {
192
193
  Name => 'EnvVarData',
193
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
194
+ SubDirectory => { TagTable => 'Image::ExifTool::LNK::EnvVarData' },
194
195
  },
195
196
  0xa0000002 => {
196
197
  Name => 'ConsoleData',
@@ -447,6 +448,52 @@ sub ProcessLinkInfo($$$);
447
448
  },
448
449
  );
449
450
 
451
+ %Image::ExifTool::LNK::EnvVarData = (
452
+ PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
453
+ GROUPS => { 2 => 'Other' },
454
+ 8 => {
455
+ Name => 'EnvironmentTarget',
456
+ Format => 'string[260]',
457
+ },
458
+ 268 => {
459
+ Name => 'EnvironmentTargetUnicode',
460
+ Format => 'unicode[260]',
461
+ },
462
+ );
463
+
464
+ %Image::ExifTool::LNK::INI = (
465
+ GROUPS => { 2 => 'Document' },
466
+ VARS => { ID_FMT => 'none' },
467
+ NOTES => 'Tags found in INI-format Windows .URL files.',
468
+ URL => { },
469
+ IconFile => { },
470
+ IconIndex => { },
471
+ WorkingDirectory => { },
472
+ HotKey => { },
473
+ ShowCommand => { PrintConv => { 1 => 'Normal', 2 => 'Minimized', 3 => 'Maximized' } },
474
+ Modified => {
475
+ Groups => { 2 => 'Time' },
476
+ Format => 'int64u',
477
+ Groups => { 2 => 'Time' },
478
+ # convert time from 100-ns intervals since Jan 1, 1601 (NC)
479
+ RawConv => q{
480
+ my $dat = pack('H*', $val);
481
+ return undef if length $dat < 8;
482
+ my ($lo, $hi) = unpack('V2', $dat);
483
+ return undef unless $lo or $hi;
484
+ return $hi * 4294967296 + $lo;
485
+ },
486
+ ValueConv => '$val=$val/1e7-11644473600; ConvertUnixTime($val,1)',
487
+ PrintConv => '$self->ConvertDateTime($val)',
488
+ },
489
+ Author => { Groups => { 2 => 'Author' } },
490
+ WhatsNew => { },
491
+ Comment => { },
492
+ Desc => { },
493
+ Roamed => { Notes => '1 if synced across multiple devices' },
494
+ IDList => { },
495
+ );
496
+
450
497
  #------------------------------------------------------------------------------
451
498
  # Extract null-terminated ASCII or Unicode string from buffer
452
499
  # Inputs: 0) buffer ref, 1) start position, 2) flag for unicode string
@@ -588,6 +635,27 @@ sub ProcessLinkInfo($$$)
588
635
  return 1;
589
636
  }
590
637
 
638
+ #------------------------------------------------------------------------------
639
+ # Extract information from a INI-format file
640
+ # Inputs: 0) ExifTool object reference, 1) dirInfo reference
641
+ # Returns: 1 on success, 0 if this wasn't a valid INI file
642
+ sub ProcessINI($$)
643
+ {
644
+ my ($et, $dirInfo) = @_;
645
+ my $raf = $$dirInfo{RAF};
646
+ my $buff;
647
+ local $/ = "\x0d\x0a";
648
+ my $tagTablePtr = GetTagTable('Image::ExifTool::LNK::INI');
649
+ while ($raf->ReadLine($buff)) {
650
+ if ($buff =~ /^\[(.*?)\]/) {
651
+ $et->VPrint(0, "$1 section:\n");
652
+ } elsif ($buff =~ /^\s*(\w+)=(.*)\x0d\x0a$/) {
653
+ $et->HandleTag($tagTablePtr, $1, $2, MakeTagInfo => 1);
654
+ }
655
+ }
656
+ return 1;
657
+ }
658
+
591
659
  #------------------------------------------------------------------------------
592
660
  # Extract information from a MS Shell Link (Windows shortcut) file
593
661
  # Inputs: 0) ExifTool object reference, 1) dirInfo reference
@@ -600,7 +668,13 @@ sub ProcessLNK($$)
600
668
 
601
669
  # read LNK file header
602
670
  $raf->Read($buff, 0x4c) == 0x4c or return 0;
603
- $buff =~ /^.{4}\x01\x14\x02\0{5}\xc0\0{6}\x46/s or return 0;
671
+ unless ($buff =~ /^.{4}\x01\x14\x02\0{5}\xc0\0{6}\x46/s) {
672
+ # check for INI-format LNK file (eg. .URL file)
673
+ return undef unless $buff =~ /^\[[InternetShortcut\][\x0d\x0a]/;
674
+ $raf->Seek(0,0) or return 0;
675
+ $et->SetFileType('URL', 'application/x-mswinurl');
676
+ return ProcessINI($et, $dirInfo);
677
+ };
604
678
  $len = unpack('V', $buff);
605
679
  $len >= 0x4c or return 0;
606
680
  if ($len > 0x4c) {
@@ -14,7 +14,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
14
14
  use Image::ExifTool::XMP;
15
15
  use Image::ExifTool::ZIP;
16
16
 
17
- $VERSION = '1.09';
17
+ $VERSION = '1.10';
18
18
 
19
19
  # test for recognized OOXML document extensions
20
20
  my %isOOXML = (
@@ -27,6 +27,7 @@ my %isOOXML = (
27
27
  XLAM => 1,
28
28
  XLSX => 1, XLSM => 1, XLSB => 1,
29
29
  XLTX => 1, XLTM => 1,
30
+ VSDX => 1,
30
31
  );
31
32
 
32
33
  # generate reverse lookup for file type based on MIME
@@ -57,7 +58,7 @@ my @vectorVals;
57
58
  VARS => { ID_FMT => 'none' },
58
59
  NOTES => q{
59
60
  The Office Open XML (OOXML) format was introduced with Microsoft Office 2007
60
- and is used by file types such as DOCX, PPTX and XLSX. These are
61
+ and is used by file types such as DOCX, PPTX, XLSX and VSDX. These are
61
62
  essentially ZIP archives containing XML files. The table below lists some
62
63
  tags which have been observed in OOXML documents, but ExifTool will extract
63
64
  any tags found from XML files of the OOXML document properties ("docProps")
@@ -31,6 +31,7 @@
31
31
  # 25) Karsten Gieselmann private communication (OM series)
32
32
  # IB) Iliah Borg private communication (LibRaw)
33
33
  # NJ) Niels Kristian Bech Jensen private communication
34
+ # KG) Karsten Gieselmann private communication
34
35
  #------------------------------------------------------------------------------
35
36
 
36
37
  package Image::ExifTool::Olympus;
@@ -41,7 +42,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
41
42
  use Image::ExifTool::Exif;
42
43
  use Image::ExifTool::APP12;
43
44
 
44
- $VERSION = '2.91';
45
+ $VERSION = '2.93';
45
46
 
46
47
  sub PrintLensInfo($$$);
47
48
 
@@ -200,7 +201,9 @@ my %olympusLensTypes = (
200
201
  # '65535 07 40' - Seen for LUMIX S 16-35/F4 on Panasonic DC-S1H (ref PH)
201
202
  # Other makes
202
203
  '24 01 10' => 'Venus Optics Laowa 50mm F2.8 2x Macro', #DonKomarechka
203
- 'f7 03 10' => 'LAOWA C&D-Dreamer MFT 7.5mm F2.0', #forum3833
204
+ '247 03 10' => 'LAOWA C&D-Dreamer MFT 7.5mm F2.0', #forum3833
205
+ '247 10 10' => 'LAOWA C&D-Dreamer MFT 6.0mm F2.0', #KG
206
+ '65522 02 10' => 'Xiaoyi 42.5mm F1.8', #github363
204
207
  );
205
208
 
206
209
  # lookup for Olympus camera types (ref PH)
@@ -59,7 +59,7 @@ use Image::ExifTool::Exif;
59
59
  use Image::ExifTool::GPS;
60
60
  use Image::ExifTool::HP;
61
61
 
62
- $VERSION = '3.58';
62
+ $VERSION = '3.59';
63
63
 
64
64
  sub CryptShutterCount($$);
65
65
  sub PrintFilter($$$);
@@ -1947,7 +1947,8 @@ my %binaryDataAttrs = (
1947
1947
  '0 28' => 'Quick Macro', # (Q)
1948
1948
  '0 29' => 'Forest', # (Q)
1949
1949
  '0 30' => 'Backlight Silhouette', # (Q)
1950
- '0 32' => 'DOF', #PH (GR III)
1950
+ '0 31' => 'Max. Aperture Priority', #KG (Ricoh GR III)
1951
+ '0 32' => 'DOF', #PH (GR III) #KG ???? GR III 'DOF Priority (Deep)' is mapped to '0 2' ???
1951
1952
  # AUTO PICT modes (auto-selected)
1952
1953
  '1 4' => 'Auto PICT (Standard)', #13
1953
1954
  '1 5' => 'Auto PICT (Portrait)', #7 (K100D)
@@ -1962,7 +1963,11 @@ my %binaryDataAttrs = (
1962
1963
  '2 22' => 'Shallow DOF (HyP)', #PH (K-5)
1963
1964
  '3 0' => 'Green Mode', #16
1964
1965
  '4 0' => 'Shutter Speed Priority',
1966
+ '4 2' => 'Shutter Speed Priority 2', #KG Coding error? 'DOF Priority' in Tv makes no sense
1967
+ '4 31' => 'Shutter Speed Priority 31',#KG Coding error? 'Max Aperture' in Tv makes no sense
1965
1968
  '5 0' => 'Aperture Priority',
1969
+ '5 2' => 'Aperture Priority 2', #KG Coding error? 'DOF Priority' in Av makes no sense
1970
+ '5 31' => 'Aperture Priority 31', #KG Coding error? 'DOF Priority' in Av makes no sense
1966
1971
  '6 0' => 'Program Tv Shift',
1967
1972
  '7 0' => 'Program Av Shift', #19
1968
1973
  '8 0' => 'Manual',
@@ -49,7 +49,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
49
49
  use Image::ExifTool::Exif;
50
50
  use Image::ExifTool::GPS;
51
51
 
52
- $VERSION = '3.21';
52
+ $VERSION = '3.23';
53
53
 
54
54
  sub ProcessMOV($$;$);
55
55
  sub ProcessKeys($$$);
@@ -578,11 +578,29 @@ my %userDefined = (
578
578
  return substr($val, 8, $len-8);
579
579
  },
580
580
  Binary => 1,
581
+ },{
582
+ Name => 'HighlightMarkers',
583
+ # (DJI Action 4, forum17700)
584
+ Notes => 'written by some DJI models',
585
+ Condition => '$$valPt =~ /^data.{4}hglg.{5}/s',
586
+ RawConv => q{
587
+ my $len = unpack 'x4N', $val;
588
+ return undef if $len < 13 or $len + 4 > length($val);
589
+ my $n = int(($len - 13) / 5);
590
+ my @a = map $_/1000, unpack "x17(xV)$n", $val;
591
+ return \@a;
592
+ },
581
593
  },{
582
594
  Unknown => 1,
583
595
  Binary => 1,
584
596
  },
585
- # (also Samsung WB750 uncompressed thumbnail data starting with "SDIC\0")
597
+ # DJI videos also have block of offset/size of various atoms, eg)
598
+ # Atom name ???? Offset Size
599
+ # 0000: 63 6f 76 72 00 00 00 00 00 ed 6f da 00 0a 46 e0 [covr......o...F.]
600
+ # 0010: 73 6e 61 6c 00 00 00 00 00 f7 b6 d2 00 0a 46 e0 [snal..........F.]
601
+ # 0020: 68 67 6c 67 00 00 00 00 01 02 0a a2 00 00 00 21 [hglg...........!]
602
+ # 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
603
+ # (also Samsung WB750 uncompressed thumbnail data starting with "SDIC\0")
586
604
  ],
587
605
  # fre1 - 4 bytes: "june" (Kodak PixPro SP360)
588
606
  frea => {
@@ -10515,9 +10533,9 @@ ItemID: foreach $id (reverse sort { $a <=> $b } keys %$items) {
10515
10533
  $et->Warn($warnStr);
10516
10534
  }
10517
10535
  }
10518
- # tweak file type based on track content ("iso*" and "dash" ftyp only)
10536
+ # tweak file type based on track content ("iso*" and "dash" ftyp only ["mp42" added in 13.39])
10519
10537
  if ($topLevel and $$et{FileType} and $$et{FileType} eq 'MP4' and
10520
- $$et{save_ftyp} and $$et{HasHandler} and $$et{save_ftyp} =~ /^(iso|dash)/ and
10538
+ $$et{save_ftyp} and $$et{HasHandler} and $$et{save_ftyp} =~ /^(iso|dash|mp42)/ and
10521
10539
  $$et{HasHandler}{soun} and not $$et{HasHandler}{vide})
10522
10540
  {
10523
10541
  $et->OverrideFileType('M4A', 'audio/mp4');
@@ -111,7 +111,7 @@ my %insvLimit = (
111
111
  The tags below are extracted from timed metadata in QuickTime and other
112
112
  formats of video files when the ExtractEmbedded option is used. Although
113
113
  most of these tags are combined into the single table below, ExifTool
114
- currently reads 111 different types of timed GPS metadata from video files.
114
+ currently reads 116 different types of timed GPS metadata from video files.
115
115
  },
116
116
  GPSLatitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', RawConv => '$$self{FoundGPSLatitude} = 1; $val' },
117
117
  GPSLongitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")' },
@@ -1006,6 +1006,28 @@ sub HandleTextTags($$$)
1006
1006
  undef %$tags; # clear the hash
1007
1007
  }
1008
1008
 
1009
+ #------------------------------------------------------------------------------
1010
+ # Handle new time in NMEA stream and store queued tags if necessary
1011
+ # Inputs: 0) ExifTool ref, 1) time string, 2) tag table ref, 3) tags hash
1012
+ sub HandleNewTime($$$$)
1013
+ {
1014
+ my ($et, $time, $tagTbl, $tags) = @_;
1015
+ if ($$et{LastTime}) {
1016
+ if ($$et{LastTime} eq $time) {
1017
+ # combine with the previous NMEA sentence
1018
+ $$et{DOC_NUM} = $$et{LastDoc};
1019
+ } elsif (%$tags) {
1020
+ # handle existing tags and start a new document
1021
+ # (see https://exiftool.org/forum/index.php?msg=75422)
1022
+ HandleTextTags($et, $tagTbl, $tags);
1023
+ # increment document number and update document count if necessary
1024
+ $$et{DOC_COUNT} < ++$$et{DOC_NUM} and $$et{DOC_COUNT} = $$et{DOC_NUM};
1025
+ }
1026
+ }
1027
+ $$et{LastTime} = $time;
1028
+ $$et{LastDoc} = $$et{DOC_NUM};
1029
+ }
1030
+
1009
1031
  #------------------------------------------------------------------------------
1010
1032
  # Process subtitle 'text'
1011
1033
  # Inputs: 0) ExifTool ref, 1) data ref or dirInfo ref, 2) tag table ref
@@ -1032,41 +1054,18 @@ sub Process_text($$$;$)
1032
1054
  next;
1033
1055
  }
1034
1056
  my $time = "$1:$2:$3";
1035
- if ($$et{LastTime}) {
1036
- if ($$et{LastTime} eq $time) {
1037
- # combine with the previous NMEA sentence
1038
- $$et{DOC_NUM} = $$et{LastDoc};
1039
- } elsif (%tags) {
1040
- # handle existing tags and start a new document
1041
- # (see https://exiftool.org/forum/index.php?msg=75422)
1042
- HandleTextTags($et, $tagTbl, \%tags);
1043
- undef %tags;
1044
- # increment document number and update document count if necessary
1045
- $$et{DOC_COUNT} < ++$$et{DOC_NUM} and $$et{DOC_COUNT} = $$et{DOC_NUM};
1046
- }
1047
- }
1048
- $$et{LastTime} = $time;
1049
- $$et{LastDoc} = $$et{DOC_NUM};
1057
+ HandleNewTime($et, $time, $tagTbl, \%tags);
1050
1058
  my $year = $14 + ($14 >= 70 ? 1900 : 2000);
1051
- my $dateTime = sprintf('%.4d:%.2d:%.2d %sZ', $year, $13, $12, $time);
1052
- $tags{GPSDateTime} = $dateTime;
1059
+ my $date = sprintf('%.4d:%.2d:%.2d', $year, $13, $12);
1060
+ $$et{LastDate} = $date;
1061
+ $tags{GPSDateTime} = "$date ${time}Z";
1053
1062
  $tags{GPSLatitude} = (($4 || 0) + $5/60) * ($6 eq 'N' ? 1 : -1);
1054
1063
  $tags{GPSLongitude} = (($7 || 0) + $8/60) * ($9 eq 'E' ? 1 : -1);
1055
1064
  $tags{GPSSpeed} = $10 * $knotsToKph if length $10;
1056
1065
  $tags{GPSTrack} = $11 if length $11;
1057
1066
  } elsif ($tag =~ /^[A-Z]{2}GGA$/ and $dat =~ /^,(\d{2})(\d{2})(\d+(?:\.\d*)?),(\d*?)(\d{1,2}\.\d+),([NS]),(\d*?)(\d{1,2}\.\d+),([EW]),[1-6]?,(\d+)?,(\.\d+|\d+\.?\d*)?,(-?\d+\.?\d*)?,M?/s) {
1058
1067
  my $time = "$1:$2:$3";
1059
- if ($$et{LastTime}) {
1060
- if ($$et{LastTime} eq $time) {
1061
- $$et{DOC_NUM} = $$et{LastDoc};
1062
- } elsif (%tags) {
1063
- HandleTextTags($et, $tagTbl, \%tags);
1064
- undef %tags;
1065
- $$et{DOC_COUNT} < ++$$et{DOC_NUM} and $$et{DOC_COUNT} = $$et{DOC_NUM};
1066
- }
1067
- }
1068
- $$et{LastTime} = $time;
1069
- $$et{LastDoc} = $$et{DOC_NUM};
1068
+ HandleNewTime($et, $time, $tagTbl, \%tags);
1070
1069
  $tags{GPSTimeStamp} = $time;
1071
1070
  $tags{GPSLatitude} = (($4 || 0) + $5/60) * ($6 eq 'N' ? 1 : -1);
1072
1071
  $tags{GPSLongitude} = (($7 || 0) + $8/60) * ($9 eq 'E' ? 1 : -1);
@@ -1114,6 +1113,11 @@ sub Process_text($$$;$)
1114
1113
  }
1115
1114
  }
1116
1115
  }
1116
+ if ($tags{GPSTimeStamp} and not $tags{GPSDateTime} and $$et{LastDate}) {
1117
+ # hack to fill in missing date for NextBase 662GW
1118
+ # (note: this doesn't necessarily handle day rollover properly)
1119
+ $tags{GPSDateTime} = "$$et{LastDate} $tags{GPSTimeStamp}Z";
1120
+ }
1117
1121
  HandleTextTags($et, $tagTbl, \%tags);
1118
1122
  return;
1119
1123
  }
@@ -3490,14 +3494,17 @@ sub ProcessGarminGPS($$$)
3490
3494
  while ($pos + 20 <= $dataLen) {
3491
3495
  $$et{DOC_NUM} = ++$$et{DOC_COUNT};
3492
3496
  my $time = Image::ExifTool::ConvertUnixTime(Get32u($dataPt, $pos) - $epoch) . 'Z';
3493
- my $lat = Get32s($dataPt, $pos + 12) * $scl;
3494
- my $lon = Get32s($dataPt, $pos + 16) * $scl;
3497
+ my $lat = Get32s($dataPt, $pos + 12);
3498
+ my $lon = Get32s($dataPt, $pos + 16);
3495
3499
  my $spd = Get16u($dataPt, $pos + 4); # (in mph)
3496
3500
  $et->HandleTag($tagTbl, 'GPSDateTime', $time);
3497
- $et->HandleTag($tagTbl, 'GPSLatitude', $lat);
3498
- $et->HandleTag($tagTbl, 'GPSLongitude', $lon);
3499
- $et->HandleTag($tagTbl, 'GPSSpeed', $spd);
3500
- $et->HandleTag($tagTbl, 'GPSSpeedRef', 'M');
3501
+ # skip bad GPS fixes
3502
+ if ($lat != -2147483648 or $lon != -2147483648) {
3503
+ $et->HandleTag($tagTbl, 'GPSLatitude', $lat * $scl);
3504
+ $et->HandleTag($tagTbl, 'GPSLongitude', $lon * $scl);
3505
+ $et->HandleTag($tagTbl, 'GPSSpeed', $spd);
3506
+ $et->HandleTag($tagTbl, 'GPSSpeedRef', 'M');
3507
+ }
3501
3508
  $pos += 20;
3502
3509
  }
3503
3510
  delete $$et{DOC_NUM};
@@ -14,7 +14,7 @@ use strict;
14
14
  use vars qw($VERSION);
15
15
  use Image::ExifTool qw(:DataAccess :Utils);
16
16
 
17
- $VERSION = '1.01';
17
+ $VERSION = '1.02';
18
18
 
19
19
  sub ProcessR3D($$);
20
20
 
@@ -45,7 +45,8 @@ my $errTrunc = 'Truncated R3D file';
45
45
  RED2 => { Name => 'Red2Header', SubDirectory => { TagTable => 'Image::ExifTool::Red::RED2' } },
46
46
 
47
47
  # (upper 4 bits of tag ID are the format code)
48
- # ---- format 1 ----
48
+ # ---- format 0 (int8u) ----
49
+ # ---- format 1 (string) ----
49
50
  0x1000 => 'StartEdgeCode', #1
50
51
  0x1001 => { Name => 'StartTimecode', Groups => { 2 => 'Time' } }, #1
51
52
  0x1002 => { #1
@@ -104,6 +105,7 @@ my $errTrunc = 'Truncated R3D file';
104
105
  # 0x1041 - seen 'NA'
105
106
  0x1042 => 'Revision', # ? (seen "TODO, rev EPIC-1.0" and "MYSTERIUM X, rev EPIC-1.0")
106
107
  # 0x1051 - seen 'C', 'L'
108
+ # 0x1052 - seen 'E9'
107
109
  0x1056 => 'OriginalFileName',
108
110
  0x106e => 'LensMake',
109
111
  0x106f => 'LensNumber', # (last 2 hex digits are LensType)
@@ -120,7 +122,8 @@ my $errTrunc = 'Truncated R3D file';
120
122
  0x1096 => 'Filter', # optical low-pass filter
121
123
  0x10a0 => 'Brain',
122
124
  0x10a1 => 'Sensor',
123
- # ---- format 2 ----
125
+ 0x10be => 'Quality',
126
+ # ---- format 2 (float) ----
124
127
  0x200d => 'ColorTemperature',
125
128
  # 0x200e - (sometimes this is frame rate)
126
129
  # 0x2015 - seen '1 1 1' (RGBGain or RGBGamma?)
@@ -130,7 +133,8 @@ my $errTrunc = 'Truncated R3D file';
130
133
  Groups => { 2 => 'Video' },
131
134
  PrintConv => 'int($val * 1000 + 0.5) / 1000',
132
135
  },
133
- # ---- format 4 ----
136
+ # ---- format 3 (int8u?) ----
137
+ # ---- format 4 (int16u) ----
134
138
  0x4037 => { Name => 'CropArea' }, # (NC)
135
139
  0x403b => 'ISO',
136
140
  # 0x404e - related to CropArea (or "0 0 0 0")
@@ -138,8 +142,12 @@ my $errTrunc = 'Truncated R3D file';
138
142
  0x406b => 'FocalLength',
139
143
  # 0x4084 - related to ISO?
140
144
  # 0x4087 - related to ISO?
141
- # ---- format 6 ----
145
+ # ---- format 5 (int8s?) ----
146
+ # ---- format 6 (int32s) ----
142
147
  0x606c => { Name => 'FocusDistance', ValueConv => '$val/1000', PrintConv => '"$val m"' },
148
+ # ---- format 7 (undef? structure?) ----
149
+ # ---- format 8 (int32u?) ----
150
+ # ---- format 9 (undef?) ----
143
151
  );
144
152
 
145
153
  # RED1 file header (ref PH)
@@ -240,9 +248,11 @@ sub ProcessR3D($$)
240
248
  $pos = 0x22; # directory starts at offset 0x22
241
249
  } else {
242
250
  # calculate position of Red directory start
243
- length($buff) < 0x41 and return $et->Warn($errTrunc);
244
- my $n = Get8u(\$buff, 0x40); # number of "rdi" records
245
- $pos = 0x44 + $n * 0x18;
251
+ $pos = 0x44;
252
+ length($buff) < $pos and return $et->Warn($errTrunc);
253
+ $pos += Get8u(\$buff, 0x40) * 0x18; # skip "rdi" records
254
+ $pos += Get8u(\$buff, 0x41) * 0x14; # skip "rda" records
255
+ $pos += Get8u(\$buff, 0x42) * 0x10; # skip "rdx" records
246
256
  }
247
257
  if ($pos + 8 > length $buff) {
248
258
  $dirLen = 0; # find directory the hard way
@@ -253,7 +263,7 @@ sub ProcessR3D($$)
253
263
  # do sanity check on the directory size (in case our assumptions were wrong)
254
264
  if ($dirLen < 300 or $dirLen >= 2048 or $pos + $dirLen > length $buff) {
255
265
  # tag 0x1000 with length 0x000f should be near the directory start
256
- $buff =~ /\0\x0f\x10\0/g or return $et->Warn("Can't find Red directory");
266
+ $buff =~ /\0\x0f\x10[\0\x06]/g or return $et->Warn("Can't find Red directory. Please submit sample for testing");
257
267
  $pos = pos($buff) - 4;
258
268
  $dirEnd = length $buff;
259
269
  undef $dirLen;
@@ -34,7 +34,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
34
34
  use Image::ExifTool::Exif;
35
35
  use Image::ExifTool::Minolta;
36
36
 
37
- $VERSION = '3.78';
37
+ $VERSION = '3.79';
38
38
 
39
39
  sub ProcessSRF($$$);
40
40
  sub ProcessSR2($$$);
@@ -180,6 +180,9 @@ sub PrintInvLensSpec($;$$);
180
180
  32889 => 'Sony FE 28-70mm F2 GM',
181
181
  32890 => 'Sony FE 400-800mm F6.3-8 G OSS', #JR
182
182
  32891 => 'Sony FE 50-150mm F2 GM', #github335
183
+ 32893 => 'Sony FE 100mm F2.8 Macro GM OSS', #JR
184
+ 33093 => 'Sony FE 100mm F2.8 Macro GM OSS + 1.4X Teleconverter', #JR (NC)
185
+ 33094 => 'Sony FE 100mm F2.8 Macro GM OSS + 2X Teleconverter', #JR
183
186
 
184
187
  # (comment this out so LensID will report the LensModel, which is more useful)
185
188
  # 32952 => 'Metabones Canon EF Speed Booster Ultra', #JR (corresponds to 184, but 'Advanced' mode, LensMount reported as E-mount)
@@ -1135,7 +1138,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
1135
1138
  SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag2010h' },
1136
1139
  },{
1137
1140
  Name => 'Tag2010i', # ?
1138
- Condition => '$$self{Model} =~ /^(ILCE-(6100A?|6400A?|6600|7C|7M3|7RM3A?|7RM4A?|9|9M2)|DSC-(RX10M4|RX100M6|RX100M5A|RX100M7|HX95|HX99|RX0M2)|ZV-(1F?|1M2|E10))\b/',
1141
+ Condition => '$$self{Model} =~ /^(ILCE-(6100A?|6400A?|6600|7C|7M3|7RM3A?|7RM4A?|9|9M2)|DSC-(RX10M4|RX100M6|RX100M5A|RX100M7A?|HX95|HX99|RX0M2)|ZV-(1[AF]?|1M2|E10))\b/',
1139
1142
  SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag2010i' },
1140
1143
  },{
1141
1144
  Name => 'Tag_0x2010',
@@ -2209,8 +2212,10 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
2209
2212
  400 => 'ILCE-1M2', #PH
2210
2213
  401 => 'DSC-RX1RM3', #JR
2211
2214
  402 => 'ILCE-6400A', #github347
2215
+ 403 => 'ILCE-6100A', #JR
2212
2216
  404 => 'DSC-RX100M7A', #github347
2213
2217
  406 => 'ILME-FX2', #JR
2218
+ 408 => 'ZV-1A', #JR
2214
2219
  },
2215
2220
  },
2216
2221
  0xb020 => { #2
@@ -8525,7 +8530,7 @@ my %isoSetting2010 = (
8525
8530
  },
8526
8531
  0x002a => [{
8527
8532
  Name => 'Quality2',
8528
- Condition => '$$self{Model} !~ /^(DSC-RX1RM3|ILCE-(1|1M2|6700|7CM2|7CR|7M4|7RM5|7SM3|9M3)|ILME-(FX2|FX3|FX30)|ZV-(E1|E10M2))\b/',
8533
+ Condition => '$$self{Model} !~ /^(DSC-RX1RM3|ILCE-(1|1M2|6700|7CM2|7CR|7M4|7RM5|7SM3|9M3)|ILME-(FX2|FX3A?|FX30)|ZV-(E1|E10M2))\b/',
8529
8534
  PrintConv => {
8530
8535
  0 => 'JPEG',
8531
8536
  1 => 'RAW',
@@ -8544,13 +8549,13 @@ my %isoSetting2010 = (
8544
8549
  }],
8545
8550
  # 0x0047 => { # often incorrect, requires 16x for some models
8546
8551
  # Name => 'SonyImageHeight',
8547
- # Condition => '$$self{Model} !~ /^(ILCE-(1|6700|7CM2|7CR|7M4|7RM5|7SM3|9M3)|ILME-(FX3|FX30)|ZV-E1)\b/',
8552
+ # Condition => '$$self{Model} !~ /^(ILCE-(1|6700|7CM2|7CR|7M4|7RM5|7SM3|9M3)|ILME-(FX3A?|FX30)|ZV-E1)\b/',
8548
8553
  # Format => 'int16u',
8549
8554
  # PrintConv => '$val > 0 ? 8*$val : "n.a."',
8550
8555
  # },
8551
8556
  0x0053 => {
8552
8557
  Name => 'ModelReleaseYear',
8553
- Condition => '$$self{Model} !~ /^(DSC-RX1RM3|ILCE-(1|6700|7CM2|7CR|7M4|7RM5|7SM3|9M3)|ILME-(FX2|FX3|FX30)|ZV-(E1|E10M2))\b/',
8558
+ Condition => '$$self{Model} !~ /^(DSC-RX1RM3|ILCE-(1|6700|7CM2|7CR|7M4|7RM5|7SM3|9M3)|ILME-(FX2|FX3A?|FX30)|ZV-(E1|E10M2))\b/',
8554
8559
  Format => 'int8u',
8555
8560
  PrintConv => 'sprintf("20%.2d", $val)',
8556
8561
  },
@@ -8572,7 +8577,7 @@ my %isoSetting2010 = (
8572
8577
  },
8573
8578
  0x013f => {
8574
8579
  Name => 'ShutterType',
8575
- Condition => '$$self{Model} =~ /^(DSC-RX100M7|ZV-(1|1F|1M2))\b/',
8580
+ Condition => '$$self{Model} =~ /^(DSC-RX100M7A?|ZV-(1A?|1F|1M2))\b/',
8576
8581
  PrintConv => {
8577
8582
  7 => 'Electronic',
8578
8583
  23 => 'Mechanical',
@@ -10087,7 +10092,7 @@ my %isoSetting2010 = (
10087
10092
  },
10088
10093
  0x088f => {
10089
10094
  Name => 'VignettingCorrParams',
10090
- Condition => '$$self{Model} =~ /^(ILCE-(1|7SM3)|ILME-FX3)\b/',
10095
+ Condition => '$$self{Model} =~ /^(ILCE-(1|7SM3)|ILME-FX3A?)\b/',
10091
10096
  Format => 'int16s[16]',
10092
10097
  },
10093
10098
  0x0891 => {
@@ -10102,7 +10107,7 @@ my %isoSetting2010 = (
10102
10107
  },
10103
10108
  0x08b5 => {
10104
10109
  Name => 'APS-CSizeCapture',
10105
- Condition => '$$self{Model} =~ /^(ILCE-(1|7SM3)|ILME-FX3)\b/',
10110
+ Condition => '$$self{Model} =~ /^(ILCE-(1|7SM3)|ILME-FX3A?)\b/',
10106
10111
  PrintConv => {
10107
10112
  0 => 'Off',
10108
10113
  1 => 'On',
@@ -10126,7 +10131,7 @@ my %isoSetting2010 = (
10126
10131
  },
10127
10132
  0x0914 => {
10128
10133
  Name => 'ChromaticAberrationCorrParams',
10129
- Condition => '$$self{Model} =~ /^(ILCE-(1|7SM3)|ILME-FX3)\b/',
10134
+ Condition => '$$self{Model} =~ /^(ILCE-(1|7SM3)|ILME-FX3A?)\b/',
10130
10135
  Format => 'int16s[32]',
10131
10136
  },
10132
10137
  0x0916 => {