exiftool-vendored.pl 12.45.0 → 12.49.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 (51) hide show
  1. package/bin/Changes +84 -3
  2. package/bin/MANIFEST +9 -0
  3. package/bin/META.json +1 -1
  4. package/bin/META.yml +1 -1
  5. package/bin/README +45 -44
  6. package/bin/config_files/acdsee.config +2 -1
  7. package/bin/config_files/frameCount.config +56 -0
  8. package/bin/config_files/tiff_version.config +1 -1
  9. package/bin/exiftool +62 -54
  10. package/bin/lib/Image/ExifTool/Apple.pm +6 -2
  11. package/bin/lib/Image/ExifTool/BuildTagLookup.pm +11 -6
  12. package/bin/lib/Image/ExifTool/Canon.pm +20 -8
  13. package/bin/lib/Image/ExifTool/CanonRaw.pm +8 -1
  14. package/bin/lib/Image/ExifTool/Exif.pm +7 -3
  15. package/bin/lib/Image/ExifTool/FLAC.pm +17 -3
  16. package/bin/lib/Image/ExifTool/FlashPix.pm +4 -2
  17. package/bin/lib/Image/ExifTool/FujiFilm.pm +31 -5
  18. package/bin/lib/Image/ExifTool/ICC_Profile.pm +1 -1
  19. package/bin/lib/Image/ExifTool/ICO.pm +141 -0
  20. package/bin/lib/Image/ExifTool/ID3.pm +5 -5
  21. package/bin/lib/Image/ExifTool/M2TS.pm +55 -8
  22. package/bin/lib/Image/ExifTool/MIE.pm +9 -3
  23. package/bin/lib/Image/ExifTool/MISB.pm +494 -0
  24. package/bin/lib/Image/ExifTool/MakerNotes.pm +3 -1
  25. package/bin/lib/Image/ExifTool/Nikon.pm +34 -31
  26. package/bin/lib/Image/ExifTool/NikonSettings.pm +5 -3
  27. package/bin/lib/Image/ExifTool/Panasonic.pm +21 -4
  28. package/bin/lib/Image/ExifTool/PanasonicRaw.pm +12 -5
  29. package/bin/lib/Image/ExifTool/Photoshop.pm +29 -3
  30. package/bin/lib/Image/ExifTool/QuickTime.pm +34 -5
  31. package/bin/lib/Image/ExifTool/QuickTimeStream.pl +42 -4
  32. package/bin/lib/Image/ExifTool/README +1 -1
  33. package/bin/lib/Image/ExifTool/RIFF.pm +106 -9
  34. package/bin/lib/Image/ExifTool/Samsung.pm +2 -2
  35. package/bin/lib/Image/ExifTool/Sigma.pm +27 -1
  36. package/bin/lib/Image/ExifTool/SigmaRaw.pm +37 -13
  37. package/bin/lib/Image/ExifTool/Sony.pm +7 -3
  38. package/bin/lib/Image/ExifTool/TagLookup.pm +176 -6
  39. package/bin/lib/Image/ExifTool/TagNames.pod +4782 -4486
  40. package/bin/lib/Image/ExifTool/Text.pm +3 -4
  41. package/bin/lib/Image/ExifTool/Torrent.pm +2 -3
  42. package/bin/lib/Image/ExifTool/WriteCanonRaw.pl +7 -0
  43. package/bin/lib/Image/ExifTool/WriteExif.pl +19 -1
  44. package/bin/lib/Image/ExifTool/WriteRIFF.pl +359 -0
  45. package/bin/lib/Image/ExifTool/Writer.pl +6 -2
  46. package/bin/lib/Image/ExifTool/XMP.pm +70 -56
  47. package/bin/lib/Image/ExifTool.pm +75 -15
  48. package/bin/lib/Image/ExifTool.pod +55 -52
  49. package/bin/perl-Image-ExifTool.spec +43 -43
  50. package/bin/pp_build_exe.args +7 -4
  51. package/package.json +2 -2
@@ -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.09';
66
+ $VERSION = '4.12';
67
67
 
68
68
  sub LensIDConv($$$);
69
69
  sub ProcessNikonAVI($$$);
@@ -363,6 +363,7 @@ sub GetAFPointGrid($$;$);
363
363
  '26 58 37 37 14 14 1C 02' => 'Sigma 24mm F1.8 EX DG Aspherical Macro',
364
364
  'E1 58 37 37 14 14 1C 02' => 'Sigma 24mm F1.8 EX DG Aspherical Macro',
365
365
  '02 46 37 37 25 25 02 00' => 'Sigma 24mm F2.8 Super Wide II Macro',
366
+ '7E 54 37 37 0C 0C 4B 06' => 'Sigma 24mm F1.4 DG HSM | A', #30
366
367
  '26 58 3C 3C 14 14 1C 02' => 'Sigma 28mm F1.8 EX DG Aspherical Macro',
