exiftool_vendored 12.25.0 → 12.35.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +174 -7
  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 +118 -92
  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 +16 -3
  14. data/bin/lib/Image/ExifTool/CBOR.pm +331 -0
  15. data/bin/lib/Image/ExifTool/Canon.pm +52 -20
  16. data/bin/lib/Image/ExifTool/Charset.pm +2 -0
  17. data/bin/lib/Image/ExifTool/DPX.pm +13 -2
  18. data/bin/lib/Image/ExifTool/Exif.pm +107 -8
  19. data/bin/lib/Image/ExifTool/FLIR.pm +33 -8
  20. data/bin/lib/Image/ExifTool/FlashPix.pm +35 -10
  21. data/bin/lib/Image/ExifTool/FujiFilm.pm +1 -0
  22. data/bin/lib/Image/ExifTool/Geotag.pm +13 -2
  23. data/bin/lib/Image/ExifTool/GoPro.pm +16 -1
  24. data/bin/lib/Image/ExifTool/ICC_Profile.pm +96 -4
  25. data/bin/lib/Image/ExifTool/ID3.pm +15 -3
  26. data/bin/lib/Image/ExifTool/JPEG.pm +68 -2
  27. data/bin/lib/Image/ExifTool/JSON.pm +7 -3
  28. data/bin/lib/Image/ExifTool/Jpeg2000.pm +164 -36
  29. data/bin/lib/Image/ExifTool/LIF.pm +153 -0
  30. data/bin/lib/Image/ExifTool/Lang/nl.pm +60 -59
  31. data/bin/lib/Image/ExifTool/M2TS.pm +103 -7
  32. data/bin/lib/Image/ExifTool/MIE.pm +2 -1
  33. data/bin/lib/Image/ExifTool/MRC.pm +1 -1
  34. data/bin/lib/Image/ExifTool/MacOS.pm +2 -2
  35. data/bin/lib/Image/ExifTool/Nikon.pm +50 -6
  36. data/bin/lib/Image/ExifTool/NikonSettings.pm +10 -2
  37. data/bin/lib/Image/ExifTool/Olympus.pm +9 -2
  38. data/bin/lib/Image/ExifTool/Other.pm +93 -0
  39. data/bin/lib/Image/ExifTool/PDF.pm +11 -12
  40. data/bin/lib/Image/ExifTool/PNG.pm +7 -6
  41. data/bin/lib/Image/ExifTool/Panasonic.pm +14 -2
  42. data/bin/lib/Image/ExifTool/Pentax.pm +28 -5
  43. data/bin/lib/Image/ExifTool/Photoshop.pm +6 -0
  44. data/bin/lib/Image/ExifTool/QuickTime.pm +123 -25
  45. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +203 -121
  46. data/bin/lib/Image/ExifTool/README +9 -2
  47. data/bin/lib/Image/ExifTool/RIFF.pm +7 -2
  48. data/bin/lib/Image/ExifTool/Samsung.pm +47 -10
  49. data/bin/lib/Image/ExifTool/Sony.pm +113 -42
  50. data/bin/lib/Image/ExifTool/TagLookup.pm +4599 -4451
  51. data/bin/lib/Image/ExifTool/TagNames.pod +276 -41
  52. data/bin/lib/Image/ExifTool/Torrent.pm +18 -11
  53. data/bin/lib/Image/ExifTool/WriteIPTC.pl +1 -1
  54. data/bin/lib/Image/ExifTool/WritePDF.pl +1 -0
  55. data/bin/lib/Image/ExifTool/WritePNG.pl +2 -0
  56. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +21 -4
  57. data/bin/lib/Image/ExifTool/WriteXMP.pl +1 -1
  58. data/bin/lib/Image/ExifTool/Writer.pl +47 -2
  59. data/bin/lib/Image/ExifTool/XMP.pm +32 -12
  60. data/bin/lib/Image/ExifTool/XMP2.pl +5 -2
  61. data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
  62. data/bin/lib/Image/ExifTool/ZISRAW.pm +121 -2
  63. data/bin/lib/Image/ExifTool.pm +153 -52
  64. data/bin/lib/Image/ExifTool.pod +70 -60
  65. data/bin/perl-Image-ExifTool.spec +43 -42
  66. data/lib/exiftool_vendored/version.rb +1 -1
  67. metadata +6 -3
@@ -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.54';
25
25
 
26
26
  sub FetchObject($$$$);
