exiftool_vendored 12.17.1 → 12.32.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 +225 -1
- data/bin/MANIFEST +23 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +45 -43
- data/bin/arg_files/xmp2exif.args +2 -1
- data/bin/config_files/acdsee.config +193 -6
- data/bin/config_files/convert_regions.config +25 -14
- data/bin/config_files/cuepointlist.config +70 -0
- data/bin/config_files/example.config +2 -9
- data/bin/exiftool +142 -87
- data/bin/fmt_files/gpx.fmt +2 -2
- data/bin/fmt_files/gpx_wpt.fmt +2 -2
- data/bin/fmt_files/kml.fmt +1 -1
- data/bin/fmt_files/kml_track.fmt +1 -1
- data/bin/lib/Image/ExifTool/Apple.pm +3 -2
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +30 -12
- data/bin/lib/Image/ExifTool/CBOR.pm +277 -0
- data/bin/lib/Image/ExifTool/Canon.pm +49 -18
- data/bin/lib/Image/ExifTool/DJI.pm +6 -6
- data/bin/lib/Image/ExifTool/DPX.pm +13 -2
- data/bin/lib/Image/ExifTool/DjVu.pm +6 -5
- data/bin/lib/Image/ExifTool/Exif.pm +28 -11
- data/bin/lib/Image/ExifTool/FITS.pm +13 -2
- data/bin/lib/Image/ExifTool/FlashPix.pm +35 -10
- data/bin/lib/Image/ExifTool/FujiFilm.pm +19 -8
- data/bin/lib/Image/ExifTool/GPS.pm +22 -11
- data/bin/lib/Image/ExifTool/Geotag.pm +13 -2
- data/bin/lib/Image/ExifTool/GoPro.pm +16 -1
- data/bin/lib/Image/ExifTool/ICC_Profile.pm +2 -2
- data/bin/lib/Image/ExifTool/ID3.pm +15 -3
- data/bin/lib/Image/ExifTool/JPEG.pm +74 -4
- data/bin/lib/Image/ExifTool/JSON.pm +27 -4
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +393 -16
- data/bin/lib/Image/ExifTool/LIF.pm +153 -0
- data/bin/lib/Image/ExifTool/Lang/nl.pm +60 -59
- data/bin/lib/Image/ExifTool/M2TS.pm +137 -5
- data/bin/lib/Image/ExifTool/MIE.pm +4 -3
- data/bin/lib/Image/ExifTool/MRC.pm +341 -0
- data/bin/lib/Image/ExifTool/MWG.pm +3 -3
- data/bin/lib/Image/ExifTool/MXF.pm +1 -1
- data/bin/lib/Image/ExifTool/MacOS.pm +1 -1
- data/bin/lib/Image/ExifTool/Microsoft.pm +298 -82
- data/bin/lib/Image/ExifTool/Nikon.pm +19 -8
- data/bin/lib/Image/ExifTool/NikonSettings.pm +28 -11
- data/bin/lib/Image/ExifTool/Olympus.pm +6 -3
- data/bin/lib/Image/ExifTool/Other.pm +93 -0
- data/bin/lib/Image/ExifTool/PDF.pm +9 -12
- data/bin/lib/Image/ExifTool/PNG.pm +8 -7
- data/bin/lib/Image/ExifTool/Panasonic.pm +28 -3
- data/bin/lib/Image/ExifTool/Pentax.pm +28 -5
- data/bin/lib/Image/ExifTool/PhaseOne.pm +4 -3
- data/bin/lib/Image/ExifTool/Photoshop.pm +6 -0
- data/bin/lib/Image/ExifTool/QuickTime.pm +247 -88
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +283 -141
- data/bin/lib/Image/ExifTool/README +3 -0
- data/bin/lib/Image/ExifTool/RIFF.pm +89 -12
- data/bin/lib/Image/ExifTool/Samsung.pm +48 -10
- data/bin/lib/Image/ExifTool/Shortcuts.pm +9 -0
- data/bin/lib/Image/ExifTool/Sony.pm +237 -78
- data/bin/lib/Image/ExifTool/TagInfoXML.pm +1 -0
- data/bin/lib/Image/ExifTool/TagLookup.pm +4125 -4028
- data/bin/lib/Image/ExifTool/TagNames.pod +644 -286
- data/bin/lib/Image/ExifTool/Torrent.pm +18 -11
- data/bin/lib/Image/ExifTool/WriteExif.pl +1 -1
- data/bin/lib/Image/ExifTool/WriteIPTC.pl +1 -1
- data/bin/lib/Image/ExifTool/WritePDF.pl +1 -0
- data/bin/lib/Image/ExifTool/WritePNG.pl +2 -0
- data/bin/lib/Image/ExifTool/WritePostScript.pl +1 -0
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +55 -21
- data/bin/lib/Image/ExifTool/WriteXMP.pl +7 -3
- data/bin/lib/Image/ExifTool/Writer.pl +47 -10
- data/bin/lib/Image/ExifTool/XMP.pm +39 -14
- data/bin/lib/Image/ExifTool/XMP2.pl +2 -1
- data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
- data/bin/lib/Image/ExifTool/ZISRAW.pm +121 -2
- data/bin/lib/Image/ExifTool.pm +223 -72
- data/bin/lib/Image/ExifTool.pod +114 -93
- data/bin/perl-Image-ExifTool.spec +43 -42
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +28 -13
@@ -47,7 +47,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
47
47
|
use Image::ExifTool::Exif;
|
48
48
|
use Image::ExifTool::GPS;
|
49
49
|
|
50
|
-
$VERSION = '2.
|
50
|
+
$VERSION = '2.69';
|
51
51
|
|
52
52
|
sub ProcessMOV($$;$);
|
53
53
|
sub ProcessKeys($$$);
|
@@ -65,6 +65,7 @@ sub Process_gsen($$$);
|
|
65
65
|
sub ProcessRIFFTrailer($$$);
|
66
66
|
sub ProcessTTAD($$$);
|
67
67
|
sub ProcessNMEA($$$);
|
68
|
+
sub ProcessGPSLog($$$);
|
68
69
|
sub SaveMetaKeys($$$);
|
69
70
|
# ++^^^^^^^^^^^^++
|
70
71
|
sub ParseItemLocation($$);
|
@@ -160,8 +161,15 @@ my %ftypLookup = (
|
|
160
161
|
'F4P ' => 'Protected Video for Adobe Flash Player 9+ (.F4P)', # video/mp4
|
161
162
|
'F4V ' => 'Video for Adobe Flash Player 9+ (.F4V)', # video/mp4
|
162
163
|
'isc2' => 'ISMACryp 2.0 Encrypted File', # ?/enc-isoff-generic
|
163
|
-
'iso2' => 'MP4 Base Media v2 [ISO 14496-12:2005]', # video/mp4
|
164
|
-
'
|
164
|
+
'iso2' => 'MP4 Base Media v2 [ISO 14496-12:2005]', # video/mp4 (or audio)
|
165
|
+
'iso3' => 'MP4 Base Media v3', # video/mp4 (or audio)
|
166
|
+
'iso4' => 'MP4 Base Media v4', # video/mp4 (or audio)
|
167
|
+
'iso5' => 'MP4 Base Media v5', # video/mp4 (or audio)
|
168
|
+
'iso6' => 'MP4 Base Media v6', # video/mp4 (or audio)
|
169
|
+
'iso7' => 'MP4 Base Media v7', # video/mp4 (or audio)
|
170
|
+
'iso8' => 'MP4 Base Media v8', # video/mp4 (or audio)
|
171
|
+
'iso9' => 'MP4 Base Media v9', # video/mp4 (or audio)
|
172
|
+
'isom' => 'MP4 Base Media v1 [IS0 14496-12:2003]', # video/mp4 (or audio)
|
165
173
|
'JP2 ' => 'JPEG 2000 Image (.JP2) [ISO 15444-1 ?]', # image/jp2
|
166
174
|
'JP20' => 'Unknown, from GPAC samples (prob non-existent)',
|
167
175
|
'jpm ' => 'JPEG 2000 Compound Image (.JPM) [ISO 15444-6]', # image/jpm
|
@@ -221,9 +229,10 @@ my %timeInfo = (
|
|
221
229
|
Writable => 1,
|
222
230
|
Permanent => 1,
|
223
231
|
DelValue => 0,
|
224
|
-
# It is not uncommon for brain-dead software to use the wrong time zero,
|
225
|
-
# so assume a time zero of Jan 1, 1970 if the date is before this
|
232
|
+
# It is not uncommon for brain-dead software to use the wrong time zero, it should be
|
233
|
+
# Jan 1, 1904, so assume a time zero of Jan 1, 1970 if the date is before this
|
226
234
|
# Note: This value will be in UTC if generated by a system that is aware of the time zone
|
235
|
+
# (also note: this code is duplicated for the CreateDate tag)
|
227
236
|
RawConv => q{
|
228
237
|
my $offset = (66 * 365 + 17) * 24 * 3600;
|
229
238
|
return $val - $offset if $val >= $offset or $$self{OPTIONS}{QuickTimeUTC};
|
@@ -243,7 +252,11 @@ my %timeInfo = (
|
|
243
252
|
},
|
244
253
|
# (all CR3 files store UTC times - PH)
|
245
254
|
ValueConv => 'ConvertUnixTime($val, $self->Options("QuickTimeUTC") || $$self{FileType} eq "CR3")',
|
246
|
-
ValueConvInv =>
|
255
|
+
ValueConvInv => q{
|
256
|
+
$val = GetUnixTime($val, $self->Options("QuickTimeUTC"));
|
257
|
+
return undef unless defined $val;
|
258
|
+
return $val + (66 * 365 + 17) * 24 * 3600;
|
259
|
+
},
|
247
260
|
PrintConv => '$self->ConvertDateTime($val)',
|
248
261
|
PrintConvInv => '$self->InverseDateTime($val)',
|
249
262
|
# (can't put Groups here because they aren't constant!)
|
@@ -258,11 +271,15 @@ my %unknownInfo = (
|
|
258
271
|
Unknown => 1,
|
259
272
|
ValueConv => '$val =~ /^([\x20-\x7e]*)\0*$/ ? $1 : \$val',
|
260
273
|
);
|
274
|
+
|
275
|
+
# multi-language text with 6-byte header
|
276
|
+
my %langText = ( IText => 6 );
|
277
|
+
|
261
278
|
# parsing for most of the 3gp udta language text boxes
|
262
|
-
my %
|
279
|
+
my %langText3gp = (
|
263
280
|
Notes => 'used in 3gp videos',
|
264
|
-
IText => 6,
|
265
281
|
Avoid => 1,
|
282
|
+
IText => 6,
|
266
283
|
);
|
267
284
|
|
268
285
|
# 4-character Vendor ID codes (ref PH)
|
@@ -670,6 +687,15 @@ my %eeBox2 = (
|
|
670
687
|
udat => { #PH (GPS NMEA-format log written by Datakam Player software)
|
671
688
|
Name => 'GPSLog',
|
672
689
|
Binary => 1, # (actually ASCII, but very lengthy)
|
690
|
+
Notes => 'parsed to extract GPS separately when ExtractEmbedded is used',
|
691
|
+
RawConv => q{
|
692
|
+
$val =~ s/\0+$//; # remove trailing nulls
|
693
|
+
if (length $val and $$self{OPTIONS}{ExtractEmbedded}) {
|
694
|
+
my $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
|
695
|
+
Image::ExifTool::QuickTime::ProcessGPSLog($self, { DataPt => \$val }, $tagTbl);
|
696
|
+
}
|
697
|
+
return $val;
|
698
|
+
},
|
673
699
|
},
|
674
700
|
# meta - proprietary XML information written by some Flip cameras - PH
|
675
701
|
# beam - 16 bytes found in an iPhone video
|
@@ -708,6 +734,11 @@ my %eeBox2 = (
|
|
708
734
|
Unknown => 1,
|
709
735
|
Binary => 1,
|
710
736
|
},
|
737
|
+
sefd => {
|
738
|
+
Name => 'SamsungTrailer',
|
739
|
+
SubDirectory => { TagTable => 'Image::ExifTool::Samsung::Trailer' },
|
740
|
+
},
|
741
|
+
# 'samn'? - seen in Vantrue N2S sample video
|
711
742
|
);
|
712
743
|
|
713
744
|
# MPEG-4 'ftyp' atom
|
@@ -1169,6 +1200,15 @@ my %eeBox2 = (
|
|
1169
1200
|
Name => 'CreateDate',
|
1170
1201
|
Groups => { 2 => 'Time' },
|
1171
1202
|
%timeInfo,
|
1203
|
+
RawConv => q{
|
1204
|
+
my $offset = (66 * 365 + 17) * 24 * 3600;
|
1205
|
+
if ($val >= $offset or $$self{OPTIONS}{QuickTimeUTC}) {
|
1206
|
+
$val -= $offset;
|
1207
|
+
} elsif ($val and not $$self{IsWriting}) {
|
1208
|
+
$self->WarnOnce('Patched incorrect time zero for QuickTime date/time tag',1);
|
1209
|
+
}
|
1210
|
+
return $$self{CreateDate} = $val;
|
1211
|
+
},
|
1172
1212
|
# this is int64u if MovieHeaderVersion == 1 (ref 13)
|
1173
1213
|
Hook => '$$self{MovieHeaderVersion} and $format = "int64u", $varSize += 4',
|
1174
1214
|
},
|
@@ -1545,47 +1585,43 @@ my %eeBox2 = (
|
|
1545
1585
|
# the following are 3gp tags, references:
|
1546
1586
|
# http://atomicparsley.sourceforge.net
|
1547
1587
|
# http://www.3gpp.org/ftp/tsg_sa/WG4_CODEC/TSGS4_25/Docs/
|
1548
|
-
# (note that all %
|
1549
|
-
cprt => { Name => 'Copyright', %
|
1550
|
-
auth => { Name => 'Author', %
|
1551
|
-
titl => { Name => 'Title', %
|
1552
|
-
dscp => { Name => 'Description',%
|
1553
|
-
perf => { Name => 'Performer', %
|
1554
|
-
gnre => { Name => 'Genre', %
|
1555
|
-
albm => { Name => 'Album', %
|
1556
|
-
coll => { Name => 'CollectionName', %
|
1588
|
+
# (note that all %langText3gp tags are Avoid => 1)
|
1589
|
+
cprt => { Name => 'Copyright', %langText3gp, Groups => { 2 => 'Author' } },
|
1590
|
+
auth => { Name => 'Author', %langText3gp, Groups => { 2 => 'Author' } },
|
1591
|
+
titl => { Name => 'Title', %langText3gp },
|
1592
|
+
dscp => { Name => 'Description',%langText3gp },
|
1593
|
+
perf => { Name => 'Performer', %langText3gp },
|
1594
|
+
gnre => { Name => 'Genre', %langText3gp },
|
1595
|
+
albm => { Name => 'Album', %langText3gp },
|
1596
|
+
coll => { Name => 'CollectionName', %langText3gp }, #17
|
1557
1597
|
rtng => {
|
1558
1598
|
Name => 'Rating',
|
1599
|
+
Writable => 'undef',
|
1600
|
+
Avoid => 1,
|
1559
1601
|
# (4-byte flags, 4-char entity, 4-char criteria, 2-byte lang, string)
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 12));
|
1565
|
-
$lang = $lang ? "($lang) " : '';
|
1566
|
-
$val = substr($val, 14);
|
1567
|
-
$val = $self->Decode($val, 'UCS2') if $val =~ /^\xfe\xff/;
|
1568
|
-
return $lang . $str . ' ' . $val;
|
1569
|
-
},
|
1602
|
+
IText => 14, # (14 bytes before string)
|
1603
|
+
Notes => 'string in the form "Entity=XXXX Criteria=XXXX XXXXX", used in 3gp videos',
|
1604
|
+
ValueConv => '$val=~s/^(.{4})(.{4})/Entity=$1 Criteria=$2 /i; $val',
|
1605
|
+
ValueConvInv => '$val=~s/Entity=(.{4}) Criteria=(.{4}) ?/$1$2/i; $val',
|
1570
1606
|
},
|
1571
1607
|
clsf => {
|
1572
1608
|
Name => 'Classification',
|
1609
|
+
Writable => 'undef',
|
1610
|
+
Avoid => 1,
|
1573
1611
|
# (4-byte flags, 4-char entity, 2-byte index, 2-byte lang, string)
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 10));
|
1579
|
-
$lang = $lang ? "($lang) " : '';
|
1580
|
-
$val = substr($val, 12);
|
1581
|
-
$val = $self->Decode($val, 'UCS2') if $val =~ /^\xfe\xff/;
|
1582
|
-
return $lang . $str . ' ' . $val;
|
1583
|
-
},
|
1612
|
+
IText => 12,
|
1613
|
+
Notes => 'string in the form "Entity=XXXX Index=### XXXXX", used in 3gp videos',
|
1614
|
+
ValueConv => '$val=~s/^(.{4})(.{2})/"Entity=$1 Index=".unpack("n",$2)." "/ie; $val',
|
1615
|
+
ValueConvInv => '$val=~s/Entity=(.{4}) Index=(\d+) ?/$1.pack("n",$2)/ie; $val',
|
1584
1616
|
},
|
1585
1617
|
kywd => {
|
1586
1618
|
Name => 'Keywords',
|
1587
|
-
# (4 byte flags, 2-byte lang, 1-byte count, count x pascal strings)
|
1619
|
+
# (4 byte flags, 2-byte lang, 1-byte count, count x pascal strings, ref 17)
|
1620
|
+
# (but I have also seen a simple string written by iPhone, so don't make writable yet)
|
1621
|
+
Notes => "not writable because Apple doesn't follow the 3gp specification",
|
1588
1622
|
RawConv => q{
|
1623
|
+
my $sep = $self->Options('ListSep');
|
1624
|
+
return join($sep, split /\0+/, $val) unless $val =~ /^\0/; # (iPhone)
|
1589
1625
|
return '<err>' unless length $val >= 7;
|
1590
1626
|
my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 4));
|
1591
1627
|
$lang = $lang ? "($lang) " : '';
|
@@ -1601,27 +1637,30 @@ my %eeBox2 = (
|
|
1601
1637
|
push @vals, $v;
|
1602
1638
|
$pos += $len;
|
1603
1639
|
}
|
1604
|
-
my $sep = $self->Options('ListSep');
|
1605
1640
|
return $lang . join($sep, @vals);
|
1606
1641
|
},
|
1607
1642
|
},
|
1608
1643
|
loci => {
|
1609
1644
|
Name => 'LocationInformation',
|
1610
1645
|
Groups => { 2 => 'Location' },
|
1646
|
+
Writable => 'undef',
|
1647
|
+
IText => 6,
|
1648
|
+
Avoid => 1,
|
1649
|
+
NoDecode => 1, # (we'll decode the data ourself)
|
1650
|
+
Notes => q{
|
1651
|
+
string in the form "XXXXX Role=XXX Lat=XXX Lon=XXX Alt=XXX Body=XXX
|
1652
|
+
Notes=XXX", used in 3gp videos
|
1653
|
+
},
|
1611
1654
|
# (4-byte flags, 2-byte lang, location string, 1-byte role, 4-byte fixed longitude,
|
1612
1655
|
# 4-byte fixed latitude, 4-byte fixed altitude, body string, notes string)
|
1613
1656
|
RawConv => q{
|
1614
|
-
return '<err>' unless length $val >= 6;
|
1615
|
-
my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 4));
|
1616
|
-
$lang = $lang ? "($lang) " : '';
|
1617
|
-
$val = substr($val, 6);
|
1618
1657
|
my $str;
|
1619
1658
|
if ($val =~ /^\xfe\xff/) {
|
1620
1659
|
$val =~ s/^(\xfe\xff(.{2})*?)\0\0//s or return '<err>';
|
1621
1660
|
$str = $self->Decode($1, 'UCS2');
|
1622
1661
|
} else {
|
1623
1662
|
$val =~ s/^(.*?)\0//s or return '<err>';
|
1624
|
-
$str = $1;
|
1663
|
+
$str = $self->Decode($1, 'UTF8');
|
1625
1664
|
}
|
1626
1665
|
$str = '(none)' unless length $str;
|
1627
1666
|
return '<err>' if length $val < 13;
|
@@ -1636,27 +1675,52 @@ my %eeBox2 = (
|
|
1636
1675
|
if ($val =~ s/^(\xfe\xff(.{2})*?)\0\0//s) {
|
1637
1676
|
$str .= ' Body=' . $self->Decode($1, 'UCS2');
|
1638
1677
|
} elsif ($val =~ s/^(.*?)\0//s) {
|
1639
|
-
$str .=
|
1678
|
+
$str .= ' Body=' . $self->Decode($1, 'UTF8');
|
1640
1679
|
}
|
1641
1680
|
if ($val =~ s/^(\xfe\xff(.{2})*?)\0\0//s) {
|
1642
1681
|
$str .= ' Notes=' . $self->Decode($1, 'UCS2');
|
1643
1682
|
} elsif ($val =~ s/^(.*?)\0//s) {
|
1644
|
-
$str .=
|
1683
|
+
$str .= ' Notes=' . $self->Decode($1, 'UTF8');
|
1645
1684
|
}
|
1646
|
-
return $
|
1685
|
+
return $str;
|
1686
|
+
},
|
1687
|
+
RawConvInv => q{
|
1688
|
+
my ($role, $lat, $lon, $alt, $body, $note);
|
1689
|
+
$lat = $1 if $val =~ s/ Lat=([-+]?[.\d]+)//i;
|
1690
|
+
$lon = $1 if $val =~ s/ Lon=([-+]?[.\d]+)//i;
|
1691
|
+
$alt = $1 if $val =~ s/ Alt=([-+]?[.\d]+)//i;
|
1692
|
+
$note = $val =~ s/ Notes=(.*)//i ? $1 : '';
|
1693
|
+
$body = $val =~ s/ Body=(.*)//i ? $1 : '';
|
1694
|
+
$role = $val =~ s/ Role=(.*)//i ? $1 : '';
|
1695
|
+
$val = '' if $val eq '(none)';
|
1696
|
+
$role = {shooting=>0,real=>1,fictional=>2}->{lc $role} || 0;
|
1697
|
+
return $self->Encode($val, 'UTF8') . "\0" . Set8u($role) .
|
1698
|
+
SetFixed32s(defined $lon ? $lon : 999) .
|
1699
|
+
SetFixed32s(defined $lat ? $lat : 999) .
|
1700
|
+
SetFixed32s(defined $alt ? $alt : 0) .
|
1701
|
+
$self->Encode($body) . "\0" .
|
1702
|
+
$self->Encode($note) . "\0";
|
1647
1703
|
},
|
1648
1704
|
},
|
1649
1705
|
yrrc => {
|
1650
1706
|
Name => 'Year',
|
1707
|
+
Writable => 'undef',
|
1651
1708
|
Groups => { 2 => 'Time' },
|
1652
|
-
|
1709
|
+
Avoid => 1,
|
1710
|
+
Notes => 'used in 3gp videos',
|
1711
|
+
ValueConv => 'length($val) >= 6 ? unpack("x4n",$val) : "<err>"',
|
1712
|
+
ValueConvInv => 'pack("Nn",0,$val)',
|
1653
1713
|
},
|
1654
1714
|
urat => { #17
|
1655
1715
|
Name => 'UserRating',
|
1656
|
-
|
1716
|
+
Writable => 'undef',
|
1717
|
+
Notes => 'used in 3gp videos',
|
1718
|
+
Avoid => 1,
|
1719
|
+
ValueConv => q{
|
1657
1720
|
return '<err>' unless length $val >= 8;
|
1658
|
-
|
1721
|
+
unpack('x7C', $val);
|
1659
1722
|
},
|
1723
|
+
ValueConvInv => 'pack("N2",0,$val)',
|
1660
1724
|
},
|
1661
1725
|
# tsel - TrackSelection (ref 17)
|
1662
1726
|
# Apple tags (ref 16[dead] -- see ref 25 instead)
|
@@ -1988,7 +2052,11 @@ my %eeBox2 = (
|
|
1988
2052
|
# ---- Microsoft ----
|
1989
2053
|
Xtra => { #PH (microsoft)
|
1990
2054
|
Name => 'MicrosoftXtra',
|
1991
|
-
|
2055
|
+
WriteGroup => 'Microsoft',
|
2056
|
+
SubDirectory => {
|
2057
|
+
DirName => 'Microsoft',
|
2058
|
+
TagTable => 'Image::ExifTool::Microsoft::Xtra',
|
2059
|
+
},
|
1992
2060
|
},
|
1993
2061
|
# ---- Minolta ----
|
1994
2062
|
MMA0 => { #PH (DiMage 7Hi)
|
@@ -2037,7 +2105,7 @@ my %eeBox2 = (
|
|
2037
2105
|
SubDirectory => { TagTable => 'Image::ExifTool::Olympus::thmb' },
|
2038
2106
|
},{ #17 (format is in bytes 3-7)
|
2039
2107
|
Name => 'ThumbnailImage',
|
2040
|
-
Condition => '$$valPt =~ /^.{8}\xff\xd8\xff\xdb/s',
|
2108
|
+
Condition => '$$valPt =~ /^.{8}\xff\xd8\xff[\xdb\xe0]/s',
|
2041
2109
|
Groups => { 2 => 'Preview' },
|
2042
2110
|
RawConv => 'substr($val, 8)',
|
2043
2111
|
Binary => 1,
|
@@ -2201,6 +2269,12 @@ my %eeBox2 = (
|
|
2201
2269
|
# opax - 164 bytes unknown (center and affine arrays? ref 26)
|
2202
2270
|
# opai - 32 bytes (maybe contains a serial number starting at byte 16? - PH) (rgb gains, degamma, gamma? ref 26)
|
2203
2271
|
# intv - 16 bytes all zero
|
2272
|
+
# ---- Xaiomi ----
|
2273
|
+
mcvr => {
|
2274
|
+
Name => 'PreviewImage',
|
2275
|
+
Groups => { 2 => 'Preview' },
|
2276
|
+
Binary => 1,
|
2277
|
+
},
|
2204
2278
|
# ---- Unknown ----
|
2205
2279
|
# CDET - 128 bytes (unknown origin)
|
2206
2280
|
# mtyp - 4 bytes all zero (some drone video)
|
@@ -2638,6 +2712,7 @@ my %eeBox2 = (
|
|
2638
2712
|
colr => [{
|
2639
2713
|
Name => 'ICC_Profile',
|
2640
2714
|
Condition => '$$valPt =~ /^(prof|rICC)/',
|
2715
|
+
Permanent => 0, # (in QuickTime, this writes a zero-length box instead of deleting)
|
2641
2716
|
SubDirectory => {
|
2642
2717
|
TagTable => 'Image::ExifTool::ICC_Profile::Main',
|
2643
2718
|
Start => 4,
|
@@ -2994,9 +3069,9 @@ my %eeBox2 = (
|
|
2994
3069
|
3-character ISO 639-2 language code and an optional ISO 3166-1 alpha 2
|
2995
3070
|
country code to the tag name (eg. "ItemList:Title-fra" or
|
2996
3071
|
"ItemList::Title-fra-FR"). When creating a new Meta box to contain the
|
2997
|
-
ItemList directory, by default ExifTool
|
2998
|
-
|
2999
|
-
|
3072
|
+
ItemList directory, by default ExifTool adds an 'mdir' (Metadata) Handler
|
3073
|
+
box because Apple software may ignore ItemList tags otherwise, but the API
|
3074
|
+
L<QuickTimeHandler|../ExifTool.html#QuickTimeHandler> option may be set to 0 to avoid this.
|
3000
3075
|
},
|
3001
3076
|
# in this table, binary 1 and 2-byte "data"-type tags are interpreted as
|
3002
3077
|
# int8u and int16u. Multi-byte binary "data" tags are extracted as binary data.
|
@@ -6157,13 +6232,12 @@ my %eeBox2 = (
|
|
6157
6232
|
PROCESS_PROC => \&ProcessKeys,
|
6158
6233
|
WRITE_PROC => \&WriteKeys,
|
6159
6234
|
CHECK_PROC => \&CheckQTValue,
|
6160
|
-
VARS => { LONG_TAGS =>
|
6235
|
+
VARS => { LONG_TAGS => 7 },
|
6161
6236
|
WRITABLE => 1,
|
6162
6237
|
# (not PREFERRED when writing)
|
6163
6238
|
GROUPS => { 1 => 'Keys' },
|
6164
6239
|
WRITE_GROUP => 'Keys',
|
6165
6240
|
LANG_INFO => \&GetLangInfo,
|
6166
|
-
FORMAT => 'string',
|
6167
6241
|
NOTES => q{
|
6168
6242
|
This directory contains a list of key names which are used to decode tags
|
6169
6243
|
written by the "mdta" handler. Also in this table are a few tags found in
|
@@ -6229,6 +6303,10 @@ my %eeBox2 = (
|
|
6229
6303
|
'location.ISO6709' => {
|
6230
6304
|
Name => 'GPSCoordinates',
|
6231
6305
|
Groups => { 2 => 'Location' },
|
6306
|
+
Notes => q{
|
6307
|
+
Google Photos may ignore this if the coorinates have more than 5 digits
|
6308
|
+
after the decimal
|
6309
|
+
},
|
6232
6310
|
ValueConv => \&ConvertISO6709,
|
6233
6311
|
ValueConvInv => \&ConvInvISO6709,
|
6234
6312
|
PrintConv => \&PrintGPSCoordinates,
|
@@ -6265,6 +6343,11 @@ my %eeBox2 = (
|
|
6265
6343
|
PrintConv => '$self->ConvertDateTime($val)',
|
6266
6344
|
PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist)
|
6267
6345
|
},
|
6346
|
+
'location.accuracy.horizontal' => { Name => 'LocationAccuracyHorizontal' },
|
6347
|
+
'live-photo.auto' => { Name => 'LivePhotoAuto', Writable => 'int8u' },
|
6348
|
+
'live-photo.vitality-score' => { Name => 'LivePhotoVitalityScore', Writable => 'float' },
|
6349
|
+
'live-photo.vitality-scoring-version' => { Name => 'LivePhotoVitalityScoringVersion', Writable => 'int64s' },
|
6350
|
+
'apple.photos.variation-identifier' => { Name => 'ApplePhotosVariationIdentifier', Writable => 'int64s' },
|
6268
6351
|
'direction.facing' => { Name => 'CameraDirection', Groups => { 2 => 'Location' } },
|
6269
6352
|
'direction.motion' => { Name => 'CameraMotion', Groups => { 2 => 'Location' } },
|
6270
6353
|
'location.body' => { Name => 'LocationBody', Groups => { 2 => 'Location' } },
|
@@ -6300,11 +6383,15 @@ my %eeBox2 = (
|
|
6300
6383
|
# com.divergentmedia.clipwrap.manufacturer ('Sony')
|
6301
6384
|
# com.divergentmedia.clipwrap.originalDateTime ('2013/2/6 10:30:40+0200')
|
6302
6385
|
#
|
6303
|
-
# seen in timed metadata (mebx), and added dynamically to the table
|
6304
|
-
#
|
6386
|
+
# seen in timed metadata (mebx), and added dynamically to the table via SaveMetaKeys()
|
6387
|
+
# NOTE: these tags are not writable! (timed metadata cannot yet be written)
|
6305
6388
|
#
|
6306
6389
|
# (mdta)com.apple.quicktime.video-orientation (dtyp=66, int16s)
|
6307
|
-
'video-orientation' => {
|
6390
|
+
'video-orientation' => {
|
6391
|
+
Name => 'VideoOrientation',
|
6392
|
+
Writable => 0,
|
6393
|
+
PrintConv => \%Image::ExifTool::Exif::orientation, #PH (NC)
|
6394
|
+
},
|
6308
6395
|
# (mdta)com.apple.quicktime.live-photo-info (dtyp=com.apple.quicktime.com.apple.quicktime.live-photo-info)
|
6309
6396
|
'live-photo-info' => {
|
6310
6397
|
Name => 'LivePhotoInfo',
|
@@ -6364,10 +6451,11 @@ my %eeBox2 = (
|
|
6364
6451
|
# iTunes info ('----') atoms
|
6365
6452
|
%Image::ExifTool::QuickTime::iTunesInfo = (
|
6366
6453
|
PROCESS_PROC => \&ProcessMOV,
|
6367
|
-
GROUPS => { 2 => 'Audio' },
|
6454
|
+
GROUPS => { 1 => 'iTunes', 2 => 'Audio' },
|
6368
6455
|
NOTES => q{
|
6369
6456
|
ExifTool will extract any iTunesInfo tags that exist, even if they are not
|
6370
|
-
defined in this table.
|
6457
|
+
defined in this table. These tags belong to the family 1 "iTunes" group,
|
6458
|
+
and are not currently writable.
|
6371
6459
|
},
|
6372
6460
|
# 'mean'/'name'/'data' atoms form a triplet, but unfortunately
|
6373
6461
|
# I haven't been able to find any documentation on this.
|
@@ -6428,9 +6516,45 @@ my %eeBox2 = (
|
|
6428
6516
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::EncodingParams' },
|
6429
6517
|
},
|
6430
6518
|
# also heard about 'iTunPGAP', but I haven't seen a sample
|
6431
|
-
|
6432
|
-
|
6433
|
-
|
6519
|
+
# all tags below were added based on samples I have seen - PH
|
6520
|
+
DISCNUMBER => 'DiscNumber',
|
6521
|
+
TRACKNUMBER => 'TrackNumber',
|
6522
|
+
ARTISTS => 'Artists',
|
6523
|
+
CATALOGNUMBER => 'CatalogNumber',
|
6524
|
+
RATING => 'Rating',
|
6525
|
+
MEDIA => 'Media',
|
6526
|
+
SCRIPT => 'Script', # character set? (seen 'Latn')
|
6527
|
+
BARCODE => 'Barcode',
|
6528
|
+
LABEL => 'Label',
|
6529
|
+
MOOD => 'Mood',
|
6530
|
+
popularimeter => 'Popularimeter',
|
6531
|
+
'Dynamic Range (DR)'=> 'DynamicRange',
|
6532
|
+
initialkey => 'InitialKey',
|
6533
|
+
originalyear => 'OriginalYear',
|
6534
|
+
originaldate => 'OriginalDate',
|
6535
|
+
'~length' => 'Length', # play length? (ie. duration?)
|
6536
|
+
replaygain_track_gain=>'ReplayTrackGain',
|
6537
|
+
replaygain_track_peak=>'ReplayTrackPeak',
|
6538
|
+
'Volume Level (ReplayGain)'=> 'ReplayVolumeLevel',
|
6539
|
+
'Dynamic Range (R128)'=> 'DynamicRangeR128',
|
6540
|
+
'Volume Level (R128)' => 'VolumeLevelR128',
|
6541
|
+
'Peak Level (Sample)' => 'PeakLevelSample',
|
6542
|
+
'Peak Level (R128)' => 'PeakLevelR128',
|
6543
|
+
# also seen (many from forum12777):
|
6544
|
+
# 'MusicBrainz Album Release Country'
|
6545
|
+
# 'MusicBrainz Album Type'
|
6546
|
+
# 'MusicBrainz Album Status'
|
6547
|
+
# 'MusicBrainz Track Id'
|
6548
|
+
# 'MusicBrainz Release Track Id'
|
6549
|
+
# 'MusicBrainz Album Id'
|
6550
|
+
# 'MusicBrainz Album Artist Id'
|
6551
|
+
# 'MusicBrainz Artist Id'
|
6552
|
+
# 'Acoustid Id' (sic)
|
6553
|
+
# 'Tool Version'
|
6554
|
+
# 'Tool Name'
|
6555
|
+
# 'ISRC'
|
6556
|
+
# 'HDCD'
|
6557
|
+
# 'Waveform'
|
6434
6558
|
);
|
6435
6559
|
|
6436
6560
|
# iTunes audio encoding parameters
|
@@ -7589,7 +7713,11 @@ my %eeBox2 = (
|
|
7589
7713
|
8 => {
|
7590
7714
|
Name => 'HandlerType',
|
7591
7715
|
Format => 'undef[4]',
|
7592
|
-
RawConv =>
|
7716
|
+
RawConv => q{
|
7717
|
+
$$self{HandlerType} = $val unless $val eq 'alis' or $val eq 'url ';
|
7718
|
+
$$self{HasHandler}{$val} = 1; # remember all our handlers
|
7719
|
+
return $val;
|
7720
|
+
},
|
7593
7721
|
PrintConvColumns => 2,
|
7594
7722
|
PrintConv => {
|
7595
7723
|
alis => 'Alias Data', #PH
|
@@ -7694,7 +7822,7 @@ my %eeBox2 = (
|
|
7694
7822
|
$val =~ s/\0+$//; # remove trailing nulls
|
7695
7823
|
if (length $val and $$self{OPTIONS}{ExtractEmbedded}) {
|
7696
7824
|
my $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
|
7697
|
-
Image::ExifTool::QuickTime::
|
7825
|
+
Image::ExifTool::QuickTime::ProcessGPSLog($self, { DataPt => \$val }, $tagTbl);
|
7698
7826
|
}
|
7699
7827
|
return $val;
|
7700
7828
|
},
|
@@ -8574,7 +8702,7 @@ sub QuickTimeFormat($$)
|
|
8574
8702
|
my ($flags, $len) = @_;
|
8575
8703
|
my $format;
|
8576
8704
|
if ($flags == 0x15 or $flags == 0x16) {
|
8577
|
-
$format = { 1=>'int8', 2=>'int16', 4=>'int32' }->{$len};
|
8705
|
+
$format = { 1=>'int8', 2=>'int16', 4=>'int32', 8=>'int64' }->{$len};
|
8578
8706
|
$format .= $flags == 0x15 ? 's' : 'u' if $format;
|
8579
8707
|
} elsif ($flags == 0x17) {
|
8580
8708
|
$format = 'float';
|
@@ -8795,20 +8923,28 @@ sub ProcessKeys($$$)
|
|
8795
8923
|
my $ns = substr($$dataPt, $pos + 4, 4);
|
8796
8924
|
my $tag = substr($$dataPt, $pos + 8, $len - 8);
|
8797
8925
|
$tag =~ s/\0.*//s; # truncate at null
|
8926
|
+
my $full = $tag;
|
8798
8927
|
$tag =~ s/^com\.(apple\.quicktime\.)?// if $ns eq 'mdta'; # remove apple quicktime domain
|
8799
8928
|
$tag = "Tag_$ns" unless $tag;
|
8800
|
-
|
8801
|
-
my $tagInfo
|
8802
|
-
|
8803
|
-
$tagInfo = $et->GetTagInfo($
|
8804
|
-
|
8929
|
+
my $short = $tag;
|
8930
|
+
my $tagInfo;
|
8931
|
+
for (;;) {
|
8932
|
+
$tagInfo = $et->GetTagInfo($tagTablePtr, $tag) and last;
|
8933
|
+
# also try ItemList and UserData tables
|
8934
|
+
$tagInfo = $et->GetTagInfo($itemList, $tag) and last;
|
8935
|
+
$tagInfo = $et->GetTagInfo($userData, $tag) and last;
|
8936
|
+
# (I have some samples where the tag is a reversed ItemList or UserData tag ID)
|
8937
|
+
if ($tag =~ /^\w{3}\xa9$/) {
|
8938
|
+
$tag = pack('N', unpack('V', $tag));
|
8939
|
+
$tagInfo = $et->GetTagInfo($itemList, $tag) and last;
|
8805
8940
|
$tagInfo = $et->GetTagInfo($userData, $tag);
|
8806
|
-
|
8807
|
-
$tag = pack('N', unpack('V', $tag));
|
8808
|
-
$tagInfo = $et->GetTagInfo($itemList, $tag);
|
8809
|
-
$tagInfo or $tagInfo = $et->GetTagInfo($userData, $tag);
|
8810
|
-
}
|
8941
|
+
last;
|
8811
8942
|
}
|
8943
|
+
if ($tag eq $full) {
|
8944
|
+
$tag = $short;
|
8945
|
+
last;
|
8946
|
+
}
|
8947
|
+
$tag = $full;
|
8812
8948
|
}
|
8813
8949
|
my ($newInfo, $msg);
|
8814
8950
|
if ($tagInfo) {
|
@@ -8849,6 +8985,7 @@ sub ProcessKeys($$$)
|
|
8849
8985
|
delete $$itemList{$id};
|
8850
8986
|
}
|
8851
8987
|
if ($newInfo) {
|
8988
|
+
$$newInfo{KeysID} = $tag; # save original ID for use in family 7 group name
|
8852
8989
|
AddTagToTable($itemList, $id, $newInfo);
|
8853
8990
|
$msg or $msg = '';
|
8854
8991
|
$out and print $out "$$et{INDENT}Added ItemList Tag $id = ($ns) $tag$msg\n";
|
@@ -8927,6 +9064,7 @@ sub ProcessMOV($$;$)
|
|
8927
9064
|
if ($raf->Read($buff, $size-8) == $size-8) {
|
8928
9065
|
$raf->Seek(-($size-8), 1);
|
8929
9066
|
my $type = substr($buff, 0, 4);
|
9067
|
+
$$et{save_ftyp} = $type;
|
8930
9068
|
# see if we know the extension for this file type
|
8931
9069
|
if ($ftypLookup{$type} and $ftypLookup{$type} =~ /\(\.(\w+)/) {
|
8932
9070
|
$fileType = $1;
|
@@ -9201,6 +9339,7 @@ ItemID: foreach $id (keys %$items) {
|
|
9201
9339
|
Name => $name,
|
9202
9340
|
Description => $desc,
|
9203
9341
|
};
|
9342
|
+
$et->VPrint(0, $$et{INDENT}, "[adding QuickTime:$name]\n");
|
9204
9343
|
AddTagToTable($tagTablePtr, $tag, $tagInfo);
|
9205
9344
|
}
|
9206
9345
|
# ignore 8-byte header
|
@@ -9212,9 +9351,9 @@ ItemID: foreach $id (keys %$items) {
|
|
9212
9351
|
$val = \$buff;
|
9213
9352
|
}
|
9214
9353
|
}
|
9215
|
-
|
9354
|
+
$$tagInfo{List} = 1; # (allow any of these tags to have multiple data elements)
|
9355
|
+
$et->VerboseInfo($tag, $tagInfo, Value => $val) if $verbose;
|
9216
9356
|
} else {
|
9217
|
-
undef %triplet if $tag eq 'mean';
|
9218
9357
|
$triplet{$tag} = substr($val,4) if length($val) > 4;
|
9219
9358
|
undef $tagInfo; # don't store this tag
|
9220
9359
|
}
|
@@ -9298,7 +9437,13 @@ ItemID: foreach $id (keys %$items) {
|
|
9298
9437
|
# (shouldn't be null terminated, but some software writes it anyway)
|
9299
9438
|
$value =~ s/\0$// unless $$tagInfo{Binary};
|
9300
9439
|
} else {
|
9301
|
-
|
9440
|
+
if (not $format) {
|
9441
|
+
$format = QuickTimeFormat($flags, $len);
|
9442
|
+
} elsif ($format =~ /^int\d+([us])$/) {
|
9443
|
+
# adjust integer to available length (but not int64)
|
9444
|
+
my $fmt = { 1=>'int8', 2=>'int16', 4=>'int32' }->{$len};
|
9445
|
+
$format = $fmt . $1 if defined $fmt;
|
9446
|
+
}
|
9302
9447
|
if ($format) {
|
9303
9448
|
$value = ReadValue(\$value, 0, $format, $$tagInfo{Count}, $len);
|
9304
9449
|
} elsif (not $$tagInfo{ValueConv}) {
|
@@ -9350,9 +9495,9 @@ ItemID: foreach $id (keys %$items) {
|
|
9350
9495
|
}
|
9351
9496
|
for (;;) {
|
9352
9497
|
my ($len, $lang);
|
9353
|
-
if ($$tagInfo{IText} and $$tagInfo{IText}
|
9354
|
-
last if $pos +
|
9355
|
-
$pos +=
|
9498
|
+
if ($$tagInfo{IText} and $$tagInfo{IText} >= 6) {
|
9499
|
+
last if $pos + $$tagInfo{IText} > $size;
|
9500
|
+
$pos += $$tagInfo{IText} - 2;
|
9356
9501
|
$lang = unpack("x${pos}n", $val);
|
9357
9502
|
$pos += 2;
|
9358
9503
|
$len = $size - $pos;
|
@@ -9372,7 +9517,7 @@ ItemID: foreach $id (keys %$items) {
|
|
9372
9517
|
# ignore any empty entries (or null padding) after the first
|
9373
9518
|
next if not $len and $pos;
|
9374
9519
|
my $str = substr($val, $pos, $len);
|
9375
|
-
my $langInfo;
|
9520
|
+
my ($langInfo, $enc);
|
9376
9521
|
if (($lang < 0x400 or $lang == 0x7fff) and $str !~ /^\xfe\xff/) {
|
9377
9522
|
# this is a Macintosh language code
|
9378
9523
|
# a language code of 0 is Macintosh english, so treat as default
|
@@ -9389,15 +9534,22 @@ ItemID: foreach $id (keys %$items) {
|
|
9389
9534
|
}
|
9390
9535
|
# the spec says only "Macintosh text encoding", but
|
9391
9536
|
# allow this to be configured by the user
|
9392
|
-
$
|
9537
|
+
$enc = $charsetQuickTime;
|
9393
9538
|
} else {
|
9394
9539
|
# convert language code to ASCII (ignore read-only bit)
|
9395
9540
|
$lang = UnpackLang($lang);
|
9396
9541
|
# may be either UTF-8 or UTF-16BE
|
9397
|
-
|
9542
|
+
$enc = $str=~s/^\xfe\xff// ? 'UTF16' : 'UTF8';
|
9543
|
+
}
|
9544
|
+
unless ($$tagInfo{NoDecode}) {
|
9398
9545
|
$str = $et->Decode($str, $enc);
|
9546
|
+
$str =~ s/\0+$//; # remove any trailing nulls (eg. 3gp tags)
|
9547
|
+
}
|
9548
|
+
if ($$tagInfo{IText} and $$tagInfo{IText} > 6) {
|
9549
|
+
my $n = $$tagInfo{IText} - 6;
|
9550
|
+
# add back extra bytes (eg. 'rtng' box)
|
9551
|
+
$str = substr($val, $pos-$n-2, $n) . $str;
|
9399
9552
|
}
|
9400
|
-
$str =~ s/\0+$//; # remove any trailing nulls (eg. 3gp tags)
|
9401
9553
|
$langInfo = GetLangInfoQT($et, $tagInfo, $lang) if $lang;
|
9402
9554
|
$et->FoundTag($langInfo || $tagInfo, $str);
|
9403
9555
|
$pos += $len;
|
@@ -9447,6 +9599,13 @@ ItemID: foreach $id (keys %$items) {
|
|
9447
9599
|
($size, $tag) = unpack('Na4', $buff);
|
9448
9600
|
++$index if defined $index;
|
9449
9601
|
}
|
9602
|
+
# tweak file type based on track content ("iso*" and "dash" ftyp only)
|
9603
|
+
if ($topLevel and $$et{VALUE}{FileType} and $$et{VALUE}{FileType} eq 'MP4' and
|
9604
|
+
$$et{save_ftyp} and $$et{HasHandler} and $$et{save_ftyp} =~ /^(iso|dash)/ and
|
9605
|
+
$$et{HasHandler}{soun} and not $$et{HasHandler}{vide})
|
9606
|
+
{
|
9607
|
+
$et->OverrideFileType('M4A', 'audio/mp4');
|
9608
|
+
}
|
9450
9609
|
# fill in missing defaults for alternate language tags
|
9451
9610
|
# (the first language is taken as the default)
|
9452
9611
|
if ($doDefaultLang and $$et{QTLang}) {
|