367
368
  '48 54 3E 3E 0C 0C 4B 06' => 'Sigma 30mm F1.4 EX DC HSM',
368
369
  'F8 54 3E 3E 0C 0C 4B 06' => 'Sigma 30mm F1.4 EX DC HSM', #JD
@@ -669,6 +670,7 @@ sub GetAFPointGrid($$;$);
669
670
  '00 40 64 64 2C 2C 00 00' => 'Voigtlander APO-Lanthar 90mm F3.5 SLII Close Focus',
670
671
  '07 40 30 45 2D 35 03 02.2' => 'Voigtlander Ultragon 19-35mm F3.5-4.5 VMV', #NJ
671
672
  '71 48 64 64 24 24 00 00' => 'Voigtlander APO-Skopar 90mm F2.8 SL IIs', #30
673
+ 'FD 00 50 50 18 18 DF 00' => 'Voigtlander APO-Lanthar 50mm F2 Aspherical', #35
672
674
  #
673
675
  '00 40 2D 2D 2C 2C 00 00' => 'Carl Zeiss Distagon T* 3.5/18 ZF.2',
674
676
  '00 48 27 27 24 24 00 00' => 'Carl Zeiss Distagon T* 2.8/15 ZF.2', #MykytaKozlov
@@ -2086,7 +2088,7 @@ my %base64coord = (
2086
2088
  TagTable => 'Image::ExifTool::Nikon::ShotInfoZ9',
2087
2089
  DecryptStart => 4,
2088
2090
  # TODO: eventually set the length dynamically according to actual offsets!
2089
- DecryptLen => 0xec4b + 1907, # decoded thru end of Offset26
2091
+ DecryptLen => 0xec4b + 2105, # decoded thru end of Offset26
2090
2092
  ByteOrder => 'LittleEndian',
2091
2093
  },
2092
2094
  },
@@ -4180,7 +4182,7 @@ my %base64coord = (
4180
4182
  },
4181
4183
  );
4182
4184
 
4183
- %Image::ExifTool::Nikon::AFInfo2V0400 = ( #V0400 related fields begin at x'3c' ( Z9)
4185
+ %Image::ExifTool::Nikon::AFInfo2V0400 = ( #V0400 related fields begin at x'3c' (Z9)
4184
4186
  %binaryDataAttrs,
4185
4187
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
4186
4188
  DATAMEMBER => [ 0 ],
@@ -4224,9 +4226,13 @@ my %base64coord = (
4224
4226
  Name => 'AFAreaHeight',
4225
4227
  Format => 'int16u',
4226
4228
  RawConv => '$val ? $val : undef',
4227
- }
4228
- # AFFocusResult is the result of the last AF operation and not necessarily an indication of the state of the of the capture (e.g., the subject may have moved or the image re-framed)
4229
- #0x4a => { Name => 'AFFocusResult',PrintConv => {0=> "No Focus", 1=>"Focus"} }, #new tag created because Z9 uses a hybrid contrast/phase AF (closest former tag was ContrastDetectAFInFocus).
4229
+ },
4230
+ 0x4a => {
4231
+ Name => 'FocusResult',
4232
+ # in Manual Foucs mode, reflects the state of viewfinder focus indicator.
4233
+ # In AF-C or AF-S, reflects the result of the last AF operation.
4234
+ PrintConv => { 0=> "Out of Focus", 1=>"Focus"},
4235
+ },
4230
4236
  );
4231
4237
 
4232
4238
  # Nikon AF fine-tune information (ref 28)
