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
@@ -27,15 +27,16 @@
27
27
  package Image::ExifTool::RIFF;
28
28
 
29
29
  use strict;
30
- use vars qw($VERSION);
30
+ use vars qw($VERSION $AUTOLOAD);
31
31
  use Image::ExifTool qw(:DataAccess :Utils);
32
32
 
33
- $VERSION = '1.59';
33
+ $VERSION = '1.61';
34
34
 
35
35
  sub ConvertTimecode($);
36
36
  sub ProcessSGLT($$$);
37
37
  sub ProcessSLLT($$$);
38
38
  sub ProcessLucas($$$);
39
+ sub WriteRIFF($$);
39
40
 
40
41
  # recognized RIFF variants
41
42
  my %riffType = (
@@ -340,6 +341,9 @@ my %code2charset = (
340
341
  Large AVI videos may be a concatenation of two or more RIFF chunks. For
341
342
  these files, information is extracted from subsequent RIFF chunks as
342
343
  sub-documents, but the Duration is calculated for the full video.
344
+
345
+ ExifTool currently has the ability to write EXIF, XMP and ICC_Profile
346
+ metadata to WEBP images, but can't yet write to other RIFF-based formats.
343
347
  },
344
348
  # (not 100% sure that the concatenation technique mentioned above is valid - PH)
345
349
  'fmt ' => {
@@ -544,7 +548,7 @@ my %code2charset = (
544
548
  },
545
549
  },{ # (WebP) - have also seen with "Exif\0\0" header - PH
546
550
  Name => 'EXIF',
547
- Condition => '$$valPt =~ /^Exif\0\0(II\x2a\0|MM\0\x2a)/',
551
+ Condition => '$$valPt =~ /^Exif\0\0(II\x2a\0|MM\0\x2a)/ and $self->Warn("Improper EXIF header",1)',
548
552
  SubDirectory => {
549
553
  TagTable => 'Image::ExifTool::Exif::Main',
550
554
  ProcessProc => \&Image::ExifTool::ProcessTIFF,
@@ -636,6 +640,11 @@ my %code2charset = (
636
640
  },
637
641
  # gpsa - seen hex "01 20 00 00", same as QuickTime
638
642
  # gsea - 16 bytes hex "04 08 02 00 20 02 00 00 1f 03 00 00 01 00 00 00"
643
+
644
+ acid => { # writen by Acidizer
645
+ Name => 'Acidizer',
646
+ SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Acidizer' },
647
+ },
639
648
  );
640
649
 
641
650
  # the maker notes used by some digital cameras
@@ -1249,6 +1258,7 @@ my %code2charset = (
1249
1258
  Name => 'ImageWidth',
1250
1259
  Format => 'int16u',
1251
1260
  Mask => 0x3fff,
1261
+ Priority => 0,
1252
1262
  },
1253
1263
  6.1 => {
1254
1264
  Name => 'HorizontalScale',
@@ -1259,6 +1269,7 @@ my %code2charset = (
1259
1269
  Name => 'ImageHeight',
1260
1270
  Format => 'int16u',
1261
1271
  Mask => 0x3fff,
1272
+ Priority => 0,
1262
1273
  },
1263
1274
  8.1 => {
1264
1275
  Name => 'VerticalScale',
@@ -1275,11 +1286,13 @@ my %code2charset = (
1275
1286
  1 => {
1276
1287
  Name => 'ImageWidth',
1277
1288
  Format => 'int16u',
1289
+ Priority => 0,
1278
1290
  ValueConv => '($val & 0x3fff) + 1',
1279
1291
  },
1280
1292
  2 => {
1281
1293
  Name => 'ImageHeight',
1282
1294
  Format => 'int32u',
1295
+ Priority => 0,
1283
1296
  ValueConv => '(($val >> 6) & 0x3fff) + 1',
1284
1297
  },
1285
1298
  );
@@ -1290,6 +1303,19 @@ my %code2charset = (
1290
1303
  GROUPS => { 2 => 'Image' },
1291
1304
  NOTES => 'This chunk is found in extended WebP files.',
1292
1305
  # 0 - bitmask: 2=ICC, 3=alpha, 4=EXIF, 5=XMP, 6=animation
1306
+ 0 => {
1307
+ Name => 'WebP_Flags',
1308
+ Description => 'WebP Flags',
1309
+ Notes => 'flags used in Extended WebP images',
1310
+ Format => 'int32u',
1311
+ PrintConv => { BITMASK => {
1312
+ 1 => 'Animation',
1313
+ 2 => 'XMP',
1314
+ 3 => 'EXIF',
1315
+ 4 => 'Alpha',
1316
+ 5 => 'ICC Profile',
1317
+ }},
1318
+ },
1293
1319
  4 => {
1294
1320
  Name => 'ImageWidth',
1295
1321
  Format => 'int32u',
@@ -1420,6 +1446,54 @@ my %code2charset = (
1420
1446
  },
1421
1447
  );
1422
1448
 
1449
+ # Acidizer information (ref https://forums.cockos.com/showthread.php?t=227118)
1450
+ %Image::ExifTool::RIFF::Acidizer = (
1451
+ PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1452
+ GROUPS => { 2 => 'Audio' },
1453
+ 0 => {
1454
+ Name => 'AcidizerFlags',
1455
+ Format => 'int32u',
1456
+ PrintConv => { BITMASK => {
1457
+ 0 => 'One shot',
1458
+ 1 => 'Root note set',
1459
+ 2 => 'Stretch',
1460
+ 3 => 'Disk-based',
1461
+ 4 => 'High octave',
1462
+ }},
1463
+ },
1464
+ 4 => {
1465
+ Name => 'RootNote',
1466
+ Format => 'int16u',
1467
+ PrintConv => {
1468
+ 0x30 => 'C', 0x3c => 'High C',
1469
+ 0x31 => 'C#', 0x3d => 'High C#',
1470
+ 0x32 => 'D', 0x3e => 'High D',
1471
+ 0x33 => 'D#', 0x3f => 'High D#',
1472
+ 0x34 => 'E', 0x40 => 'High E',
1473
+ 0x35 => 'F', 0x41 => 'High F',
1474
+ 0x36 => 'F#', 0x42 => 'High F#',
1475
+ 0x37 => 'G', 0x43 => 'High G',
1476
+ 0x38 => 'G#', 0x44 => 'High G#',
1477
+ 0x39 => 'A', 0x45 => 'High A',
1478
+ 0x3a => 'A#', 0x46 => 'High A#',
1479
+ 0x3b => 'B', 0x47 => 'High B',
1480
+ },
1481
+ },
1482
+ 12 => {
1483
+ Name => 'Beats',
1484
+ Format => 'int32u',
1485
+ },
1486
+ 16 => {
1487
+ Name => 'Meter',
1488
+ Format => 'int16u[2]',
1489
+ PrintConv => '$val =~ s/(\d+) (\d+)/$2\/$1/; $val', # denominator comes first, so swap them
1490
+ },
1491
+ 20 => {
1492
+ Name => 'Tempo',
1493
+ Format => 'float',
1494
+ },
1495
+ );
1496
+
1423
1497
  # RIFF composite tags
1424
1498
  %Image::ExifTool::RIFF::Composite = (
1425
1499
  Duration => {
@@ -1459,6 +1533,14 @@ my %code2charset = (
1459
1533
  Image::ExifTool::AddCompositeTags('Image::ExifTool::RIFF');
1460
1534
 
1461
1535
 
1536
+ #------------------------------------------------------------------------------
1537
+ # AutoLoad our writer routines when necessary
1538
+ #
1539
+ sub AUTOLOAD
1540
+ {
1541
+ return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_);
1542
+ }
1543
+
1462
1544
  #------------------------------------------------------------------------------
1463
1545
  # Convert RIFF date to EXIF format
1464
1546
  my %monthNum = (
@@ -1642,7 +1724,7 @@ sub ProcessChunks($$$)
1642
1724
  my $start = $$dirInfo{DirStart};
1643
1725
  my $size = $$dirInfo{DirLen};
1644
1726
  my $end = $start + $size;
1645
- my $base = $$dirInfo{Base};
1727
+ my $base = $$dirInfo{Base} || 0;
1646
1728
  my $verbose = $et->Options('Verbose');
1647
1729
  my $unknown = $et->Options('Unknown');
1648
1730
  my $charset = $et->Options('CharsetRIFF');
@@ -1896,6 +1978,7 @@ sub ProcessRIFF($$)
1896
1978
  my ($buff, $buf2, $type, $mime, $err, $rf64);
1897
1979
  my $verbose = $et->Options('Verbose');
1898
1980
  my $unknown = $et->Options('Unknown');
1981
+ my $validate = $et->Options('Validate');
1899
1982
  my $ee = $et->Options('ExtractEmbedded');
1900
1983
 
1901
1984
  # verify this is a valid RIFF file
@@ -1917,6 +2000,8 @@ sub ProcessRIFF($$)
1917
2000
  $$et{RIFFStreamType} = ''; # initialize stream type
1918
2001
  $$et{RIFFStreamCodec} = []; # initialize codec array
1919
2002
  SetByteOrder('II');
2003
+ my $riffEnd = Get32u(\$buff, 4) + 8;
2004
+ $riffEnd += $riffEnd & 0x01; # (account for padding)
1920
2005
  my $tagTbl = GetTagTable('Image::ExifTool::RIFF::Main');
1921
2006
  my $pos = 12;
1922
2007
  #
@@ -1926,10 +2011,13 @@ sub ProcessRIFF($$)
1926
2011
  my $num = $raf->Read($buff, 8);
1927
2012
  if ($num < 8) {
1928
2013
  $err = 1 if $num;
2014
+ $et->Warn('Incorrect RIFF chunk size' . " $pos vs. $riffEnd") if $validate and $pos != $riffEnd;
1929
2015
  last;
1930
2016
  }
1931
2017
  $pos += 8;
1932
2018
  my ($tag, $len) = unpack('a4V', $buff);
2019
+ # tweak WEBP type if this is an extended WebP
2020
+ $et->OverrideFileType('Extended WEBP',undef,'webp') if $tag eq 'VP8X' and $type eq 'WEBP';
1933
2021
  # special case: construct new tag name from specific LIST type
1934
2022
  if ($tag eq 'LIST') {
1935
2023
  $raf->Read($buff, 4) == 4 or $err=1, last;
@@ -1949,7 +2037,6 @@ sub ProcessRIFF($$)
1949
2037
  } else {
1950
2038
  next;
1951
2039
  }
1952
- last;
1953
2040
  }
1954
2041
  # stop when we hit the audio data or AVI index or AVI movie data
1955
2042
  # --> no more because Adobe Bridge stores XMP after this!!
@@ -1969,6 +2056,7 @@ sub ProcessRIFF($$)
1969
2056
  $$et{DOC_NUM} = ++$$et{DOC_COUNT};
1970
2057
  }
1971
2058
  my $tagInfo = $$tagTbl{$tag};
2059
+ # (in LIST_movi chunk: ##db = uncompressed DIB, ##dc = compressed DIB, ##wb = audio data)
1972
2060
  if ($tagInfo or (($verbose or $unknown) and $tag !~ /^(data|idx1|LIST_movi|RIFF|\d{2}(db|dc|wb))$/)) {
1973
2061
  $raf->Read($buff, $len2) == $len2 or $err=1, last;
1974
2062
  my $setGroups;
@@ -1980,7 +2068,7 @@ sub ProcessRIFF($$)
1980
2068
  DataPt => \$buff,
1981
2069
  DataPos => 0, # (relative to Base)
1982
2070
  Start => 0,
1983
- Size => $len2,
2071
+ Size => $len,
1984
2072
  Base => $pos,
1985
2073
  );
1986
2074
  if ($setGroups) {
@@ -1989,10 +2077,14 @@ sub ProcessRIFF($$)
1989
2077
  }
1990
2078
  delete $$et{DOC_NUM} if $ee;
1991
2079
  } elsif ($tag eq 'RIFF') {
2080
+ $et->Warn('Incorrect RIFF chunk size') if $validate and $pos - 8 != $riffEnd;
2081
+ $riffEnd += $len2 + 8;
1992
2082
  # don't read into RIFF chunk (eg. concatenated video file)
1993
- $raf->Read($buff, 4) == 4 or $err=1, last;
2083
+ $raf->Read($buff, 4) == 4 or $err=1, last; # (skip RIFF type word)
2084
+ $pos += 4;
1994
2085
  # extract information from remaining file as an embedded file
1995
- $$et{DOC_NUM} = ++$$et{DOC_COUNT}
2086
+ $$et{DOC_NUM} = ++$$et{DOC_COUNT};
2087
+ next; # (must not increment $pos)
1996
2088
  } elsif ($tag eq 'LIST_movi' and $ee) {
1997
2089
  next; # parse into movi chunk
1998
2090
  } else {
@@ -2000,7 +2092,12 @@ sub ProcessRIFF($$)
2000
2092
  $et->Warn("Stopped parsing at large $tag chunk (LargeFileSupport not set)");
2001
2093
  last;
2002
2094
  }
2003
- $raf->Seek($len2, 1) or $err=1, last;
2095
+ if ($validate and $len2) {
2096
+ # (must actually try to read something after seeking to detect error)
2097
+ $raf->Seek($len2-1, 1) and $raf->Read($buff, 1) == 1 or $err = 1, last;
2098
+ } else {
2099
+ $raf->Seek($len2, 1) or $err=1, last;
2100
+ }
2004
2101
  }
2005
2102
  $pos += $len2;
2006
2103
  }
@@ -22,7 +22,7 @@ use vars qw($VERSION %samsungLensTypes);
22
22
  use Image::ExifTool qw(:DataAccess :Utils);
23
23
  use Image::ExifTool::Exif;
24
24
 
25
- $VERSION = '1.52';
25
+ $VERSION = '1.53';
26
26
 
27
27
  sub WriteSTMN($$$);
28
28
  sub ProcessINFO($$$);
@@ -991,7 +991,7 @@ my %formatMinMax = (
991
991
  '0x0a01' => { #forum7161
992
992
  Name => 'TimeStamp',
993
993
  Groups => { 2 => 'Time' },
994
- ValueConv => 'ConvertUnixTime($val / 1e3, 1)',
994
+ ValueConv => 'ConvertUnixTime($val / 1e3, 1, 3)',
995
995
  PrintConv => '$self->ConvertDateTime($val)',
996
996
  },
997
997
  '0x0a20-name' => 'DualCameraImageName', # ("FlipPhoto_002")
@@ -19,7 +19,7 @@ use strict;
19
19
  use vars qw($VERSION %sigmaLensTypes);
20
20
  use Image::ExifTool::Exif;
21
21
 
22
- $VERSION = '1.31';
22
+ $VERSION = '1.32';
23
23
 
24
24
  # sigma LensType lookup (ref IB)
25
25
  %sigmaLensTypes = (
@@ -226,9 +226,35 @@ $VERSION = '1.31';
226
226
  0x1008 => 'Sigma 50mm F2.8 Macro', #NJ (DP3 Quattro kit)
227
227
  0x1009 => 'Sigma 14mm F4', #NJ (DP0 Quattro kit)
228
228
  # L-mount lenses?:
229
+ 0x4001 => 'Lumix S 24-105mm F4 Macro OIS (S-R24105)', #IB
230
+ 0x4002 => 'Lumix S 70-200mm F4 OIS (S-R70200)', #IB
231
+ 0x4003 => 'Lumix S 50mm F1.4 (S-X50)', #IB
232
+ 0x4006 => 'Lumix S 24-70mm F2.8 (S-E2470)', #IB
233
+ 0x4007 => 'Lumix S 16-35mm F4 (S-R1635)', #IB
234
+ 0x4008 => 'Lumix S 70-200mm F2.8 OIS (S-E70200)', #IB
235
+ 0x4010 => 'Lumix S 35mm F1.8 (S-S35)', #IB
236
+ 0x4011 => 'LUMIX S 18mm F1.8 (S-S18)', #IB
237
+ 0x400b => 'Lumix S 20-60mm F3.5-5.6 (S-R2060)', #IB
238
+ 0x400c => 'Lumix S 85mm F1.8 (S-S85)', #IB
239
+ 0x400d => 'Lumix S 70-300 F4.5-5.6 Macro OIS (S-R70300)', #IB
240
+ 0x400f => 'Lumix S 24mm F1.8 (S-S24)', #IB
229
241
  0x6001 => 'Sigma 150-600mm F5-6.3 DG OS HSM | S', #PH (NC, fp)
230
242
  0x6003 => 'Sigma 45mm F2.8 DG DN | C', #PH (NC, fp)
243
+ 0x6005 => 'Sigma 14-24mm F2.8 DG DN | A', #IB
231
244
  0x6006 => 'Sigma 50mm F1.4 DG HSM | A', #IB (014)
245
+ 0x6011 => 'Sigma 24-70mm F2.8 DG DN | A', #IB
246
+ 0x6012 => 'Sigma 100-400mm F5-6.3 DG DN OS | C', #IB
247
+ 0x6013 => 'Sigma 100-400mm F5-6.3 DG DN OS | C + TC-1411', #IB
248
+ 0x6015 => 'Sigma 85mm F1.4 DG DN | A', #IB
249
+ 0x6017 => 'Sigma 65mm F2 DG DN | C', #IB
250
+ 0x6018 => 'Sigma 35mm F2 DG DN | C', #IB
251
+ 0x601a => 'Sigma 28-70mm F2.8 DG DN | C', #IB
252
+ 0x601b => 'Sigma 150-600mm F5-6.3 DG DN OS | S', #IB
253
+ 0x6020 => 'Sigma 35mm F1.4 DG DN | A', #IB
254
+ 0x6021 => 'Sigma 90mm F2.8 DG DN | C', #IB
255
+ 0x6023 => 'Sigma 20mm F2 DG DN | C', #IB
256
+ 0x6025 => 'Sigma 20mm F1.4 DG DN | A', #IB
257
+ 0x6026 => 'Sigma 24mm F1.4 DG DN | A', #IB
232
258
  0x8005 => 'Sigma 35mm F1.4 DG HSM | A', #PH (012)
233
259
  0x8009 => 'Sigma 18-35mm F1.8 DC HSM | A', #PH
234
260
  0x8900 => 'Sigma 70-300mm F4-5.6 DG OS', #PH (SD15)
@@ -16,7 +16,7 @@ use vars qw($VERSION);
16
16
  use Image::ExifTool qw(:DataAccess :Utils);
17
17
  use Image::ExifTool::Sigma;
18
18
 
19
- $VERSION = '1.27';
19
+ $VERSION = '1.29';
20
20
 
21
21
  sub ProcessX3FHeader($$$);
22
22
  sub ProcessX3FDirectory($$$);
@@ -385,14 +385,14 @@ sub WriteX3F($$)
385
385
  my ($et, $dirInfo) = @_;
386
386
  my $raf = $$dirInfo{RAF};
387
387
  my $outfile = $$dirInfo{OutFile};
388
- my ($outDir, $buff, $ver, $entries, $dir, $outPos, $index, $didContain);
388
+ my ($hdr, $buff, $ver, $entries, $dir, $outPos, $index, $didContain, %order, @order);
389
389
 
390
390
  $raf->Seek($$dirInfo{DirStart}, 0) or return 'Error seeking to directory start';
391
391
 
392
392
  # read the X3F directory header (will be copied directly to output)
393
- $raf->Read($outDir, 12) == 12 or return 'Truncated X3F image';
394
- $outDir =~ /^SECd/ or return 'Bad section header';
395
- ($ver, $entries) = unpack('x4V2', $outDir);
393
+ $raf->Read($hdr, 12) == 12 or return 'Truncated X3F image';
394
+ $hdr =~ /^SECd/ or return 'Bad section header';
395
+ ($ver, $entries) = unpack('x4V2', $hdr);
396
396
 
397
397
  # do sanity check on number of entries in directory
398
398
  return 'Invalid X3F directory count' unless $entries > 2 and $entries < 20;
@@ -400,12 +400,16 @@ sub WriteX3F($$)
400
400
  unless ($raf->Read($dir, $entries * 12) == $entries * 12) {
401
401
  return 'Truncated X3F directory';
402
402
  }
403
- # do a quick scan to determine the offset of the first data subsection
403
+ # do a quick scan to determine the offset of the first data subsection,
404
+ # and the order in which the actual data is stored in the file
404
405
  for ($index=0; $index<$entries; ++$index) {
405
406
  my $pos = $index * 12;
406
407
  my ($offset, $len, $tag) = unpack("x${pos}V2a4", $dir);
407
408
  # remember position of first data subsection
408
409
  $outPos = $offset if not defined $outPos or $outPos > $offset;
410
+ # save the order of the data
411
+ $order{BAD} = 1 if defined $order{$offset};
412
+ $order{$offset} = $index;
409
413
  }
410
414
  # copy the file header up to the start of the first data subsection
411
415
  unless ($raf->Seek(0,0) and $raf->Read($buff, $outPos) == $outPos) {
@@ -413,8 +417,25 @@ sub WriteX3F($$)
413
417
  }
414
418
  Write($outfile, $buff) or return -1;
415
419
 
416
- # loop through directory, rewriting each section
417
- for ($index=0; $index<$entries; ++$index) {
420
+ # this is a bit tricky/unfortunate: the current version of Sigma Photo Pro
421
+ # (2022-10-18) is sensitive to the order of the data sections, and these may
422
+ # differ from the order of their respective entries in the footer. To patch
423
+ # this, instead of looping through the footer sections in order, we process
424
+ # them in the order of the offsets they contain, writing their referenced data
425
+ # sequentially as we go. This preserves both the order of the data sections
426
+ # and the order of the footer entries. (Note that the upcoming release of
427
+ # Sigma Photo Pro will fix this issue at their end, but this patch will remain
428
+ # to maintain backward compatibilty with older SPP versions.)
429
+ if ($order{BAD}) {
430
+ # (this could perhaps happen if any of the sections is ever zero-length)
431
+ $et->Error('Double-referenced data in footer directory!', 1);
432
+ @order = ( 0 .. $entries-1 );
433
+ } else {
434
+ @order = map $order{$_}, sort { $a <=> $b } keys %order;
435
+ }
436
+
437
+ # loop through footer directory, rewriting each section
438
+ foreach $index (@order) {
418
439
 
419
440
  my $pos = $index * 12;
420
441
  my ($offset, $len, $tag) = unpack("x${pos}V2a4", $dir);
@@ -450,6 +471,8 @@ sub WriteX3F($$)
450
471
  return -1 if $success < 0;
451
472
  # (this shouldn't happen unless someone tries to delete the EXIF...)
452
473
  return 'EXIF segment must come first in X3F JpgFromRaw' unless $newData =~ /^\xff\xd8\xff\xe1/;
474
+ # trim off any extra null bytes (since section length includes padding -- silly Sigma)
475
+ $newData =~ s/\0+$//;
453
476
  # write new data if anything changed, otherwise copy old image
454
477
  my $outPt = $$et{CHANGED} ? \$newData : \$buff;
455
478
  Write($outfile, $$outPt) or return -1;
@@ -468,20 +491,21 @@ sub WriteX3F($$)
468
491
  # copy data for this subsection
469
492
  Image::ExifTool::CopyBlock($raf, $outfile, $len) or return 'Corrupted X3F directory';
470
493
  }
471
- # add directory entry and update output file position
472
- $outDir .= pack('V2a4', $outPos, $len, $tag);
473
- $outPos += $len;
474
494
  # pad data to an even 4-byte boundary
495
+ # (stored length includes padding! ref Sigma engineer Yuki Miyahara)
475
496
  if ($len & 0x03) {
476
497
  my $pad = 4 - ($len & 0x03);
477
498
  Write($outfile, "\0" x $pad) or return -1;
478
- $outPos += $pad;
499
+ $len += $pad;
479
500
  }
501
+ # update footer entry with new offset/size
502
+ substr($dir, $pos, 8) = pack('V2', $outPos, $len);
503
+ $outPos += $len;
480
504
  }
481
505
  # warn if we couldn't add metadata to this image (should only be SD9 or SD10)
482
506
  $didContain or $et->Warn("Can't yet write SD9 or SD10 X3F images");
483
507
  # write out the directory and the directory pointer, and we are done
484
- Write($outfile, $outDir, pack('V', $outPos)) or return -1;
508
+ Write($outfile, $hdr, $dir, pack('V', $outPos)) or return -1;
485
509
  return undef;
486
510
  }
487
511
 
@@ -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.52';
37
+ $VERSION = '3.54';
38
38
 
39
39
  sub ProcessSRF($$$);
40
40
  sub ProcessSR2($$$);
@@ -212,6 +212,7 @@ sub PrintInvLensSpec($;$$);
212
212
  49473.2 => 'Viltrox 56mm F1.4 E', #JR
213
213
  49712 => 'Tokina FiRIN 20mm F2 FE AF', # (firmware Ver.01)
214
214
  49713 => 'Tokina FiRIN 100mm F2.8 FE MACRO', # (firmware Ver.01)
215
+ 49714 => 'Tokina atx-m 11-18mm F2.8 E', #JR
215
216
 
216
217
  50480 => 'Sigma 30mm F1.4 DC DN | C', #IB/JR (016)
217
218
  50481 => 'Sigma 50mm F1.4 DG HSM | A', #JR (014 + MC-11 or 018)
@@ -1049,7 +1050,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
1049
1050
  SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag2010h' },
1050
1051
  },{
1051
1052
  Name => 'Tag2010i', # ?
1052
- Condition => '$$self{Model} =~ /^(ILCE-(6100|6400|6600|7C|7M3|7RM3A?|7RM4A?|9|9M2)|DSC-(RX10M4|RX100M6|RX100M5A|RX100M7|HX99|RX0M2)|ZV-(1|E10))\b/',
1053
+ Condition => '$$self{Model} =~ /^(ILCE-(6100|6400|6600|7C|7M3|7RM3A?|7RM4A?|9|9M2)|DSC-(RX10M4|RX100M6|RX100M5A|RX100M7|HX99|RX0M2)|ZV-(1F?|E10))\b/',
1053
1054
  SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag2010i' },
1054
1055
  },{
1055
1056
  Name => 'Tag_0x2010',
@@ -2050,6 +2051,8 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
2050
2051
  386 => 'ILCE-7RM3A', #JR
2051
2052
  387 => 'ILCE-7RM4A', #forum12542
2052
2053
  388 => 'ILCE-7M4', #IB/JR
2054
+ 389 => 'ZV-1F', #IB
2055
+ 391 => 'ILME-FX30', #JR
2053
2056
  },
2054
2057
  },
2055
2058
  0xb020 => { #2
@@ -8251,9 +8254,10 @@ my %isoSetting2010 = (
8251
8254
  FIRST_ENTRY => 0,
8252
8255
  GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
8253
8256
  DATAMEMBER => [ 0 ],
8254
- IS_SUBDIR => [ 0x0498, 0x049d, 0x04a1, 0x04a2, 0x059d, 0x0634, 0x0636, 0x064c, 0x0653, 0x0678, 0x06b8, 0x06de, 0x06e7 ],
8257
+ IS_SUBDIR => [ 0x044e, 0x0498, 0x049d, 0x04a1, 0x04a2, 0x059d, 0x0634, 0x0636, 0x064c, 0x0653, 0x0678, 0x06b8, 0x06de, 0x06e7 ],
8255
8258
  0x0000 => { Name => 'Ver9401', Hidden => 1, RawConv => '$$self{Ver9401} = $val; $$self{OPTIONS}{Unknown}<2 ? undef : $val' },
8256
8259
 
8260
+ 0x044e => { Name => 'ISOInfo', Condition => '$$self{Ver9401} == 178', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } },
8257
8261
  0x0498 => { Name => 'ISOInfo', Condition => '$$self{Ver9401} == 148', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } },
8258
8262
  0x049d => { Name => 'ISOInfo', Condition => '$$self{Ver9401} == 167', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } },
8259
8263
  0x04a1 => { Name => 'ISOInfo', Condition => '$$self{Ver9401} =~ /^(160|164)/', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } },