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