exiftool_vendored 12.25.0 → 12.32.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +114 -4
  3. data/bin/MANIFEST +11 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +44 -43
  7. data/bin/arg_files/xmp2exif.args +2 -1
  8. data/bin/config_files/convert_regions.config +25 -14
  9. data/bin/config_files/example.config +1 -1
  10. data/bin/exiftool +72 -56
  11. data/bin/fmt_files/gpx.fmt +1 -1
  12. data/bin/fmt_files/gpx_wpt.fmt +1 -1
  13. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +10 -2
  14. data/bin/lib/Image/ExifTool/CBOR.pm +277 -0
  15. data/bin/lib/Image/ExifTool/Canon.pm +25 -18
  16. data/bin/lib/Image/ExifTool/DPX.pm +13 -2
  17. data/bin/lib/Image/ExifTool/Exif.pm +11 -6
  18. data/bin/lib/Image/ExifTool/FlashPix.pm +35 -10
  19. data/bin/lib/Image/ExifTool/FujiFilm.pm +1 -0
  20. data/bin/lib/Image/ExifTool/Geotag.pm +13 -2
  21. data/bin/lib/Image/ExifTool/GoPro.pm +16 -1
  22. data/bin/lib/Image/ExifTool/ID3.pm +15 -3
  23. data/bin/lib/Image/ExifTool/JPEG.pm +68 -2
  24. data/bin/lib/Image/ExifTool/JSON.pm +4 -2
  25. data/bin/lib/Image/ExifTool/Jpeg2000.pm +58 -26
  26. data/bin/lib/Image/ExifTool/LIF.pm +153 -0
  27. data/bin/lib/Image/ExifTool/Lang/nl.pm +60 -59
  28. data/bin/lib/Image/ExifTool/M2TS.pm +103 -7
  29. data/bin/lib/Image/ExifTool/MIE.pm +2 -1
  30. data/bin/lib/Image/ExifTool/MRC.pm +1 -1
  31. data/bin/lib/Image/ExifTool/Nikon.pm +15 -4
  32. data/bin/lib/Image/ExifTool/NikonSettings.pm +10 -2
  33. data/bin/lib/Image/ExifTool/Olympus.pm +5 -2
  34. data/bin/lib/Image/ExifTool/Other.pm +93 -0
  35. data/bin/lib/Image/ExifTool/PDF.pm +9 -12
  36. data/bin/lib/Image/ExifTool/PNG.pm +7 -6
  37. data/bin/lib/Image/ExifTool/Panasonic.pm +14 -2
  38. data/bin/lib/Image/ExifTool/Pentax.pm +28 -5
  39. data/bin/lib/Image/ExifTool/Photoshop.pm +6 -0
  40. data/bin/lib/Image/ExifTool/QuickTime.pm +103 -24
  41. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +203 -121
  42. data/bin/lib/Image/ExifTool/README +3 -0
  43. data/bin/lib/Image/ExifTool/RIFF.pm +7 -2
  44. data/bin/lib/Image/ExifTool/Samsung.pm +47 -10
  45. data/bin/lib/Image/ExifTool/Sony.pm +84 -33
  46. data/bin/lib/Image/ExifTool/TagLookup.pm +50 -3
  47. data/bin/lib/Image/ExifTool/TagNames.pod +135 -29
  48. data/bin/lib/Image/ExifTool/Torrent.pm +18 -11
  49. data/bin/lib/Image/ExifTool/WriteIPTC.pl +1 -1
  50. data/bin/lib/Image/ExifTool/WritePDF.pl +1 -0
  51. data/bin/lib/Image/ExifTool/WritePNG.pl +2 -0
  52. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +11 -4
  53. data/bin/lib/Image/ExifTool/WriteXMP.pl +1 -1
  54. data/bin/lib/Image/ExifTool/Writer.pl +3 -0
  55. data/bin/lib/Image/ExifTool/XMP.pm +17 -5
  56. data/bin/lib/Image/ExifTool/XMP2.pl +2 -1
  57. data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
  58. data/bin/lib/Image/ExifTool/ZISRAW.pm +121 -2
  59. data/bin/lib/Image/ExifTool.pm +79 -37
  60. data/bin/lib/Image/ExifTool.pod +62 -60
  61. data/bin/perl-Image-ExifTool.spec +43 -42
  62. data/lib/exiftool_vendored/version.rb +1 -1
  63. metadata +6 -3
@@ -40,7 +40,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
40
40
  use Image::ExifTool::Exif;
41
41
  use Image::ExifTool::APP12;
42
42
 
43
- $VERSION = '2.71';
43
+ $VERSION = '2.74';
44
44
 
45
45
  sub PrintLensInfo($$$);
46
46
 