27
27
  sub ExtractObject($$;$$);
@@ -280,7 +280,12 @@ my %supportedFilter = (
280
280
  ConvertToDict => 1,
281
281
  },
282
282
  Cs1 => {
283
- SubDirectory => { TagTable => 'Image::ExifTool::PDF::Cs1' },
283
+ SubDirectory => { TagTable => 'Image::ExifTool::PDF::DefaultRGB' },
284
+ ConvertToDict => 1, # (just in case)
285
+ },
286
+ CS0 => {
287
+ SubDirectory => { TagTable => 'Image::ExifTool::PDF::DefaultRGB' },
288
+ ConvertToDict => 1, # (just in case)
284
289
  },
285
290
  );
286
291
 
@@ -291,14 +296,7 @@ my %supportedFilter = (
291
296
  },
292
297
  );
293
298
 
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
299
+ # tags in PDF ICCBased, Cs1 and CS0 dictionaries
302
300
  %Image::ExifTool::PDF::ICCBased = (
303
301
  _stream => {
304
302
  SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' },
@@ -1989,16 +1987,17 @@ sub ProcessDict($$$$;$$)
1989
1987
  } else {
1990
1988
  $val = ReadPDFValue($val);
1991
1989
  }
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
1990
  if (ref $val) {
1995
1991
  if (ref $val eq 'ARRAY') {
1992
+ delete $$et{LIST_TAGS}{$tagInfo} if $$tagInfo{List};
1996
1993
  my $v;
1997
1994
  foreach $v (@$val) {
1998
1995
  $et->FoundTag($tagInfo, $v);
1999
1996
  }
2000
1997
  }
2001
1998
  } elsif (defined $val) {
1999
+ # convert from UTF-16 (big endian) to UTF-8 or Latin if necessary
2000
+ # unless this is binary data (hex-encoded strings would not have been converted)
2002
2001
  my $format = $$tagInfo{Format} || $$tagInfo{Writable} || 'string';
2003
2002
  $val = ConvertPDFDate($val) if $format eq 'date';
2004
2003
  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.72';
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};
@@ -481,6 +482,17 @@ my %eeBox2 = (
481
482
  # (Pittasoft Blackview dashcam MP4 videos)
482
483
  Condition => '$$valPt =~ /^\0\0..(cprt|sttm|ptnm|ptrh|thum|gps |3gf )/s',
483
484
  SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Pittasoft' },
485
+ },{
486
+ Name => 'ThumbnailImage',
487
+ # (DJI Zenmuse XT2 thermal camera)
488
+ Groups => { 2 => 'Preview' },
489
+ Condition => '$$valPt =~ /^.{4}mdat\xff\xd8\xff/s',
490
+ RawConv => q{
491
+ my $len = unpack('N', $val);
492
+ return undef if $len <= 8 or $len > length($val);
493
+ return substr($val, 8, $len-8);
494
+ },
495
+ Binary => 1,
484
496
  },{
485
497
  Unknown => 1,
486
498
  Binary => 1,
@@ -557,6 +569,7 @@ my %eeBox2 = (
557
569
  # *** this is where ExifTool writes XMP in MP4 videos (as per XMP spec) ***
558
570
  Condition => '$$valPt=~/^\xbe\x7a\xcf\xcb\x97\xa9\x42\xe8\x9c\x71\x99\x94\x91\xe3\xaf\xac/',
559
571
  WriteGroup => 'XMP', # (write main XMP tags here)
572
+ PreservePadding => 1,
560
573
  SubDirectory => {
561
574
  TagTable => 'Image::ExifTool::XMP::Main',
562
575
  Start => 16,
@@ -606,6 +619,7 @@ my %eeBox2 = (
606
619
  Name => 'PreviewImage',
607
620
  Condition => '$$valPt=~/^\xea\xf4\x2b\x5e\x1c\x98\x4b\x88\xb9\xfb\xb7\xdc\x40\x6e\x4d\x16/',
608
621
  Groups => { 2 => 'Preview' },
622
+ PreservePadding => 1,
609
623
  # 0x00 - undef[16]: UUID
610
624
  # 0x10 - int32u[2]: "0 1" (version and/or item count?)
611
625
  # 0x18 - int32u: PRVW atom size
@@ -733,6 +747,11 @@ my %eeBox2 = (
733
747
  Unknown => 1,
734
748
  Binary => 1,
735
749
  },
750
+ sefd => {
751
+ Name => 'SamsungTrailer',
752
+ SubDirectory => { TagTable => 'Image::ExifTool::Samsung::Trailer' },
753
+ },
754
+ # 'samn'? - seen in Vantrue N2S sample video
736
755
  );
737
756
 
738
757
  # MPEG-4 'ftyp' atom
@@ -1194,6 +1213,15 @@ my %eeBox2 = (
1194
1213
  Name => 'CreateDate',
1195
1214
  Groups => { 2 => 'Time' },
1196
1215
  %timeInfo,
1216
+ RawConv => q{
1217
+ my $offset = (66 * 365 + 17) * 24 * 3600;
1218
+ if ($val >= $offset or $$self{OPTIONS}{QuickTimeUTC}) {
1219
+ $val -= $offset;
1220
+ } elsif ($val and not $$self{IsWriting}) {
1221
+ $self->WarnOnce('Patched incorrect time zero for QuickTime date/time tag',1);
1222
+ }
1223
+ return $$self{CreateDate} = $val;
1224
+ },
1197
1225
  # this is int64u if MovieHeaderVersion == 1 (ref 13)
1198
1226
  Hook => '$$self{MovieHeaderVersion} and $format = "int64u", $varSize += 4',
1199
1227
  },
@@ -2254,6 +2282,12 @@ my %eeBox2 = (
2254
2282
  # opax - 164 bytes unknown (center and affine arrays? ref 26)
2255
2283
  # opai - 32 bytes (maybe contains a serial number starting at byte 16? - PH) (rgb gains, degamma, gamma? ref 26)
2256
2284
  # intv - 16 bytes all zero
2285
+ # ---- Xaiomi ----
2286
+ mcvr => {
2287
+ Name => 'PreviewImage',
2288
+ Groups => { 2 => 'Preview' },
2289
+ Binary => 1,
2290
+ },
2257
2291
  # ---- Unknown ----
2258
2292
  # CDET - 128 bytes (unknown origin)
2259
2293
  # mtyp - 4 bytes all zero (some drone video)
@@ -2691,6 +2725,7 @@ my %eeBox2 = (
2691
2725
  colr => [{
2692
2726
  Name => 'ICC_Profile',
2693
2727
  Condition => '$$valPt =~ /^(prof|rICC)/',
2728
+ Permanent => 0, # (in QuickTime, this writes a zero-length box instead of deleting)
2694
2729
  SubDirectory => {
2695
2730
  TagTable => 'Image::ExifTool::ICC_Profile::Main',
2696
2731
  Start => 4,
@@ -6281,6 +6316,10 @@ my %eeBox2 = (
6281
6316
  'location.ISO6709' => {
6282
6317
  Name => 'GPSCoordinates',
6283
6318
  Groups => { 2 => 'Location' },
6319
+ Notes => q{
6320
+ Google Photos may ignore this if the coorinates have more than 5 digits
6321
+ after the decimal
6322
+ },
6284
6323
  ValueConv => \&ConvertISO6709,
6285
6324
  ValueConvInv => \&ConvInvISO6709,
6286
6325
  PrintConv => \&PrintGPSCoordinates,
@@ -6425,10 +6464,11 @@ my %eeBox2 = (
6425
6464
  # iTunes info ('----') atoms
6426
6465
  %Image::ExifTool::QuickTime::iTunesInfo = (
6427
6466
  PROCESS_PROC => \&ProcessMOV,
6428
- GROUPS => { 2 => 'Audio' },
6467
+ GROUPS => { 1 => 'iTunes', 2 => 'Audio' },
6429
6468
  NOTES => q{
6430
6469
  ExifTool will extract any iTunesInfo tags that exist, even if they are not
6431
- defined in this table.
6470
+ defined in this table. These tags belong to the family 1 "iTunes" group,
6471
+ and are not currently writable.
6432
6472
  },
6433
6473
  # 'mean'/'name'/'data' atoms form a triplet, but unfortunately
6434
6474
  # I haven't been able to find any documentation on this.
@@ -6489,9 +6529,45 @@ my %eeBox2 = (
6489
6529
  SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::EncodingParams' },
6490
6530
  },
6491
6531
  # also heard about 'iTunPGAP', but I haven't seen a sample
6492
- DISCNUMBER => 'DiscNumber', #PH
6493
- TRACKNUMBER => 'TrackNumber', #PH
6494
- popularimeter => 'Popularimeter', #PH
6532
+ # all tags below were added based on samples I have seen - PH
6533
+ DISCNUMBER => 'DiscNumber',
6534
+ TRACKNUMBER => 'TrackNumber',
6535
+ ARTISTS => 'Artists',
6536
+ CATALOGNUMBER => 'CatalogNumber',
6537
+ RATING => 'Rating',
6538
+ MEDIA => 'Media',
6539
+ SCRIPT => 'Script', # character set? (seen 'Latn')
6540
+ BARCODE => 'Barcode',
6541
+ LABEL => 'Label',
6542
+ MOOD => 'Mood',
6543
+ popularimeter => 'Popularimeter',
6544
+ 'Dynamic Range (DR)'=> 'DynamicRange',
6545
+ initialkey => 'InitialKey',
6546
+ originalyear => 'OriginalYear',
6547
+ originaldate => 'OriginalDate',
6548
+ '~length' => 'Length', # play length? (ie. duration?)
6549
+ replaygain_track_gain=>'ReplayTrackGain',
6550
+ replaygain_track_peak=>'ReplayTrackPeak',
6551
+ 'Volume Level (ReplayGain)'=> 'ReplayVolumeLevel',
6552
+ 'Dynamic Range (R128)'=> 'DynamicRangeR128',
6553
+ 'Volume Level (R128)' => 'VolumeLevelR128',
6554
+ 'Peak Level (Sample)' => 'PeakLevelSample',
6555
+ 'Peak Level (R128)' => 'PeakLevelR128',
6556
+ # also seen (many from forum12777):
6557
+ # 'MusicBrainz Album Release Country'
6558
+ # 'MusicBrainz Album Type'
6559
+ # 'MusicBrainz Album Status'
6560
+ # 'MusicBrainz Track Id'
6561
+ # 'MusicBrainz Release Track Id'
6562
+ # 'MusicBrainz Album Id'
6563
+ # 'MusicBrainz Album Artist Id'
6564
+ # 'MusicBrainz Artist Id'
6565
+ # 'Acoustid Id' (sic)
6566
+ # 'Tool Version'
6567
+ # 'Tool Name'
6568
+ # 'ISRC'
6569
+ # 'HDCD'
6570
+ # 'Waveform'
6495
6571
  );
6496
6572
 
6497
6573
  # iTunes audio encoding parameters
@@ -8860,20 +8936,28 @@ sub ProcessKeys($$$)
8860
8936
  my $ns = substr($$dataPt, $pos + 4, 4);
8861
8937
  my $tag = substr($$dataPt, $pos + 8, $len - 8);
8862
8938
  $tag =~ s/\0.*//s; # truncate at null
8939
+ my $full = $tag;
8863
8940
  $tag =~ s/^com\.(apple\.quicktime\.)?// if $ns eq 'mdta'; # remove apple quicktime domain
8864
8941
  $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) {
8942
+ my $short = $tag;
8943
+ my $tagInfo;
8944
+ for (;;) {
8945
+ $tagInfo = $et->GetTagInfo($tagTablePtr, $tag) and last;
8946
+ # also try ItemList and UserData tables
8947
+ $tagInfo = $et->GetTagInfo($itemList, $tag) and last;
8948
+ $tagInfo = $et->GetTagInfo($userData, $tag) and last;
8949
+ # (I have some samples where the tag is a reversed ItemList or UserData tag ID)
8950
+ if ($tag =~ /^\w{3}\xa9$/) {
8951
+ $tag = pack('N', unpack('V', $tag));
8952
+ $tagInfo = $et->GetTagInfo($itemList, $tag) and last;
8870
8953
  $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
- }
8954
+ last;
8955
+ }
8956
+ if ($tag eq $full) {
8957
+ $tag = $short;
8958
+ last;
8876
8959
  }
8960
+ $tag = $full;
8877
8961
  }
8878
8962
  my ($newInfo, $msg);
8879
8963
  if ($tagInfo) {
@@ -8914,6 +8998,7 @@ sub ProcessKeys($$$)
8914
8998
  delete $$itemList{$id};
8915
8999
  }
8916
9000
  if ($newInfo) {
9001
+ $$newInfo{KeysID} = $tag; # save original ID for use in family 7 group name
8917
9002
  AddTagToTable($itemList, $id, $newInfo);
8918
9003
  $msg or $msg = '';
8919
9004
  $out and print $out "$$et{INDENT}Added ItemList Tag $id = ($ns) $tag$msg\n";
@@ -9041,6 +9126,12 @@ sub ProcessMOV($$;$)
9041
9126
  } else {
9042
9127
  my $t = PrintableTagID($tag,2);
9043
9128
  $et->VPrint(0,"$$et{INDENT}Tag '${t}' extends to end of file");
9129
+ if ($$tagTablePtr{"$tag-size"}) {
9130
+ my $pos = $raf->Tell();
9131
+ $raf->Seek(0, 2);
9132
+ $et->HandleTag($tagTablePtr, "$tag-size", $raf->Tell() - $pos);
9133
+ $et->HandleTag($tagTablePtr, "$tag-offset", $pos) if $$tagTablePtr{"$tag-offset"};
9134
+ }
9044
9135
  }
9045
9136
  last;
9046
9137
  }
@@ -9267,6 +9358,7 @@ ItemID: foreach $id (keys %$items) {
9267
9358
  Name => $name,
9268
9359
  Description => $desc,
9269
9360
  };
9361
+ $et->VPrint(0, $$et{INDENT}, "[adding QuickTime:$name]\n");
9270
9362
  AddTagToTable($tagTablePtr, $tag, $tagInfo);
9271
9363
  }
9272
9364
  # ignore 8-byte header
@@ -9278,9 +9370,9 @@ ItemID: foreach $id (keys %$items) {
9278
9370
  $val = \$buff;
9279
9371
  }
9280
9372
  }
9281
- undef %triplet;
9373
+ $$tagInfo{List} = 1; # (allow any of these tags to have multiple data elements)
9374
+ $et->VerboseInfo($tag, $tagInfo, Value => $val) if $verbose;
9282
9375
  } else {
9283
- undef %triplet if $tag eq 'mean';
9284
9376
  $triplet{$tag} = substr($val,4) if length($val) > 4;
9285
9377
  undef $tagInfo; # don't store this tag
9286
9378
  }
@@ -9346,7 +9438,7 @@ ItemID: foreach $id (keys %$items) {
9346
9438
  for (;;) {
9347
9439
  last if $pos + 16 > $size;
9348
9440
  my ($len, $type, $flags, $ctry, $lang) = unpack("x${pos}Na4Nnn", $val);
9349
- last if $pos + $len > $size;
9441
+ last if $pos + $len > $size or not $len;
9350
9442
  my ($value, $langInfo, $oldDir);
9351
9443
  my $format = $$tagInfo{Format};
9352
9444
  if ($type eq 'data' and $len >= 16) {
@@ -9364,7 +9456,13 @@ ItemID: foreach $id (keys %$items) {
9364
9456
  # (shouldn't be null terminated, but some software writes it anyway)
9365
9457
  $value =~ s/\0$// unless $$tagInfo{Binary};
9366
9458
  } else {
9367
- $format = QuickTimeFormat($flags, $len) unless $format;
9459
+ if (not $format) {
9460
+ $format = QuickTimeFormat($flags, $len);
9461
+ } elsif ($format =~ /^int\d+([us])$/) {
9462
+ # adjust integer to available length (but not int64)
9463
+ my $fmt = { 1=>'int8', 2=>'int16', 4=>'int32' }->{$len};
9464
+ $format = $fmt . $1 if defined $fmt;
9465
+ }
9368
9466
  if ($format) {
9369
9467
  $value = ReadValue(\$value, 0, $format, $$tagInfo{Count}, $len);
9370
9468
  } elsif (not $$tagInfo{ValueConv}) {
@@ -9520,9 +9618,9 @@ ItemID: foreach $id (keys %$items) {
9520
9618
  ($size, $tag) = unpack('Na4', $buff);
9521
9619
  ++$index if defined $index;
9522
9620
  }
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
9621
+ # tweak file type based on track content ("iso*" and "dash" ftyp only)
9622
+ if ($topLevel and $$et{VALUE}{FileType} and $$et{VALUE}{FileType} eq 'MP4' and
9623
+ $$et{save_ftyp} and $$et{HasHandler} and $$et{save_ftyp} =~ /^(iso|dash)/ and
9526
9624
  $$et{HasHandler}{soun} and not $$et{HasHandler}{vide})
9527
9625
  {
9528
9626
  $et->OverrideFileType('M4A', 'audio/mp4');