exiftool_vendored 12.18.0 → 12.33.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 (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};