exiftool_vendored 11.99.0 → 12.06.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.

Potentially problematic release.


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

Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +119 -2
  3. data/bin/MANIFEST +5 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +32 -32
  7. data/bin/exiftool +55 -50
  8. data/bin/lib/Image/ExifTool.pm +155 -109
  9. data/bin/lib/Image/ExifTool.pod +103 -77
  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 +11 -6
  13. data/bin/lib/Image/ExifTool/Canon.pm +2 -1
  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 +16 -3
  17. data/bin/lib/Image/ExifTool/Exif.pm +15 -6
  18. data/bin/lib/Image/ExifTool/Font.pm +9 -2
  19. data/bin/lib/Image/ExifTool/GIF.pm +5 -0
  20. data/bin/lib/Image/ExifTool/GeoTiff.pm +2 -0
  21. data/bin/lib/Image/ExifTool/GoPro.pm +10 -1
  22. data/bin/lib/Image/ExifTool/H264.pm +1 -1
  23. data/bin/lib/Image/ExifTool/ID3.pm +86 -12
  24. data/bin/lib/Image/ExifTool/Lang/de.pm +3 -1
  25. data/bin/lib/Image/ExifTool/Lang/es.pm +1 -1
  26. data/bin/lib/Image/ExifTool/M2TS.pm +1 -1
  27. data/bin/lib/Image/ExifTool/MacOS.pm +1 -1
  28. data/bin/lib/Image/ExifTool/Minolta.pm +3 -2
  29. data/bin/lib/Image/ExifTool/Nikon.pm +134 -15
  30. data/bin/lib/Image/ExifTool/Olympus.pm +34 -17
  31. data/bin/lib/Image/ExifTool/PNG.pm +14 -3
  32. data/bin/lib/Image/ExifTool/PPM.pm +5 -5
  33. data/bin/lib/Image/ExifTool/Panasonic.pm +147 -13
  34. data/bin/lib/Image/ExifTool/PanasonicRaw.pm +33 -0
  35. data/bin/lib/Image/ExifTool/Parrot.pm +2 -1
  36. data/bin/lib/Image/ExifTool/Pentax.pm +2 -1
  37. data/bin/lib/Image/ExifTool/Photoshop.pm +2 -1
  38. data/bin/lib/Image/ExifTool/QuickTime.pm +204 -27
  39. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +355 -19
  40. data/bin/lib/Image/ExifTool/README +20 -19
  41. data/bin/lib/Image/ExifTool/Ricoh.pm +19 -1
  42. data/bin/lib/Image/ExifTool/Shift.pl +1 -0
  43. data/bin/lib/Image/ExifTool/SigmaRaw.pm +40 -33
  44. data/bin/lib/Image/ExifTool/Sony.pm +376 -11
  45. data/bin/lib/Image/ExifTool/TagLookup.pm +1949 -1872
  46. data/bin/lib/Image/ExifTool/TagNames.pod +329 -53
  47. data/bin/lib/Image/ExifTool/Validate.pm +4 -4
  48. data/bin/lib/Image/ExifTool/WriteExif.pl +1 -0
  49. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +23 -15
  50. data/bin/lib/Image/ExifTool/Writer.pl +44 -21
  51. data/bin/lib/Image/ExifTool/XMP.pm +41 -4
  52. data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
  53. data/bin/lib/Image/ExifTool/ZISRAW.pm +123 -0
  54. data/bin/perl-Image-ExifTool.spec +31 -31
  55. data/lib/exiftool_vendored/version.rb +1 -1
  56. metadata +4 -3
@@ -531,14 +531,45 @@ my %panasonicWhiteBalance = ( #forum9396
531
531
  PrintConv => '"$val mm"',
532
532
  PrintConvInv => '$val=~s/\s*mm$//;$val',
533
533
  },
