exiftool_vendored 11.94.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 (62) hide show
  1. checksums.yaml +5 -5
  2. data/bin/Changes +163 -3
  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 +152 -52
  8. data/bin/lib/Image/ExifTool.pm +166 -115
  9. data/bin/lib/Image/ExifTool.pod +108 -81
  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 +13 -7
  13. data/bin/lib/Image/ExifTool/Canon.pm +6 -3
  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/Geotag.pm +69 -21
  22. data/bin/lib/Image/ExifTool/GoPro.pm +10 -1
  23. data/bin/lib/Image/ExifTool/H264.pm +1 -1
  24. data/bin/lib/Image/ExifTool/HtmlDump.pm +2 -2
  25. data/bin/lib/Image/ExifTool/ID3.pm +91 -12
  26. data/bin/lib/Image/ExifTool/Lang/de.pm +3 -1
  27. data/bin/lib/Image/ExifTool/Lang/es.pm +1 -1
  28. data/bin/lib/Image/ExifTool/M2TS.pm +44 -24
  29. data/bin/lib/Image/ExifTool/MWG.pm +9 -1
  30. data/bin/lib/Image/ExifTool/MacOS.pm +1 -1
  31. data/bin/lib/Image/ExifTool/Minolta.pm +3 -2
  32. data/bin/lib/Image/ExifTool/MinoltaRaw.pm +11 -10
  33. data/bin/lib/Image/ExifTool/Nikon.pm +156 -18
  34. data/bin/lib/Image/ExifTool/Olympus.pm +34 -17
  35. data/bin/lib/Image/ExifTool/PNG.pm +14 -3
  36. data/bin/lib/Image/ExifTool/PPM.pm +5 -5
  37. data/bin/lib/Image/ExifTool/Panasonic.pm +147 -13
  38. data/bin/lib/Image/ExifTool/PanasonicRaw.pm +33 -0
  39. data/bin/lib/Image/ExifTool/Parrot.pm +2 -1
  40. data/bin/lib/Image/ExifTool/Pentax.pm +3 -1
  41. data/bin/lib/Image/ExifTool/Photoshop.pm +2 -1
  42. data/bin/lib/Image/ExifTool/QuickTime.pm +277 -33
  43. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +460 -67
  44. data/bin/lib/Image/ExifTool/README +21 -20
  45. data/bin/lib/Image/ExifTool/RIFF.pm +123 -3
  46. data/bin/lib/Image/ExifTool/RTF.pm +12 -7
  47. data/bin/lib/Image/ExifTool/Ricoh.pm +19 -1
  48. data/bin/lib/Image/ExifTool/Shift.pl +1 -0
  49. data/bin/lib/Image/ExifTool/SigmaRaw.pm +40 -33
  50. data/bin/lib/Image/ExifTool/Sony.pm +379 -12
  51. data/bin/lib/Image/ExifTool/TagLookup.pm +1959 -1874
  52. data/bin/lib/Image/ExifTool/TagNames.pod +346 -55
  53. data/bin/lib/Image/ExifTool/Validate.pm +4 -4
  54. data/bin/lib/Image/ExifTool/WriteExif.pl +3 -2
  55. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +26 -15
  56. data/bin/lib/Image/ExifTool/Writer.pl +52 -23
  57. data/bin/lib/Image/ExifTool/XMP.pm +41 -4
  58. data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
  59. data/bin/lib/Image/ExifTool/ZISRAW.pm +123 -0
  60. data/bin/perl-Image-ExifTool.spec +31 -31
  61. data/lib/exiftool_vendored/version.rb +1 -1
  62. metadata +4 -4
@@ -6,6 +6,7 @@
6
6
  # Revisions: 2013-09-19 - P. Harvey created
7
7
  #
8
8
  # References: 1) http://www.cineon.com/ff_draft.php
9
+ # 2) Harry Mallon private communication
9
10
  #------------------------------------------------------------------------------
10
11
 
11
12
  package Image::ExifTool::DPX;
@@ -14,7 +15,7 @@ use strict;
14
15
  use vars qw($VERSION);
15
16
  use Image::ExifTool qw(:DataAccess :Utils);
16
17
 
17
- $VERSION = '1.03';
18
+ $VERSION = '1.04';
18
19
 
19
20
  # DPX tags
20
21
  %Image::ExifTool::DPX::Main = (
@@ -86,6 +87,56 @@ $VERSION = '1.03';
86
87
  156 => 'User-defined 8 component element',
87
88
  },
88
89
  },
