exiftool_vendored 12.18.0 → 12.33.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +236 -4
  3. data/bin/MANIFEST +23 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +45 -43
  7. data/bin/arg_files/xmp2exif.args +2 -1
  8. data/bin/config_files/acdsee.config +193 -6
  9. data/bin/config_files/convert_regions.config +25 -14
  10. data/bin/config_files/cuepointlist.config +70 -0
  11. data/bin/config_files/example.config +2 -9
  12. data/bin/exiftool +152 -97
  13. data/bin/fmt_files/gpx.fmt +2 -2
  14. data/bin/fmt_files/gpx_wpt.fmt +2 -2
  15. data/bin/fmt_files/kml.fmt +1 -1
  16. data/bin/fmt_files/kml_track.fmt +1 -1
  17. data/bin/lib/Image/ExifTool/Apple.pm +3 -2
  18. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +31 -13
  19. data/bin/lib/Image/ExifTool/CBOR.pm +331 -0
  20. data/bin/lib/Image/ExifTool/Canon.pm +44 -19
  21. data/bin/lib/Image/ExifTool/DJI.pm +6 -6
  22. data/bin/lib/Image/ExifTool/DPX.pm +13 -2
  23. data/bin/lib/Image/ExifTool/DjVu.pm +6 -5
  24. data/bin/lib/Image/ExifTool/Exif.pm +124 -13
  25. data/bin/lib/Image/ExifTool/FITS.pm +13 -2
  26. data/bin/lib/Image/ExifTool/FlashPix.pm +35 -10
  27. data/bin/lib/Image/ExifTool/FujiFilm.pm +19 -8
  28. data/bin/lib/Image/ExifTool/GPS.pm +22 -11
  29. data/bin/lib/Image/ExifTool/Geotag.pm +13 -2
  30. data/bin/lib/Image/ExifTool/GoPro.pm +16 -1
  31. data/bin/lib/Image/ExifTool/ICC_Profile.pm +2 -2
  32. data/bin/lib/Image/ExifTool/ID3.pm +15 -3
  33. data/bin/lib/Image/ExifTool/JPEG.pm +74 -4
  34. data/bin/lib/Image/ExifTool/JSON.pm +30 -5
  35. data/bin/lib/Image/ExifTool/Jpeg2000.pm +395 -16
  36. data/bin/lib/Image/ExifTool/LIF.pm +153 -0
  37. data/bin/lib/Image/ExifTool/Lang/nl.pm +60 -59
  38. data/bin/lib/Image/ExifTool/M2TS.pm +137 -5
  39. data/bin/lib/Image/ExifTool/MIE.pm +4 -3
  40. data/bin/lib/Image/ExifTool/MRC.pm +341 -0
  41. data/bin/lib/Image/ExifTool/MWG.pm +3 -3
  42. data/bin/lib/Image/ExifTool/MXF.pm +1 -1
  43. data/bin/lib/Image/ExifTool/MacOS.pm +3 -3
  44. data/bin/lib/Image/ExifTool/Microsoft.pm +298 -82
  45. data/bin/lib/Image/ExifTool/Nikon.pm +18 -5
  46. data/bin/lib/Image/ExifTool/NikonSettings.pm +19 -2
  47. data/bin/lib/Image/ExifTool/Olympus.pm +10 -3
  48. data/bin/lib/Image/ExifTool/Other.pm +93 -0
  49. data/bin/lib/Image/ExifTool/PDF.pm +9 -12
  50. data/bin/lib/Image/ExifTool/PNG.pm +8 -7
  51. data/bin/lib/Image/ExifTool/Panasonic.pm +28 -3
  52. data/bin/lib/Image/ExifTool/Pentax.pm +28 -5
  53. data/bin/lib/Image/ExifTool/PhaseOne.pm +4 -3
  54. data/bin/lib/Image/ExifTool/Photoshop.pm +6 -0
  55. data/bin/lib/Image/ExifTool/QuickTime.pm +234 -75
  56. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +283 -141
  57. data/bin/lib/Image/ExifTool/README +5 -2
  58. data/bin/lib/Image/ExifTool/RIFF.pm +89 -12
  59. data/bin/lib/Image/ExifTool/Samsung.pm +48 -10
  60. data/bin/lib/Image/ExifTool/Shortcuts.pm +9 -0
  61. data/bin/lib/Image/ExifTool/Sony.pm +230 -69
  62. data/bin/lib/Image/ExifTool/TagInfoXML.pm +1 -0
  63. data/bin/lib/Image/ExifTool/TagLookup.pm +4145 -4029
  64. data/bin/lib/Image/ExifTool/TagNames.pod +671 -287
  65. data/bin/lib/Image/ExifTool/Torrent.pm +18 -11
  66. data/bin/lib/Image/ExifTool/WriteExif.pl +1 -1
  67. data/bin/lib/Image/ExifTool/WriteIPTC.pl +1 -1
  68. data/bin/lib/Image/ExifTool/WritePDF.pl +1 -0
  69. data/bin/lib/Image/ExifTool/WritePNG.pl +2 -0
  70. data/bin/lib/Image/ExifTool/WritePostScript.pl +1 -0
  71. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +55 -21
  72. data/bin/lib/Image/ExifTool/WriteXMP.pl +7 -3
  73. data/bin/lib/Image/ExifTool/Writer.pl +47 -10
  74. data/bin/lib/Image/ExifTool/XMP.pm +45 -15
  75. data/bin/lib/Image/ExifTool/XMP2.pl +3 -1
  76. data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
  77. data/bin/lib/Image/ExifTool/ZISRAW.pm +121 -2
  78. data/bin/lib/Image/ExifTool.pm +233 -81
  79. data/bin/lib/Image/ExifTool.pod +114 -93
  80. data/bin/perl-Image-ExifTool.spec +43 -42
  81. data/lib/exiftool_vendored/version.rb +1 -1
  82. metadata +28 -13