534
+ # 0x1300 - incident light value? (ref forum11395)
535
+ 0x1301 => { #forum11395
536
+ Name => 'ApertureValue',
537
+ Writable => 'int16s',
538
+ Priority => 0,
539
+ ValueConv => '2 ** ($val / 512)',
540
+ ValueConvInv => '$val>0 ? 512*log($val)/log(2) : 0',
541
+ PrintConv => 'sprintf("%.1f",$val)',
542
+ PrintConvInv => '$val',
543
+ },
544
+ 0x1302 => { #forum11395
545
+ Name => 'ShutterSpeedValue',
546
+ Writable => 'int16s',
547
+ Priority => 0,
548
+ ValueConv => 'abs($val/256)<100 ? 2**(-$val/256) : 0',
549
+ ValueConvInv => '$val>0 ? -256*log($val)/log(2) : -25600',
550
+ PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
551
+ PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)',
552
+ },
553
+ 0x1303 => { #forum11395
554
+ Name => 'SensitivityValue',
555
+ Writable => 'int16s',
556
+ ValueConv => '$val / 256',
557
+ ValueConvInv => 'int($val * 256)',
558
+ },
534
559
  0x1305 => { #forum9384
535
560
  Name => 'HighISOMode',
536
561
  Writable => 'int16u',
537
562
  RawConv => '$val || undef',
538
563
  PrintConv => { 1 => 'On', 2 => 'Off' },
539
564
  },
565
+ # 0x1306 EV for some models like the GX8 (forum11395)
540
566
  # 0x140b - scaled overall black level? (ref forum9281)
541
567
  # 0x1411 - scaled black level per channel difference (ref forum9281)
568
+ 0x1412 => { #forum11397
569
+ Name => 'FacesDetected',
570
+ Writable => 'int8u',
571
+ PrintConv => { 0 => 'No', 1 => 'Yes' },
572
+ },
542
573
  # 0x2000 - WB tungsten=3, daylight=4 (ref forum9467)
543
574
  # 0x2009 - scaled black level per channel (ref forum9281)
544
575
  # 0x3000-0x310b - red/blue balances * 1024 (ref forum9467)
@@ -600,6 +631,8 @@ my %panasonicWhiteBalance = ( #forum9396
600
631
  Writable => 'int8u',
601
632
  PrintConv => \%Image::ExifTool::Exif::orientation,
602
633
  },
634
+ # 0x3504 = Tag 0x1301+0x1302-0x1303 (Bv = Av+Tv-Sv) (forum11395)
635
+ # 0x3505 - same as 0x1300 (forum11395)
603
636
  0x3600 => { #forum9396
604
637
  Name => 'WhiteBalanceDetected',
605
638
  Writable => 'int8u',
@@ -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.32';
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
@@ -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.49';
50
+ $VERSION = '2.52';
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
  );
@@ -418,7 +421,8 @@ my %eeBox = (
418
421
  sbtl => { %eeStd },
419
422
  data => { %eeStd },
420
423
  camm => { %eeStd }, # (Insta360)
421
- '' => { 'gps ' => 'moov' }, # (no handler -- in top level 'moov' box)
424
+ ctbx => { %eeStd }, # (GM cars)
425
+ '' => { 'gps ' => 'moov', 'GPS ' => 'main' }, # (no handler -- in top level 'moov' box, and main)
422
426
  );
423
427
 
424
428
  # QuickTime atoms
@@ -555,6 +559,20 @@ my %eeBox = (
555
559
  Start => 16,
556
560
  },
557
561
  },
562
+ { # (ref https://github.com/JamesHeinrich/getID3/blob/master/getid3/module.audio-video.quicktime.php)
563
+ Name => 'SensorData', # sensor data for the 360Fly
564
+ Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/ and $$self{OPTIONS}{ExtractEmbedded}',
565
+ SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Tags360Fly' },
566
+ },
567
+ {
568
+ Name => 'SensorData',
569
+ Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/',
570
+ Notes => 'raw 360Fly sensor data without ExtractEmbedded option',
571
+ RawConv => q{
572
+ $self->WarnOnce('Use the ExtractEmbedded option to decode timed SensorData',3);
573
+ return \$val;
574
+ },
575
+ },
558
576
  { #PH (Canon CR3)
559
577
  Name => 'PreviewImage',
560
578
  Condition => '$$valPt=~/^\xea\xf4\x2b\x5e\x1c\x98\x4b\x88\xb9\xfb\xb7\xdc\x40\x6e\x4d\x16/',
@@ -667,6 +685,11 @@ my %eeBox = (
667
685
  },
668
686
  # gpsa - seen hex "01 20 00 00" (DuDuBell M1, VSYS M6L)
669
687
  # gsea - 20 bytes hex "05 00's..." (DuDuBell M1) "05 08 02 01 ..." (VSYS M6L)
688
+ 'GPS ' => { # GPS data written by 70mai dashcam (parsed in QuickTimeStream.pl)
689
+ Name => 'GPSDataList2',
690
+ Unknown => 1,
691
+ Binary => 1,
692
+ },
670
693
  );