@@ -113,6 +113,8 @@ my %olympusLensTypes = (
113
113
  '0 34 00' => 'Olympus Zuiko Digital ED 9-18mm F4.0-5.6', #7
114
114
  '0 34 10' => 'Olympus M.Zuiko Digital ED 12-45mm F4.0 Pro', #IB
115
115
  '0 35 00' => 'Olympus Zuiko Digital 14-54mm F2.8-3.5 II', #PH
116
+ '0 35 10' => 'Olympus M.Zuiko 100-400mm F5.0-6.3', #IB
117
+ '0 36 10' => 'Olympus M.Zuiko Digital ED 8-25mm F4 Pro', #IB
116
118
  # Sigma lenses
117
119
  '1 01 00' => 'Sigma 18-50mm F3.5-5.6 DC', #8
118
120
  '1 01 10' => 'Sigma 30mm F2.8 EX DN', #NJ
@@ -138,7 +140,6 @@ my %olympusLensTypes = (
138
140
  '1 15 00' => 'Sigma 10-20mm F4.0-5.6 EX DC HSM', #11
139
141
  '1 16 00' => 'Sigma APO 70-200mm F2.8 II EX DG Macro HSM', #11
140
142
  '1 17 00' => 'Sigma 50mm F1.4 EX DG HSM', #11
141
- '1 18 60' => 'Test',
142
143
  # Panasonic/Leica lenses
143
144
  '2 01 00' => 'Leica D Vario Elmarit 14-50mm F2.8-3.5 Asph.', #11
144
145
  '2 01 10' => 'Lumix G Vario 14-45mm F3.5-5.6 Asph. Mega OIS', #16
@@ -183,6 +184,7 @@ my %olympusLensTypes = (
183
184
  '2 36 10' => 'Leica DG Elmarit 200mm F2.8 Power OIS', #IB
184
185
  '2 37 10' => 'Leica DG Vario-Elmarit 50-200mm F2.8-4 Asph. Power OIS', #IB
185
186
  '2 38 10' => 'Leica DG Vario-Summilux 10-25mm F1.7 Asph.', #IB
187
+ '2 40 10' => 'Leica DG Vario-Summilux 25-50mm F1.7 Asph.', #IB (H-X2550)
186
188
  '3 01 00' => 'Leica D Vario Elmarit 14-50mm F2.8-3.5 Asph.', #11
187
189
  '3 02 00' => 'Leica D Summilux 25mm F1.4 Asph.', #11
188
190
  # Tamron lenses
@@ -429,6 +431,7 @@ my %olympusCameraTypes = (
429
431
  S0085 => 'E-PL10', #IB
430
432
  S0089 => 'E-M5MarkIII',
431
433
  S0092 => 'E-M1MarkIII', #IB
434
+ S0093 => 'E-P7', #IB
432
435
  SR45 => 'D220',
433
436
  SR55 => 'D320L',
434
437
  SR83 => 'D340L',
@@ -0,0 +1,93 @@
1
+ #------------------------------------------------------------------------------
2
+ # File: Other.pm
3
+ #
4
+ # Description: Read meta information from other uncommon formats
5
+ #
6
+ # Revisions: 2021/07/16 - P. Harvey Created
7
+ #
8
+ # References: 1) PFM - http://www.pauldebevec.com/Research/HDR/PFM/
9
+ #------------------------------------------------------------------------------
10
+
11
+ package Image::ExifTool::Other;
12
+
13
+ use strict;
14
+ use vars qw($VERSION);
15
+ use Image::ExifTool qw(:DataAccess :Utils);
16
+ use Image::ExifTool::Exif;
17
+
18
+ $VERSION = '1.00';
19
+
20
+ # Other info
21
+ %Image::ExifTool::Other::PFM = (
22
+ GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' },
23
+ VARS => { NO_ID => 1 },
24
+ NOTES => q{
25
+ Tags extracted from Portable FloatMap images. See
26
+ L<http://www.pauldebevec.com/Research/HDR/PFM/> for the specification.
27
+ },
28
+ ColorSpace => { PrintConv => { PF => 'RGB', 'Pf' => 'Monochrome'} },
29
+ ImageWidth => { },
30
+ ImageHeight => { },
31
+ ByteOrder => { PrintConv => '$val > 0 ? "Big-endian" : "Little-endian"' },
32
+ );
33
+
34
+ #------------------------------------------------------------------------------
35
+ # Extract information from a Portable FloatMap image
36
+ # Inputs: 0) ExifTool object reference, 1) dirInfo reference
37
+ # Returns: 1 on success, 0 if this wasn't a valid PFM file
38
+ sub ProcessPFM2($$)
39
+ {
40
+ my ($et, $dirInfo) = @_;
41
+ my $raf = $$dirInfo{RAF};
42
+ my $buff;
43
+ return 0 unless $raf->Read($buff, 256) and $buff =~ /^(P[Ff])\x0a(\d+) (\d+)\x0a([-+0-9.]+)\x0a/;
44
+ $et->SetFileType('PFM', 'image/x-pfm');
45
+ my $tagTablePtr = GetTagTable('Image::ExifTool::Other::PFM');
46
+ $et->HandleTag($tagTablePtr, ColorSpace => $1);
47
+ $et->HandleTag($tagTablePtr, ImageWidth => $2);
48
+ $et->HandleTag($tagTablePtr, ImageHeight => $3);
49
+ $et->HandleTag($tagTablePtr, ByteOrder => $4);
50
+ # hack to set proper file description (extension is the same for Printer Font Metrics files)
51
+ $Image::ExifTool::static_vars{OverrideFileDescription}{PFM} = 'Portable FloatMap',
52
+ return 1;
53
+ }
54
+
55
+ 1; # end
56
+
57
+ __END__
58
+
59
+ =head1 NAME
60
+
61
+ Image::ExifTool::Other - Read meta information from other uncommon formats
62
+
63
+ =head1 SYNOPSIS
64
+
65
+ This module is used by Image::ExifTool
66
+
67
+ =head1 DESCRIPTION
68
+
69
+ This module contains routines required by Image::ExifTool to extract
70
+ information from Portable FloatMap (PFM) images.
71
+
72
+ =head1 AUTHOR
73
+
74
+ Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
75
+
76
+ This library is free software; you can redistribute it and/or modify it
77
+ under the same terms as Perl itself.
78
+
79
+ =head1 REFERENCES
80
+
81
+ =over 4
82
+
83
+ =item PFM L<http://www.pauldebevec.com/Research/HDR/PFM/>
84
+
85
+ =back
86
+
87
+ =head1 SEE ALSO
88
+
89
+ L<Image::ExifTool::TagNames/Other Tags>,
90
+ L<Image::ExifTool(3pm)|Image::ExifTool>
91
+
92
+ =cut
93
+
@@ -21,7 +21,7 @@ use vars qw($VERSION $AUTOLOAD $lastFetched);
21
21
  use Image::ExifTool qw(:DataAccess :Utils);
22
22
  require Exporter;
23
23
 
24
- $VERSION = '1.51';
24
+ $VERSION = '1.53';
25
25
 
26
26
  sub FetchObject($$$$);
27
27
  sub ExtractObject($$;$$);
@@ -280,7 +280,10 @@ my %supportedFilter = (
280
280
  ConvertToDict => 1,
281
281
  },
282
282
  Cs1 => {
283
- SubDirectory => { TagTable => 'Image::ExifTool::PDF::Cs1' },
283
+ SubDirectory => { TagTable => 'Image::ExifTool::PDF::ICCBased' },
284
+ },
285
+ CS0 => {
286
+ SubDirectory => { TagTable => 'Image::ExifTool::PDF::ICCBased' },
284
287
  },
285
288
  );
286
289
 
@@ -291,14 +294,7 @@ my %supportedFilter = (
291
294
  },
292
295
  );
293
296
 
294
- # tags in PDF Cs1 dictionary
295
- %Image::ExifTool::PDF::Cs1 = (
296
- _stream => {
297
- SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' },
298
- },
299
- );
300
-
301
- # tags in PDF ICCBased dictionary
297
+ # tags in PDF ICCBased, Cs1 and CS0 dictionaries
302
298
  %Image::ExifTool::PDF::ICCBased = (
303
299
  _stream => {
304
300
  SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' },
@@ -1989,16 +1985,17 @@ sub ProcessDict($$$$;$$)
1989
1985
  } else {
1990
1986
  $val = ReadPDFValue($val);
1991
1987
  }
1992
- # convert from UTF-16 (big endian) to UTF-8 or Latin if necessary
1993
- # unless this is binary data (hex-encoded strings would not have been converted)
1994
1988
  if (ref $val) {
1995
1989
  if (ref $val eq 'ARRAY') {
1990
+ delete $$et{LIST_TAGS}{$tagInfo} if $$tagInfo{List};
1996
1991
  my $v;
1997
1992
  foreach $v (@$val) {
1998
1993
  $et->FoundTag($tagInfo, $v);
1999
1994
  }
2000
1995
  }
2001
1996
  } elsif (defined $val) {
1997
+ # convert from UTF-16 (big endian) to UTF-8 or Latin if necessary
1998
+ # unless this is binary data (hex-encoded strings would not have been converted)
2002
1999
  my $format = $$tagInfo{Format} || $$tagInfo{Writable} || 'string';
2003
2000
  $val = ConvertPDFDate($val) if $format eq 'date';
2004
2001
  if (not $$tagInfo{Binary} and $val =~ /[\x18-\x1f\x80-\xff]/) {
@@ -36,7 +36,7 @@ use strict;
36
36
  use vars qw($VERSION $AUTOLOAD %stdCase);
37
37
  use Image::ExifTool qw(:DataAccess :Utils);
38
38
 
39
- $VERSION = '1.57';
39
+ $VERSION = '1.59';
40
40
 
41
41
  sub ProcessPNG_tEXt($$$);
42
42
  sub ProcessPNG_iTXt($$$);
@@ -89,7 +89,7 @@ $Image::ExifTool::PNG::colorType = -1;
89
89
 
90
90
  # data and text chunk types
91
91
  my %isDatChunk = ( IDAT => 1, JDAT => 1, JDAA => 1 );
92
- my %isTxtChunk = ( tEXt => 1, zTXt => 1, iTXt => 1 );
92
+ my %isTxtChunk = ( tEXt => 1, zTXt => 1, iTXt => 1, eXIf => 1 );
93
93
 
94
94
  # chunks that we shouldn't move other chunks across (ref 3)
95
95
  my %noLeapFrog = ( SAVE => 1, SEEK => 1, IHDR => 1, JHDR => 1, IEND => 1, MEND => 1,
@@ -478,6 +478,8 @@ my %unreg = ( Notes => 'unregistered' );
478
478
  if the L<Compress|../ExifTool.html#Compress> option is used and Compress::Zlib is available. Raw profile
479
479
  information is always created as compressed zTXt if Compress::Zlib is
480
480
  available, or tEXt otherwise. Standard XMP is written as uncompressed iTXt.
481
+ User-defined tags may set an 'iTXt' flag in the tag definition to be written
482
+ only as iTXt.
481
483
 
482
484
  Alternate languages are accessed by suffixing the tag name with a '-',
483
485
  followed by an RFC 3066 language code (eg. "PNG:Comment-fr", or
@@ -1382,9 +1384,8 @@ sub ProcessPNG($$)
1382
1384
  # to add it as a text profile chunk if this isn't successful
1383
1385
  # (ie. if Compress::Zlib wasn't available)
1384
1386
  Add_iCCP($et, $outfile);
1385
- AddChunks($et, $outfile) or $err = 1; # all all text chunks
1386
- # add EXIF before end chunk if not found already
1387
- AddChunks($et, $outfile, 'IFD0') if $chunk eq $endChunk;
1387
+ AddChunks($et, $outfile) or $err = 1; # add all text chunks
1388
+ AddChunks($et, $outfile, 'IFD0') or $err = 1; # and eXIf chunk
1388
1389
  } elsif ($chunk eq 'PLTE') {
1389
1390
  # iCCP chunk must come before PLTE (and IDAT, handled above)
1390
1391
  # (ignore errors -- will add later as text profile if this fails)
@@ -1444,7 +1445,7 @@ sub ProcessPNG($$)
1444
1445
  } else {
1445
1446
  $msg = 'fixed';
1446
1447
  }
1447
- $et->WarnOnce("Text chunk(s) found after $$et{FileType} $wasDat ($msg)", 1);
1448
+ $et->WarnOnce("Text/EXIF chunk(s) found after $$et{FileType} $wasDat ($msg)", 1);
1448
1449
  }
1449
1450
  # read chunk data and CRC
1450
1451
  unless ($raf->Read($dbuf,$len)==$len and $raf->Read($cbuf, 4)==4) {
@@ -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.14';
40
+ $VERSION = '2.16';
41
41
 
42
42
  sub ProcessLeicaLEIC($$$);
43
43
  sub WhiteBalanceConv($;$$);
@@ -449,7 +449,7 @@ my %shootingMode = (
449
449
  same as the number printed on the camera body
450
450
  },
451
451
  PrintConv => q{
452
- return $val unless $val=~/^([A-Z]\d{2})(\d{2})(\d{2})(\d{2})(\d{4})/;
452
+ return $val unless $val=~/^([A-Z][0-9A-Z]{2})(\d{2})(\d{2})(\d{2})(\d{4})/;
453
453
  my $yr = $2 + ($2 < 70 ? 2000 : 1900);
454
454
  return "($1) $yr:$3:$4 no. $5";
455
455
  },
@@ -1423,6 +1423,18 @@ my %shootingMode = (
1423
1423
  Name => 'NoiseReductionStrength',
1424
1424
  Writable => 'rational64s',
1425
1425
  },
1426
+ 0xe4 => { #IB
1427
+ Name => 'LensTypeModel',
1428
+ Condition => '$format eq "int16u"',
1429
+ Writable => 'int16u',
1430
+ RawConv => q{
1431
+ return undef unless $val;
1432
+ require Image::ExifTool::Olympus; # (to load Composite LensID)
1433
+ return $val;
1434
+ },
1435
+ ValueConv => '$_=sprintf("%.4x",$val); s/(..)(..)/$2 $1/; $_',
1436
+ ValueConvInv => '$val =~ s/(..) (..)/$2$1/; hex($val)',
1437
+ },
1426
1438
  0x0e00 => {
1427
1439
  Name => 'PrintIM',
1428
1440
  Description => 'Print Image Matching',
@@ -58,7 +58,7 @@ use Image::ExifTool::Exif;
58
58
  use Image::ExifTool::GPS;
59
59
  use Image::ExifTool::HP;
60
60
 
61
- $VERSION = '3.36';
61
+ $VERSION = '3.39';
62
62
 
63
63
  sub CryptShutterCount($$);
64
64
  sub PrintFilter($$$);
@@ -340,6 +340,7 @@ sub DecodeAFPoints($$$$;$);
340
340
  '8 64' => 'HD PENTAX-D FA* 50mm F1.4 SDM AW', #27
341
341
  '8 65' => 'HD PENTAX-D FA 70-210mm F4 ED SDM WR', #PH
342
342
  '8 66' => 'HD PENTAX-D FA 85mm F1.4 ED SDM AW', #James O'Neill
343
+ '8 195' => 'HD PENTAX DA* 16-50mm F2.8 ED PLM AW', #27
343
344
  '8 196' => 'HD PENTAX-DA* 11-18mm F2.8 ED DC AW', #29
344
345
  '8 197' => 'HD PENTAX-DA 55-300mm F4.5-6.3 ED PLM WR RE', #29
345
346
  '8 198' => 'smc PENTAX-DA L 18-50mm F4-5.6 DC WR RE', #29
@@ -548,6 +549,7 @@ my %pentaxModelID = (
548
549
  0x13222 => 'K-70', #29 (Ricoh)
549
550
  0x1322c => 'KP', #29 (Ricoh)
550
551
  0x13240 => 'K-1 Mark II', # (Ricoh)
552
+ 0x13254 => 'K-3 Mark III', #IB (Ricoh)
551
553
  0x13290 => 'WG-70', # (Ricoh)
552
554
  );
553
555
 
@@ -2222,6 +2224,7 @@ my %binaryDataAttrs = (
2222
2224
  17 => '17 (K-70)', #29
2223
2225
  18 => '18 (KP)', #PH
2224
2226
  19 => '19 (GR III)', #PH
2227
+ 20 => '20 (K-3III)', #PH
2225
2228
  },
2226
2229
  },
2227
2230
  0x0067 => { #PH (K-5)
@@ -2454,6 +2457,7 @@ my %binaryDataAttrs = (
2454
2457
  '2 0' => 'Standard',
2455
2458
  '3 0' => 'Fast',
2456
2459
  # '1 108' - seen for GR III
2460
+ # '3 84' - seen for K-3III
2457
2461
  },
2458
2462
  },
2459
2463
  0x007b => { #PH (K-5)
@@ -2597,8 +2601,9 @@ my %binaryDataAttrs = (
2597
2601
  },
2598
2602
  },
2599
2603
  },
2600
- 0x0095 => { #31
2604
+ 0x0095 => [{ #31
2601
2605
  Name => 'SkinToneCorrection',
2606
+ Condition => '$count == 2',
2602
2607
  Writable => 'int8s',
2603
2608
  Count => 2,
2604
2609
  PrintConv => {
@@ -2606,7 +2611,15 @@ my %binaryDataAttrs = (
2606
2611
  '1 1' => 'On (type 1)',
2607
2612
  '1 2' => 'On (type 2)',
2608
2613
  },
2609
- },
2614
+ },{
2615
+ Name => 'SkinToneCorrection',
2616
+ Condition => '$count == 3',
2617
+ Writable => 'int8s',
2618
+ Count => 3,
2619
+ PrintConv => {
2620
+ '0 0 0' => 'Off',
2621
+ },
2622
+ }],
2610
2623
  0x0096 => { #31
2611
2624
  Name => 'ClarityControl',
2612
2625
  Writable => 'int8s',
@@ -2842,8 +2855,18 @@ my %binaryDataAttrs = (
2842
2855
  # High: 0000000238c0e960fde0f9203140f5a0fce0f1e031403f00e600fb00f7803760f120fc60ef403460
2843
2856
  # Very High:000000023d20e520fdc0f7203420f4c0fb60ee6036404400e120fae0f5403aa0f020fac0eb403a00
2844
2857
  },
2845
- # 0x021c - undef[18] (K-5)
2846
- # 0x021d - undef[18] (K-5)
2858
+ 0x021c => { #IB
2859
+ Name => 'ColorMatrixA2',
2860
+ Format => 'int16s',
2861
+ Writable => 'undef',
2862
+ Count => 9,
2863
+ },
2864
+ 0x021d => { #IB
2865
+ Name => 'ColorMatrixB2',
2866
+ Format => 'int16s',
2867
+ Writable => 'undef',
2868
+ Count => 9,
2869
+ },
2847
2870
  # 0x021e - undef[8] (K-5, Q)
2848
2871
  0x021f => { #JD
2849
2872
  Name => 'AFInfo',
@@ -988,6 +988,12 @@ sub ProcessPhotoshop($$$)
988
988
  $size += 1 if $size & 0x01; # size is padded to an even # bytes
989
989
  $pos += $size;
990
990
  }
991
+ # warn about incorrect IPTCDigest
992
+ if ($$et{VALUE}{IPTCDigest} and $$et{VALUE}{CurrentIPTCDigest} and
993
+ $$et{VALUE}{IPTCDigest} ne $$et{VALUE}{CurrentIPTCDigest})
994
+ {
995
+ $et->WarnOnce('IPTCDigest is not current. XMP may be out of sync');
996
+ }
991
997
  delete $$et{LOW_PRIORITY_DIR}{'*'};
992
998
  return $success;
993
999
  }
@@ -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.63';
50
+ $VERSION = '2.69';
51
51
 
52
52
  sub ProcessMOV($$;$);
53
53
  sub ProcessKeys($$$);
@@ -229,9 +229,10 @@ my %timeInfo = (
229
229
  Writable => 1,
230
230
  Permanent => 1,
231
231
  DelValue => 0,
232
- # It is not uncommon for brain-dead software to use the wrong time zero,
233
- # so assume a time zero of Jan 1, 1970 if the date is before this
232
+ # It is not uncommon for brain-dead software to use the wrong time zero, it should be
233
+ # Jan 1, 1904, so assume a time zero of Jan 1, 1970 if the date is before this
234
234
  # Note: This value will be in UTC if generated by a system that is aware of the time zone
235
+ # (also note: this code is duplicated for the CreateDate tag)
235
236
  RawConv => q{
236
237
  my $offset = (66 * 365 + 17) * 24 * 3600;
237
238
  return $val - $offset if $val >= $offset or $$self{OPTIONS}{QuickTimeUTC};
@@ -733,6 +734,11 @@ my %eeBox2 = (
733
734
  Unknown => 1,
734
735
  Binary => 1,
735
736
  },
737
+ sefd => {
738
+ Name => 'SamsungTrailer',
739
+ SubDirectory => { TagTable => 'Image::ExifTool::Samsung::Trailer' },
740
+ },
741
+ # 'samn'? - seen in Vantrue N2S sample video
736
742
  );
737
743
 
738
744
  # MPEG-4 'ftyp' atom
@@ -1194,6 +1200,15 @@ my %eeBox2 = (
1194
1200
  Name => 'CreateDate',
1195
1201
  Groups => { 2 => 'Time' },
1196
1202
  %timeInfo,
1203
+ RawConv => q{
1204
+ my $offset = (66 * 365 + 17) * 24 * 3600;
1205
+ if ($val >= $offset or $$self{OPTIONS}{QuickTimeUTC}) {
1206
+ $val -= $offset;
1207
+ } elsif ($val and not $$self{IsWriting}) {
1208
+ $self->WarnOnce('Patched incorrect time zero for QuickTime date/time tag',1);
1209
+ }
1210
+ return $$self{CreateDate} = $val;
1211
+ },
1197
1212
  # this is int64u if MovieHeaderVersion == 1 (ref 13)
1198
1213
  Hook => '$$self{MovieHeaderVersion} and $format = "int64u", $varSize += 4',
1199
1214
  },
@@ -2254,6 +2269,12 @@ my %eeBox2 = (
2254
2269
  # opax - 164 bytes unknown (center and affine arrays? ref 26)
2255
2270
  # opai - 32 bytes (maybe contains a serial number starting at byte 16? - PH) (rgb gains, degamma, gamma? ref 26)
2256
2271
  # intv - 16 bytes all zero
2272
+ # ---- Xaiomi ----
2273
+ mcvr => {
2274
+ Name => 'PreviewImage',
2275
+ Groups => { 2 => 'Preview' },
2276
+ Binary => 1,
2277
+ },
2257
2278
  # ---- Unknown ----
2258
2279
  # CDET - 128 bytes (unknown origin)
2259
2280
  # mtyp - 4 bytes all zero (some drone video)
@@ -2691,6 +2712,7 @@ my %eeBox2 = (
2691
2712
  colr => [{
2692
2713
  Name => 'ICC_Profile',
2693
2714
  Condition => '$$valPt =~ /^(prof|rICC)/',
2715
+ Permanent => 0, # (in QuickTime, this writes a zero-length box instead of deleting)
2694
2716
  SubDirectory => {
2695
2717
  TagTable => 'Image::ExifTool::ICC_Profile::Main',
2696
2718
  Start => 4,
@@ -6281,6 +6303,10 @@ my %eeBox2 = (
6281
6303
  'location.ISO6709' => {
6282
6304
  Name => 'GPSCoordinates',
6283
6305
  Groups => { 2 => 'Location' },
6306
+ Notes => q{
6307
+ Google Photos may ignore this if the coorinates have more than 5 digits
6308
+ after the decimal
6309
+ },
6284
6310
  ValueConv => \&ConvertISO6709,
6285
6311
  ValueConvInv => \&ConvInvISO6709,
6286
6312
  PrintConv => \&PrintGPSCoordinates,
@@ -6425,10 +6451,11 @@ my %eeBox2 = (
6425
6451
  # iTunes info ('----') atoms
6426
6452
  %Image::ExifTool::QuickTime::iTunesInfo = (
6427
6453
  PROCESS_PROC => \&ProcessMOV,
6428
- GROUPS => { 2 => 'Audio' },
6454
+ GROUPS => { 1 => 'iTunes', 2 => 'Audio' },
6429
6455
  NOTES => q{
6430
6456
  ExifTool will extract any iTunesInfo tags that exist, even if they are not
6431
- defined in this table.
6457
+ defined in this table. These tags belong to the family 1 "iTunes" group,
6458
+ and are not currently writable.
6432
6459
  },
6433
6460
  # 'mean'/'name'/'data' atoms form a triplet, but unfortunately
6434
6461
  # I haven't been able to find any documentation on this.
@@ -6489,9 +6516,45 @@ my %eeBox2 = (
6489
6516
  SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::EncodingParams' },
6490
6517
  },
6491
6518
  # also heard about 'iTunPGAP', but I haven't seen a sample
6492
- DISCNUMBER => 'DiscNumber', #PH
6493
- TRACKNUMBER => 'TrackNumber', #PH
6494
- popularimeter => 'Popularimeter', #PH
6519
+ # all tags below were added based on samples I have seen - PH
6520
+ DISCNUMBER => 'DiscNumber',
6521
+ TRACKNUMBER => 'TrackNumber',
6522
+ ARTISTS => 'Artists',
6523
+ CATALOGNUMBER => 'CatalogNumber',
6524
+ RATING => 'Rating',
6525
+ MEDIA => 'Media',
6526
+ SCRIPT => 'Script', # character set? (seen 'Latn')
6527
+ BARCODE => 'Barcode',
6528
+ LABEL => 'Label',
6529
+ MOOD => 'Mood',
6530
+ popularimeter => 'Popularimeter',
6531
+ 'Dynamic Range (DR)'=> 'DynamicRange',
6532
+ initialkey => 'InitialKey',
6533
+ originalyear => 'OriginalYear',
6534
+ originaldate => 'OriginalDate',
6535
+ '~length' => 'Length', # play length? (ie. duration?)
6536
+ replaygain_track_gain=>'ReplayTrackGain',
6537
+ replaygain_track_peak=>'ReplayTrackPeak',
6538
+ 'Volume Level (ReplayGain)'=> 'ReplayVolumeLevel',
6539
+ 'Dynamic Range (R128)'=> 'DynamicRangeR128',
6540
+ 'Volume Level (R128)' => 'VolumeLevelR128',
6541
+ 'Peak Level (Sample)' => 'PeakLevelSample',
6542
+ 'Peak Level (R128)' => 'PeakLevelR128',
6543
+ # also seen (many from forum12777):
6544
+ # 'MusicBrainz Album Release Country'
6545
+ # 'MusicBrainz Album Type'
6546
+ # 'MusicBrainz Album Status'
6547
+ # 'MusicBrainz Track Id'
6548
+ # 'MusicBrainz Release Track Id'
6549
+ # 'MusicBrainz Album Id'
6550
+ # 'MusicBrainz Album Artist Id'
6551
+ # 'MusicBrainz Artist Id'
6552
+ # 'Acoustid Id' (sic)
6553
+ # 'Tool Version'
6554
+ # 'Tool Name'
6555
+ # 'ISRC'
6556
+ # 'HDCD'
6557
+ # 'Waveform'
6495
6558
  );
6496
6559
 
6497
6560
  # iTunes audio encoding parameters
@@ -8860,20 +8923,28 @@ sub ProcessKeys($$$)
8860
8923
  my $ns = substr($$dataPt, $pos + 4, 4);
8861
8924
  my $tag = substr($$dataPt, $pos + 8, $len - 8);
8862
8925
  $tag =~ s/\0.*//s; # truncate at null
8926
+ my $full = $tag;
8863
8927
  $tag =~ s/^com\.(apple\.quicktime\.)?// if $ns eq 'mdta'; # remove apple quicktime domain
8864
8928
  $tag = "Tag_$ns" unless $tag;
8865
- # (I have some samples where the tag is a reversed ItemList or UserData tag ID)
8866
- my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
8867
- unless ($tagInfo) {
8868
- $tagInfo = $et->GetTagInfo($itemList, $tag);
8869
- unless ($tagInfo) {
8929
+ my $short = $tag;
8930
+ my $tagInfo;
8931
+ for (;;) {
8932
+ $tagInfo = $et->GetTagInfo($tagTablePtr, $tag) and last;
8933
+ # also try ItemList and UserData tables
8934
+ $tagInfo = $et->GetTagInfo($itemList, $tag) and last;
8935
+ $tagInfo = $et->GetTagInfo($userData, $tag) and last;
8936
+ # (I have some samples where the tag is a reversed ItemList or UserData tag ID)
8937
+ if ($tag =~ /^\w{3}\xa9$/) {
8938
+ $tag = pack('N', unpack('V', $tag));
8939
+ $tagInfo = $et->GetTagInfo($itemList, $tag) and last;
8870
8940
  $tagInfo = $et->GetTagInfo($userData, $tag);
8871
- if (not $tagInfo and $tag =~ /^\w{3}\xa9$/) {
8872
- $tag = pack('N', unpack('V', $tag));
8873
- $tagInfo = $et->GetTagInfo($itemList, $tag);
8874
- $tagInfo or $tagInfo = $et->GetTagInfo($userData, $tag);
8875
- }
8941
+ last;
8942
+ }
8943
+ if ($tag eq $full) {
8944
+ $tag = $short;
8945
+ last;
8876
8946
  }
8947
+ $tag = $full;
8877
8948
  }
8878
8949
  my ($newInfo, $msg);
8879
8950
  if ($tagInfo) {
@@ -8914,6 +8985,7 @@ sub ProcessKeys($$$)
8914
8985
  delete $$itemList{$id};
8915
8986
  }
8916
8987
  if ($newInfo) {
8988
+ $$newInfo{KeysID} = $tag; # save original ID for use in family 7 group name
8917
8989
  AddTagToTable($itemList, $id, $newInfo);
8918
8990
  $msg or $msg = '';
8919
8991
  $out and print $out "$$et{INDENT}Added ItemList Tag $id = ($ns) $tag$msg\n";
@@ -9267,6 +9339,7 @@ ItemID: foreach $id (keys %$items) {
9267
9339
  Name => $name,
9268
9340
  Description => $desc,
9269
9341
  };
9342
+ $et->VPrint(0, $$et{INDENT}, "[adding QuickTime:$name]\n");
9270
9343
  AddTagToTable($tagTablePtr, $tag, $tagInfo);
9271
9344
  }
9272
9345
  # ignore 8-byte header
@@ -9278,9 +9351,9 @@ ItemID: foreach $id (keys %$items) {
9278
9351
  $val = \$buff;
9279
9352
  }
9280
9353
  }
9281
- undef %triplet;
9354
+ $$tagInfo{List} = 1; # (allow any of these tags to have multiple data elements)
9355
+ $et->VerboseInfo($tag, $tagInfo, Value => $val) if $verbose;
9282
9356
  } else {
9283
- undef %triplet if $tag eq 'mean';
9284
9357
  $triplet{$tag} = substr($val,4) if length($val) > 4;
9285
9358
  undef $tagInfo; # don't store this tag
9286
9359
  }
@@ -9364,7 +9437,13 @@ ItemID: foreach $id (keys %$items) {
9364
9437
  # (shouldn't be null terminated, but some software writes it anyway)
9365
9438
  $value =~ s/\0$// unless $$tagInfo{Binary};
9366
9439
  } else {
9367
- $format = QuickTimeFormat($flags, $len) unless $format;
9440
+ if (not $format) {
9441
+ $format = QuickTimeFormat($flags, $len);
9442
+ } elsif ($format =~ /^int\d+([us])$/) {
9443
+ # adjust integer to available length (but not int64)
9444
+ my $fmt = { 1=>'int8', 2=>'int16', 4=>'int32' }->{$len};
9445
+ $format = $fmt . $1 if defined $fmt;
9446
+ }
9368
9447
  if ($format) {
9369
9448
  $value = ReadValue(\$value, 0, $format, $$tagInfo{Count}, $len);
9370
9449
  } elsif (not $$tagInfo{ValueConv}) {
@@ -9520,9 +9599,9 @@ ItemID: foreach $id (keys %$items) {
9520
9599
  ($size, $tag) = unpack('Na4', $buff);
9521
9600
  ++$index if defined $index;
9522
9601
  }
9523
- # tweak file type based on track content ("iso*" ftyp only)
9524
- if ($$et{VALUE}{FileType} and $$et{VALUE}{FileType} eq 'MP4' and
9525
- $$et{save_ftyp} and $$et{HasHandler} and $$et{save_ftyp} =~ /^iso/ and
9602
+ # tweak file type based on track content ("iso*" and "dash" ftyp only)
9603
+ if ($topLevel and $$et{VALUE}{FileType} and $$et{VALUE}{FileType} eq 'MP4' and
9604
+ $$et{save_ftyp} and $$et{HasHandler} and $$et{save_ftyp} =~ /^(iso|dash)/ and
9526
9605
  $$et{HasHandler}{soun} and not $$et{HasHandler}{vide})
9527
9606
  {
9528
9607
  $et->OverrideFileType('M4A', 'audio/mp4');