@@ -5043,31 +5049,31 @@ my %nikonFocalConversions = (
5043
5049
  0x4c => { #28
5044
5050
  Name => 'FocusDistanceRangeWidth', #reflects the number of discrete absolute lens positions that are mapped to the reported FocusDistance. Will be 1 near CFD reflecting very narrow focus distance bands (i.e., quite accurate). Near Infinity will be something like 32. Note: 0 at infinity.
5045
5051
  Format => 'int8u',
5046
- Condition => '$$self{NewLensData} and $$self{LensMountType} == 1',
5052
+ Condition => '$$self{NewLensData} and $$self{LensMountType} and $$self{LensMountType} == 1',
5047
5053
  RawConv => '$$self{FocusDistanceRangeWidth} = $val',
5048
5054
  Unknown => 1,
5049
5055
  },
5050
5056
  0x4e => { #28
5051
5057
  Name => 'FocusDistance',
5052
5058
  Format => 'int16u',
5053
- Condition => '$$self{NewLensData} and $$self{LensMountType} == 1',
5059
+ Condition => '$$self{NewLensData} and $$self{LensMountType} and $$self{LensMountType} == 1',
5054
5060
  RawConv => '$val = $val/256', # 1st byte is the fractional component. This byte was not previously considered in the legacy calculation (which only used the 2nd byte). When 2nd byte < 80; distance is < 1 meter
5055
5061
  ValueConv => '0.01 * 10**($val/40)', # in m
5056
5062
  ValueConvInv => '$val>0 ? 40*log($val*100)/log(10) : 0',
5057
5063
  PrintConv => q{
5058
- $$self{FocusDistanceRangeWidth} == 0 ? "Inf" : $val < 1 ? $val < 0.35 ? sprintf("%.4f m", $val): sprintf("%.3f m", $val): sprintf("%.2f m", $val), #distances less than 35mm are quite accurate with increasingly less precision past 1m
5064
+ (defined $$self{FocusDistanceRangeWidth} and not $$self{FocusDistanceRangeWidth}) ? "Inf" : $val < 1 ? $val < 0.35 ? sprintf("%.4f m", $val): sprintf("%.3f m", $val): sprintf("%.2f m", $val), #distances less than 35mm are quite accurate with increasingly less precision past 1m
5059
5065
  },
5060
5066
  },
5061
5067
  0x56 => { #28
5062
5068
  Name => 'LensDriveEnd', # byte contains: 1 at CFD/MOD; 2 at Infinity; 0 otherwise
5063
- Condition => '$$self{NewLensData} and $$self{LensMountType} == 1',
5069
+ Condition => '$$self{NewLensData} and $$self{LensMountType} and $$self{LensMountType} == 1',
5064
5070
  Format => 'int8u',
5065
- RawConv => 'unless ($$self{FocusDistanceRangeWidth} == 0 ) { if ($val == 0 ) {$$self{LensDriveEnd} = "No"} else { $$self{LensDriveEnd} = "CFD"}; } else{ $$self{LensDriveEnd} = "Inf"}',
5071
+ RawConv => 'unless (defined $$self{FocusDistanceRangeWidth} and not $$self{FocusDistanceRangeWidth}) { if ($val == 0 ) {$$self{LensDriveEnd} = "No"} else { $$self{LensDriveEnd} = "CFD"}; } else{ $$self{LensDriveEnd} = "Inf"}',
5066
5072
  Unknown => 1,
5067
5073
  },
5068
5074
  0x5a => { #28
5069
5075
  Name => 'LensPositionAbsolute', # <=0 at infinity. Typical value at CFD might be 58000. Only valid for Z-mount lenses.
5070
- Condition => '$$self{NewLensData} and $$self{LensMountType} == 1',
5076
+ Condition => '$$self{NewLensData} and $$self{LensMountType} and $$self{LensMountType} == 1',
5071
5077
  Format => 'int32s',
5072
5078
  Unknown => 1,
5073
5079
  },
@@ -8041,8 +8047,8 @@ my %nikonFocalConversions = (
8041
8047
  WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
8042
8048
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
8043
8049
  VARS => { ID_LABEL => 'Index' },
8044
- DATAMEMBER => [ 0x04, 0x30, 0x38, 0x84, 0x8c, 0x6c6f, 0x6c98,
8045
- 0x6c9a, 0x7717, 0x7844, 0xeaea, 0xeb6f, 0xeb70 ],
8050
+ DATAMEMBER => [ 0x04, 0x30, 0x38, 0x84, 0x8c, 0x6c6f, 0x6c90, 0x6c98,
8051
+ 0x6c9a, 0xeaea, 0xeb6f, 0xeb70 ],
8046
8052
  IS_SUBDIR => [ 0xec4b ],
8047
8053
  WRITABLE => 1,
8048
8054
  FIRST_ENTRY => 0,
@@ -8119,6 +8125,15 @@ my %nikonFocalConversions = (
8119
8125
  # account for variable location of Offset3 data
8120
8126
  Hook => '$varSize = $$self{Offset3} - 0x6c70',
8121
8127
  },
8128
+ 0x6c90 => {
8129
+ Name => 'FocusShiftShooting',
8130
+ RawConv => '$$self{FocusShiftShooting} = $val',
8131
+ PrintConv => q{
8132
+ return 'Off' if $val == 0 ;
8133
+ my $i = sprintf("Frame %.0f of %.0f",$val, $$self{FocusShiftNumberShots}); # something like Frame 1 of 100"
8134
+ return "On: $i"
8135
+ },
8136
+ },
8122
8137
  0x6c98 => {
8123
8138
  Name => 'IntervalShooting',
8124
8139
  RawConv => '$$self{IntervalShooting} = $val',
@@ -8138,23 +8153,6 @@ my %nikonFocalConversions = (
8138
8153
  Format => 'int16u',
8139
8154
  Hidden => 1,
8140
8155
  },
8141
- ### 0x7718 - Offset5 info start (Z9 firmware 1.00)
8142
- 0x7717 => {
8143
- Name => 'Offsset5Hook',
8144
- Hidden => 1,
8145
- RawConv => 'undef',
8146
- # account for variable location of Offset5 data
8147
- Hook => '$varSize = $$self{Offset5} - 0x7718',
8148
- },
8149
- 0x7844 => {
8150
- Name => 'FocusShiftShooting',
8151
- RawConv => '$$self{FocusShiftShooting} = $val',
8152
- PrintConv => q{
8153
- return 'Off' if $val == 0 ;
8154
- my $i = sprintf("Frame %.0f of %.0f",$val, $$self{FocusShiftNumberShots}); # something like Frame 1 of 100"
8155
- return "On: $i"
8156
- },
8157
- },
8158
8156
  ### 0xeaeb - OrientationInfo start (Z9 firmware 1.00)
8159
8157
  0xeaea => {
8160
8158
  Name => 'OrientationHook',
@@ -10902,9 +10900,14 @@ my %nikonFocalConversions = (
10902
10900
  Name => 'LocationInfo',
10903
10901
  SubDirectory => { TagTable => 'Image::ExifTool::Nikon::LocationInfo' },
10904
10902
  },
10903
+ 0x200003f => 'WhiteBalanceFineTune',
10905
10904
  # 0x200003f - rational64s[2]: "0 0"
10906
10905
  # 0x2000042 - undef[6]: "0100\x03\0"
10907
10906
  # 0x2000043 - undef[12]: all zeros
10907
+ 0x200004e => {
10908
+ Name => 'NikonSettings',
10909
+ SubDirectory => { TagTable => 'Image::ExifTool::NikonSettings::Main' },
10910
+ },
10908
10911
  0x2000083 => {
10909
10912
  Name => 'LensType',
10910
10913
  # credit to Tom Christiansen (ref 7) for figuring this out...
@@ -2036,11 +2036,13 @@ sub ProcessNikonSettings($$$)
2036
2036
  for ($i=0; $i<$num; ++$i) {
2037
2037
  my $entry = $start + 0x18 + $i * 8;
2038
2038
  my $tag = Get16u($dataPt, $entry);
2039
- my $fmt = Get16u($dataPt, $entry + 2);
2039
+ # this is odd, but either the format is 16-bit and always big-endian,
2040
+ # or it is 8-bit and we have an unknown byte in the entry...
2041
+ my $fmt = Get8u($dataPt, $entry + 3);
2040
2042
  my $val = Get32u($dataPt, $entry + 4);
2041
2043
  # abort if the tag has a format that we haven't yet seen
2042
- # (assuming this is a size/format code. So far we have only seen 0x400)
2043
- $fmt == 0x400 or $et->Warn(sprintf('Unknown format 0x%x for NikonSettings tag 0x%.4x',$fmt,$tag)), last;
2044
+ # (assuming this is a size/format code. So far we have only seen a code of 4)
2045
+ $fmt == 4 or $et->Warn(sprintf('Unknown format $fmt for NikonSettings tag 0x%.4x',$tag)), last;
2044
2046
  $et->HandleTag($tagTablePtr, $tag, $val,
2045
2047
  DataPt => $dataPt,
2046
2048
  DataPos => $$dirInfo{DataPos},
@@ -37,7 +37,7 @@ use vars qw($VERSION %leicaLensTypes);
37
37
  use Image::ExifTool qw(:DataAccess :Utils);
38
38
  use Image::ExifTool::Exif;
39
39
 
40
- $VERSION = '2.17';
40
+ $VERSION = '2.18';
41
41
 
42
42
  sub ProcessLeicaLEIC($$$);
43
43
  sub WhiteBalanceConv($;$$);
@@ -543,7 +543,11 @@ my %shootingMode = (
543
543
  0x2c => [
544
544
  {
545
545
  Name => 'ContrastMode',
546
- Condition => '$$self{Model} !~ /^DMC-(FX10|G1|L1|L10|LC80|GF\d+|G2|TZ10|ZS7)$/',
546
+ Condition => q{
547
+ $$self{Model} !~ /^DMC-(FX10|G1|L1|L10|LC80|GF\d+|G2|TZ10|ZS7)$/ and
548
+ # tested for DC-GH6, but rule out other DC- models just in case - PH
549
+ $$self{Model} !~ /^DC-/
550
+ },
547
551
  Flags => 'PrintHex',
548
552
  Writable => 'int16u',
549
553
  Notes => q{
@@ -1129,7 +1133,10 @@ my %shootingMode = (
1129
1133
  8 => 'Cinelike D', #forum11194
1130
1134
  9 => 'Cinelike V', #forum11194
1131
1135
  11 => 'L. Monochrome', #forum11194
1136
+ 12 => 'Like709', #forum14033
1132
1137
  15 => 'L. Monochrome D', #forum11194
1138
+ 17 => 'V-Log', #forum14033
1139
+ 18 => 'Cinelike D2', #forum14033
1133
1140
  },
1134
1141
  },
1135
1142
  0x8a => { #18
@@ -1255,8 +1262,9 @@ my %shootingMode = (
1255
1262
  Writable => 'rational64u',
1256
1263
  Format => 'int32u',
1257
1264
  PrintConv => {
1258
- '0 0' => 'Expressive',
1259
- # '0 1' => have seen this for XS1 (PH)
1265
+ # '0 0' => 'Expressive', #forum11194
1266
+ '0 0' => 'Off', #forum14033 (GH6)
1267
+ '0 1' => 'Expressive', #forum14033 (GH6) (have also seen this for XS1)
1260
1268
  '0 2' => 'Retro',
1261
1269
  '0 4' => 'High Key',
1262
1270
  '0 8' => 'Sepia',
@@ -1435,6 +1443,15 @@ my %shootingMode = (
1435
1443
  ValueConv => '$_=sprintf("%.4x",$val); s/(..)(..)/$2 $1/; $_',
1436
1444
  ValueConvInv => '$val =~ s/(..) (..)/$2$1/; hex($val)',
1437
1445
  },
1446
+ 0xe8 => { #PH (DC-GH6)
1447
+ Name => 'MinimumISO',
1448
+ Writable => 'int32u',
1449
+ },
1450
+ 0xee => { #PH (DC-GH6)
1451
+ Name => 'DynamicRangeBoost',
1452
+ Writable => 'int16u',
1453
+ PrintConv => { 0 => 'Off', 1 => 'On' },
1454
+ },
1438
1455
  0x0e00 => {
1439
1456
  Name => 'PrintIM',
1440
1457
  Description => 'Print Image Matching',
@@ -21,7 +21,7 @@ use vars qw($VERSION);
21
21
  use Image::ExifTool qw(:DataAccess :Utils);
22
22
  use Image::ExifTool::Exif;
23
23
 
24
- $VERSION = '1.26';
24
+ $VERSION = '1.27';
25
25
 
26
26
  sub ProcessJpgFromRaw($$$);
27
27
  sub WriteJpgFromRaw($$$);
@@ -739,6 +739,7 @@ sub WriteDistortionInfo($$$)
739
739
  # 3 - reference to list of original offset values
740
740
  # 4 - IFD format number
741
741
  # 5 - (pointer to StripOffsets value added by this PatchRawDataOffset routine)
742
+ # 6 - flag set if this is a fixed offset (Panasonic GH6 fixed-offset hack)
742
743
  sub PatchRawDataOffset($$$)
743
744
  {
744
745
  my ($offsetInfo, $raf, $ifd) = @_;
@@ -752,10 +753,16 @@ sub PatchRawDataOffset($$$)
752
753
  } else {
753
754
  # the DC-GH6 and DC-GH5M2 write RawDataOffset with no Strip tags, so we need
754
755
  # to create fake StripByteCounts information for copying the data
755
- # (disable this until SilkyPix and Adobe utilities can deal with a variable
756
- # RawDataOffset, see https://exiftool.org/forum/index.php?topic=13861.0 --
757
- # so these files will continue to give a "No size tag" error when writing)
758
- # $stripByteCounts = $$offsetInfo{0x117} = [ $PanasonicRaw::Main{0x117}, 0, 1, [ 0 ], 4 ];
756
+ if ($$offsetInfo{0x118}) { # (just to be safe)
757
+ $stripByteCounts = $$offsetInfo{0x117} = [ $PanasonicRaw::Main{0x117}, 0, 1, [ 0 ], 4 ];
758
+ # set flag so the offset will be fixed (GH6 hack, see https://exiftool.org/forum/index.php?topic=13861.0)
759
+ # (of course, fixing up the offset is now unnecessary, but continue to do this even
760
+ # though the fixup adjustment will be 0 because this allows us to delete the following
761
+ # line to remove the fix-offset restriction if Panasonic ever sees the light, but note
762
+ # that in this case we should investigate the purpose of the seemily-duplicate raw
763
+ # data offset contained within PanasonicRaw_0x0044)
764
+ $$offsetInfo{0x118}[6] = 1;
765
+ }
759
766
  }
760
767
  if ($rawDataOffset and not $err) {
761
768
  $err = 1 unless $$rawDataOffset[2] == 1;
@@ -25,15 +25,28 @@
25
25
  package Image::ExifTool::Photoshop;
26
26
 
27
27
  use strict;
28
- use vars qw($VERSION $AUTOLOAD $iptcDigestInfo);
28
+ use vars qw($VERSION $AUTOLOAD $iptcDigestInfo %printFlags);
29
29
  use Image::ExifTool qw(:DataAccess :Utils);
30
30
 
31
- $VERSION = '1.65';
31
+ $VERSION = '1.67';
32
32
 
33
33
  sub ProcessPhotoshop($$$);
34
34
  sub WritePhotoshop($$$);
35
35
  sub ProcessLayers($$$);
36
36
 
37
+ # PrintFlags bit definitions (ref forum13785)
38
+ %printFlags = (
39
+ 0 => 'Labels',
40
+ 1 => 'Corner crop marks',
41
+ 2 => 'Color bars', # (deprecated)
42
+ 3 => 'Registration marks',
43
+ 4 => 'Negative',
44
+ 5 => 'Emulsion down',
45
+ 6 => 'Interpolate', # (deprecated)
46
+ 7 => 'Description',
47
+ 8 => 'Print flags',
48
+ );
49
+
37
50
  # map of where information is stored in PSD image
38
51
  my %psdMap = (
39
52
  IPTC => 'Photoshop',
@@ -106,7 +119,17 @@ my %unicodeString = (
106
119
  0x03f0 => { Unknown => 1, Name => 'PStringCaption' },
107
120
  0x03f1 => { Unknown => 1, Name => 'BorderInformation' },
108
121
  0x03f2 => { Unknown => 1, Name => 'BackgroundColor' },
109
- 0x03f3 => { Unknown => 1, Name => 'PrintFlags', Format => 'int8u' },
122
+ 0x03f3 => {
123
+ Unknown => 1,
124
+ Name => 'PrintFlags',
125
+ Format => 'int8u',
126
+ PrintConv => q{
127
+ my $byte = 0;
128
+ my @bits = $val =~ /\d+/g;
129
+ $byte = ($byte << 1) | ($_ ? 1 : 0) foreach reverse @bits;
130
+ return DecodeBits($byte, \%Image::ExifTool::Photoshop::printFlags);
131
+ },
132
+ },
110
133
  0x03f4 => { Unknown => 1, Name => 'BW_HalftoningInfo' },
111
134
  0x03f5 => { Unknown => 1, Name => 'ColorHalftoningInfo' },
112
135
  0x03f6 => { Unknown => 1, Name => 'DuotoneHalftoningInfo' },
@@ -332,6 +355,7 @@ my %unicodeString = (
332
355
  PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
333
356
  WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
334
357
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
358
+ DATAMEMBER => [ 1 ],
335
359
  FORMAT => 'int16s',
336
360
  GROUPS => { 2 => 'Image' },
337
361
  0 => {
@@ -342,6 +366,7 @@ my %unicodeString = (
342
366
  },
343
367
  1 => {
344
368
  Name => 'PhotoshopFormat',
369
+ RawConv => '$$self{PhotoshopFormat} = $val',
345
370
  PrintConv => {
346
371
  0x0000 => 'Standard',
347
372
  0x0001 => 'Optimized',
@@ -350,6 +375,7 @@ my %unicodeString = (
350
375
  },
351
376
  2 => {
352
377
  Name => 'ProgressiveScans',
378
+ Condition => '$$self{PhotoshopFormat} == 0x0101',
353
379
  PrintConv => {
354
380
  1 => '3 Scans',
355
381
  2 => '4 Scans',
@@ -47,7 +47,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
47
47
  use Image::ExifTool::Exif;
48
48
  use Image::ExifTool::GPS;
49
49
 
50
- $VERSION = '2.76';
50
+ $VERSION = '2.79';
51
51
 
52
52
  sub ProcessMOV($$;$);
53
53
  sub ProcessKeys($$$);
@@ -66,6 +66,7 @@ sub ProcessRIFFTrailer($$$);
66
66
  sub ProcessTTAD($$$);
67
67
  sub ProcessNMEA($$$);
68
68
  sub ProcessGPSLog($$$);
69
+ sub ProcessGarminGPS($$$);
69
70
  sub SaveMetaKeys($$$);
70
71
  # ++^^^^^^^^^^^^++
71
72
  sub ParseItemLocation($$);
@@ -1122,6 +1123,23 @@ my %eeBox2 = (
1122
1123
  Start => 16,
1123
1124
  },
1124
1125
  },
1126
+ {
1127
+ Name => 'GarminGPS',
1128
+ Condition => '$$valPt=~/^\x9b\x63\x0f\x8d\x63\x74\x40\xec\x82\x04\xbc\x5f\xf5\x09\x17\x28/ and $$self{OPTIONS}{ExtractEmbedded}',
1129
+ SubDirectory => {
1130
+ TagTable => 'Image::ExifTool::QuickTime::Stream',
1131
+ ProcessProc => \&ProcessGarminGPS,
1132
+ },
1133
+ },
1134
+ {
1135
+ Name => 'GarminGPS',
1136
+ Condition => '$$valPt=~/^\x9b\x63\x0f\x8d\x63\x74\x40\xec\x82\x04\xbc\x5f\xf5\x09\x17\x28/',
1137
+ Notes => 'Garmin GPS sensor data',
1138
+ RawConv => q{
1139
+ $self->WarnOnce('Use the ExtractEmbedded option to decode timed Garmin GPS',3);
1140
+ return \$val;
1141
+ },
1142
+ },
1125
1143
  {
1126
1144
  Name => 'UUID-Unknown',
1127
1145
  %unknownInfo,
@@ -7630,6 +7648,11 @@ my %eeBox2 = (
7630
7648
  Format => 'undef[4]',
7631
7649
  RawConv => '$$self{MetaFormat} = $val', # (yes, use MetaFormat for this too)
7632
7650
  },
7651
+ 24 => {
7652
+ Condition => '$$self{MetaFormat} eq "tmcd"',
7653
+ Name => 'PlaybackFrameRate', # (may differ from recorded FrameRate eg. ../pics/FujiFilmX-H1.mov)
7654
+ Format => 'rational64u',
7655
+ },
7633
7656
  #
7634
7657
  # Observed offsets for child atoms of various OtherFormat types:
7635
7658
  #
@@ -8082,9 +8105,12 @@ sub AUTOLOAD
8082
8105
  # Returns: 9-element rotation matrix as a string (with 0 x/y offsets)
8083
8106
  sub GetRotationMatrix($)
8084
8107
  {
8085
- my $ang = 3.1415926536 * shift() / 180;
8108
+ my $ang = 3.14159265358979323846264 * shift() / 180;
8086
8109
  my $cos = cos $ang;
8087
8110
  my $sin = sin $ang;
8111
+ # round to zero
8112
+ $cos = 0 if abs($cos) < 1e-12;
8113
+ $sin = 0 if abs($sin) < 1e-12;
8088
8114
  my $msn = -$sin;
8089
8115
  return "$cos $sin 0 $msn $cos 0 0 0 1";
8090
8116
  }
@@ -9637,10 +9663,14 @@ ItemID: foreach $id (keys %$items) {
9637
9663
  require Image::ExifTool::Font;
9638
9664
  $lang = $Image::ExifTool::Font::ttLang{Macintosh}{$lang};
9639
9665
  }
9666
+ } else {
9667
+ # for the default language code of 0x0000, use UTF-8 instead
9668
+ # of the CharsetQuickTime setting if obviously UTF8
9669
+ $enc = 'UTF8' if Image::ExifTool::IsUTF8(\$str) > 0;
9640
9670
  }
9641
9671
  # the spec says only "Macintosh text encoding", but
9642
9672
  # allow this to be configured by the user
9643
- $enc = $charsetQuickTime;
9673
+ $enc = $charsetQuickTime unless $enc;
9644
9674
  } else {
9645
9675
  # convert language code to ASCII (ignore read-only bit)
9646
9676
  $lang = UnpackLang($lang);
@@ -9681,8 +9711,7 @@ ItemID: foreach $id (keys %$items) {
9681
9711
  if (not ref $$vp and length($$vp) <= 65536 and $$vp =~ /[\x80-\xff]/) {
9682
9712
  # the encoding of this is not specified, so use CharsetQuickTime
9683
9713
  # unless the string is valid UTF-8
9684
- require Image::ExifTool::XMP;
9685
- my $enc = Image::ExifTool::XMP::IsUTF8($vp) > 0 ? 'UTF8' : $charsetQuickTime;
9714
+ my $enc = Image::ExifTool::IsUTF8($vp) > 0 ? 'UTF8' : $charsetQuickTime;
9686
9715
  $$vp = $et->Decode($$vp, $enc);
9687
9716
  }
9688
9717
  }
@@ -99,7 +99,7 @@ my %insvLimit = (
99
99
  The tags below are extracted from timed metadata in QuickTime and other
100
100
  formats of video files when the ExtractEmbedded option is used. Although
101
101
  most of these tags are combined into the single table below, ExifTool
102
- currently reads 59 different formats of timed GPS metadata from video files.
102
+ currently reads 61 different formats of timed GPS metadata from video files.
103
103
  },
104
104
  VARS => { NO_ID => 1 },
105
105
  GPSLatitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', RawConv => '$$self{FoundGPSLatitude} = 1; $val' },
@@ -896,10 +896,15 @@ sub Process_text($$$)
896
896
  my $time = "$1:$2:$3";
897
897
  if ($$et{LastTime}) {
898
898
  if ($$et{LastTime} eq $time) {
899
+ # combine with the previous NMEA sentence
899
900
  $$et{DOC_NUM} = $$et{LastDoc};
900
901
  } elsif (%tags) {
902
+ # handle existing tags and start a new document
903
+ # (see https://exiftool.org/forum/index.php?msg=75422)
901
904
  HandleTextTags($et, $tagTbl, \%tags);
902
- $$et{DOC_NUM} = ++$$et{DOC_COUNT};
905
+ undef %tags;
906
+ # increment document number and update document count if necessary
907
+ $$et{DOC_COUNT} < ++$$et{DOC_NUM} and $$et{DOC_COUNT} = $$et{DOC_NUM};
903
908
  }
904
909
  }
905
910
  $$et{LastTime} = $time;
@@ -918,7 +923,8 @@ sub Process_text($$$)
918
923
  $$et{DOC_NUM} = $$et{LastDoc};
919
924
  } elsif (%tags) {
920
925
  HandleTextTags($et, $tagTbl, \%tags);
921
- $$et{DOC_NUM} = ++$$et{DOC_COUNT};
926
+ undef %tags;
927
+ $$et{DOC_COUNT} < ++$$et{DOC_NUM} and $$et{DOC_COUNT} = $$et{DOC_NUM};
922
928
  }
923
929
  }
924
930
  $$et{LastTime} = $time;
@@ -2533,7 +2539,7 @@ sub ProcessTTAD($$$)
2533
2539
  # (I think "5" may be the number of satellites. seen: 5,6,7 - PH)
2534
2540
  FoundSomething($et, $tagTbl, $sampleTime / 1000);
2535
2541
  my $t = GetDouble($dataPt, $pos);
2536
- $et->HandleTag($tagTbl, GPSDateTime => Image::ExifTool::ConvertUnixTime($t,undef,3).'Z');
2542
+ $et->HandleTag($tagTbl, GPSDateTime => Image::ExifTool::ConvertUnixTime($t,undef,3) . 'Z');
2537
2543
  $et->HandleTag($tagTbl, GPSLatitude => GetDouble($dataPt, $pos+0x1c));
2538
2544
  $et->HandleTag($tagTbl, GPSLongitude => GetDouble($dataPt, $pos+0x24));
2539
2545
  $et->HandleTag($tagTbl, GPSAltitude => GetDouble($dataPt, $pos+0x14));
@@ -2734,6 +2740,38 @@ sub ProcessInsta360($;$)
2734
2740
  return 1;
2735
2741
  }
2736
2742
 
2743
+ #------------------------------------------------------------------------------
2744
+ # Process Garmin GPS 'uuid' atom (ref PH)
2745
+ # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
2746
+ # Returns: 1 on success
2747
+ # Note: This format is used by the Garmin DriveAssist 51, but the DriveAssist 50
2748
+ # uses a completely different format. :(
2749
+ sub ProcessGarminGPS($$$)
2750
+ {
2751
+ my ($et, $dirInfo, $tagTbl) = @_;
2752
+ my $dataPt = $$dirInfo{DataPt};
2753
+ my $dataLen = length $$dataPt;
2754
+ my $pos = 33;
2755
+ my $epoch = (66 * 365 + 17) * 24 * 3600; # time is relative to Jan 1, 1904
2756
+ my $scl = 180 / (32768 * 65536); # scaling factor for lat/lon
2757
+ $et->VerboseDir('GarminGPS');
2758
+ while ($pos + 20 <= $dataLen) {
2759
+ $$et{DOC_NUM} = ++$$et{DOC_COUNT};
2760
+ my $time = Image::ExifTool::ConvertUnixTime(Get32u($dataPt, $pos) - $epoch) . 'Z';
2761
+ my $lat = Get32s($dataPt, $pos + 12) * $scl;
2762
+ my $lon = Get32s($dataPt, $pos + 16) * $scl;
2763
+ my $spd = Get16u($dataPt, $pos + 4); # (in mph)
2764
+ $et->HandleTag($tagTbl, 'GPSDateTime', $time);
2765
+ $et->HandleTag($tagTbl, 'GPSLatitude', $lat);
2766
+ $et->HandleTag($tagTbl, 'GPSLongitude', $lon);
2767
+ $et->HandleTag($tagTbl, 'GPSSpeed', $spd);
2768
+ $et->HandleTag($tagTbl, 'GPSSpeedRef', 'M');
2769
+ $pos += 20;
2770
+ }
2771
+ delete $$et{DOC_NUM};
2772
+ return 1;
2773
+ }
2774
+
2737
2775
  #------------------------------------------------------------------------------
2738
2776
  # Process 360Fly 'uuid' atom containing sensor data
2739
2777
  # (ref https://github.com/JamesHeinrich/getID3/blob/master/getid3/module.audio-video.quicktime.php)
@@ -720,7 +720,7 @@ numerical, and generated automatically otherwise.
720
720
  condition exists, then a 'true' condition is assumed. The
721
721
  expression may use $self to access the ExifTool object. The
722
722
  first 128 bytes of the raw data value are accessible through
723
- the reference $valPt for EXIF, Jpeg2000, QuickTime and
723
+ the reference $valPt for EXIF, Jpeg2000, QuickTime, FLAC and
724
724
  BinaryData tags only (note that for BinaryData tags, the raw
725
725
  data of $$valPt is always 'undef' type, and may not be used
726
726
  when writing except for SubDirectory tags). EXIF tags (and