exiftool_vendored 11.98.0 → 12.10.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of exiftool_vendored might be problematic. Click here for more details.

Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +198 -2
  3. data/bin/MANIFEST +8 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +43 -42
  7. data/bin/exiftool +102 -75
  8. data/bin/lib/Image/ExifTool.pm +163 -111
  9. data/bin/lib/Image/ExifTool.pod +127 -93
  10. data/bin/lib/Image/ExifTool/AIFF.pm +2 -2
  11. data/bin/lib/Image/ExifTool/APE.pm +2 -2
  12. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +21 -10
  13. data/bin/lib/Image/ExifTool/Canon.pm +202 -14
  14. data/bin/lib/Image/ExifTool/CanonCustom.pm +82 -16
  15. data/bin/lib/Image/ExifTool/DPX.pm +56 -2
  16. data/bin/lib/Image/ExifTool/DarwinCore.pm +22 -3
  17. data/bin/lib/Image/ExifTool/EXE.pm +8 -5
  18. data/bin/lib/Image/ExifTool/Exif.pm +15 -6
  19. data/bin/lib/Image/ExifTool/Font.pm +9 -2
  20. data/bin/lib/Image/ExifTool/GIF.pm +6 -1
  21. data/bin/lib/Image/ExifTool/GeoTiff.pm +2 -0
  22. data/bin/lib/Image/ExifTool/Geotag.pm +2 -2
  23. data/bin/lib/Image/ExifTool/GoPro.pm +48 -22
  24. data/bin/lib/Image/ExifTool/H264.pm +1 -1
  25. data/bin/lib/Image/ExifTool/ID3.pm +91 -12
  26. data/bin/lib/Image/ExifTool/IPTC.pm +1 -0
  27. data/bin/lib/Image/ExifTool/JSON.pm +27 -4
  28. data/bin/lib/Image/ExifTool/Lang/de.pm +3 -1
  29. data/bin/lib/Image/ExifTool/Lang/es.pm +1 -1
  30. data/bin/lib/Image/ExifTool/M2TS.pm +19 -19
  31. data/bin/lib/Image/ExifTool/MacOS.pm +154 -38
  32. data/bin/lib/Image/ExifTool/Matroska.pm +3 -1
  33. data/bin/lib/Image/ExifTool/Minolta.pm +7 -2
  34. data/bin/lib/Image/ExifTool/MinoltaRaw.pm +11 -10
  35. data/bin/lib/Image/ExifTool/Nikon.pm +164 -20
  36. data/bin/lib/Image/ExifTool/Olympus.pm +39 -17
  37. data/bin/lib/Image/ExifTool/PNG.pm +14 -3
  38. data/bin/lib/Image/ExifTool/PPM.pm +5 -5
  39. data/bin/lib/Image/ExifTool/Panasonic.pm +148 -14
  40. data/bin/lib/Image/ExifTool/PanasonicRaw.pm +34 -0
  41. data/bin/lib/Image/ExifTool/Parrot.pm +2 -1
  42. data/bin/lib/Image/ExifTool/Pentax.pm +3 -1
  43. data/bin/lib/Image/ExifTool/Photoshop.pm +2 -1
  44. data/bin/lib/Image/ExifTool/QuickTime.pm +289 -37
  45. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +419 -60
  46. data/bin/lib/Image/ExifTool/README +26 -22
  47. data/bin/lib/Image/ExifTool/RSRC.pm +17 -11
  48. data/bin/lib/Image/ExifTool/RTF.pm +12 -7
  49. data/bin/lib/Image/ExifTool/Radiance.pm +7 -2
  50. data/bin/lib/Image/ExifTool/Ricoh.pm +19 -1
  51. data/bin/lib/Image/ExifTool/Shift.pl +1 -0
  52. data/bin/lib/Image/ExifTool/SigmaRaw.pm +40 -33
  53. data/bin/lib/Image/ExifTool/Sony.pm +426 -40
  54. data/bin/lib/Image/ExifTool/TagLookup.pm +5799 -5671
  55. data/bin/lib/Image/ExifTool/TagNames.pod +584 -97
  56. data/bin/lib/Image/ExifTool/Validate.pm +4 -4
  57. data/bin/lib/Image/ExifTool/WriteExif.pl +3 -2
  58. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +26 -18
  59. data/bin/lib/Image/ExifTool/Writer.pl +47 -24
  60. data/bin/lib/Image/ExifTool/XMP.pm +99 -17
  61. data/bin/lib/Image/ExifTool/XMP2.pl +1 -0
  62. data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
  63. data/bin/lib/Image/ExifTool/ZISRAW.pm +123 -0
  64. data/bin/perl-Image-ExifTool.spec +42 -41
  65. data/lib/exiftool_vendored/version.rb +1 -1
  66. metadata +8 -7
@@ -13,7 +13,7 @@ package Image::ExifTool::Parrot;
13
13
  use strict;
14
14
  use vars qw($VERSION);
15
15
 
16
- $VERSION = '1.00';
16
+ $VERSION = '1.01';
17
17
 
18
18
  sub Process_mett($$$);
19
19
 
@@ -703,6 +703,7 @@ sub Process_mett($$$)
703
703
  $et->HandleTag($tagTbl, $id, undef,
704
704
  DataPt => $dataPt,
705
705
  DataPos => $dataPos,
706
+ Base => $$dirInfo{Base},
706
707
  Start => $pos,
707
708
  Size => $size,
708
709
  );
@@ -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.31';
61
+ $VERSION = '3.34';
62
62
 
63
63
  sub CryptShutterCount($$);
64
64
  sub PrintFilter($$$);
@@ -338,6 +338,7 @@ sub DecodeAFPoints($$$$;$);
338
338
  '8 63' => 'HD PENTAX-D FA 15-30mm F2.8 ED SDM WR', #PH
339
339
  '8 64' => 'HD PENTAX-D FA* 50mm F1.4 SDM AW', #27