671
694
 
672
695
  # MPEG-4 'ftyp' atom
@@ -962,7 +985,7 @@ my %eeBox = (
962
985
  %Image::ExifTool::QuickTime::CleanAperture = (
963
986
  PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
964
987
  GROUPS => { 2 => 'Video' },
965
- FORMAT => 'rational64u',
988
+ FORMAT => 'rational64s',
966
989
  0 => 'CleanApertureWidth',
967
990
  1 => 'CleanApertureHeight',
968
991
  2 => 'CleanApertureOffsetX',
@@ -1307,6 +1330,7 @@ my %eeBox = (
1307
1330
  Format => 'fixed32s[9]',
1308
1331
  Notes => 'writable for the video track via the Composite Rotation tag',
1309
1332
  Writable => 1,
1333
+ Protected => 1,
1310
1334
  Permanent => 1,
1311
1335
  # only set rotation if image size is non-zero
1312
1336
  RawConvInv => \&GetMatrixStructure,
@@ -1371,8 +1395,8 @@ my %eeBox = (
1371
1395
  },
1372
1396
  ValueConvInv => q{
1373
1397
  require Image::ExifTool::XMP;
1374
- $val = Image::ExifTool::XMP::FormatXMPDate($val);
1375
- $val =~ s/([-+]\d{2}):(\d{2})$/$1$2/; # remove time zone colon
1398
+ my $tmp = Image::ExifTool::XMP::FormatXMPDate($val);
1399
+ ($val = $tmp) =~ s/([-+]\d{2}):(\d{2})$/$1$2/ if defined $tmp; # remove time zone colon
1376
1400
  return $val;
1377
1401
  },
1378
1402
  PrintConv => '$self->ConvertDateTime($val)',
@@ -1634,7 +1658,7 @@ my %eeBox = (
1634
1658
  Groups => { 2 => 'Time' },
1635
1659
  Notes => q{
1636
1660
  Apple Photos has been reported to show a crazy date/time for some MP4 files
1637
- containing this tag
1661
+ containing this tag, but perhaps only if it is missing a time zone
1638
1662
  }, #forum10690/11125
1639
1663
  Shift => 'Time',
1640
1664
  ValueConv => q{
@@ -1857,6 +1881,25 @@ my %eeBox = (
1857
1881
  ByteOrder => 'LittleEndian',
1858
1882
  },
1859
1883
  },
1884
+ # ---- Garmin ---- (ref PH)
1885
+ uuid => [{
1886
+ Name => 'GarminSoftware', # (NC)
1887
+ Condition => '$$valPt =~ /^VIRBactioncamera/',
1888
+ RawConv => 'substr($val, 16)',
1889
+ RawConvInv => '"VIRBactioncamera$val"',
1890
+ },{
1891
+ # 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)
1892
+ Name => 'UUID-Unknown',
1893
+ Writable => 0,
1894
+ %unknownInfo,
1895
+ }],
1896
+ pmcc => {
1897
+ Name => 'GarminSettings',
1898
+ ValueConv => 'substr($val, 4)',
1899
+ ValueConvInv => '"\0\0\0\x01$val"',
1900
+ },
1901
+ # hmtp - "\0\0\0\x01" followed by 408 bytes of zero
1902
+ # vrin - "\0\0\0\x01" followed by 8 bytes of zero
1860
1903
  # ---- GoPro ---- (ref PH)
1861
1904
  GoPr => 'GoProType', # (Hero3+)
1862
1905
  FIRM => { Name => 'FirmwareVersion', Avoid => 1 }, # (Hero4)
@@ -2040,6 +2083,63 @@ my %eeBox = (
2040
2083
  ProcessProc => \&Image::ExifTool::ProcessTIFF, # (because ProcessMOV is default)
2041
2084
  },
2042
2085
  },
2086
+ '@mak' => { Name => 'Make', Avoid => 1 },
2087
+ '@mod' => { Name => 'Model', Avoid => 1 },
2088
+ '@swr' => { Name => 'SoftwareVersion', Avoid => 1 },
2089
+ '@day' => {
2090
+ Name => 'ContentCreateDate',
2091
+ Notes => q{
2092
+ some stupid Ricoh programmer used the '@' symbol instead of the copyright
2093
+ symbol in these tag ID's for the Ricoh Theta Z1 and maybe other models
2094
+ },
2095
+ Groups => { 2 => 'Time' },
2096
+ Shift => 'Time',
2097
+ Avoid => 1,
2098
+ # handle values in the form "2010-02-12T13:27:14-0800"
2099
+ ValueConv => q{
2100
+ require Image::ExifTool::XMP;
2101
+ $val = Image::ExifTool::XMP::ConvertXMPDate($val);
2102
+ $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary
2103
+ return $val;
2104
+ },
2105
+ ValueConvInv => q{
2106
+ require Image::ExifTool::XMP;
2107
+ my $tmp = Image::ExifTool::XMP::FormatXMPDate($val);
2108
+ ($val = $tmp) =~ s/([-+]\d{2}):(\d{2})$/$1$2/ if defined $tmp; # remove time zone colon
2109
+ return $val;
2110
+ },
2111
+ PrintConv => '$self->ConvertDateTime($val)',
2112
+ PrintConvInv => '$self->InverseDateTime($val)',
2113
+ },
2114
+ '@xyz' => { #PH (iPhone 3GS)
2115
+ Name => 'GPSCoordinates',
2116
+ Groups => { 2 => 'Location' },
2117
+ Avoid => 1,
2118
+ ValueConv => \&ConvertISO6709,
2119
+ ValueConvInv => \&ConvInvISO6709,
2120
+ PrintConv => \&PrintGPSCoordinates,
2121
+ PrintConvInv => \&PrintInvGPSCoordinates,
2122
+ },
2123
+ # RDT1 - pairs of int32u_BE, starting at byte 8: "458275 471846"
2124
+ # RDT2 - pairs of int32u_BE, starting at byte 8: "472276 468526"
2125
+ # RDT3 - pairs of int32u_BE, starting at byte 8: "876603 482191"
2126
+ # RDT4 - pairs of int32u_BE, starting at byte 8: "1955 484612"
2127
+ # RDT6 - empty
2128
+ # RDT7 - empty
2129
+ # RDT8 - empty
2130
+ # RDT9 - only 16-byte header?
2131
+ # the boxes below all have a similar header (little-endian):
2132
+ # 0 int32u - number of records
2133
+ # 4 ? - "1e 00"
2134
+ # 6 int16u - record length in bytes
2135
+ # 8 ? - "23 01 00 00 00 00 00 00"
2136
+ # 16 - start of records (each record ends in an int64u timestamp in ns)
2137
+ # RDTA - float[4],ts: "-0.31289672 -0.2245330 11.303817 0 775.780"
2138
+ # RDTB - float[4],ts: "-0.04841613 -0.2166595 0.0724792 0 775.780"
2139
+ # RDTC - float[4],ts: "27.60925 -27.10037 -13.27285 0 775.829"
2140
+ # RDTD - int16s[3],ts: "353 -914 16354 0 775.829"
2141
+ # RDTG - ts: "775.825"
2142
+ # RDTI - float[4],ts: "0.00165951 0.005770059 0.06838259 0.1744695 775.862"
2043
2143
  # ---- Samsung ----
2044
2144
  vndr => 'Vendor', #PH (Samsung PL70)
2045
2145
  SDLN => 'PlayMode', #PH (NC, Samsung ST80 "SEQ_PLAY")
@@ -2516,6 +2616,7 @@ my %eeBox = (
2516
2616
  Name => 'Rotation',
2517
2617
  Format => 'int8u',
2518
2618
  Writable => 'int8u',
2619
+ Protected => 1,
2519
2620
  ValueConv => '$val * 90',
2520
2621
  ValueConvInv => 'int($val / 90 + 0.5)',
2521
2622
  },
@@ -2547,6 +2648,7 @@ my %eeBox = (
2547
2648
  Name => 'PixelAspectRatio',
2548
2649
  Format => 'int32u',
2549
2650
  Writable => 'int32u',
2651
+ Protected => 1,
2550
2652
  },
2551
2653
  rloc => {
2552
2654
  Name => 'RelativeLocation',
@@ -2555,7 +2657,7 @@ my %eeBox = (
2555
2657
  },
2556
2658
  clap => {
2557
2659
  Name => 'CleanAperture',
2558
- Format => 'rational64u',
2660
+ Format => 'rational64s',
2559
2661
  Notes => '4 numbers: width, height, left and top',
2560
2662
  },
2561
2663
  hvcC => {
@@ -2893,10 +2995,25 @@ my %eeBox = (
2893
2995
  "\xa9grp" => 'Grouping',
2894
2996
  "\xa9lyr" => 'Lyrics',
2895
2997
  "\xa9nam" => 'Title',
2896
- # "\xa9st3" ? #10
2897
2998
  "\xa9too" => 'Encoder',
2898
2999
  "\xa9trk" => 'Track',
2899
3000
  "\xa9wrt" => 'Composer',
3001
+ #
3002
+ # the following tags written by AtomicParsley 0.9.6
3003
+ # (ref https://exiftool.org/forum/index.php?topic=11455.0)
3004
+ #
3005
+ "\xa9st3" => 'Subtitle',
3006
+ "\xa9con" => 'Conductor',
3007
+ "\xa9sol" => 'Soloist',
3008
+ "\xa9arg" => 'Arranger',
3009
+ "\xa9ope" => 'OriginalArtist',
3010
+ "\xa9dir" => 'Director',
3011
+ "\xa9ard" => 'ArtDirector',
3012
+ "\xa9sne" => 'SoundEngineer',
3013
+ "\xa9prd" => 'Producer',
3014
+ "\xa9xpd" => 'ExecutiveProducer',
3015
+ sdes => 'StoreDescription',
3016
+ #
2900
3017
  '----' => {
2901
3018
  Name => 'iTunesInfo',
2902
3019
  SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::iTunesInfo' },
@@ -2905,18 +3022,29 @@ my %eeBox = (
2905
3022
  covr => { Name => 'CoverArt', Groups => { 2 => 'Preview' } },
2906
3023
  cpil => { #10
2907
3024
  Name => 'Compilation',
2908
- Format => 'int8u', #23
3025
+ Format => 'int8u', #27 (ref 23 contradicts what AtomicParsley actually writes, which is int8s)
3026
+ Writable => 'int8s',
2909
3027
  PrintConv => { 0 => 'No', 1 => 'Yes' },
2910
3028
  },
2911
3029
  disk => {
2912
3030
  Name => 'DiskNumber',
2913
3031
  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',
3032
+ ValueConv => q{
3033
+ return \$val unless length($val) >= 6;
3034
+ my @a = unpack 'x2nn', $val;
3035
+ return $a[1] ? join(' of ', @a) : $a[0];
3036
+ },
3037
+ ValueConvInv => q{
3038
+ my @a = $val =~ /\d+/g;
3039
+ return undef if @a == 0 or @a > 2;
3040
+ push @a, 0 if @a == 1;
3041
+ return pack('n3', 0, @a);
3042
+ },
2916
3043
  },
2917
3044
  pgap => { #10
2918
3045
  Name => 'PlayGap',
2919
3046
  Format => 'int8u', #23
3047
+ Writable => 'int8s', #27
2920
3048
  PrintConv => {
2921
3049
  0 => 'Insert Gap',
2922
3050
  1 => 'No Gap',
@@ -2924,13 +3052,26 @@ my %eeBox = (
2924
3052
  },
2925
3053
  tmpo => {
2926
3054
  Name => 'BeatsPerMinute',
2927
- Format => 'int16u', # marked as boolean but really int16u in my sample
3055
+ # marked as boolean but really int16u in my sample
3056
+ # (but written as int16s by iTunes and AtomicParsley, ref forum11506)
3057
+ Format => 'int16u',
3058
+ Writable => 'int16s',
2928
3059
  },
2929
3060
  trkn => {
2930
3061
  Name => 'TrackNumber',
2931
3062
  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',
3063
+ ValueConv => q{
3064
+ return \$val unless length($val) >= 6;
3065
+ my @a = unpack 'x2nn', $val;
3066
+ return $a[1] ? join(' of ', @a) : $a[0];
3067
+ },
3068
+ # (see forum11501 for discussion about the format used)
3069
+ ValueConvInv => q{
3070
+ my @a = $val =~ /\d+/g;
3071
+ return undef if @a == 0 or @a > 2;
3072
+ push @a, 0 if @a == 1;
3073
+ return pack('n4', 0, @a, 0);
3074
+ },
2934
3075
  },
2935
3076
  #
2936
3077
  # Note: it is possible that the tags below are not being decoded properly
@@ -2939,6 +3080,7 @@ my %eeBox = (
2939
3080
  akID => { #10
2940
3081
  Name => 'AppleStoreAccountType',
2941
3082
  Format => 'int8u', #24
3083
+ Writable => 'int8s', #27
2942
3084
  PrintConv => {
2943
3085
  0 => 'iTunes',
2944
3086
  1 => 'AOL',
@@ -2949,12 +3091,14 @@ my %eeBox = (
2949
3091
  atID => { #10 (or TV series)
2950
3092
  Name => 'AlbumTitleID',
2951
3093
  Format => 'int32u',
3094
+ Writable => 'int32s', #27
2952
3095
  },
2953
3096
  auth => { Name => 'Author', Groups => { 2 => 'Author' } },
2954
3097
  catg => 'Category', #7
2955
3098
  cnID => { #10
2956
3099
  Name => 'AppleStoreCatalogID',
2957
3100
  Format => 'int32u',
3101
+ Writable => 'int32s', #27
2958
3102
  },
2959
3103
  cprt => { Name => 'Copyright', Groups => { 2 => 'Author' } },
2960
3104
  dscp => { Name => 'Description', Avoid => 1 },
@@ -2962,22 +3106,28 @@ my %eeBox = (
2962
3106
  gnre => { #10
2963
3107
  Name => 'Genre',
2964
3108
  Avoid => 1,
2965
- # (Note: not written as int16u if numerical, although it should be)
3109
+ # (Note: see https://exiftool.org/forum/index.php?topic=11537.0)
3110
+ Format => 'undef',
3111
+ ValueConv => 'unpack("n",$val)',
3112
+ ValueConvInv => '$val =~ /^\d+$/ ? pack("n",$val) : undef',
2966
3113
  PrintConv => q{
2967
3114
  return $val unless $val =~ /^\d+$/;
2968
3115
  require Image::ExifTool::ID3;
2969
3116
  Image::ExifTool::ID3::PrintGenre($val - 1); # note the "- 1"
2970
3117
  },
2971
3118
  PrintConvInv => q{
3119
+ return $val if $val =~ /^[0-9]+$/;
2972
3120
  require Image::ExifTool::ID3;
2973
3121
  my $id = Image::ExifTool::ID3::GetGenreID($val);
2974
- return defined $id ? $id : $val;
2975
- },
3122
+ return unless defined $id and $id =~ /^\d+$/;
3123
+ return $id + 1;
3124
+ },
2976
3125
  },
2977
3126
  egid => 'EpisodeGlobalUniqueID', #7
2978
3127
  geID => { #10
2979
3128
  Name => 'GenreID',
2980
3129
  Format => 'int32u',
3130
+ Writable => 'int32s', #27
2981
3131
  SeparateTable => 1,
2982
3132
  # the following lookup is based on http://itunes.apple.com/WebObjects/MZStoreServices.woa/ws/genres
2983
3133
  # (see scripts/parse_genre to parse genre JSON file from above)
@@ -5630,6 +5780,7 @@ my %eeBox = (
5630
5780
  hdvd => { #10
5631
5781
  Name => 'HDVideo',
5632
5782
  Format => 'int8u', #24
5783
+ Writable => 'int8s', #27
5633
5784
  PrintConv => { 0 => 'No', 1 => 'Yes' },
5634
5785
  },
5635
5786
  keyw => 'Keyword', #7
@@ -5637,18 +5788,21 @@ my %eeBox = (
5637
5788
  pcst => { #7
5638
5789
  Name => 'Podcast',
5639
5790
  Format => 'int8u', #23
5791
+ Writable => 'int8s', #27
5640
5792
  PrintConv => { 0 => 'No', 1 => 'Yes' },
5641
5793
  },
5642
5794
  perf => 'Performer',
5643
5795
  plID => { #10 (or TV season)
5644
5796
  Name => 'PlayListID',
5645
5797
  Format => 'int8u', # actually int64u, but split it up
5798
+ Writable => 'int32s', #27
5646
5799
  },
5647
5800
  purd => 'PurchaseDate', #7
5648
5801
  purl => 'PodcastURL', #7
5649
5802
  rtng => { #10
5650
5803
  Name => 'Rating',
5651
5804
  Format => 'int8u', #23
5805
+ Writable => 'int8s', #27
5652
5806
  PrintConv => {
5653
5807
  0 => 'none',
5654
5808
  1 => 'Explicit',
@@ -5659,6 +5813,7 @@ my %eeBox = (
5659
5813
  sfID => { #10
5660
5814
  Name => 'AppleStoreCountry',
5661
5815
  Format => 'int32u',
5816
+ Writable => 'int32s', #27
5662
5817
  SeparateTable => 1,
5663
5818
  PrintConv => { #21
5664
5819
  143441 => 'United States', # US
@@ -5827,6 +5982,7 @@ my %eeBox = (
5827
5982
  stik => { #10
5828
5983
  Name => 'MediaType',
5829
5984
  Format => 'int8u', #23
5985
+ Writable => 'int8s', #27
5830
5986
  PrintConvColumns => 2,
5831
5987
  PrintConv => { #(http://weblog.xanga.com/gryphondwb/615474010/iphone-ringtones---what-did-itunes-741-really-do.html)
5832
5988
  0 => 'Movie (old)', #forum9059 (was Movie)
@@ -5848,6 +6004,7 @@ my %eeBox = (
5848
6004
  tves => { #7/10
5849
6005
  Name => 'TVEpisode',
5850
6006
  Format => 'int32u',
6007
+ Writable => 'int32s', #27
5851
6008
  },
5852
6009
  tvnn => 'TVNetworkName', #7
5853
6010
  tvsh => 'TVShow', #10
@@ -5858,7 +6015,8 @@ my %eeBox = (
5858
6015
  yrrc => 'Year', #(ffmpeg source)
5859
6016
  itnu => { #PH (iTunes 10.5)
5860
6017
  Name => 'iTunesU',
5861
- Format => 'int8s',
6018
+ Format => 'int8u', #27
6019
+ Writable => 'int8s', #27
5862
6020
  Description => 'iTunes U',
5863
6021
  PrintConv => { 0 => 'No', 1 => 'Yes' },
5864
6022
  },
@@ -5915,15 +6073,18 @@ my %eeBox = (
5915
6073
  "\xa9mvn" => 'MovementName', #PH
5916
6074
  "\xa9mvi" => { #PH
5917
6075
  Name => 'MovementNumber',
5918
- Format => 'int16s',
6076
+ Format => 'int16u', #27
6077
+ Writable => 'int16s', #27
5919
6078
  },
5920
6079
  "\xa9mvc" => { #PH
5921
6080
  Name => 'MovementCount',
5922
- Format => 'int16s',
6081
+ Format => 'int16u', #27
6082
+ Writable => 'int16s', #27
5923
6083
  },
5924
6084
  shwm => { #PH
5925
6085
  Name => 'ShowMovement',
5926
- Format => 'int8s',
6086
+ Format => 'int8u', #27
6087
+ Writable => 'int8s', #27
5927
6088
  PrintConv => { 0 => 'No', 1 => 'Yes' },
5928
6089
  },
5929
6090
  );
@@ -6737,6 +6898,7 @@ my %eeBox = (
6737
6898
  # alac - 28 bytes
6738
6899
  # adrm - AAX DRM atom? 148 bytes
6739
6900
  # aabd - AAX unknown 17kB (contains 'aavd' strings)
6901
+ # SA3D - written by Garmin VIRB360
6740
6902
  );
6741
6903
 
6742
6904
  # AMR decode config box (ref 3)
@@ -7223,6 +7385,20 @@ my %eeBox = (
7223
7385
  #
7224
7386
  ftab => { Name => 'FontTable', Format => 'undef', ValueConv => 'substr($val, 5)' },
7225
7387
  name => { Name => 'OtherName', Format => 'undef', ValueConv => 'substr($val, 4)' },
7388
+ # mrlh = GM header?
7389
+ # mrlv = GM data
7390
+ # mrld = GM data (448-byte records):
7391
+ # 0 - int32u count
7392
+ # 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=%
7393
+ # 8 - int32u ? (0,1,3,4,5)
7394
+ # 12 - string[64] units
7395
+ # 76 - int32u ? (1,3,7,15)
7396
+ # 80 - int32u 0
7397
+ # 84 - undef[4] ?
7398
+ # 88 - int16u[6] ?
7399
+ # 100 - undef[32] ?
7400
+ # 132 - string[64] measurement name
7401
+ # 196 - string[64] measurement name
7226
7402
  );
7227
7403
 
7228
7404
  # MP4 data information box (ref 5)
@@ -7519,6 +7695,7 @@ my %eeBox = (
7519
7695
  1 => 'QuickTime:HandlerType',
7520
7696
  },
7521
7697
  Writable => 1,
7698
+ Protected => 1,
7522
7699
  WriteAlso => {
7523
7700
  MatrixStructure => 'Image::ExifTool::QuickTime::GetRotationMatrix($val)',
7524
7701
  },
@@ -8353,7 +8530,7 @@ sub EEWarn($)
8353
8530
  #------------------------------------------------------------------------------
8354
8531
  # Get quicktime format from flags word
8355
8532
  # Inputs: 0) quicktime atom flags, 1) data length
8356
- # Returns: Exiftool format string
8533
+ # Returns: ExifTool format string
8357
8534
  sub QuickTimeFormat($$)
8358
8535
  {
8359
8536
  my ($flags, $len) = @_;
@@ -8580,7 +8757,7 @@ sub ProcessKeys($$$)
8580
8757
  my $ns = substr($$dataPt, $pos + 4, 4);
8581
8758
  my $tag = substr($$dataPt, $pos + 8, $len - 8);
8582
8759
  $tag =~ s/\0.*//s; # truncate at null
8583
- $tag =~ s/^com\.apple\.quicktime\.// if $ns eq 'mdta'; # remove apple quicktime domain
8760
+ $tag =~ s/^com\.(apple\.quicktime\.)?// if $ns eq 'mdta'; # remove apple quicktime domain
8584
8761
  $tag = "Tag_$ns" unless $tag;
8585
8762
  # (I have some samples where the tag is a reversed ItemList or UserData tag ID)
8586
8763
  my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
@@ -9091,10 +9268,10 @@ ItemID: foreach $id (keys %$items) {
9091
9268
  }
9092
9269
  }
9093
9270
  if ($ctry or $lang) {
9094
- $lang = GetLangCode($lang, $ctry);
9095
- if ($lang) {
9271
+ my $langCode = GetLangCode($lang, $ctry);
9272
+ if ($langCode) {
9096
9273
  # get tagInfo for other language
9097
- $langInfo = GetLangInfoQT($et, $tagInfo, $lang);
9274
+ $langInfo = GetLangInfoQT($et, $tagInfo, $langCode);
9098
9275
  # save other language tag ID's so we can delete later if necessary
9099
9276
  if ($langInfo) {
9100
9277
  $$tagInfo{OtherLang} or $$tagInfo{OtherLang} = [ ];
@@ -9111,7 +9288,7 @@ ItemID: foreach $id (keys %$items) {
9111
9288
  Size => $len,
9112
9289
  Format => $format,
9113
9290
  Index => $index,
9114
- Extra => sprintf(", Type='${type}', Flags=0x%x%s",$flags,($lang ? ", Lang=$lang" : '')),
9291
+ Extra => sprintf(", Type='${type}', Flags=0x%x, Lang=0x%.4x",$flags,$lang),
9115
9292
  ) if $verbose;
9116
9293
  # use "Keys" in path instead of ItemList if this was defined by a Keys tag
9117
9294
  my $isKey = $$tagInfo{Groups} && $$tagInfo{Groups}{1} && $$tagInfo{Groups}{1} eq 'Keys';