90
+ 801 => { #2
91
+ Name => 'TransferCharacteristic',
92
+ Format => 'int8u',
93
+ PrintConv => {
94
+ 0 => 'User-defined',
95
+ 1 => 'Printing density',
96
+ 2 => 'Linear',
97
+ 3 => 'Logarithmic',
98
+ 4 => 'Unspecified video',
99
+ 5 => 'SMPTE 274M',
100
+ 6 => 'ITU-R 704-4',
101
+ 7 => 'ITU-R 601-5 system B or G (625)',
102
+ 8 => 'ITU-R 601-5 system M (525)',
103
+ 9 => 'Composite video (NTSC)',
104
+ 10 => 'Composite video (PAL)',
105
+ 11 => 'Z (depth) - linear',
106
+ 12 => 'Z (depth) - homogeneous',
107
+ 13 => 'SMPTE ADX',
108
+ 14 => 'ITU-R 2020 NCL',
109
+ 15 => 'ITU-R 2020 CL',
110
+ 16 => 'IEC 61966-2-4 xvYCC',
111
+ 17 => 'ITU-R 2100 NCL/PQ',
112
+ 18 => 'ITU-R 2100 ICtCp/PQ',
113
+ 19 => 'ITU-R 2100 NCL/HLG',
114
+ 20 => 'ITU-R 2100 ICtCp/HLG',
115
+ 21 => 'RP 431-2:2011 Gama 2.6',
116
+ 22 => 'IEC 61966-2-1 sRGB',
117
+ },
118
+ },
119
+ 802 => { #2
120
+ Name => 'ColorimetricSpecification',
121
+ Format => 'int8u',
122
+ PrintConv => {
123
+ 0 => 'User-defined',
124
+ 1 => 'Printing density',
125
+ 4 => 'Unspecified video',
126
+ 5 => 'SMPTE 274M',
127
+ 6 => 'ITU-R 704-4',
128
+ 7 => 'ITU-R 601-5 system B or G (625)',
129
+ 8 => 'ITU-R 601-5 system M (525)',
130
+ 9 => 'Composite video (NTSC)',
131
+ 10 => 'Composite video (PAL)',
132
+ 13 => 'SMPTE ADX',
133
+ 14 => 'ITU-R 2020',
134
+ 15 => 'P3D65',
135
+ 16 => 'P3DCI',
136
+ 17 => 'P3D60',
137
+ 18 => 'ACES',
138
+ },
139
+ },
89
140
  803 => { Name => 'BitDepth', Format => 'int8u' },
90
141
  820 => { Name => 'ImageDescription', Format => 'string[32]' },
91
142
  892 => { Name => 'Image2Description', Format => 'string[32]', RawConv => '$val=~/[^\xff]/ ? $val : undef' },
@@ -106,9 +157,12 @@ $VERSION = '1.03';
106
157
  1556=> { Name => 'InputDeviceName', Format => 'string[32]' },
107
158
  1588=> { Name => 'InputDeviceSerialNumber', Format => 'string[32]' },
108
159
  # 1620=> { Name => 'AspectRatio', Format => 'int32u' },
109
- 1724 => { Name => 'FrameRate', Format => 'float' },
160
+ 1724 => { Name => 'OriginalFrameRate',Format => 'float' },
161
+ 1728 => { Name => 'ShutterAngle', Format => 'float', RawConv => '$val =~ /\d/ ? $val : undef' }, #2
110
162
  1732 => { Name => 'FrameID', Format => 'string[32]' },
111
163
  1764 => { Name => 'SlateInformation', Format => 'string[100]' },
164
+ 1920 => { Name => 'TimeCode', Format => 'int32u' }, #2
165
+ 1940 => { Name => 'FrameRate', Format => 'float', RawConv => '$val =~ /\d/ ? $val : undef' }, #2
112
166
  1972 => { Name => 'Reserved5', Format => 'string[76]', Unknown => 1 },
113
167
  2048 => { Name => 'UserID', Format => 'string[32]' },
114
168
  );
@@ -15,7 +15,7 @@ use strict;
15
15
  use vars qw($VERSION);
16
16
  use Image::ExifTool::XMP;
17
17
 
18
- $VERSION = '1.02';
18
+ $VERSION = '1.04';
19
19
 