340
340
  '8 65' => 'HD PENTAX-D FA 70-210mm F4 ED SDM WR', #PH
341
+ '8 66' => 'HD PENTAX-D FA 85mm F1.4 ED SDM AW', #James O'Neill
341
342
  '8 196' => 'HD PENTAX-DA* 11-18mm F2.8 ED DC AW', #29
342
343
  '8 197' => 'HD PENTAX-DA 55-300mm F4.5-6.3 ED PLM WR RE', #29
343
344
  '8 198' => 'smc PENTAX-DA L 18-50mm F4-5.6 DC WR RE', #29
@@ -546,6 +547,7 @@ my %pentaxModelID = (
546
547
  0x13222 => 'K-70', #29 (Ricoh)
547
548
  0x1322c => 'KP', #29 (Ricoh)
548
549
  0x13240 => 'K-1 Mark II', # (Ricoh)
550
+ 0x13290 => 'WG-70', # (Ricoh)
549
551
  );
550
552
 
551
553
  # Pentax city codes - (PH, Optio WP)
@@ -28,7 +28,7 @@ use strict;
28
28
  use vars qw($VERSION $AUTOLOAD $iptcDigestInfo);
29
29
  use Image::ExifTool qw(:DataAccess :Utils);
30
30
 
31
- $VERSION = '1.64';
31
+ $VERSION = '1.65';
32
32
 
33
33
  sub ProcessPhotoshop($$$);
34
34
  sub WritePhotoshop($$$);
@@ -982,6 +982,7 @@ sub ProcessPhotoshop($$$)
982
982
  DataPos => $$dirInfo{DataPos},
983
983
  Size => $size,
984
984
  Start => $pos,
985
+ Base => $$dirInfo{Base},
985
986
  Parent => $$dirInfo{DirName},
986
987
  );
987
988
  $size += 1 if $size & 0x01; # size is padded to an even # bytes
@@ -36,6 +36,7 @@
36
36
  # 24) https://github.com/sergiomb2/libmp4v2/wiki/iTunesMetadata
37
37
  # 25) https://cconcolato.github.io/mp4ra/atoms.html
38
38
  # 26) https://github.com/SamsungVR/android_upload_sdk/blob/master/SDKLib/src/main/java/com/samsung/msca/samsungvr/sdk/UserVideo.java
39
+ # 27) https://exiftool.org/forum/index.php?topic=11517.0
39
40
  #------------------------------------------------------------------------------
40
41
 
41
42
  package Image::ExifTool::QuickTime;
@@ -46,7 +47,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
46
47
  use Image::ExifTool::Exif;
47
48
  use Image::ExifTool::GPS;
48
49
 
49
- $VERSION = '2.48';
50
+ $VERSION = '2.55';
50
51
 
51
52
  sub ProcessMOV($$;$);
52
53
  sub ProcessKeys($$$);
@@ -105,7 +106,9 @@ my %mimeLookup = (
105
106
  MQV => 'video/quicktime',
106
107
  HEIC => 'image/heic',
107
108
  HEVC => 'image/heic-sequence',
109
+ HEICS=> 'image/heic-sequence',
108
110
  HEIF => 'image/heif',
111
+ HEIFS=> 'image/heif-sequence',
109
112
  AVIF => 'image/avif', #PH (NC)
110
113
  CRX => 'video/x-canon-crx', # (will get overridden)
111
114
  );
@@ -228,9 +231,10 @@ my %timeInfo = (
228
231
  Writable => 1,
229
232
  Permanent => 1,
230
233
  DelValue => 0,
231
- # Note: This value will be in UTC if generated by a system that is aware of the time zone
232
- ValueConv => 'ConvertUnixTime($val, $self->Options("QuickTimeUTC"))',
233
- ValueConvInv => 'GetUnixTime($val, $self->Options("QuickTimeUTC")) + (66 * 365 + 17) * 24 * 3600',
234
+ # Note: This value will be in UTC if generated by a system that is aware of the time zone (ie. CR3 files)
235
+ RawConvInv => 'GetUnixTime($val, $self->Options("QuickTimeUTC") || $$self{FileType} eq "CR3") + (66 * 365 + 17) * 24 * 3600',
236
+ ValueConv => 'ConvertUnixTime($val, $self->Options("QuickTimeUTC") || $$self{FileType} eq "CR3")',
237
+ ValueConvInv => '$val',
234
238
  PrintConv => '$self->ConvertDateTime($val)',
235
239
  PrintConvInv => '$self->InverseDateTime($val)',
236
240
  # (can't put Groups here because they aren't constant!)
@@ -418,7 +422,8 @@ my %eeBox = (
418
422
  sbtl => { %eeStd },
419
423
  data => { %eeStd },
420
424
  camm => { %eeStd }, # (Insta360)
421
- '' => { 'gps ' => 'moov' }, # (no handler -- in top level 'moov' box)
425
+ ctbx => { %eeStd }, # (GM cars)
426
+ '' => { 'gps ' => 'moov', 'GPS ' => 'main' }, # (no handler -- in top level 'moov' box, and main)
422
427
  );
423
428
 
424
429
  # QuickTime atoms
@@ -555,6 +560,20 @@ my %eeBox = (
555
560
  Start => 16,
556
561
  },
557
562
  },