@@ -18,7 +18,7 @@ use strict;
18
18
  use vars qw($VERSION);
19
19
  use Image::ExifTool qw(:DataAccess :Utils);
20
20
 
21
- $VERSION = '1.06';
21
+ $VERSION = '1.07';
22
22
 
23
23
  sub ParseAnt($);
24
24
  sub ProcessAnt($$$);
@@ -227,10 +227,11 @@ Tok: for (;;) {
227
227
  last unless $tok =~ /(\\+)$/ and length($1) & 0x01;
228
228
  $tok .= '"'; # quote is part of the string
229
229
  }
230
- # must protect unescaped "$" and "@" symbols, and "\" at end of string
231
- $tok =~ s{\\(.)|([\$\@]|\\$)}{'\\'.($2 || $1)}sge;
232
- # convert C escape sequences (allowed in quoted text)
233
- $tok = eval qq{"$tok"};
230
+ # convert C escape sequences, allowed in quoted text
231
+ # (note: this only converts a few of them!)
232
+ my %esc = ( a => "\a", b => "\b", f => "\f", n => "\n",
233
+ r => "\r", t => "\t", '"' => '"', '\\' => '\\' );
234
+ $tok =~ s/\\(.)/$esc{$1}||'\\'.$1/egs;
234
235
  } else { # key name
235
236
  pos($$dataPt) = pos($$dataPt) - 1;
236
237
  # allow anything in key but whitespace, braces and double quotes
@@ -56,7 +56,7 @@ use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber %intFormat
56
56
  use Image::ExifTool qw(:DataAccess :Utils);
57
57
  use Image::ExifTool::MakerNotes;
58
58
 
59
- $VERSION = '4.32';
59
+ $VERSION = '4.37';
60
60
 
61
61
  sub ProcessExif($$$);
62
62
  sub WriteExif($$$);
@@ -265,6 +265,7 @@ sub BINARY_DATA_LIMIT { return 10 * 1024 * 1024; }
265
265
  32892 => 'Sequential Color Filter', #JR (Sony ARQ)
266
266
  34892 => 'Linear Raw', #2
267
267
  51177 => 'Depth Map', # (DNG 1.5)
268
+ 52527 => 'Semantic Mask', # (DNG 1.6)
268
269
  );
269
270
 
