exiftool_vendored 11.99.0 → 12.11.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.
- checksums.yaml +4 -4
- data/bin/Changes +201 -2
- data/bin/MANIFEST +8 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +43 -42
- data/bin/exiftool +172 -99
- data/bin/lib/Image/ExifTool.pm +170 -117
- data/bin/lib/Image/ExifTool.pod +132 -97
- data/bin/lib/Image/ExifTool/AIFF.pm +2 -2
- data/bin/lib/Image/ExifTool/APE.pm +2 -2
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +21 -10
- data/bin/lib/Image/ExifTool/Canon.pm +202 -13
- data/bin/lib/Image/ExifTool/CanonCustom.pm +82 -16
- data/bin/lib/Image/ExifTool/DPX.pm +56 -2
- data/bin/lib/Image/ExifTool/DarwinCore.pm +22 -3
- data/bin/lib/Image/ExifTool/EXE.pm +8 -5
- data/bin/lib/Image/ExifTool/Exif.pm +15 -6
- data/bin/lib/Image/ExifTool/Font.pm +9 -2
- data/bin/lib/Image/ExifTool/GIF.pm +6 -1
- data/bin/lib/Image/ExifTool/GeoTiff.pm +2 -0
- data/bin/lib/Image/ExifTool/Geotag.pm +2 -2
- data/bin/lib/Image/ExifTool/GoPro.pm +48 -22
- data/bin/lib/Image/ExifTool/H264.pm +1 -1
- data/bin/lib/Image/ExifTool/ID3.pm +86 -12
- data/bin/lib/Image/ExifTool/IPTC.pm +1 -0
- data/bin/lib/Image/ExifTool/Import.pm +12 -9
- data/bin/lib/Image/ExifTool/JSON.pm +27 -4
- data/bin/lib/Image/ExifTool/Lang/de.pm +3 -1
- data/bin/lib/Image/ExifTool/Lang/es.pm +1 -1
- data/bin/lib/Image/ExifTool/M2TS.pm +1 -1
- data/bin/lib/Image/ExifTool/MPF.pm +2 -2
- data/bin/lib/Image/ExifTool/MacOS.pm +154 -38
- data/bin/lib/Image/ExifTool/Matroska.pm +3 -1
- data/bin/lib/Image/ExifTool/Minolta.pm +7 -2
- data/bin/lib/Image/ExifTool/Nikon.pm +143 -17
- data/bin/lib/Image/ExifTool/Olympus.pm +40 -17
- data/bin/lib/Image/ExifTool/PNG.pm +14 -3
- data/bin/lib/Image/ExifTool/PPM.pm +5 -5
- data/bin/lib/Image/ExifTool/Panasonic.pm +148 -14
- data/bin/lib/Image/ExifTool/PanasonicRaw.pm +34 -0
- data/bin/lib/Image/ExifTool/Parrot.pm +2 -1
- data/bin/lib/Image/ExifTool/Pentax.pm +11 -3
- data/bin/lib/Image/ExifTool/Photoshop.pm +2 -1
- data/bin/lib/Image/ExifTool/QuickTime.pm +240 -37
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +419 -60
- data/bin/lib/Image/ExifTool/README +25 -21
- data/bin/lib/Image/ExifTool/RSRC.pm +17 -11
- data/bin/lib/Image/ExifTool/Radiance.pm +7 -2
- data/bin/lib/Image/ExifTool/Ricoh.pm +19 -1
- data/bin/lib/Image/ExifTool/Shift.pl +1 -0
- data/bin/lib/Image/ExifTool/SigmaRaw.pm +40 -33
- data/bin/lib/Image/ExifTool/Sony.pm +423 -39
- data/bin/lib/Image/ExifTool/Stim.pm +2 -2
- data/bin/lib/Image/ExifTool/TagLookup.pm +5798 -5675
- data/bin/lib/Image/ExifTool/TagNames.pod +575 -100
- data/bin/lib/Image/ExifTool/Validate.pm +4 -4
- data/bin/lib/Image/ExifTool/WriteExif.pl +1 -0
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +30 -21
- data/bin/lib/Image/ExifTool/Writer.pl +49 -24
- data/bin/lib/Image/ExifTool/XMP.pm +99 -17
- data/bin/lib/Image/ExifTool/XMP2.pl +1 -0
- data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
- data/bin/lib/Image/ExifTool/ZISRAW.pm +123 -0
- data/bin/perl-Image-ExifTool.spec +42 -41
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +9 -8
@@ -20,7 +20,7 @@ use strict;
|
|
20
20
|
use vars qw($VERSION);
|
21
21
|
use Image::ExifTool qw(:DataAccess :Utils);
|
22
22
|
|
23
|
-
$VERSION = '1.
|
23
|
+
$VERSION = '1.18';
|
24
24
|
|
25
25
|
# road map of directory locations in GIF images
|
26
26
|
my %gifMap = (
|
@@ -115,6 +115,11 @@ my %gifMap = (
|
|
115
115
|
ValueConv => '$val + 1',
|
116
116
|
},
|
117
117
|
5 => 'BackgroundColor',
|
118
|
+
6 => {
|
119
|
+
Name => 'PixelAspectRatio',
|
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',
|
@@ -27,7 +27,7 @@ use vars qw($VERSION);
|
|
27
27
|
use Image::ExifTool qw(:Public);
|
28
28
|
use Image::ExifTool::GPS;
|
29
29
|
|
30
|
-
$VERSION = '1.
|
30
|
+
$VERSION = '1.63';
|
31
31
|
|
32
32
|
sub JITTER() { return 2 } # maximum time jitter
|
33
33
|
|
@@ -217,7 +217,7 @@ sub LoadTrackLog($$;$)
|
|
217
217
|
# (don't set format yet because we want to read HFDTE first)
|
218
218
|
$nmeaStart = 'B' ;
|
219
219
|
next;
|
220
|
-
} elsif (/^HFDTE(\d{2})(\d{2})(\d{2})/) {
|
220
|
+
} elsif (/^HFDTE(?:DATE:)?(\d{2})(\d{2})(\d{2})/) {
|
221
221
|
my $year = $3 + ($3 >= 70 ? 1900 : 2000);
|
222
222
|
$dateFlarm = Time::Local::timegm(0,0,0,$1,$2-1,$year);
|
223
223
|
$nmeaStart = 'B' ;
|
@@ -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.
|
19
|
+
$VERSION = '1.06';
|
20
20
|
|
21
21
|
sub ProcessGoPro($$$);
|
22
22
|
sub ProcessString($$$);
|
@@ -77,6 +77,9 @@ my %addUnits = (
|
|
77
77
|
Notes => 'accelerator readings in m/s2',
|
78
78
|
Binary => 1,
|
79
79
|
},
|
80
|
+
# ANGX (GPMF-GEOC) - seen -0.05 (fmt d, Max)
|
81
|
+
# ANGY (GPMF-GEOC) - seen 179.9 (fmt d, Max)
|
82
|
+
# ANGZ (GPMF-GEOC) - seen 0.152 (fmt d, Max)
|
80
83
|
ALLD => 'AutoLowLightDuration', #1 (gpmd) (untested)
|
81
84
|
# APTO (GPMF) - seen: 'RAW', 'DYNM' (fmt c)
|
82
85
|
ATTD => { #PH (Karma)
|
@@ -105,16 +108,14 @@ my %addUnits = (
|
|
105
108
|
},
|
106
109
|
# BRID (GPMF) - seen: 0 (fmt B)
|
107
110
|
# BROD (GPMF) - seen: 'ASK','' (fmt c)
|
111
|
+
# CALH (GPMF-GEOC) - seen 3040 (fmt L, Max)
|
112
|
+
# CALW (GPMF-GEOC) - seen 4056 (fmt L, Max)
|
108
113
|
CASN => 'CameraSerialNumber', #PH (GPMF - seen: 'C3221324545448', fmt c)
|
109
|
-
# CINF (GPMF) - seen: 0x67376be7709bc8876a8baf3940908618, 0xe230988539b30cf5f016627ae8fc5395
|
110
|
-
#
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
# TYPE=LLLLLfffBB
|
115
|
-
# SCAL=1000 1 1 1 1 1 1 1 1 1
|
116
|
-
Binary => 1,
|
117
|
-
},
|
114
|
+
# CINF (GPMF) - seen: 0x67376be7709bc8876a8baf3940908618, 0xe230988539b30cf5f016627ae8fc5395,
|
115
|
+
# 0x8bcbe424acc5b37d7d77001635198b3b (fmt B) (Camera INFormation?)
|
116
|
+
# CMOD (GPMF) - seen: 12,13,17 [12 360 video, 13 time-laps video, 17 JPEG] (fmt B)
|
117
|
+
# CRTX (GPMF-BACK/FRNT) - double[1]
|
118
|
+
# CRTY (GPMF-BACK/FRNT) - double[1]
|
118
119
|
CSEN => { #PH (Karma)
|
119
120
|
Name => 'CoyoteSense',
|
120
121
|
# UNIT=s,rad/s,rad/s,rad/s,g,g,g,,,,
|
@@ -122,13 +123,27 @@ my %addUnits = (
|
|
122
123
|
# SCAL=1000 1 1 1 1 1 1 1 1 1 1
|
123
124
|
Binary => 1,
|
124
125
|
},
|
126
|
+
CYTS => { #PH (Karma)
|
127
|
+
Name => 'CoyoteStatus',
|
128
|
+
# UNIT=s,,,,,rad,rad,rad,,
|
129
|
+
# TYPE=LLLLLfffBB
|
130
|
+
# SCAL=1000 1 1 1 1 1 1 1 1 1
|
131
|
+
Binary => 1,
|
132
|
+
},
|
125
133
|
DEVC => { #PH (gpmd,GPMF, fmt \0)
|
126
134
|
Name => 'DeviceContainer',
|
127
135
|
SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' },
|
128
|
-
|
129
|
-
|
136
|
+
# (Max) DVID=1,DVNM='Global Settings',VERS,FMWR,LINF,CINF,CASN,MINF,MUID,CMOD,MTYP,OREN,
|
137
|
+
# DZOM,DZST,SMTR,PRTN,PTWB,PTSH,PTCL,EXPT,PIMX,PIMN,PTEV,RATE,SROT,ZFOV,VLTE,VLTA,
|
138
|
+
# EISE,EISA,AUPT,AUDO,BROD,BRID,PVUL,PRJT,SOFF
|
139
|
+
# (Max) DVID='GEOC',DVNM='Geometry Calibrations',SHFX,SHFY,SHFZ,ANGX,ANGY,ANGZ,CALW,CALH
|
140
|
+
# (Max) DVID='BACK',DVNM='Back Lens',KLNS,CTRX,CTRY,MFOV,SFTR
|
141
|
+
# (Max) DVID='FRNT',DVNM='Front Lens',KLNS,CTRX,CTRY,MFOV,SFTR
|
142
|
+
# (Max) DVID='HLMT',DVNM='Highlights'
|
143
|
+
},
|
144
|
+
# DVID (GPMF) - DeviceID; seen: 1 (fmt L), HLMT (fmt F), GEOC (fmt F), 'BACK' (fmt F, Max)
|
130
145
|
DVID => { Name => 'DeviceID', Unknown => 1 }, #2 (gpmd)
|
131
|
-
# DVNM (GPMF) seen: 'Video Global Settings' (fmt c), 'Highlights' (fmt c)
|
146
|
+
# DVNM (GPMF) seen: 'Video Global Settings' (fmt c), 'Highlights' (fmt c), 'Geometry Calibrations' (Max)
|
132
147
|
# DVNM (gpmd) seen: 'Camera' (Hero5), 'Hero6 Black' (Hero6), 'GoPro Karma v1.0' (Karma)
|
133
148
|
DVNM => 'DeviceName', #PH (n/c)
|
134
149
|
DZOM => { #PH (GPMF - seen: 'Y', fmt c)
|
@@ -136,10 +151,10 @@ my %addUnits = (
|
|
136
151
|
PrintConv => { N => 'No', Y => 'Yes' },
|
137
152
|
},
|
138
153
|
# DZST (GPMF) - seen: 0 (fmt L) (something to do with digital zoom maybe?)
|
139
|
-
EISA => { #PH (GPMF) - seen: 'Y','N',
|
154
|
+
EISA => { #PH (GPMF) - seen: 'Y','N','HS EIS','N/A' (fmt c) [N was for a time-lapse video]
|
140
155
|
Name => 'ElectronicImageStabilization',
|
141
156
|
},
|
142
|
-
# EISE (GPMF) - seen: 'Y' (fmt c)
|
157
|
+
# EISE (GPMF) - seen: 'Y','N' (fmt c)
|
143
158
|
EMPT => { Name => 'Empty', Unknown => 1 }, #2 (gpmd)
|
144
159
|
ESCS => { #PH (Karma)
|
145
160
|
Name => 'EscapeStatus',
|
@@ -215,7 +230,8 @@ my %addUnits = (
|
|
215
230
|
RawConv => '$val', # necessary to use scaled value instead of raw data as subdir data
|
216
231
|
SubDirectory => { TagTable => 'Image::ExifTool::GoPro::KBAT' },
|
217
232
|
},
|
218
|
-
#
|
233
|
+
# KLNS (GPMF-BACK/FRNT) - double[5] (fmt d, Max)
|
234
|
+
# LINF (GPMF) - seen: LAJ7061916601668,C3341326002180,C33632245450981 (fmt c) (Lens INFormation?)
|
219
235
|
LNED => { #PH (Karma)
|
220
236
|
Name => 'LocalPositionNED',
|
221
237
|
# UNIT=s,m,m,m,m/s,m/s,m/s
|
@@ -224,12 +240,13 @@ my %addUnits = (
|
|
224
240
|
Binary => 1,
|
225
241
|
},
|
226
242
|
MAGN => 'Magnetometer', #1 (gpmd) (units of uT)
|
243
|
+
# MFOV (GPMF-BACK/FRNT) - seen: 100 (fmt d, Max)
|
227
244
|
MINF => { #PH (GPMF - seen: HERO6 Black, fmt c)
|
228
245
|
Name => 'Model',
|
229
246
|
Groups => { 2 => 'Camera' },
|
230
247
|
Description => 'Camera Model Name',
|
231
248
|
},
|
232
|
-
# MTYP (GPMF) - seen: 0,1,11 [1 for time-lapse video, 11 for JPEG] (fmt B)
|
249
|
+
# MTYP (GPMF) - seen: 0,1,5,11 [1 for time-lapse video, 5 for 360 video, 11 for JPEG] (fmt B)
|
233
250
|
# MUID (GPMF) - seen: 3882563431 2278071152 967805802 411471936 0 0 0 0 (fmt L)
|
234
251
|
OREN => { #PH (GPMF - seen: 'U', fmt c)
|
235
252
|
Name => 'AutoRotation',
|
@@ -245,7 +262,7 @@ my %addUnits = (
|
|
245
262
|
PIMX => 'AutoISOMax', #PH (GPMF - seen: 1600, fmt L)
|
246
263
|
# PRAW (APP6) - seen: 0, 'N', 'Y' (fmt c)
|
247
264
|
PRES => 'PhotoResolution', #PH (APP6 - seen: '12MP_W')
|
248
|
-
# PRJT (APP6) - seen: 'GPRO' (fmt F, Hero8)
|
265
|
+
# PRJT (APP6) - seen: 'GPRO','EACO' (fmt F, Hero8, Max)
|
249
266
|
PRTN => { #PH (GPMF - seen: 'N', fmt c)
|
250
267
|
Name => 'ProTune',
|
251
268
|
PrintConv => {
|
@@ -257,7 +274,7 @@ my %addUnits = (
|
|
257
274
|
PTEV => 'ExposureCompensation', #PH (GPMF - seen: '0.0', fmt c)
|
258
275
|
PTSH => 'Sharpness', #PH (GPMF - seen: 'HIGH', fmt c)
|
259
276
|
PTWB => 'WhiteBalance', #PH (GPMF - seen: 'AUTO', fmt c)
|
260
|
-
# PVUL (APP6) - seen: 'F' (fmt c, Hero8)
|
277
|
+
# PVUL (APP6) - seen: 'F' (fmt c, Hero8, Max)
|
261
278
|
RATE => 'Rate', #PH (GPMF - seen: '0_5SEC', fmt c; APP6 - seen: '4_1SEC')
|
262
279
|
RMRK => { #2 (gpmd)
|
263
280
|
Name => 'Comments',
|
@@ -274,6 +291,10 @@ my %addUnits = (
|
|
274
291
|
# SCAL=1000 0.00999999977648258 0.00999999977648258 100
|
275
292
|
%addUnits,
|
276
293
|
},
|
294
|
+
# SFTR (GPMF-BACK/FRNT) - seen 0.999,1.00004 (fmt d, Max)
|
295
|
+
# SHFX (GPMF-GEOC) - seen 22.92 (fmt d, Max)
|
296
|
+
# SHFY (GPMF-GEOC) - seen 0.123 (fmt d, Max)
|
297
|
+
# SHFZ (GPMF-GEOC) - seen 36.06 (fmt d, Max)
|
277
298
|
SHUT => { #2 (gpmd)
|
278
299
|
Name => 'ExposureTimes',
|
279
300
|
PrintConv => q{
|
@@ -295,7 +316,8 @@ my %addUnits = (
|
|
295
316
|
ValueConv => '$self->Decode($val, "Latin")',
|
296
317
|
},
|
297
318
|
# SMTR (GPMF) - seen: 'N' (fmt c)
|
298
|
-
# SOFF (APP6) - seen: 0 (fmt L, Hero8)
|
319
|
+
# SOFF (APP6) - seen: 0 (fmt L, Hero8, Max)
|
320
|
+
# SROT (GPMF) - seen 20.60 (fmt f, Max)
|
299
321
|
STMP => { #1 (gpmd)
|
300
322
|
Name => 'TimeStamp',
|
301
323
|
ValueConv => '$val / 1e6',
|
@@ -338,7 +360,10 @@ my %addUnits = (
|
|
338
360
|
Unknown => 1,
|
339
361
|
ValueConv => '$self->Decode($val, "Latin")',
|
340
362
|
},
|
341
|
-
|
363
|
+
VERS => {
|
364
|
+
Name => 'MetadataVersion',
|
365
|
+
PrintConv => '$val =~ tr/ /./; $val',
|
366
|
+
},
|
342
367
|
VFOV => { #PH (GPMF - seen: 'W', fmt c)
|
343
368
|
Name => 'FieldOfView',
|
344
369
|
PrintConv => {
|
@@ -360,7 +385,7 @@ my %addUnits = (
|
|
360
385
|
Name => 'WhiteBalanceRGB',
|
361
386
|
Binary => 1,
|
362
387
|
},
|
363
|
-
# ZFOV (APP6) - seen: 148.34 (fmt f, Hero8)
|
388
|
+
# ZFOV (APP6,GPMF) - seen: 148.34, 0 (fmt f, Hero8, Max)
|
364
389
|
);
|
365
390
|
|
366
391
|
# GoPro GPS5 tags (ref 2) (Hero5,Hero6)
|
@@ -590,6 +615,7 @@ sub ProcessString($$$)
|
|
590
615
|
# Process GoPro metadata (gpmd samples, GPMF box, or APP6) (ref PH/1/2)
|
591
616
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
|
592
617
|
# Returns: 1 on success
|
618
|
+
# - with hack to check for encrypted text in gpmd data (Rove Stealth 4K)
|
593
619
|
sub ProcessGoPro($$$)
|
594
620
|
{
|
595
621
|
my ($et, $dirInfo, $tagTablePtr) = @_;
|
@@ -890,7 +890,7 @@ sub ParsePictureTiming($$)
|
|
890
890
|
|
891
891
|
#------------------------------------------------------------------------------
|
892
892
|
# Process H.264 Supplementary Enhancement Information (ref 1/PH)
|
893
|
-
# Inputs: 0)
|
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
|
@@ -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.
|
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,
|
72
|
-
and RealAudio files. ID3v2 tags which support multiple
|
73
|
-
Comment and Lyrics) are extracted by specifying the tag name,
|
74
|
-
dash ('-'), then a 3-character ISO 639-2 language code (eg.
|
75
|
-
See L<http://www.id3.org/> for the official ID3
|
76
|
-
L<http://www.loc.gov/standards/iso639-2/php/code_list.php>
|
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',
|
@@ -1347,7 +1367,7 @@ sub ProcessID3v2($$$)
|
|
1347
1367
|
# Inputs: 0) ExifTool object reference, 1) dirInfo reference
|
1348
1368
|
# Returns: 1 on success, 0 if this file didn't contain ID3 information
|
1349
1369
|
# - also processes audio data if any ID3 information was found
|
1350
|
-
# - sets ExifTool DoneID3 to 1 when called, or to
|
1370
|
+
# - sets ExifTool DoneID3 to 1 when called, or to trailer size if an ID3v1 trailer exists
|
1351
1371
|
sub ProcessID3($$)
|
1352
1372
|
{
|
1353
1373
|
my ($et, $dirInfo) = @_;
|
@@ -1426,8 +1446,9 @@ sub ProcessID3($$)
|
|
1426
1446
|
#
|
1427
1447
|
# read ID3v1 trailer if it exists
|
1428
1448
|
#
|
1449
|
+
my $trailSize = 0;
|
1429
1450
|
if ($raf->Seek(-128, 2) and $raf->Read($tBuff, 128) == 128 and $tBuff =~ /^TAG/) {
|
1430
|
-
|
1451
|
+
$trailSize = 128;
|
1431
1452
|
%id3Trailer = (
|
1432
1453
|
DataPt => \$tBuff,
|
1433
1454
|
DataPos => $raf->Tell() - 128,
|
@@ -1437,8 +1458,59 @@ sub ProcessID3($$)
|
|
1437
1458
|
$id3Len += length($tBuff);
|
1438
1459
|
$rtnVal = 1;
|
1439
1460
|
# load 'Enhanced TAG' information if available
|
1440
|
-
|
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+/) {
|
1441
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');
|
1442
1514
|
}
|
1443
1515
|
}
|
1444
1516
|
#
|
@@ -1583,6 +1655,8 @@ under the same terms as Perl itself.
|
|
1583
1655
|
|
1584
1656
|
=item L<http://www.fortunecity.com/underworld/sonic/3/id3tag.html>
|
1585
1657
|
|
1658
|
+
=item L<https://id3.org/Lyrics3>
|
1659
|
+
|
1586
1660
|
=back
|
1587
1661
|
|
1588
1662
|
=head1 SEE ALSO
|
@@ -23,14 +23,15 @@ my $charset;
|
|
23
23
|
|
24
24
|
#------------------------------------------------------------------------------
|
25
25
|
# Read CSV file
|
26
|
-
# Inputs: 0) CSV file name, file ref or RAF ref, 1) database hash ref,
|
26
|
+
# Inputs: 0) CSV file name, file ref or RAF ref, 1) database hash ref,
|
27
|
+
# 2) missing tag value, 3) delimiter if other than ','
|
27
28
|
# Returns: undef on success, or error string
|
28
29
|
# Notes: There are various flavours of CSV, but here we assume that only
|
29
30
|
# double quotes are escaped, and they are escaped by doubling them
|
30
|
-
sub ReadCSV(
|
31
|
+
sub ReadCSV($$;$$)
|
31
32
|
{
|
32
33
|
local ($_, $/);
|
33
|
-
my ($file, $database, $missingValue) = @_;
|
34
|
+
my ($file, $database, $missingValue, $delim) = @_;
|
34
35
|
my ($buff, @tags, $found, $err, $raf, $openedFile);
|
35
36
|
|
36
37
|
if (UNIVERSAL::isa($file, 'File::RandomAccess')) {
|
@@ -45,6 +46,7 @@ sub ReadCSV($$;$)
|
|
45
46
|
$openedFile = 1;
|
46
47
|
$raf = new File::RandomAccess(\*CSVFILE);
|
47
48
|
}
|
49
|
+
$delim = ',' unless defined $delim;
|
48
50
|
# set input record separator by first newline found in the file
|
49
51
|
# (safe because first line should contain only tag names)
|
50
52
|
while ($raf->Read($buff, 65536)) {
|
@@ -53,18 +55,18 @@ sub ReadCSV($$;$)
|
|
53
55
|
$raf->Seek(0,0);
|
54
56
|
while ($raf->ReadLine($buff)) {
|
55
57
|
my (@vals, $v, $i, %fileInfo);
|
56
|
-
my @toks = split
|
58
|
+
my @toks = split /\Q$delim/, $buff;
|
57
59
|
while (@toks) {
|
58
60
|
($v = shift @toks) =~ s/^ +//; # remove leading spaces
|
59
61
|
if ($v =~ s/^"//) {
|
60
62
|
# quoted value must end in an odd number of quotes
|
61
63
|
while ($v !~ /("+)\s*$/ or not length($1) & 1) {
|
62
64
|
if (@toks) {
|
63
|
-
$v .=
|
65
|
+
$v .= $delim . shift @toks;
|
64
66
|
} else {
|
65
67
|
# read another line from the file
|
66
68
|
$raf->ReadLine($buff) or last;
|
67
|
-
@toks = split
|
69
|
+
@toks = split /\Q$delim/, $buff;
|
68
70
|
last unless @toks;
|
69
71
|
$v .= shift @toks;
|
70
72
|
}
|
@@ -330,9 +332,10 @@ Read CSV or JSON file into a database hash.
|
|
330
332
|
2) Optional string used to represent an undefined (missing) tag value.
|
331
333
|
(Used for deleting tags.)
|
332
334
|
|
333
|
-
3)
|
334
|
-
|
335
|
-
|
335
|
+
3) For ReadCSV this gives the delimiter for CSV entries, with a default of
|
336
|
+
",". For ReadJSON this is the character set for converting Unicode escape
|
337
|
+
sequences in strings, with a default of "UTF8". See the ExifTool Charset
|
338
|
+
option for a list of valid character sets.
|
336
339
|
|
337
340
|
=item Return Value:
|
338
341
|
|