563
+ { # (ref https://github.com/JamesHeinrich/getID3/blob/master/getid3/module.audio-video.quicktime.php)
564
+ Name => 'SensorData', # sensor data for the 360Fly
565
+ Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/ and $$self{OPTIONS}{ExtractEmbedded}',
566
+ SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Tags360Fly' },
567
+ },
568
+ {
569
+ Name => 'SensorData',
570
+ Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/',
571
+ Notes => 'raw 360Fly sensor data without ExtractEmbedded option',
572
+ RawConv => q{
573
+ $self->WarnOnce('Use the ExtractEmbedded option to decode timed SensorData',3);
574
+ return \$val;
575
+ },
576
+ },
558
577
  { #PH (Canon CR3)
559
578
  Name => 'PreviewImage',
560
579
  Condition => '$$valPt=~/^\xea\xf4\x2b\x5e\x1c\x98\x4b\x88\xb9\xfb\xb7\xdc\x40\x6e\x4d\x16/',
@@ -589,6 +608,11 @@ my %eeBox = (
589
608
  Groups => { 2 => 'Preview' },
590
609
  Binary => 1,
591
610
  },
611
+ 'thm ' => { #PH (70mai A800)
612
+ Name => 'ThumbnailImage',
613
+ Groups => { 2 => 'Preview' },
614
+ Binary => 1,
615
+ },
592
616
  ardt => { #PH
593
617
  Name => 'ARDroneFile',
594
618
  ValueConv => 'length($val) > 4 ? substr($val,4) : $val', # remove length
@@ -667,6 +691,11 @@ my %eeBox = (
667
691
  },
668
692
  # gpsa - seen hex "01 20 00 00" (DuDuBell M1, VSYS M6L)
669
693
  # gsea - 20 bytes hex "05 00's..." (DuDuBell M1) "05 08 02 01 ..." (VSYS M6L)
694
+ 'GPS ' => { # GPS data written by 70mai dashcam (parsed in QuickTimeStream.pl)
695
+ Name => 'GPSDataList2',
696
+ Unknown => 1,
697
+ Binary => 1,
698
+ },
670
699
  );
671
700
 
672
701
  # MPEG-4 'ftyp' atom
@@ -962,7 +991,7 @@ my %eeBox = (
962
991
  %Image::ExifTool::QuickTime::CleanAperture = (
963
992
  PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
964
993
  GROUPS => { 2 => 'Video' },
965
- FORMAT => 'rational64u',
994
+ FORMAT => 'rational64s',
966
995
  0 => 'CleanApertureWidth',
967
996
  1 => 'CleanApertureHeight',
968
997
  2 => 'CleanApertureOffsetX',
@@ -1307,6 +1336,7 @@ my %eeBox = (
1307
1336
  Format => 'fixed32s[9]',
1308
1337
  Notes => 'writable for the video track via the Composite Rotation tag',
1309
1338
  Writable => 1,
1339
+ Protected => 1,
1310
1340
  Permanent => 1,
1311
1341
  # only set rotation if image size is non-zero
1312
1342
  RawConvInv => \&GetMatrixStructure,
@@ -1371,8 +1401,8 @@ my %eeBox = (
1371
1401
  },
1372
1402
  ValueConvInv => q{
1373
1403
  require Image::ExifTool::XMP;
1374
- $val = Image::ExifTool::XMP::FormatXMPDate($val);
1375
- $val =~ s/([-+]\d{2}):(\d{2})$/$1$2/; # remove time zone colon
1404
+ my $tmp = Image::ExifTool::XMP::FormatXMPDate($val);
1405
+ ($val = $tmp) =~ s/([-+]\d{2}):(\d{2})$/$1$2/ if defined $tmp; # remove time zone colon
1376
1406
  return $val;
1377
1407
  },
1378
1408
  PrintConv => '$self->ConvertDateTime($val)',
@@ -1634,7 +1664,7 @@ my %eeBox = (
1634
1664
  Groups => { 2 => 'Time' },
1635
1665
  Notes => q{
1636
1666
  Apple Photos has been reported to show a crazy date/time for some MP4 files
1637
- containing this tag
1667
+ containing this tag, but perhaps only if it is missing a time zone
1638
1668
  }, #forum10690/11125
1639
1669
  Shift => 'Time',
1640
1670
  ValueConv => q{
@@ -1857,6 +1887,25 @@ my %eeBox = (
1857
1887
  ByteOrder => 'LittleEndian',
1858
1888
  },
1859
1889
  },
1890
+ # ---- Garmin ---- (ref PH)
1891
+ uuid => [{
1892
+ Name => 'GarminSoftware', # (NC)
1893
+ Condition => '$$valPt =~ /^VIRBactioncamera/',
1894
+ RawConv => 'substr($val, 16)',
1895
+ RawConvInv => '"VIRBactioncamera$val"',
1896
+ },{
1897
+ # have seen "28 f3 11 e2 b7 91 4f 6f 94 e2 4f 5d ea cb 3c 01" for RicohThetaZ1 accelerometer RADT data (not yet decoded)
1898
+ Name => 'UUID-Unknown',
1899
+ Writable => 0,
1900
+ %unknownInfo,
1901
+ }],
1902
+ pmcc => {
1903
+ Name => 'GarminSettings',
1904
+ ValueConv => 'substr($val, 4)',
1905
+ ValueConvInv => '"\0\0\0\x01$val"',
1906
+ },
1907
+ # hmtp - "\0\0\0\x01" followed by 408 bytes of zero
1908
+ # vrin - "\0\0\0\x01" followed by 8 bytes of zero
1860
1909
  # ---- GoPro ---- (ref PH)
1861
1910
  GoPr => 'GoProType', # (Hero3+)
1862
1911
  FIRM => { Name => 'FirmwareVersion', Avoid => 1 }, # (Hero4)
@@ -1870,7 +1919,7 @@ my %eeBox = (
1870
1919
  # SETT? 12 bytes (Hero4)
1871
1920
  # MUID? 32 bytes (Hero4, starts with serial number hash)
1872
1921
  # HMMT? 404 bytes (Hero4, all zero)
1873
- # BCID? 26 bytes (Hero5, all zero)
1922
+ # BCID? 26 bytes (Hero5, all zero), 36 bytes GoPro Max
1874
1923
  # GUMI? 16 bytes (Hero5)
1875
1924
  "FOV\0" => 'FieldOfView', #forum8938 (Hero2) seen: "Wide"
1876
1925
  GPMF => {
@@ -2040,6 +2089,63 @@ my %eeBox = (
2040
2089
  ProcessProc => \&Image::ExifTool::ProcessTIFF, # (because ProcessMOV is default)
2041
2090
  },
2042
2091
  },
2092
+ '@mak' => { Name => 'Make', Avoid => 1 },
2093
+ '@mod' => { Name => 'Model', Avoid => 1 },
2094
+ '@swr' => { Name => 'SoftwareVersion', Avoid => 1 },
2095
+ '@day' => {
2096
+ Name => 'ContentCreateDate',
2097
+ Notes => q{
2098
+ some stupid Ricoh programmer used the '@' symbol instead of the copyright
2099
+ symbol in these tag ID's for the Ricoh Theta Z1 and maybe other models
2100
+ },
2101
+ Groups => { 2 => 'Time' },
2102
+ Shift => 'Time',
2103
+ Avoid => 1,
2104
+ # handle values in the form "2010-02-12T13:27:14-0800"
2105
+ ValueConv => q{
2106
+ require Image::ExifTool::XMP;
2107
+ $val = Image::ExifTool::XMP::ConvertXMPDate($val);
2108
+ $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary
2109
+ return $val;
2110
+ },
2111
+ ValueConvInv => q{
2112
+ require Image::ExifTool::XMP;
2113
+ my $tmp = Image::ExifTool::XMP::FormatXMPDate($val);
2114
+ ($val = $tmp) =~ s/([-+]\d{2}):(\d{2})$/$1$2/ if defined $tmp; # remove time zone colon
2115
+ return $val;
2116
+ },
2117
+ PrintConv => '$self->ConvertDateTime($val)',
2118
+ PrintConvInv => '$self->InverseDateTime($val)',
2119
+ },
2120
+ '@xyz' => { #PH (iPhone 3GS)
2121
+ Name => 'GPSCoordinates',
2122
+ Groups => { 2 => 'Location' },
2123
+ Avoid => 1,
2124
+ ValueConv => \&ConvertISO6709,
2125
+ ValueConvInv => \&ConvInvISO6709,
2126
+ PrintConv => \&PrintGPSCoordinates,
2127
+ PrintConvInv => \&PrintInvGPSCoordinates,
2128
+ },
2129
+ # RDT1 - pairs of int32u_BE, starting at byte 8: "458275 471846"
2130
+ # RDT2 - pairs of int32u_BE, starting at byte 8: "472276 468526"
2131
+ # RDT3 - pairs of int32u_BE, starting at byte 8: "876603 482191"
2132
+ # RDT4 - pairs of int32u_BE, starting at byte 8: "1955 484612"
2133
+ # RDT6 - empty
2134
+ # RDT7 - empty
2135
+ # RDT8 - empty
2136
+ # RDT9 - only 16-byte header?
2137
+ # the boxes below all have a similar header (little-endian):
2138
+ # 0 int32u - number of records
2139
+ # 4 ? - "1e 00"
2140
+ # 6 int16u - record length in bytes
2141
+ # 8 ? - "23 01 00 00 00 00 00 00"
2142
+ # 16 - start of records (each record ends in an int64u timestamp in ns)
2143
+ # RDTA - float[4],ts: "-0.31289672 -0.2245330 11.303817 0 775.780"
2144
+ # RDTB - float[4],ts: "-0.04841613 -0.2166595 0.0724792 0 775.780"
2145
+ # RDTC - float[4],ts: "27.60925 -27.10037 -13.27285 0 775.829"
2146
+ # RDTD - int16s[3],ts: "353 -914 16354 0 775.829"
2147
+ # RDTG - ts: "775.825"
2148
+ # RDTI - float[4],ts: "0.00165951 0.005770059 0.06838259 0.1744695 775.862"
2043
2149
  # ---- Samsung ----
2044
2150
  vndr => 'Vendor', #PH (Samsung PL70)
2045
2151
  SDLN => 'PlayMode', #PH (NC, Samsung ST80 "SEQ_PLAY")
@@ -2450,7 +2556,23 @@ my %eeBox = (
2450
2556
  Start => 4,
2451
2557
  },
2452
2558
  },
2453
- # idat
2559
+ idat => {
2560
+ Name => 'MetaImageSize', #PH (NC)
2561
+ Format => 'int16u',
2562
+ # (don't know what the first two numbers are for)
2563
+ PrintConv => '$val =~ s/^(\d+) (\d+) (\d+) (\d+)/${3}x$4/; $val',
2564
+ },
2565
+ uuid => [
2566
+ { #PH (Canon R5/R6 HIF)
2567
+ Name => 'MetaVersion', # (NC)
2568
+ Condition => '$$valPt=~/^\x85\xc0\xb6\x87\x82\x0f\x11\xe0\x81\x11\xf4\xce\x46\x2b\x6a\x48/',
2569
+ RawConv => 'substr($val, 0x14)',
2570
+ },
2571
+ {
2572
+ Name => 'UUID-Unknown',
2573
+ %unknownInfo,
2574
+ },
2575
+ ],
2454
2576
  );
2455
2577
 
2456
2578
  # additional metadata container (ref ISO14496-12:2015)
@@ -2516,6 +2638,7 @@ my %eeBox = (
2516
2638
  Name => 'Rotation',
2517
2639
  Format => 'int8u',
2518
2640
  Writable => 'int8u',
2641
+ Protected => 1,
2519
2642
  ValueConv => '$val * 90',
2520
2643
  ValueConvInv => 'int($val / 90 + 0.5)',
2521
2644
  },
@@ -2547,6 +2670,7 @@ my %eeBox = (
2547
2670
  Name => 'PixelAspectRatio',
2548
2671
  Format => 'int32u',
2549
2672
  Writable => 'int32u',
2673
+ Protected => 1,
2550
2674
  },
2551
2675
  rloc => {
2552
2676
  Name => 'RelativeLocation',
@@ -2555,7 +2679,7 @@ my %eeBox = (
2555
2679
  },
2556
2680
  clap => {
2557
2681
  Name => 'CleanAperture',
2558
- Format => 'rational64u',
2682
+ Format => 'rational64s',
2559
2683
  Notes => '4 numbers: width, height, left and top',
2560
2684
  },
2561
2685
  hvcC => {
@@ -2760,12 +2884,16 @@ my %eeBox = (
2760
2884
  WRITE_PROC => \&WriteQuickTime,
2761
2885
  GROUPS => { 2 => 'Image' },
2762
2886
  # (Note: ExifTool's ItemRefVersion may be used to test the iref version number)
2763
- # dimg - DerivedImage
2764
- # thmb - Thumbnail
2765
- # auxl - AuxiliaryImage
2887
+ NOTES => q{
2888
+ The Item reference entries listed in the table below contain information about
2889
+ the associations between items in the file. This information is used by
2890
+ ExifTool, but these entries are not extracted as tags.
2891
+ },
2892
+ dimg => { Name => 'DerivedImageRef', RawConv => 'undef' },
2893
+ thmb => { Name => 'ThumbnailRef', RawConv => 'undef' },
2894
+ auxl => { Name => 'AuxiliaryImageRef', RawConv => 'undef' },
2766
2895
  cdsc => {
2767
2896
  Name => 'ContentDescribes',
2768
- Notes => 'parsed, but not extracted as a tag',
2769
2897
  RawConv => \&ParseContentDescribes,
2770
2898
  WriteHook => \&ParseContentDescribes,
2771
2899
  },
@@ -2893,10 +3021,25 @@ my %eeBox = (
2893
3021
  "\xa9grp" => 'Grouping',
2894
3022
  "\xa9lyr" => 'Lyrics',
2895
3023
  "\xa9nam" => 'Title',
2896
- # "\xa9st3" ? #10
2897
3024
  "\xa9too" => 'Encoder',
2898
3025
  "\xa9trk" => 'Track',
2899
3026
  "\xa9wrt" => 'Composer',
3027
+ #
3028
+ # the following tags written by AtomicParsley 0.9.6
3029
+ # (ref https://exiftool.org/forum/index.php?topic=11455.0)
3030
+ #
3031
+ "\xa9st3" => 'Subtitle',
3032
+ "\xa9con" => 'Conductor',
3033
+ "\xa9sol" => 'Soloist',
3034
+ "\xa9arg" => 'Arranger',
3035
+ "\xa9ope" => 'OriginalArtist',
3036
+ "\xa9dir" => 'Director',
3037
+ "\xa9ard" => 'ArtDirector',
3038
+ "\xa9sne" => 'SoundEngineer',
3039
+ "\xa9prd" => 'Producer',
3040
+ "\xa9xpd" => 'ExecutiveProducer',
3041
+ sdes => 'StoreDescription',
3042
+ #
2900
3043
  '----' => {
2901
3044
  Name => 'iTunesInfo',
2902
3045
  SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::iTunesInfo' },
@@ -2905,18 +3048,29 @@ my %eeBox = (
2905
3048
  covr => { Name => 'CoverArt', Groups => { 2 => 'Preview' } },
2906
3049
  cpil => { #10
2907
3050
  Name => 'Compilation',
2908
- Format => 'int8u', #23
3051
+ Format => 'int8u', #27 (ref 23 contradicts what AtomicParsley actually writes, which is int8s)
3052
+ Writable => 'int8s',
2909
3053
  PrintConv => { 0 => 'No', 1 => 'Yes' },
2910
3054
  },
2911
3055
  disk => {
2912
3056
  Name => 'DiskNumber',
2913
3057
  Format => 'undef', # (necessary to prevent decoding as string!)
2914
- ValueConv => 'length($val) >= 6 ? join(" of ",unpack("x2nn",$val)) : \$val',
2915
- ValueConvInv => 'my @a = split / of /, $val; @a==2 ? pack("n3",0,@a) : undef',
3058
+ ValueConv => q{
3059
+ return \$val unless length($val) >= 6;
3060
+ my @a = unpack 'x2nn', $val;
3061
+ return $a[1] ? join(' of ', @a) : $a[0];
3062
+ },
3063
+ ValueConvInv => q{
3064
+ my @a = $val =~ /\d+/g;
3065
+ return undef if @a == 0 or @a > 2;
3066
+ push @a, 0 if @a == 1;
3067
+ return pack('n3', 0, @a);
3068
+ },
2916
3069
  },
2917
3070
  pgap => { #10
2918
3071
  Name => 'PlayGap',
2919
3072
  Format => 'int8u', #23
3073
+ Writable => 'int8s', #27
2920
3074
  PrintConv => {
2921
3075
  0 => 'Insert Gap',
2922
3076
  1 => 'No Gap',
@@ -2924,13 +3078,26 @@ my %eeBox = (
2924
3078
  },
2925
3079
  tmpo => {
2926
3080
  Name => 'BeatsPerMinute',
2927
- Format => 'int16u', # marked as boolean but really int16u in my sample
3081
+ # marked as boolean but really int16u in my sample
3082
+ # (but written as int16s by iTunes and AtomicParsley, ref forum11506)
3083
+ Format => 'int16u',
3084
+ Writable => 'int16s',
2928
3085
  },
2929
3086
  trkn => {
2930
3087
  Name => 'TrackNumber',
2931
3088
  Format => 'undef', # (necessary to prevent decoding as string!)
2932
- ValueConv => 'length($val) >= 6 ? join(" of ",unpack("x2nn",$val)) : \$val',
2933
- ValueConvInv => 'my @a = split / of /, $val; @a==2 ? pack("n3",0,@a) : undef',
3089
+ ValueConv => q{
3090
+ return \$val unless length($val) >= 6;
3091
+ my @a = unpack 'x2nn', $val;
3092
+ return $a[1] ? join(' of ', @a) : $a[0];
3093
+ },
3094
+ # (see forum11501 for discussion about the format used)
3095
+ ValueConvInv => q{
3096
+ my @a = $val =~ /\d+/g;
3097
+ return undef if @a == 0 or @a > 2;
3098
+ push @a, 0 if @a == 1;
3099
+ return pack('n4', 0, @a, 0);
3100
+ },
2934
3101
  },
2935
3102
  #
2936
3103
  # Note: it is possible that the tags below are not being decoded properly
@@ -2939,6 +3106,7 @@ my %eeBox = (
2939
3106
  akID => { #10
2940
3107
  Name => 'AppleStoreAccountType',
2941
3108
  Format => 'int8u', #24
3109
+ Writable => 'int8s', #27
2942
3110
  PrintConv => {
2943
3111
  0 => 'iTunes',
2944
3112
  1 => 'AOL',
@@ -2949,12 +3117,14 @@ my %eeBox = (
2949
3117
  atID => { #10 (or TV series)
2950
3118
  Name => 'AlbumTitleID',
2951
3119
  Format => 'int32u',
3120
+ Writable => 'int32s', #27
2952
3121
  },
2953
3122
  auth => { Name => 'Author', Groups => { 2 => 'Author' } },
2954
3123
  catg => 'Category', #7
2955
3124
  cnID => { #10
2956
3125
  Name => 'AppleStoreCatalogID',
2957
3126
  Format => 'int32u',
3127
+ Writable => 'int32s', #27
2958
3128
  },
2959
3129
  cprt => { Name => 'Copyright', Groups => { 2 => 'Author' } },
2960
3130
  dscp => { Name => 'Description', Avoid => 1 },
@@ -2962,22 +3132,28 @@ my %eeBox = (
2962
3132
  gnre => { #10
2963
3133
  Name => 'Genre',
2964
3134
  Avoid => 1,
2965
- # (Note: not written as int16u if numerical, although it should be)
3135
+ # (Note: see https://exiftool.org/forum/index.php?topic=11537.0)
3136
+ Format => 'undef',
3137
+ ValueConv => 'unpack("n",$val)',
3138
+ ValueConvInv => '$val =~ /^\d+$/ ? pack("n",$val) : undef',
2966
3139
  PrintConv => q{
2967
3140
  return $val unless $val =~ /^\d+$/;
2968
3141
  require Image::ExifTool::ID3;
2969
3142
  Image::ExifTool::ID3::PrintGenre($val - 1); # note the "- 1"
2970
3143
  },
2971
3144
  PrintConvInv => q{
3145
+ return $val if $val =~ /^[0-9]+$/;
2972
3146
  require Image::ExifTool::ID3;
2973
3147
  my $id = Image::ExifTool::ID3::GetGenreID($val);
2974
- return defined $id ? $id : $val;
2975
- },
3148
+ return unless defined $id and $id =~ /^\d+$/;
3149
+ return $id + 1;
3150
+ },
2976
3151
  },
2977
3152
  egid => 'EpisodeGlobalUniqueID', #7
2978
3153
  geID => { #10
2979
3154
  Name => 'GenreID',
2980
3155
  Format => 'int32u',
3156
+ Writable => 'int32s', #27
2981
3157
  SeparateTable => 1,
2982
3158
  # the following lookup is based on http://itunes.apple.com/WebObjects/MZStoreServices.woa/ws/genres
2983
3159
  # (see scripts/parse_genre to parse genre JSON file from above)
@@ -5630,6 +5806,7 @@ my %eeBox = (
5630
5806
  hdvd => { #10
5631
5807
  Name => 'HDVideo',
5632
5808
  Format => 'int8u', #24
5809
+ Writable => 'int8s', #27
5633
5810
  PrintConv => { 0 => 'No', 1 => 'Yes' },
5634
5811
  },
5635
5812
  keyw => 'Keyword', #7
@@ -5637,18 +5814,21 @@ my %eeBox = (
5637
5814
  pcst => { #7
5638
5815
  Name => 'Podcast',
5639
5816
  Format => 'int8u', #23
5817
+ Writable => 'int8s', #27
5640
5818
  PrintConv => { 0 => 'No', 1 => 'Yes' },
5641
5819
  },
5642
5820
  perf => 'Performer',
5643
5821
  plID => { #10 (or TV season)
5644
5822
  Name => 'PlayListID',
5645
5823
  Format => 'int8u', # actually int64u, but split it up
5824
+ Writable => 'int32s', #27
5646
5825
  },
5647
5826
  purd => 'PurchaseDate', #7
5648
5827
  purl => 'PodcastURL', #7
5649
5828
  rtng => { #10
5650
5829
  Name => 'Rating',
5651
5830
  Format => 'int8u', #23
5831
+ Writable => 'int8s', #27
5652
5832
  PrintConv => {
5653
5833
  0 => 'none',
5654
5834
  1 => 'Explicit',
@@ -5659,6 +5839,7 @@ my %eeBox = (
5659
5839
  sfID => { #10
5660
5840
  Name => 'AppleStoreCountry',
5661
5841
  Format => 'int32u',
5842
+ Writable => 'int32s', #27
5662
5843
  SeparateTable => 1,
5663
5844
  PrintConv => { #21
5664
5845
  143441 => 'United States', # US
@@ -5827,6 +6008,7 @@ my %eeBox = (
5827
6008
  stik => { #10
5828
6009
  Name => 'MediaType',
5829
6010
  Format => 'int8u', #23
6011
+ Writable => 'int8s', #27
5830
6012
  PrintConvColumns => 2,
5831
6013
  PrintConv => { #(http://weblog.xanga.com/gryphondwb/615474010/iphone-ringtones---what-did-itunes-741-really-do.html)
5832
6014
  0 => 'Movie (old)', #forum9059 (was Movie)
@@ -5848,6 +6030,7 @@ my %eeBox = (
5848
6030
  tves => { #7/10
5849
6031
  Name => 'TVEpisode',
5850
6032
  Format => 'int32u',
6033
+ Writable => 'int32s', #27
5851
6034
  },
5852
6035
  tvnn => 'TVNetworkName', #7
5853
6036
  tvsh => 'TVShow', #10
@@ -5858,7 +6041,8 @@ my %eeBox = (
5858
6041
  yrrc => 'Year', #(ffmpeg source)
5859
6042
  itnu => { #PH (iTunes 10.5)
5860
6043
  Name => 'iTunesU',
5861
- Format => 'int8s',
6044
+ Format => 'int8u', #27
6045
+ Writable => 'int8s', #27
5862
6046
  Description => 'iTunes U',
5863
6047
  PrintConv => { 0 => 'No', 1 => 'Yes' },
5864
6048
  },
@@ -5908,6 +6092,27 @@ my %eeBox = (
5908
6092
  PrintConv => \&PrintGPSCoordinates,
5909
6093
  PrintConvInv => \&PrintInvGPSCoordinates,
5910
6094
  },
6095
+ # the following tags written by iTunes 12.5.1.21
6096
+ # (ref https://www.ventismedia.com/mantis/view.php?id=14963
6097
+ # https://community.mp3tag.de/t/x-mp4-new-tag-problems/19488)
6098
+ "\xa9wrk" => 'Work', #PH
6099
+ "\xa9mvn" => 'MovementName', #PH
6100
+ "\xa9mvi" => { #PH
6101
+ Name => 'MovementNumber',
6102
+ Format => 'int16u', #27
6103
+ Writable => 'int16s', #27
6104
+ },
6105
+ "\xa9mvc" => { #PH
6106
+ Name => 'MovementCount',
6107
+ Format => 'int16u', #27
6108
+ Writable => 'int16s', #27
6109
+ },
6110
+ shwm => { #PH
6111
+ Name => 'ShowMovement',
6112
+ Format => 'int8u', #27
6113
+ Writable => 'int8s', #27
6114
+ PrintConv => { 0 => 'No', 1 => 'Yes' },
6115
+ },
5911
6116
  );
5912
6117
 
5913
6118
  # tag decoded from timed face records
@@ -6127,6 +6332,21 @@ my %eeBox = (
6127
6332
  'detected-face.roll-angle' => { Name => 'DetectedFaceRollAngle', Writable => 0 },
6128
6333
  # (fiel)com.apple.quicktime.detected-face.yaw-angle (dtyp=23, float)
6129
6334
  'detected-face.yaw-angle' => { Name => 'DetectedFaceYawAngle', Writable => 0 },
6335
+ #
6336
+ # seen in Apple ProRes RAW file
6337
+ #
6338
+ # (mdta)com.apple.proapps.manufacturer (eg. "Sony")
6339
+ # (mdta)com.apple.proapps.exif.{Exif}.FNumber (float, eg. 1.0)
6340
+ # (mdta)org.smpte.rdd18.lens.irisfnumber (eg. "F1.0")
6341
+ # (mdta)com.apple.proapps.exif.{Exif}.ShutterSpeedValue (float, eg. 1.006)
6342
+ # (mdta)org.smpte.rdd18.camera.shutterspeed_angle (eg. "179.2deg")
6343
+ # (mdta)org.smpte.rdd18.camera.neutraldensityfilterwheelsetting (eg. "ND1")
6344
+ # (mdta)org.smpte.rdd18.camera.whitebalance (eg. "4300K")
6345
+ # (mdta)com.apple.proapps.exif.{Exif}.ExposureIndex (float, eg. 4000)
6346
+ # (mdta)org.smpte.rdd18.camera.isosensitivity (eg. "4000")
6347
+ # (mdta)com.apple.proapps.image.{TIFF}.Make (eg. "Atmos")
6348
+ # (mdta)com.apple.proapps.image.{TIFF}.Model (eg. "ShogunInferno")
6349
+ # (mdta)com.apple.proapps.image.{TIFF}.Software (eg. "9.0")
6130
6350
  );
6131
6351
 
6132
6352
  # iTunes info ('----') atoms
@@ -6667,7 +6887,7 @@ my %eeBox = (
6667
6887
  #
6668
6888
  # AudioFormat Offset Child atoms
6669
6889
  # ----------- ------ ----------------
6670
- # mp4a 52 * wave, chan, esds, SA3D(Insta360 spherical video params?)
6890
+ # mp4a 52 * wave, chan, esds, SA3D(Insta360 spherical video params?,also GoPro Max)
6671
6891
  # in24 52 wave, chan
6672
6892
  # "ms\0\x11" 52 wave
6673
6893
  # sowt 52 chan
@@ -6704,6 +6924,7 @@ my %eeBox = (
6704
6924
  # alac - 28 bytes
6705
6925
  # adrm - AAX DRM atom? 148 bytes
6706
6926
  # aabd - AAX unknown 17kB (contains 'aavd' strings)
6927
+ # SA3D - written by Garmin VIRB360
6707
6928
  );
6708
6929
 
6709
6930
  # AMR decode config box (ref 3)
@@ -6734,13 +6955,28 @@ my %eeBox = (
6734
6955
  Name => 'SchemeInfo',
6735
6956
  SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::SchemeInfo' },
6736
6957
  },
6958
+ enda => {
6959
+ Name => 'Endianness',
6960
+ Format => 'int16u',
6961
+ PrintConv => {
6962
+ 0 => 'Big-endian (Motorola, MM)',
6963
+ 1 => 'Little-endian (Intel, II)',
6964
+ },
6965
+ },
6737
6966
  # skcr
6738
- # enda
6739
6967
  );
6740
6968
 
6741
6969
  %Image::ExifTool::QuickTime::Wave = (
6742
6970
  PROCESS_PROC => \&ProcessMOV,
6743
6971
  frma => 'PurchaseFileFormat',
6972
+ enda => {
6973
+ Name => 'Endianness',
6974
+ Format => 'int16u',
6975
+ PrintConv => {
6976
+ 0 => 'Big-endian (Motorola, MM)',
6977
+ 1 => 'Little-endian (Intel, II)',
6978
+ },
6979
+ },
6744
6980
  # "ms\0\x11" - 20 bytes
6745
6981
  );
6746
6982
 
@@ -7175,6 +7411,20 @@ my %eeBox = (
7175
7411
  #
7176
7412
  ftab => { Name => 'FontTable', Format => 'undef', ValueConv => 'substr($val, 5)' },
7177
7413
  name => { Name => 'OtherName', Format => 'undef', ValueConv => 'substr($val, 4)' },
7414
+ # mrlh = GM header?
7415
+ # mrlv = GM data
7416
+ # mrld = GM data (448-byte records):
7417
+ # 0 - int32u count
7418
+ # 4 - int32u ? (related to units) 0=none,1=m/km,2=L,3=kph,4=C,7=deg,8=rpm,9=kPa,10=G,11=V,15=Nm,16=%
7419
+ # 8 - int32u ? (0,1,3,4,5)
7420
+ # 12 - string[64] units
7421
+ # 76 - int32u ? (1,3,7,15)
7422
+ # 80 - int32u 0
7423
+ # 84 - undef[4] ?
7424
+ # 88 - int16u[6] ?
7425
+ # 100 - undef[32] ?
7426
+ # 132 - string[64] measurement name
7427
+ # 196 - string[64] measurement name
7178
7428
  );
7179
7429
 
7180
7430
  # MP4 data information box (ref 5)
@@ -7471,6 +7721,7 @@ my %eeBox = (
7471
7721
  1 => 'QuickTime:HandlerType',
7472
7722
  },
7473
7723
  Writable => 1,
7724
+ Protected => 1,
7474
7725
  WriteAlso => {
7475
7726
  MatrixStructure => 'Image::ExifTool::QuickTime::GetRotationMatrix($val)',
7476
7727
  },
@@ -8305,7 +8556,7 @@ sub EEWarn($)
8305
8556
  #------------------------------------------------------------------------------
8306
8557
  # Get quicktime format from flags word
8307
8558
  # Inputs: 0) quicktime atom flags, 1) data length
8308
- # Returns: Exiftool format string
8559
+ # Returns: ExifTool format string
8309
8560
  sub QuickTimeFormat($$)
8310
8561
  {
8311
8562
  my ($flags, $len) = @_;
@@ -8532,7 +8783,7 @@ sub ProcessKeys($$$)
8532
8783
  my $ns = substr($$dataPt, $pos + 4, 4);
8533
8784
  my $tag = substr($$dataPt, $pos + 8, $len - 8);
8534
8785
  $tag =~ s/\0.*//s; # truncate at null
8535
- $tag =~ s/^com\.apple\.quicktime\.// if $ns eq 'mdta'; # remove apple quicktime domain
8786
+ $tag =~ s/^com\.(apple\.quicktime\.)?// if $ns eq 'mdta'; # remove apple quicktime domain
8536
8787
  $tag = "Tag_$ns" unless $tag;
8537
8788
  # (I have some samples where the tag is a reversed ItemList or UserData tag ID)
8538
8789
  my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
@@ -8564,9 +8815,10 @@ sub ProcessKeys($$$)
8564
8815
  $$newInfo{Groups} = $groups ? { %$groups } : { };
8565
8816
  $$newInfo{Groups}{$_} or $$newInfo{Groups}{$_} = $$tagTablePtr{GROUPS}{$_} foreach 0..2;
8566
8817
  $$newInfo{Groups}{1} = 'Keys';
8567
- } elsif ($tag =~ /^[-\w. ]+$/) {
8818
+ } elsif ($tag =~ /^[-\w. ]+$/ or $tag =~ /\w{4}/) {
8568
8819
  # create info for tags with reasonable id's
8569
8820
  my $name = ucfirst $tag;
8821
+ $name =~ tr/-0-9a-zA-Z_. //dc;
8570
8822
  $name =~ s/[. ]+(.?)/\U$1/g;
8571
8823
  $name =~ s/_([a-z])/_\U$1/g;
8572
8824
  $name =~ s/([a-z])_([A-Z])/$1$2/g;
@@ -8587,7 +8839,7 @@ sub ProcessKeys($$$)
8587
8839
  if ($newInfo) {
8588
8840
  AddTagToTable($itemList, $id, $newInfo);
8589
8841
  $msg or $msg = '';
8590
- $out and print $out "$$et{INDENT}Added ItemList Tag $id = $tag$msg\n";
8842
+ $out and print $out "$$et{INDENT}Added ItemList Tag $id = ($ns) $tag$msg\n";
8591
8843
  }
8592
8844
  $pos += $len;
8593
8845
  ++$index;
@@ -9042,10 +9294,10 @@ ItemID: foreach $id (keys %$items) {
9042
9294
  }
9043
9295
  }
9044
9296
  if ($ctry or $lang) {
9045
- $lang = GetLangCode($lang, $ctry);
9046
- if ($lang) {
9297
+ my $langCode = GetLangCode($lang, $ctry);
9298
+ if ($langCode) {
9047
9299
  # get tagInfo for other language
9048
- $langInfo = GetLangInfoQT($et, $tagInfo, $lang);
9300
+ $langInfo = GetLangInfoQT($et, $tagInfo, $langCode);
9049
9301
  # save other language tag ID's so we can delete later if necessary
9050
9302
  if ($langInfo) {
9051
9303
  $$tagInfo{OtherLang} or $$tagInfo{OtherLang} = [ ];
@@ -9062,7 +9314,7 @@ ItemID: foreach $id (keys %$items) {
9062
9314
  Size => $len,
9063
9315
  Format => $format,
9064
9316
  Index => $index,
9065
- Extra => sprintf(", Type='${type}', Flags=0x%x%s",$flags,($lang ? ", Lang=$lang" : '')),
9317
+ Extra => sprintf(", Type='${type}', Flags=0x%x, Lang=0x%.4x",$flags,$lang),
9066
9318
  ) if $verbose;
9067
9319
  # use "Keys" in path instead of ItemList if this was defined by a Keys tag
9068
9320
  my $isKey = $$tagInfo{Groups} && $$tagInfo{Groups}{1} && $$tagInfo{Groups}{1} eq 'Keys';