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