20
20
  my %dateTimeInfo = (
21
21
  # NOTE: Do NOT put "Groups" here because Groups hash must not be common!
@@ -28,7 +28,7 @@ my %dateTimeInfo = (
28
28
  my %materialSample = (
29
29
  STRUCT_NAME => 'DarwinCore MaterialSample',
30
30
  NAMESPACE => 'dwc',
31
- materialSampleID => { },
31
+ materialSampleID => { },
32
32
  );
33
33
 
34
34
  my %event = (
@@ -40,7 +40,20 @@ my %event = (
40
40
  eventDate => { %dateTimeInfo, Groups => { 2 => 'Time' } },
41
41
  eventID => { },
42
42
  eventRemarks => { Writable => 'lang-alt' },
43
- eventTime => { %dateTimeInfo, Groups => { 2 => 'Time' } },
43
+ eventTime => {
44
+ Groups => { 2 => 'Time' },
45
+ Writable => 'string', # (so we can format this ourself)
46
+ Shift => 'Time',
47
+ # (pass straight through if this isn't a full date/time value)
48
+ ValueConv => 'Image::ExifTool::XMP::ConvertXMPDate($val)',
49
+ PrintConv => '$self->ConvertDateTime($val)',
50
+ ValueConvInv => 'Image::ExifTool::XMP::FormatXMPDate($val) or $val',
51
+ PrintConvInv => q{
52
+ my $v = $self->InverseDateTime($val,undef,1);
53
+ undef $Image::ExifTool::evalWarning;
54
+ return $v || $val;
55
+ },
56
+ },
44
57
  fieldNotes => { },
45
58
  fieldNumber => { },
46
59
  habitat => { },
@@ -56,7 +56,7 @@ use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber %intFormat
56
56
  use Image::ExifTool qw(:DataAccess :Utils);
57
57
  use Image::ExifTool::MakerNotes;
58
58
 
59
- $VERSION = '4.30';
59
+ $VERSION = '4.31';
60
60
 
61
61
  sub ProcessExif($$$);
62
62
  sub WriteExif($$$);
@@ -4715,8 +4715,8 @@ my %subSecConv = (
4715
4715
  },
4716
4716
  LensID => {
4717
4717
  Groups => { 2 => 'Camera' },
4718
- Require => 'LensType',
4719
4718
  Desire => {
4719
+ 0 => 'LensType',
4720
4720
  1 => 'FocalLength',
4721
4721
  2 => 'MaxAperture',
4722
4722
  3 => 'MaxApertureValue',
@@ -4735,16 +4735,25 @@ my %subSecConv = (
4735
4735
  Applies only to LensType values with a lookup table. May be configured
4736
4736
  by adding user-defined lenses
4737
4737
  },
4738
- # this LensID is only valid if the LensType has a PrintConv or is a model name
4738
+ # this LensID is only valid if the LensType has a PrintConv,
4739
+ # or LensType or LensModel are the model name
4739
4740
  RawConv => q{
4740
4741
  my $printConv = $$self{TAG_INFO}{LensType}{PrintConv};
4741
- return $val if ref $printConv eq 'HASH' or (ref $printConv eq 'ARRAY' and
4742
- ref $$printConv[0] eq 'HASH') or $val[0] =~ /(mm|\d\/F)/;
4742
+ return $val if ref $printConv eq 'HASH' or
4743
+ (ref $printConv eq 'ARRAY' and ref $$printConv[0] eq 'HASH') or
4744
+ (defined $val[0] and $val[0] =~ /(mm|\d\/F)/) or
4745
+ (defined $val[6] and $val[6] =~ /(mm|\d\/F)/);
4743
4746
  return undef;
4744
4747
  },
4745
- ValueConv => '$val',
4748
+ ValueConv => '$val[0] || $val[6]',
4746
4749
  PrintConv => q{
4747
4750
  my $pcv;
4751
+ # use LensModel ([6]) if LensType ([0]) is not populated
4752
+ # (iPhone populates LensModel but not LensType)
4753
+ if (not defined $val[0] and defined $val[6]) {
4754
+ $val[0] = $val[6];
4755
+ $prt[0] = $prt[6];
4756
+ }
4748
4757
  # use LensType2 instead of LensType if available and valid (Sony E-mount lenses)
4749
4758
  # (0x8000 or greater; 0 for several older/3rd-party E-mount lenses)
4750
4759
  if (defined $val[9] and ($val[9] & 0x8000 or $val[9] == 0)) {
@@ -19,7 +19,7 @@ use strict;
19
19
  use vars qw($VERSION %ttLang);
20
20
  use Image::ExifTool qw(:DataAccess :Utils);
21
21
 
22
- $VERSION = '1.09';
22
+ $VERSION = '1.10';
23
23
 
24
24
  sub ProcessOTF($$);
25
25
 
@@ -589,6 +589,11 @@ sub ProcessFont($$)
589
589
  $et->HandleTag($tagTablePtr, 'postfont', $2);
590
590
  }
591
591
  $rtnVal = 1;
592
+ } elsif ($buff =~ /^(wOF[F2])/) {
593
+ my $type = $1 eq 'wOFF' ? 'woff' : 'woff2';
594
+ $et->SetFileType(uc($type), "font/$type");
595
+ # (don't yet extract metadata from these files)
596
+ $rtnVal = 1;
592
597
  } else {
593
598
  $rtnVal = 0;
594
599
  }
@@ -611,7 +616,9 @@ This module is used by Image::ExifTool
611
616
 
612
617
  This module contains the routines required by Image::ExifTool to read meta
613
618
  information from various format font files. Currently recognized font file
614
- types are OTF, TTF, TTC, DFONT, PFA, PFB, PFM, AFM, ACFM and AMFM.
619
+ types are OTF, TTF, TTC, DFONT, PFA, PFB, PFM, AFM, ACFM and AMFM. As well,
620
+ WOFF and WOFF2 font files are identified, but metadata is not currently
621
+ extracted from these formats.
615
622
 
616
623
  =head1 AUTHOR
617
624
 
@@ -115,6 +115,11 @@ my %gifMap = (
115
115
  ValueConv => '$val + 1',
116
116
  },
117
117
  5 => 'BackgroundColor',
118
+ 6 => {
119
+ Name => 'AspectRatio',
120
+ RawConv => '$val ? $val : undef',
121
+ ValueConv => '($val + 15) / 64',
122
+ },
118
123
  );
119
124
 
120
125
  # GIF Netscape 2.0 animation extension (ref 3)
@@ -573,6 +573,8 @@ my %epsg_vertcs = (
573
573
  3053 => 'Hjorsey 1955 Lambert',
574
574
  3057 => 'ISN93 Lambert 1993',
575
575
  3300 => 'Estonian Coordinate System of 1992',
576
+ 3786 => 'Popular Visualisation CRS / Mercator', #PH (NC)
577
+ 3857 => 'WGS 84 / Pseudo-Mercator', #PH (NC)
576
578
  20137 => 'Adindan UTM zone 37N',
577
579
  20138 => 'Adindan UTM zone 38N',
578
580
  20248 => 'AGD66 AMG zone 48',
@@ -25,8 +25,9 @@ package Image::ExifTool::Geotag;
25
25
  use strict;
26
26
  use vars qw($VERSION);
27
27
  use Image::ExifTool qw(:Public);
28
+ use Image::ExifTool::GPS;
28
29
 
29
- $VERSION = '1.61';
30
+ $VERSION = '1.62';
30
31
 
31
32
  sub JITTER() { return 2 } # maximum time jitter
32
33
 
@@ -229,9 +230,41 @@ sub LoadTrackLog($$;$)
229
230
  $format = 'Winplus';
230
231
  } elsif (/^\s*\d+\s+.*\sypr\s*$/ and (@tmp=split) == 12) {
231
232
  $format = 'Bramor';
232
- } elsif (/\bDate\b/i and /\bTime\b/ and ',') {
233
+ } elsif (/\b(GPS)?Date/i and /\b(GPS)?(Date)?Time/i and /,/) {
234
+ chomp;
233
235
  @csvHeadings = split ',';
234
236
  $format = 'CSV';
237
+ # convert recognized headings to our parameter names
238
+ foreach (@csvHeadings) {
239
+ my $param;
240
+ s/^GPS ?//; # remove leading "GPS" to simplify regex patterns
241
+ if (/^Date ?Time/i) { # ExifTool addition
242
+ $param = 'datetime';
243
+ } elsif (/^Date/i) {
244
+ $param = 'date';
245
+ } elsif (/^Time/i) {
246
+ $param = 'time';
247
+ } elsif (/^(Pos)?Lat/i) {
248
+ $param = 'lat';
249
+ } elsif (/^(Pos)?Lon/i) {
250
+ $param = 'lon';
251
+ } elsif (/^(Pos)?Alt/i) {
252
+ $param = 'alt';
253
+ } elsif (/^(Angle)?(Heading|Track)/i) {
254
+ $param = 'track';
255
+ } elsif (/^(Angle)?Pitch/i or /^Camera ?Elevation ?Angle/i) {
256
+ $param = 'pitch';
257
+ } elsif (/^(Angle)?Roll/i) {
258
+ $param = 'roll';
259
+ }
260
+ if ($param) {
261
+ $et->VPrint(2, "CSV column '${_}' is $param\n");
262
+ $_ = $param;
263
+ } else {
264
+ $et->VPrint(2, "CSV column '${_}' ignored\n");
265
+ $_ = ''; # ignore this column
266
+ }
267
+ }
235
268
  next;
236
269
  } else {
237
270
  # search only first 50 lines of file for a valid fix
@@ -388,35 +421,50 @@ DoneFix: $isDate = 1;
388
421
  # set necessary flags for extra available information
389
422
  @$has{qw(alt track orient)} = (1,1,1);
390
423
  goto DoneFix; # save this fix
424
+ } elsif ($format eq 'CSV') {
425
+ chomp;
426
+ my @vals = split ',';
391
427
  #
392
428
  # CSV format output of GPS/IMU POS system
429
+ # Date* - date in DD/MM/YYYY format
430
+ # Time* - time in HH:MM:SS.SSS format
431
+ # [Pos]Lat* - latitude in decimal degrees
432
+ # [Pos]Lon* - longitude in decimal degrees
433
+ # [Pos]Alt* - altitude in m relative to sea level
434
+ # [Angle]Heading* - GPSTrack in degrees true
435
+ # [Angle]Pitch* - pitch angle in degrees
436
+ # [Angle]Roll* - roll angle in degrees
437
+ # (ExifTool enhancements allow for standard tag names or descriptions as the column headings,
438
+ # add support for time zones and flexible coordinates, and allow a new DateTime column)
393
439
  #
394
- } elsif ($format eq 'CSV') {
395
- my @vals = split ',';
396
- my ($label, $date, $secs);
397
- foreach $label (@csvHeadings) {
440
+ my ($param, $date, $secs);
441
+ foreach $param (@csvHeadings) {
398
442
  my $val = shift @vals;
399
443
  last unless defined $val;
400
- if ($label =~ /^Date/i) {
444
+ next unless $param;
445
+ if ($param eq 'datetime') {
446
+ local $SIG{'__WARN__'} = sub { };
447
+ my $dateTime = $et->InverseDateTime($val);
448
+ if ($dateTime) {
449
+ $date = Image::ExifTool::GetUnixTime($val, 2);
450
+ $secs = 0;
451
+ }
452
+ } elsif ($param eq 'date') {
401
453
  if ($val =~ m{^(\d{2})/(\d{2})/(\d{4})$}) {
402
454
  $date = Time::Local::timegm(0,0,0,$1,$2-1,$3);
455
+ } elsif ($val =~ /(\d{4}).*?(\d{2}).*?(\d{2})/) {
456
+ $date = Time::Local::timegm(0,0,0,$3,$2-1,$1);
403
457
  }
404
- } elsif ($label =~ /^Time/i) {
405
- if ($val =~ /^(\d{1,2}):(\d{2}):(\d{2}(\.\d+)?)/) {
458
+ } elsif ($param eq 'time') {
459
+ if ($val =~ /^(\d{1,2}):(\d{2}):(\d{2}(\.\d+)?).*?(([-+])(\d{1,2}):?(\d{2}))?/) {
406
460
  $secs = (($1 * 60) + $2) * 60 + $3;
461
+ # adjust for time zone if specified
462
+ $secs += ($7 * 60 + $8) * ($6 eq '-' ? 60 : -60) if $5;
407
463
  }
408
- } elsif ($label =~ /^(Pos)?Lat/) {
409
- $$fix{lat} = $val;
410
- } elsif ($label =~ /^(Pos)?Lon/) {
411
- $$fix{lon} = $val;
412
- } elsif ($label =~ /^(Pos)?Alt/) {
413
- $$fix{alt} = $val;
414
- } elsif ($label =~ /^(Angle)?Heading/) {
415
- $$fix{track} = $val;
416
- } elsif ($label =~ /^(Angle)?Pitch/) {
417
- $$fix{pitch} = $val;
418
- } elsif ($label =~ /^(Angle)?Roll/) {
419
- $$fix{roll} = $val;
464
+ } elsif ($param eq 'lat' or $param eq 'lon') {
465
+ $$fix{$param} = Image::ExifTool::GPS::ToDegrees($val, 1);
466
+ } else {
467
+ $$fix{$param} = $val;
420
468
  }
421
469
  }
422
470
  if ($date and defined $secs and defined $$fix{lat} and defined $$fix{lon}) {
@@ -16,7 +16,7 @@ use vars qw($VERSION);
16
16
  use Image::ExifTool qw(:DataAccess :Utils);
17
17
  use Image::ExifTool::QuickTime;
18
18
 
19
- $VERSION = '1.03';
19
+ $VERSION = '1.04';
20
20
 
21
21
  sub ProcessGoPro($$$);
22
22
  sub ProcessString($$$);
@@ -590,6 +590,7 @@ sub ProcessString($$$)
590
590
  # Process GoPro metadata (gpmd samples, GPMF box, or APP6) (ref PH/1/2)
591
591
  # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
592
592
  # Returns: 1 on success
593
+ # - with hack to check for encrypted text in gpmd data (Rove Stealth 4K)
593
594
  sub ProcessGoPro($$$)
594
595
  {
595
596
  my ($et, $dirInfo, $tagTablePtr) = @_;
@@ -601,6 +602,14 @@ sub ProcessGoPro($$$)
601
602
  my $unknown = $verbose || $et->Options('Unknown');
602
603
  my ($size, $type, $unit, $scal, $setGroup0);
603
604
 
605
+ # the Rove Stealth 4K writes encrypted text here, so check for this first
606
+ # (really should check for this before loading GoPro module, but I was lazy) PHIL
607
+ if ($$dataPt =~ /^\0\0\xf2\xe1\xf0\xeeTT/) {
608
+ $et->VerboseDir('gpmd encrypted text', undef, length($$dataPt));
609
+ my $strmTbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
610
+ Image::ExifTool::QuickTime::Process_text($et, $strmTbl, $dataPt);
611
+ return 1;
612
+ }
604
613
  $et->VerboseDir($$dirInfo{DirName} || 'GPMF', undef, $dirEnd-$pos) if $verbose;
605
614
  if ($pos) {
606
615
  my $parent = $$dirInfo{Parent};
@@ -890,7 +890,7 @@ sub ParsePictureTiming($$)
890
890
 
891
891
  #------------------------------------------------------------------------------
892
892
  # Process H.264 Supplementary Enhancement Information (ref 1/PH)
893
- # Inputs: 0) Exiftool ref, 1) dirInfo ref, 2) tag table ref
893
+ # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
894
894
  # Returns: 1 if we processed payload type 5
895
895
  # Payload types:
896
896
  # 0 - buffer period
@@ -13,7 +13,7 @@ use vars qw($VERSION);
13
13
  use Image::ExifTool; # only for FinishTiffDump()
14
14
  use Image::ExifTool::HTML qw(EscapeHTML);
15
15
 
16
- $VERSION = '1.38';
16
+ $VERSION = '1.39';
17
17
 
18
18
  sub DumpTable($$$;$$$$$$);
19
19
  sub Open($$$;@);
@@ -122,7 +122,7 @@ function doClick(e)
122
122
  if (!clicked) {
123
123
  firstOutEvt = lastInEvt = undefined;
124
124
  high(e, 2);
125
- clicked = 1;
125
+ if (hlist) clicked = 1;
126
126
  } else {
127
127
  clicked = 0;
128
128
  if (firstOutEvt) high(firstOutEvt, 0);
@@ -1,13 +1,15 @@
1
1
  #------------------------------------------------------------------------------
2
2
  # File: ID3.pm
3
3
  #
4
- # Description: Read ID3 meta information
4
+ # Description: Read ID3 and Lyrics3 meta information
5
5
  #
6
6
  # Revisions: 09/12/2005 - P. Harvey Created
7
+ # 09/08/2020 - PH Added Lyrics3 support
7
8
  #
8
9
  # References: 1) http://www.id3.org/
9
10
  # 2) http://www.mp3-tech.org/
10
11
  # 3) http://www.fortunecity.com/underworld/sonic/3/id3tag.html
12
+ # 4) https://id3.org/Lyrics3
11
13
  #------------------------------------------------------------------------------
12
14
 
13
15
  package Image::ExifTool::ID3;
@@ -16,7 +18,7 @@ use strict;
16
18
  use vars qw($VERSION);
17
19
  use Image::ExifTool qw(:DataAccess :Utils);
18
20
 
19
- $VERSION = '1.53';
21
+ $VERSION = '1.55';
20
22
 
21
23
  sub ProcessID3v2($$$);
22
24
  sub ProcessPrivate($$$);
@@ -68,13 +70,13 @@ my %dateTimeConv = (
68
70
  %Image::ExifTool::ID3::Main = (
69
71
  VARS => { NO_ID => 1 },
70
72
  NOTES => q{
71
- ExifTool extracts ID3 information from MP3, MPEG, AIFF, OGG, FLAC, APE, MPC
72
- and RealAudio files. ID3v2 tags which support multiple languages (eg.
73
- Comment and Lyrics) are extracted by specifying the tag name, followed by a
74
- dash ('-'), then a 3-character ISO 639-2 language code (eg. "Comment-spa").
75
- See L<http://www.id3.org/> for the official ID3 specification and
76
- L<http://www.loc.gov/standards/iso639-2/php/code_list.php> for a list of ISO
77
- 639-2 language codes.
73
+ ExifTool extracts ID3 and Lyrics3 information from MP3, MPEG, AIFF, OGG,
74
+ FLAC, APE, MPC and RealAudio files. ID3v2 tags which support multiple
75
+ languages (eg. Comment and Lyrics) are extracted by specifying the tag name,
76
+ followed by a dash ('-'), then a 3-character ISO 639-2 language code (eg.
77
+ "Comment-spa"). See L<http://www.id3.org/> for the official ID3
78
+ specification and L<http://www.loc.gov/standards/iso639-2/php/code_list.php>
79
+ for a list of ISO 639-2 language codes.
78
80
  },
79
81
  ID3v1 => {
80
82
  Name => 'ID3v1',
@@ -98,6 +100,24 @@ my %dateTimeConv = (
98
100
  },
99
101
  );
100
102
 
103
+ # Lyrics3 tags (ref 4)
104
+ %Image::ExifTool::ID3::Lyrics3 = (
105
+ GROUPS => { 1 => 'Lyrics3', 2 => 'Audio' },
106
+ NOTES => q{
107
+ ExifTool extracts Lyrics3 version 1.00 and 2.00 tags from any file that
108
+ supports ID3. See L<https://id3.org/Lyrics3> for the specification.
109
+ },
110
+ IND => 'Indications',
111
+ LYR => 'Lyrics',
112
+ INF => 'AdditionalInfo',
113
+ AUT => { Name => 'Author', Groups => { 2 => 'Author' } },
114
+ EAL => 'ExtendedAlbumName',
115
+ EAR => 'ExtendedArtistName',
116
+ ETT => 'ExtendedTrackTitle',
117
+ IMG => 'AssociatedImageFile',
118
+ CRC => 'CRC', #PH
119
+ );
120
+
101
121
  # Mapping for ID3v1 Genre numbers
102
122
  my %genre = (
103
123
  0 => 'Blues',
@@ -613,6 +633,9 @@ my %id3v2_common = (
613
633
  Name => 'OlympusDSS',
614
634
  SubDirectory => { TagTable => 'Image::ExifTool::Olympus::DSS' },
615
635
  },
636
+ GRP1 => 'Grouping',
637
+ MVNM => 'MovementName', # (NC)
638
+ MVIN => 'MovementNumber', # (NC)
616
639
  );
617
640
 
618
641
  # Tags for ID3v2.3 (http://www.id3.org/id3v2.3.0)
@@ -1318,6 +1341,8 @@ sub ProcessID3v2($$$)
1318
1341
  } elsif ($$tagInfo{Format} or $$tagInfo{SubDirectory}) {
1319
1342
  $et->HandleTag($tagTablePtr, $id, undef, DataPt => \$val);
1320
1343
  next;
1344
+ } elsif ($id eq 'GRP1' or $id eq 'MVNM' or $id eq 'MVIN') {
1345
+ $val =~ s/(^\0+|\0+$)//g; # (PH guess)
1321
1346
  } elsif (not $$tagInfo{Binary}) {
1322
1347
  $et->Warn("Don't know how to handle $id frame");
1323
1348
  next;
@@ -1342,7 +1367,7 @@ sub ProcessID3v2($$$)
1342
1367
  # Inputs: 0) ExifTool object reference, 1) dirInfo reference
1343
1368
  # Returns: 1 on success, 0 if this file didn't contain ID3 information
1344
1369
  # - also processes audio data if any ID3 information was found
1345
- # - sets ExifTool DoneID3 to 1 when called, or to 2 if an ID3v1 trailer exists
1370
+ # - sets ExifTool DoneID3 to 1 when called, or to trailer size if an ID3v1 trailer exists
1346
1371
  sub ProcessID3($$)
1347
1372
  {
1348
1373
  my ($et, $dirInfo) = @_;
@@ -1421,8 +1446,9 @@ sub ProcessID3($$)
1421
1446
  #
1422
1447
  # read ID3v1 trailer if it exists
1423
1448
  #
1449
+ my $trailSize = 0;
1424
1450
  if ($raf->Seek(-128, 2) and $raf->Read($tBuff, 128) == 128 and $tBuff =~ /^TAG/) {
1425
- $$et{DoneID3} = 2; # set to 2 as flag that trailer exists
1451
+ $trailSize = 128;
1426
1452
  %id3Trailer = (
1427
1453
  DataPt => \$tBuff,
1428
1454
  DataPos => $raf->Tell() - 128,
@@ -1432,8 +1458,59 @@ sub ProcessID3($$)
1432
1458
  $id3Len += length($tBuff);
1433
1459
  $rtnVal = 1;
1434
1460
  # load 'Enhanced TAG' information if available
1435
- if ($raf->Seek(-355, 2) and $raf->Read($eBuff, 227) == 227 and $eBuff =~ /^TAG+/) {
1461
+ my $eSize = 227; # size of ID3 Enhanced TAG info
1462
+ if ($raf->Seek(-$trailSize - $eSize, 2) and $raf->Read($eBuff, $eSize) == $eSize and $eBuff =~ /^TAG+/) {
1436
1463
  $id3Trailer{EnhancedTAG} = \$eBuff;
1464
+ $trailSize += $eSize;
1465
+ }
1466
+ $$et{DoneID3} = $trailSize; # save trailer size
1467
+ }
1468
+ #
1469
+ # read Lyrics3 trailer if it exists
1470
+ #
1471
+ if ($raf->Seek(-$trailSize-15, 2) and $raf->Read($buff, 15) == 15 and $buff =~ /^(.{6})LYRICS(END|200)$/) {
1472
+ my $ver = $2; # Lyrics3 version ('END' for version 1)
1473
+ my $len = ($ver eq 'END') ? 5100 : $1 + 15; # max Lyrics3 length
1474
+ my $tbl = GetTagTable('Image::ExifTool::ID3::Lyrics3');
1475
+ $len = $raf->Tell() if $len > $raf->Tell();
1476
+ if ($raf->Seek(-$len, 1) and $raf->Read($buff, $len) == $len and $buff =~ /LYRICSBEGIN/g) {
1477
+ my $pos = pos($buff);
1478
+ $$et{DoneID3} = $trailSize + $len - $pos + 11; # update trailer length
1479
+ my $oldIndent = $$et{INDENT};
1480
+ $$et{INDENT} .= '| ';
1481
+ if ($et->Options('Verbose')) {
1482
+ $et->VPrint(0, "Lyrics3:\n");
1483
+ $et->VerboseDir('Lyrics3', undef, $len);
1484
+ if ($pos > 11) {
1485
+ $buff = substr($buff, $pos - 11);
1486
+ $pos = 11;
1487
+ }
1488
+ $et->VerboseDump(\$buff);
1489
+ }
1490
+ if ($ver eq 'END') {
1491
+ # Lyrics3 v1.00
1492
+ my $val = substr($buff, $pos, $len - $pos - 9);
1493
+ $et->HandleTag($tbl, 'LYR', $et->Decode($val, 'Latin'));
1494
+ } else {
1495
+ # Lyrics3 v2.00
1496
+ for (;;) {
1497
+ # (note: the size field is 5 digits,, not 6 as per the documentation)
1498
+ last unless $buff =~ /\G(.{3})(\d{5})/g;
1499
+ my ($tag, $size) = ($1, $2);
1500
+ $pos += 8;
1501
+ last if $pos + $size > length($buff);
1502
+ unless ($$tbl{$tag}) {
1503
+ AddTagToTable($tbl, $tag, { Name => Image::ExifTool::MakeTagName("Lyrics3_$tag") });
1504
+ }
1505
+ $et->HandleTag($tbl, $tag, $et->Decode(substr($buff, $pos, $size), 'Latin'));
1506
+ $pos += $size;
1507
+ pos($buff) = $pos;
1508
+ }
1509
+ $pos == length($buff) - 15 or $et->Warn('Malformed Lyrics3 v2.00 block');
1510
+ }
1511
+ $$et{INDENT} = $oldIndent;
1512
+ } else {
1513
+ $et->Warn('Error reading Lyrics3 trailer');
1437
1514
  }
1438
1515
  }
1439
1516
  #
@@ -1578,6 +1655,8 @@ under the same terms as Perl itself.
1578
1655
 
1579
1656
  =item L<http://www.fortunecity.com/underworld/sonic/3/id3tag.html>
1580
1657
 
1658
+ =item L<https://id3.org/Lyrics3>
1659
+
1581
1660
  =back
1582
1661
 
1583
1662
  =head1 SEE ALSO