270
271
  %orientation = (
@@ -291,6 +292,7 @@ sub BINARY_DATA_LIMIT { return 10 * 1024 * 1024; }
291
292
  9 => 'Depth map of reduced-resolution image', # (DNG 1.5)
292
293
  16 => 'Enhanced image data', # (DNG 1.5)
293
294
  0x10001 => 'Alternate reduced-resolution image', # (DNG 1.2)
295
+ 0x10004 => 'Semantic Mask', # (DNG 1.6)
294
296
  0xffffffff => 'invalid', #(found in E5700 NEF's)
295
297
  BITMASK => {
296
298
  0 => 'Reduced resolution',
@@ -321,6 +323,7 @@ my %utf8StringConv = (
321
323
  my %longBin = (
322
324
  ValueConv => 'length($val) > 64 ? \$val : $val',
323
325
  ValueConvInv => '$val',
326
+ LongBinary => 1, # flag to avoid decoding values of a large array
324
327
  );
325
328
 
326
329
  # PrintConv for SampleFormat (0x153)
@@ -365,6 +368,7 @@ my %opcodeInfo = (
365
368
  11 => 'DeltaPerColumn',
366
369
  12 => 'ScalePerRow',
367
370
  13 => 'ScalePerColumn',
371
+ 14 => 'WarpRectilinear2', # (DNG 1.6)
368
372
  },
369
373
  PrintConvInv => undef, # (so the inverse conversion is not performed)
370
374
  );
@@ -1452,6 +1456,7 @@ my %opcodeInfo = (
1452
1456
  1 => 'Sony Uncompressed 12-bit RAW', #IB
1453
1457
  2 => 'Sony Compressed RAW', # (lossy, ref IB)
1454
1458
  3 => 'Sony Lossless Compressed RAW', #IB
1459
+ 4 => 'Sony Lossless Compressed RAW 2', #JR (ILCE-1)
1455
1460
  },
1456
1461
  },
1457
1462
  # 0x7001 - int16u[1] (in SubIFD of Sony ARW images) - values: 0,1
@@ -1472,6 +1477,7 @@ my %opcodeInfo = (
1472
1477
  PrintConv => {
1473
1478
  256 => 'Off',
1474
1479
  257 => 'Auto',
1480
+ 272 => 'Auto (ILCE-1)', #JR
1475
1481
  511 => 'No correction params available',
1476
1482
  },
1477
1483
  },
@@ -2578,7 +2584,7 @@ my %opcodeInfo = (
2578
2584
  0xa301 => {
2579
2585
  Name => 'SceneType',
2580
2586
  Writable => 'undef',
2581
- ValueConvInv => 'chr($val)',
2587
+ ValueConvInv => 'chr($val & 0xff)',
2582
2588
  PrintConv => {
2583
2589
  1 => 'Directly photographed',
2584
2590
  },
@@ -3035,12 +3041,12 @@ my %opcodeInfo = (
3035
3041
  },
3036
3042
  },
3037
3043
  #
3038
- # DNG tags 0xc6XX and 0xc7XX (ref 2 unless otherwise stated)
3044
+ # DNG tags 0xc6XX, 0xc7XX and 0xcdXX (ref 2 unless otherwise stated)
3039
3045
  #
3040
3046
  0xc612 => {
3041
3047
  Name => 'DNGVersion',
3042
3048
  Notes => q{
3043
- tags 0xc612-0xc7b5 are defined by the DNG specification unless otherwise
3049
+ tags 0xc612-0xcd3b are defined by the DNG specification unless otherwise
3044
3050
  noted. See L<https://helpx.adobe.com/photoshop/digital-negative.html> for
3045
3051
  the specification
3046
3052
  },
@@ -3616,11 +3622,11 @@ my %opcodeInfo = (
3616
3622
  },
3617
3623
  0xc6fc => {
3618
3624
  Name => 'ProfileToneCurve',
3625
+ %longBin,
3619
3626
  Writable => 'float',
3620
3627
  WriteGroup => 'IFD0',
3621
3628
  Count => -1,
3622
3629
  Protected => 1,
3623
- Binary => 1,
3624
3630
  },
3625
3631
  0xc6fd => {
3626
3632
  Name => 'ProfileEmbedPolicy',
@@ -3745,11 +3751,11 @@ my %opcodeInfo = (
3745
3751
  },
3746
3752
  0xc726 => {
3747
3753
  Name => 'ProfileLookTableData',
3754
+ %longBin,
3748
3755
  Writable => 'float',
3749
3756
  WriteGroup => 'IFD0',
3750
3757
  Count => -1,
3751
3758
  Protected => 1,
3752
- Binary => 1,
3753
3759
  },
3754
3760
  0xc740 => { Name => 'OpcodeList1', %opcodeInfo }, # DNG 1.3
3755
3761
  0xc741 => { Name => 'OpcodeList2', %opcodeInfo }, # DNG 1.3
@@ -4038,6 +4044,97 @@ my %opcodeInfo = (
4038
4044
  Protected => 1,
4039
4045
  WriteGroup => 'IFD0',
4040
4046
  },
4047
+ 0xcd2d => { # DNG 1.6
4048
+ Name => 'ProfileGainTableMap',
4049
+ Writable => 'undef',
4050
+ WriteGroup => 'SubIFD',
4051
+ Protected => 1,
4052
+ Binary => 1,
4053
+ },
4054
+ 0xcd2e => { # DNG 1.6
4055
+ Name => 'SemanticName',
4056
+ # Writable => 'string',
4057
+ WriteGroup => 'SubIFD' #? (NC) Semantic Mask IFD (only for Validate)
4058
+ },
4059
+ 0xcd30 => { # DNG 1.6
4060
+ Name => 'SemanticInstanceIFD',
4061
+ # Writable => 'string',
4062
+ WriteGroup => 'SubIFD' #? (NC) Semantic Mask IFD (only for Validate)
4063
+ },
4064
+ 0xcd31 => { # DNG 1.6
4065
+ Name => 'CalibrationIlluminant3',
4066
+ Writable => 'int16u',
4067
+ WriteGroup => 'IFD0',
4068
+ Protected => 1,
4069
+ SeparateTable => 'LightSource',
4070
+ PrintConv => \%lightSource,
4071
+ },
4072
+ 0xcd32 => { # DNG 1.6
4073
+ Name => 'CameraCalibration3',
4074
+ Writable => 'rational64s',
4075
+ WriteGroup => 'IFD0',
4076
+ Count => -1,
4077
+ Protected => 1,
4078
+ },
4079
+ 0xcd33 => { # DNG 1.6
4080
+ Name => 'ColorMatrix3',
4081
+ Writable => 'rational64s',
4082
+ WriteGroup => 'IFD0',
4083
+ Count => -1,
4084
+ Protected => 1,
4085
+ },
4086
+ 0xcd34 => { # DNG 1.6
4087
+ Name => 'ForwardMatrix3',
4088
+ Writable => 'rational64s',
4089
+ WriteGroup => 'IFD0',
4090
+ Count => -1,
4091
+ Protected => 1,
4092
+ },
4093
+ 0xcd35 => { # DNG 1.6
4094
+ Name => 'IlluminantData1',
4095
+ Writable => 'undef',
4096
+ WriteGroup => 'IFD0',
4097
+ Protected => 1,
4098
+ },
4099
+ 0xcd36 => { # DNG 1.6
4100
+ Name => 'IlluminantData2',
4101
+ Writable => 'undef',
4102
+ WriteGroup => 'IFD0',
4103
+ Protected => 1,
4104
+ },
4105
+ 0xcd37 => { # DNG 1.6
4106
+ Name => 'IlluminantData3',
4107
+ Writable => 'undef',
4108
+ WriteGroup => 'IFD0',
4109
+ Protected => 1,
4110
+ },
4111
+ 0xcd38 => { # DNG 1.6
4112
+ Name => 'MaskSubArea',
4113
+ # Writable => 'int32u',
4114
+ WriteGroup => 'SubIFD', #? (NC) Semantic Mask IFD (only for Validate)
4115
+ Count => 4,
4116
+ },
4117
+ 0xcd39 => { # DNG 1.6
4118
+ Name => 'ProfileHueSatMapData3',
4119
+ %longBin,
4120
+ Writable => 'float',
4121
+ WriteGroup => 'IFD0',
4122
+ Count => -1,
4123
+ Protected => 1,
4124
+ },
4125
+ 0xcd3a => { # DNG 1.6
4126
+ Name => 'ReductionMatrix3',
4127
+ Writable => 'rational64s',
4128
+ WriteGroup => 'IFD0',
4129
+ Count => -1,
4130
+ Protected => 1,
4131
+ },
4132
+ 0xcd3b => { # DNG 1.6
4133
+ Name => 'RGBTables',
4134
+ Writable => 'undef',
4135
+ WriteGroup => 'IFD0',
4136
+ Protected => 1,
4137
+ },
4041
4138
  0xea1c => { #13
4042
4139
  Name => 'Padding',
4043
4140
  Binary => 1,
@@ -5796,7 +5893,8 @@ sub ProcessExif($$$)
5796
5893
  $numEntries = Get16u($dataPt, $dirStart);
5797
5894
  } else {
5798
5895
  $et->Warn("Bad $dir directory", $inMakerNotes);
5799
- return 0 unless $inMakerNotes and $dirLen >= 14;
5896
+ return 0 unless $inMakerNotes and $dirLen >= 14 and $dirStart >= 0 and
5897
+ $dirStart + $dirLen <= length($$dataPt);
5800
5898
  $dirSize = $dirLen;
5801
5899
  $numEntries = int(($dirSize - 2) / 12); # read what we can
5802
5900
  Set16u($numEntries, $dataPt, $dirStart);
@@ -5914,7 +6012,7 @@ sub ProcessExif($$$)
5914
6012
  my $size = $count * $formatSize[$format];
5915
6013
  my $readSize = $size;
5916
6014
  if ($size > 4) {
5917
- if ($size > 0x7fffffff) {
6015
+ if ($size > 0x7fffffff and (not $tagInfo or not $$tagInfo{ReadFromRAF})) {
5918
6016
  $et->Warn(sprintf("Invalid size (%u) for %s %s",$size,$dir,TagName($tagID,$tagInfo)), $inMakerNotes);
5919
6017
  ++$warnCount;
5920
6018
  next;
@@ -6167,17 +6265,30 @@ sub ProcessExif($$$)
6167
6265
  unless ($bad) {
6168
6266
  # limit maximum length of data to reformat
6169
6267
  # (avoids long delays when processing some corrupted files)
6268
+ my $warned;
6170
6269
  if ($count > 100000 and $formatStr !~ /^(undef|string|binary)$/) {
6171
6270
  my $tagName = $tagInfo ? $$tagInfo{Name} : sprintf('tag 0x%.4x', $tagID);
6271
+ # (count of 196608 is typical for ColorMap)
6172
6272
  if ($tagName ne 'TransferFunction' or $count != 196608) {
6173
6273
  my $minor = $count > 2000000 ? 0 : 2;
6174
- next if $et->Warn("Ignoring $dirName $tagName with excessive count", $minor);
6274
+ if ($et->Warn("Ignoring $dirName $tagName with excessive count", $minor)) {
6275
+ next unless $$et{OPTIONS}{HtmlDump};
6276
+ $warned = 1;
6277
+ }
6175
6278
  }
6176
6279
  }
6177
- # convert according to specified format
6178
- $val = ReadValue($valueDataPt,$valuePtr,$formatStr,$count,$readSize,\$rational);
6179
- # re-code if necessary
6180
- $val = $et->Decode($val, $strEnc) if $strEnc and $formatStr eq 'string' and defined $val;
6280
+ if ($count > 500 and $formatStr !~ /^(undef|string|binary)$/ and
6281
+ (not $tagInfo or $$tagInfo{LongBinary} or $warned) and not $$et{OPTIONS}{IgnoreMinorErrors})
6282
+ {
6283
+ $et->WarnOnce('Not decoding some large array(s). Ignore minor errors to decode', 2) unless $warned;
6284
+ next if $$et{TAGS_FROM_FILE}; # don't generate bogus value when copying tags
6285
+ $val = "(large array of $count $formatStr values)";
6286
+ } else {
6287
+ # convert according to specified format
6288
+ $val = ReadValue($valueDataPt,$valuePtr,$formatStr,$count,$readSize,\$rational);
6289
+ # re-code if necessary
6290
+ $val = $et->Decode($val, $strEnc) if $strEnc and $formatStr eq 'string' and defined $val;
6291
+ }
6181
6292
  }
6182
6293
 
6183
6294
  if ($verbose) {
@@ -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.00';
17
+ $VERSION = '1.02';
18
18
 
19
19
  # FITS tags (ref 1)
20
20
  %Image::ExifTool::FITS::Main = (
@@ -36,6 +36,10 @@ $VERSION = '1.00';
36
36
  'TIME-OBS'=> { Name => 'ObservationTime', Groups => { 2 => 'Time' } },
37
37
  'DATE-END'=> { Name => 'ObservationDateEnd', Groups => { 2 => 'Time' } },
38
38
  'TIME-END'=> { Name => 'ObservationTimeEnd', Groups => { 2 => 'Time' } },
39
+ COMMENT => { Name => 'Comment', PrintConv => '$val =~ s/^ +//; $val',
40
+ Notes => 'leading spaces are removed if L<PrintConv|../ExifTool.html#PrintConv> is enabled' },
41
+ HISTORY => { Name => 'History', PrintConv => '$val =~ s/^ +//; $val',
42
+ Notes => 'leading spaces are removed if L<PrintConv|../ExifTool.html#PrintConv> is enabled' },
39
43
  );
40
44
 
41
45
  #------------------------------------------------------------------------------
@@ -67,7 +71,14 @@ sub ProcessFITS($$)
67
71
  last if $key eq 'END';
68
72
  # make sure the key is valid
69
73
  $key =~ /^[-_A-Z0-9]*$/ or $et->Warn('Format error in FITS header'), last;
70
- next unless substr($buff,8,2) eq '= '; # ignore comment lines
74
+ if ($key eq 'COMMENT' or $key eq 'HISTORY') {
75
+ my $val = substr($buff, 8); # comments start in column 9
76
+ $val =~ s/ +$//; # remove trailing spaces
77
+ $et->HandleTag($tagTablePtr, $key, $val);
78
+ next;
79
+ }
80
+ # ignore other lines that aren't tags
81
+ next unless substr($buff,8,2) eq '= ';
71
82
  # save tag name (avoiding potential conflict with ExifTool variables)
72
83
  $tag = $Image::ExifTool::specialTags{$key} ? "_$key" : $key;
73
84
  # add to tag table if necessary
@@ -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.38';
24
+ $VERSION = '1.39';
25
25
 
26
26
  sub ProcessFPX($$);
27
27
  sub ProcessFPXR($$$);
@@ -1369,29 +1369,48 @@ sub ReadFPXValue($$$$$;$$)
1369
1369
  my $flags = $type & 0xf000;
1370
1370
  if ($flags) {
1371
1371
  if ($flags == VT_VECTOR) {
1372
- $noPad = 1; # values don't seem to be padded inside vectors
1372
+ $noPad = 1; # values sometimes aren't padded inside vectors!!
1373
1373
  my $size = $oleFormatSize{VT_VECTOR};
1374
- last if $valPos + $size > $dirEnd;
1374
+ if ($valPos + $size > $dirEnd) {
1375
+ $et->WarnOnce('Incorrect FPX VT_VECTOR size');
1376
+ last;
1377
+ }
1375
1378
  $count = Get32u($dataPt, $valPos);
1376
1379
  push @vals, '' if $count == 0; # allow zero-element vector
1377
1380
  $valPos += 4;
1378
1381
  } else {
1379
1382
  # can't yet handle this property flag
1383
+ $et->WarnOnce('Unknown FPX property');
1380
1384
  last;
1381
1385
  }
1382
1386
  }
1383
1387
  unless ($format =~ /^VT_/) {
1384
1388
  my $size = Image::ExifTool::FormatSize($format) * $count;
1385
- last if $valPos + $size > $dirEnd;
1389
+ if ($valPos + $size > $dirEnd) {
1390
+ $et->WarnOnce("Incorrect FPX $format size");
1391
+ last;
1392
+ }
1386
1393
  @vals = ReadValue($dataPt, $valPos, $format, $count, $size);
1387
1394
  # update position to end of value plus padding
1388
1395
  $valPos += ($count * $size + 3) & 0xfffffffc;
1389
1396
  last;
1390
1397
  }
1391
1398
  my $size = $oleFormatSize{$format};
1392
- my ($item, $val);
1399
+ my ($item, $val, $len);
1393
1400
  for ($item=0; $item<$count; ++$item) {
1394
- last if $valPos + $size > $dirEnd;
1401
+ if ($valPos + $size > $dirEnd) {
1402
+ $et->WarnOnce("Truncated FPX $format value");
1403
+ last;
1404
+ }
1405
+ # sometimes VT_VECTOR items are padded to even 4-byte boundaries, and sometimes they aren't
1406
+ if ($noPad and defined $len and $len & 0x03) {
1407
+ my $pad = 4 - ($len & 0x03);
1408
+ if ($valPos + $pad + $size <= $dirEnd) {
1409
+ # skip padding if all zeros
1410
+ $valPos += $pad if substr($$dataPt, $valPos, $pad) eq "\0" x $pad;
1411
+ }
1412
+ }
1413
+ undef $len;
1395
1414
  if ($format eq 'VT_VARIANT') {
1396
1415
  my $subType = Get32u($dataPt, $valPos);
1397
1416
  $valPos += $size;
@@ -1429,9 +1448,12 @@ sub ReadFPXValue($$$$$;$$)
1429
1448
  $val = ($val - 25569) * 24 * 3600 if $val != 0;
1430
1449
  $val = Image::ExifTool::ConvertUnixTime($val);
1431
1450
  } elsif ($format =~ /STR$/) {
1432
- my $len = Get32u($dataPt, $valPos);
1451
+ $len = Get32u($dataPt, $valPos);
1433
1452
  $len *= 2 if $format eq 'VT_LPWSTR'; # convert to byte count
1434
- last if $valPos + $len + 4 > $dirEnd;
1453
+ if ($valPos + $len + 4 > $dirEnd) {
1454
+ $et->WarnOnce("Truncated $format value");
1455
+ last;
1456
+ }
1435
1457
  $val = substr($$dataPt, $valPos + 4, $len);
1436
1458
  if ($format eq 'VT_LPWSTR') {
1437
1459
  # convert wide string from Unicode
@@ -1450,8 +1472,11 @@ sub ReadFPXValue($$$$$;$$)
1450
1472
  # on even 32-bit boundaries, but this isn't always the case)
1451
1473
  $valPos += $noPad ? $len : ($len + 3) & 0xfffffffc;
1452
1474
  } elsif ($format eq 'VT_BLOB' or $format eq 'VT_CF') {
1453
- my $len = Get32u($dataPt, $valPos);
1454
- last if $valPos + $len + 4 > $dirEnd;
1475
+ my $len = Get32u($dataPt, $valPos); # (use local $len because we always expect padding)
1476
+ if ($valPos + $len + 4 > $dirEnd) {
1477
+ $et->WarnOnce("Truncated $format value");
1478
+ last;
1479
+ }
1455
1480
  $val = substr($$dataPt, $valPos + 4, $len);
1456
1481
  # update position for data length plus padding
1457
1482
  # (does this padding disappear in arrays too?)
@@ -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.79';
34
+ $VERSION = '1.80';
35
35
 
36
36
  sub ProcessFujiDir($$$);
37
37
  sub ProcessFaceRec($$$);
@@ -489,6 +489,7 @@ my %faceCategories = (
489
489
  3 => 'Electronic Front Curtain', #10
490
490
  },
491
491
  },
492
+ # 0x1100 - This may not work well for newer cameras (ref forum12682)
492
493
  0x1100 => [{
493
494
  Name => 'AutoBracketing',
494
495
  Condition => '$$self{Model} eq "X-T3"',
@@ -507,6 +508,7 @@ my %faceCategories = (
507
508
  0 => 'Off',
508
509
  1 => 'On',
509
510
  2 => 'No flash & flash', #3
511
+ 6 => 'Pixel Shift', #IB (GFX100S)
510
512
  },
511
513
  }],
512
514
  0x1101 => {
@@ -517,6 +519,8 @@ my %faceCategories = (
517
519
  Name => 'DriveSettings',
518
520
  SubDirectory => { TagTable => 'Image::ExifTool::FujiFilm::DriveSettings' },
519
521
  },
522
+ 0x1105 => { Name => 'PixelShiftShots', Writable => 'int16u' }, #IB
523
+ 0x1106 => { Name => 'PixelShiftOffset', Writable => 'rational64s', Count => 2 }, #IB
520
524
  # (0x1150-0x1152 exist only for Pro Low-light and Pro Focus PictureModes)
521
525
  # 0x1150 - Pro Low-light - val=1; Pro Focus - val=2 (ref 7); HDR - val=128 (forum10799)
522
526
  # 0x1151 - Pro Low-light - val=4 (number of pictures taken?); Pro Focus - val=2,3 (ref 7); HDR - val=3 (forum10799)
@@ -915,15 +919,22 @@ my %faceCategories = (
915
919
  WRITABLE => 1,
916
920
  0.1 => {
917
921
  Name => 'FocusMode2',
918
- Mask => 0x000000ff,
922
+ Mask => 0x0000000f,
919
923
  PrintConv => {
920
- 0x00 => 'AF-M',
921
- 0x01 => 'AF-S',
922
- 0x02 => 'AF-C',
923
- 0x11 => 'AF-S (Auto)',
924
+ 0x0 => 'AF-M',
925
+ 0x1 => 'AF-S',
926
+ 0x2 => 'AF-C',
924
927
  },
925
928
  },
926
929
  0.2 => {
930
+ Name => 'PreAF',
931
+ Mask => 0x00f0,
932
+ PrintConv => {
933
+ 0 => 'Off',
934
+ 1 => 'On',
935
+ },
936
+ },
937
+ 0.3 => {
927
938
  Name => 'AFAreaMode',
928
939
  Mask => 0x0f00,
929
940
  PrintConv => {
@@ -932,7 +943,7 @@ my %faceCategories = (
932
943
  2 => 'Wide/Tracking',
933
944
  },
934
945
  },
935
- 0.3 => {
946
+ 0.4 => {
936
947
  Name => 'AFAreaPointSize',
937
948
  Mask => 0xf000,
938
949
  PrintConv => {
@@ -940,7 +951,7 @@ my %faceCategories = (
940
951
  OTHER => sub { return $_[0] },
941
952
  },
942
953
  },
943
- 0.4 => {
954
+ 0.5 => {
944
955
  Name => 'AFAreaZoneSize',
945
956
  Mask => 0xf0000,
946
957
  PrintConv => {
@@ -12,13 +12,12 @@ use strict;
12
12
  use vars qw($VERSION);
13
13
  use Image::ExifTool::Exif;
14
14
 
15
- $VERSION = '1.52';
15
+ $VERSION = '1.53';
16
16
 
17
17
  my %coordConv = (
18
18
  ValueConv => 'Image::ExifTool::GPS::ToDegrees($val)',
19
19
  ValueConvInv => 'Image::ExifTool::GPS::ToDMS($self, $val)',
20
20
  PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1)',
21
- PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val)',
22
21
  );
23
22
 
24
23
  %Image::ExifTool::GPS::Main = (
@@ -41,7 +40,7 @@ my %coordConv = (
41
40
  Notes => q{
42
41
  tags 0x0001-0x0006 used for camera location according to MWG 2.0. ExifTool
43
42
  will also accept a number when writing GPSLatitudeRef, positive for north
44
- latitudes or negative for south, or a string ending in N or S
43
+ latitudes or negative for south, or a string containing N, North, S or South
45
44
  },
46
45
  Count => 2,
47
46
  PrintConv => {
@@ -50,7 +49,7 @@ my %coordConv = (
50
49
  OTHER => sub {
51
50
  my ($val, $inv) = @_;
52
51
  return undef unless $inv;
53
- return uc $1 if $val =~ /\b([NS])\b/i;
52
+ return uc $2 if $val =~ /(^|[^A-Z])([NS])(orth|outh)?\b/i;
54
53
  return $1 eq '-' ? 'S' : 'N' if $val =~ /([-+]?)\d+/;
55
54
  return undef;
56
55
  },
@@ -63,6 +62,7 @@ my %coordConv = (
63
62
  Writable => 'rational64u',
64
63
  Count => 3,
65
64
  %coordConv,
65
+ PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val,undef,"lat")',
66
66
  },
67
67
  0x0003 => {
68
68
  Name => 'GPSLongitudeRef',
@@ -70,7 +70,7 @@ my %coordConv = (
70
70
  Count => 2,
71
71
  Notes => q{
72
72
  ExifTool will also accept a number when writing this tag, positive for east
73
- longitudes or negative for west, or a string ending in E or W
73
+ longitudes or negative for west, or a string containing E, East, W or West
74
74
  },
75
75
  PrintConv => {
76
76
  # extract E/W if written from Composite:GPSLongitude
@@ -78,7 +78,7 @@ my %coordConv = (
78
78
  OTHER => sub {
79
79
  my ($val, $inv) = @_;
80
80
  return undef unless $inv;
81
- return uc $1 if $val =~ /\b([EW])\b/i;
81
+ return uc $2 if $val =~ /(^|[^A-Z])([EW])(ast|est)?\b/i;
82
82
  return $1 eq '-' ? 'W' : 'E' if $val =~ /([-+]?)\d+/;
83
83
  return undef;
84
84
  },
@@ -91,6 +91,7 @@ my %coordConv = (
91
91
  Writable => 'rational64u',
92
92
  Count => 3,
93
93
  %coordConv,
94
+ PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val,undef,"lon")',
94
95
  },
95
96
  0x0005 => {
96
97
  Name => 'GPSAltitudeRef',
@@ -238,6 +239,7 @@ my %coordConv = (
238
239
  Writable => 'rational64u',
239
240
  Count => 3,
240
241
  %coordConv,
242
+ PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val,undef,"lat")',
241
243
  },
242
244
  0x0015 => {
243
245
  Name => 'GPSDestLongitudeRef',
@@ -250,6 +252,7 @@ my %coordConv = (
250
252
  Writable => 'rational64u',
251
253
  Count => 3,
252
254
  %coordConv,
255
+ PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val,undef,"lon")',
253
256
  },
254
257
  0x0017 => {
255
258
  Name => 'GPSDestBearingRef',
@@ -529,18 +532,26 @@ sub ToDMS($$;$$)
529
532
  #------------------------------------------------------------------------------
530
533
  # Convert to decimal degrees
531
534
  # Inputs: 0) a string containing 1-3 decimal numbers and any amount of other garbage
532
- # 1) true if value should be negative if coordinate ends in 'S' or 'W'
533
- # Returns: Coordinate in degrees
534
- sub ToDegrees($;$)
535
+ # 1) true if value should be negative if coordinate ends in 'S' or 'W',
536
+ # 2) 'lat' or 'lon' to extract lat or lon from GPSCoordinates string
537
+ # Returns: Coordinate in degrees, or '' on error
538
+ sub ToDegrees($;$$)
535
539
  {
536
- my ($val, $doSign) = @_;
540
+ my ($val, $doSign, $coord) = @_;
537
541
  return '' if $val =~ /\b(inf|undef)\b/; # ignore invalid values
542
+ # use only lat or lon part of combined GPSCoordinates inputs
543
+ if ($coord and ($coord eq 'lat' or $coord eq 'lon') and
544
+ # (two formatted coordinate values with cardinal directions, separated by a comma)
545
+ $val =~ /^(.*(?:N(?:orth)?|S(?:outh)?)),\s*(.*(?:E(?:ast)?|W(?:est)?))$/i)
546
+ {
547
+ $val = $coord eq 'lat' ? $1 : $2;
548
+ }
538
549
  # extract decimal or floating point values out of any other garbage
539
550
  my ($d, $m, $s) = ($val =~ /((?:[+-]?)(?=\d|\.\d)\d*(?:\.\d*)?(?:[Ee][+-]\d+)?)/g);
540
551
  return '' unless defined $d;
541
552
  my $deg = $d + (($m || 0) + ($s || 0)/60) / 60;
542
553
  # make negative if S or W coordinate
543
- $deg = -$deg if $doSign ? $val =~ /[^A-Z](S|W)$/i : $deg < 0;
554
+ $deg = -$deg if $doSign ? $val =~ /[^A-Z](S(outh)?|W(est)?)\s*$/i : $deg < 0;
544
555
  return $deg;
545
556
  }
546
557
 
@@ -28,7 +28,7 @@ use vars qw($VERSION);
28
28
  use Image::ExifTool qw(:Public);
29
29
  use Image::ExifTool::GPS;
30
30
 
31
- $VERSION = '1.64';
31
+ $VERSION = '1.65';
32
32
 
33
33
  sub JITTER() { return 2 } # maximum time jitter
34
34
 
@@ -262,8 +262,10 @@ sub LoadTrackLog($$;$)
262
262
  $param = 'time';
263
263
  } elsif (/^(Pos)?Lat/i) {
264
264
  $param = 'lat';
265
+ /ref$/i and $param .= 'ref';
265
266
  } elsif (/^(Pos)?Lon/i) {
266
267
  $param = 'lon';
268
+ /ref$/i and $param .= 'ref';
267
269
  } elsif (/^(Pos)?Alt/i) {
268
270
  $param = 'alt';
269
271
  } elsif (/^(Angle)?(Heading|Track)/i) {
@@ -453,7 +455,7 @@ DoneFix: $isDate = 1;
453
455
  # (ExifTool enhancements allow for standard tag names or descriptions as the column headings,
454
456
  # add support for time zones and flexible coordinates, and allow new DateTime and Shift columns)
455
457
  #
456
- my ($param, $date, $secs);
458
+ my ($param, $date, $secs, %neg);
457
459
  foreach $param (@csvHeadings) {
458
460
  my $val = shift @vals;
459
461
  last unless defined $val;
@@ -479,6 +481,10 @@ DoneFix: $isDate = 1;
479
481
  }
480
482
  } elsif ($param eq 'lat' or $param eq 'lon') {
481
483
  $$fix{$param} = Image::ExifTool::GPS::ToDegrees($val, 1);
484
+ } elsif ($param eq 'latref') {
485
+ $neg{lat} = 1 if $val =~ /^S/i;
486
+ } elsif ($param eq 'lonref') {
487
+ $neg{lon} = 1 if $val =~ /^W/i;
482
488
  } elsif ($param eq 'runtime') {
483
489
  $date = $trackTime;
484
490
  $secs = $val;
@@ -486,6 +492,11 @@ DoneFix: $isDate = 1;
486
492
  $$fix{$param} = $val;
487
493
  }
488
494
  }
495
+ # make coordinate negative according to reference direction if necessary
496
+ foreach $param (keys %neg) {
497
+ next unless defined $$fix{$param};
498
+ $$fix{$param} = -abs($$fix{$param});
499
+ }
489
500
  if ($date and defined $secs and defined $$fix{lat} and defined $$fix{lon}) {
490
501
  $time = $date + $secs;
491
502
  $$has{alt} = 1 if defined $$fix{alt};