exiftool-vendored.exe 12.91.0 → 12.96.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.
- package/bin/exiftool_files/exiftool.pl +16 -2896
- package/bin/exiftool_files/lib/Image/ExifTool/Canon.pm +135 -3
- package/bin/exiftool_files/lib/Image/ExifTool/Font.pm +15 -4
- package/bin/exiftool_files/lib/Image/ExifTool/Geotag.pm +19 -5
- package/bin/exiftool_files/lib/Image/ExifTool/Jpeg2000.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Nikon.pm +2 -1
- package/bin/exiftool_files/lib/Image/ExifTool/NikonSettings.pm +56 -1
- package/bin/exiftool_files/lib/Image/ExifTool/OpenEXR.pm +3 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PostScript.pm +3 -12
- package/bin/exiftool_files/lib/Image/ExifTool/QuickTime.pm +34 -14
- package/bin/exiftool_files/lib/Image/ExifTool/QuickTimeStream.pl +117 -37
- package/bin/exiftool_files/lib/Image/ExifTool/Samsung.pm +5 -3
- package/bin/exiftool_files/lib/Image/ExifTool/TagLookup.pm +6920 -6904
- package/bin/exiftool_files/lib/Image/ExifTool/TagNames.pod +104 -5
- package/bin/exiftool_files/lib/Image/ExifTool/WriteQuickTime.pl +48 -16
- package/bin/exiftool_files/lib/Image/ExifTool/Writer.pl +8 -54
- package/bin/exiftool_files/lib/Image/ExifTool.pm +66 -4
- package/bin/exiftool_files/windows_exiftool.txt +2831 -0
- package/package.json +5 -5
|
@@ -109,7 +109,7 @@ my %insvLimit = (
|
|
|
109
109
|
The tags below are extracted from timed metadata in QuickTime and other
|
|
110
110
|
formats of video files when the ExtractEmbedded option is used. Although
|
|
111
111
|
most of these tags are combined into the single table below, ExifTool
|
|
112
|
-
currently reads
|
|
112
|
+
currently reads 77 different formats of timed GPS metadata from video files.
|
|
113
113
|
},
|
|
114
114
|
VARS => { NO_ID => 1 },
|
|
115
115
|
GPSLatitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', RawConv => '$$self{FoundGPSLatitude} = 1; $val' },
|
|
@@ -757,6 +757,15 @@ my %insvLimit = (
|
|
|
757
757
|
10 => { Name => 'FusionYPR', Format => 'float[3]' },
|
|
758
758
|
);
|
|
759
759
|
|
|
760
|
+
#------------------------------------------------------------------------------
|
|
761
|
+
# Convert unsigned 32-bit integer to signed
|
|
762
|
+
# Inputs: <none> (uses value in $_)
|
|
763
|
+
# Returns: signed integer
|
|
764
|
+
sub SignedInt32()
|
|
765
|
+
{
|
|
766
|
+
return $_ < 0x80000000 ? $_ : $_ - 4294967296;
|
|
767
|
+
}
|
|
768
|
+
|
|
760
769
|
#------------------------------------------------------------------------------
|
|
761
770
|
# Save information from keys in OtherSampleDesc directory for processing timed metadata
|
|
762
771
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
|
|
@@ -1474,6 +1483,31 @@ sub ConvertLatLon($$)
|
|
|
1474
1483
|
$_[1] = $deg + ($_[1] - $deg * 100) / 60;
|
|
1475
1484
|
}
|
|
1476
1485
|
|
|
1486
|
+
#------------------------------------------------------------------------------
|
|
1487
|
+
# Decrypt Lucky data
|
|
1488
|
+
# Inputs: 0) string to decrypt, 1) encryption key
|
|
1489
|
+
# Returns: decrypted string
|
|
1490
|
+
my @luckyKeys = ('luckychip gps', 'customer ## gps');
|
|
1491
|
+
sub DecryptLucky($$) {
|
|
1492
|
+
my ($str, $key) = @_;
|
|
1493
|
+
my @str = unpack('C*', $str);
|
|
1494
|
+
my @key = unpack('C*', $key);
|
|
1495
|
+
my @enc = (0..255);
|
|
1496
|
+
my ($i, $j, $k) = (0, 0, 0);
|
|
1497
|
+
do {
|
|
1498
|
+
$j = ($j + $enc[$i] + $key[$i % length($key)]) & 0xff;
|
|
1499
|
+
@enc[$i,$j] = @enc[$j,$i];
|
|
1500
|
+
} while (++$i < 256);
|
|
1501
|
+
($i, $j, $k) = (0, 0, 0);
|
|
1502
|
+
do {
|
|
1503
|
+
$j = ($j + 1) & 0xff;
|
|
1504
|
+
$k = ($k + $enc[$j]) & 0xff;
|
|
1505
|
+
@enc[$j,$k] = @enc[$k,$j];
|
|
1506
|
+
$str[$i] ^= $enc[($enc[$j] + $enc[$k]) & 0xff];
|
|
1507
|
+
} while (++$i < @str);
|
|
1508
|
+
return pack('C*', @str);
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1477
1511
|
#------------------------------------------------------------------------------
|
|
1478
1512
|
# Process "freeGPS " data blocks
|
|
1479
1513
|
# Inputs: 0) ExifTool ref, 1) dirInfo ref {DataPt,SampleTime,SampleDuration}, 2) tagTable ref
|
|
@@ -1589,40 +1623,87 @@ sub ProcessFreeGPS($$$)
|
|
|
1589
1623
|
}
|
|
1590
1624
|
if (defined $lat) {
|
|
1591
1625
|
# extract accelerometer readings if GPS was valid
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
map { $_ = $_ - 4294967296 if $_ >= 0x80000000; $_ /= 256 } @acc;
|
|
1626
|
+
# and change to signed integer and divide by 256
|
|
1627
|
+
@acc = map { SignedInt32 / 256 } unpack('x68V3', $$dataPt);
|
|
1595
1628
|
}
|
|
1596
1629
|
|
|
1597
|
-
} elsif ($$dataPt =~ /^.{37}\0\0\0A([NS])([EW])/s) {
|
|
1630
|
+
} elsif ($$dataPt =~ /^.{37}\0\0\0A([NS])([EW])\0/s) {
|
|
1598
1631
|
|
|
1599
|
-
$debug and $et->FoundTag(GPSType => 3);
|
|
1600
|
-
# decode freeGPS from ViofoA119v3 dashcam (similar to Novatek GPS format)
|
|
1601
|
-
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 03 00 00 [..@.freeGPS ....]
|
|
1602
|
-
# 0010: 05 00 00 00 2f 00 00 00 03 00 00 00 13 00 00 00 [..../...........]
|
|
1603
|
-
# 0020: 09 00 00 00 1b 00 00 00 41 4e 57 00 25 d1 99 45 [........ANW.%..E]
|
|
1604
|
-
# 0030: f1 47 40 46 66 66 d2 41 85 eb 83 41 00 00 00 00 [.G@Fff.A...A....]
|
|
1605
1632
|
($latRef, $lonRef) = ($1, $2);
|
|
1606
1633
|
($hr,$min,$sec,$yr,$mon,$day) = unpack('x16V6', $$dataPt);
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
$
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
}
|
|
1617
|
-
$
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1634
|
+
# test for base64-encoded and encrypted lucky gps strings
|
|
1635
|
+
my ($notEnc, $notStr, $lt, $ln);
|
|
1636
|
+
if (length($$dataPt) < 0x78) {
|
|
1637
|
+
$notEnc = $notStr = 1;
|
|
1638
|
+
} else {
|
|
1639
|
+
$lt = substr($$dataPt, 0x2c, 20), # latitude
|
|
1640
|
+
$ln = substr($$dataPt, 0x40, 20), # longitude
|
|
1641
|
+
/^[A-Za-z0-9+\/]{8,20}={0,2}\0*$/ or $notEnc = 1, last foreach ($lt, $ln);
|
|
1642
|
+
/^\d{1,5}\.\d+\0*$/ or $notStr = 1, last foreach ($lt, $ln);
|
|
1643
|
+
}
|
|
1644
|
+
if ($notEnc and $notStr) {
|
|
1645
|
+
|
|
1646
|
+
$debug and $et->FoundTag(GPSType => '3a');
|
|
1647
|
+
# decode freeGPS from ViofoA119v3 dashcam (similar to Novatek GPS format)
|
|
1648
|
+
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 03 00 00 [..@.freeGPS ....]
|
|
1649
|
+
# 0010: 05 00 00 00 2f 00 00 00 03 00 00 00 13 00 00 00 [..../...........]
|
|
1650
|
+
# 0020: 09 00 00 00 1b 00 00 00 41 4e 57 00 25 d1 99 45 [........ANW.%..E]
|
|
1651
|
+
# 0030: f1 47 40 46 66 66 d2 41 85 eb 83 41 00 00 00 00 [.G@Fff.A...A....]
|
|
1652
|
+
if ($yr >= 2000) {
|
|
1653
|
+
# Kenwood dashcam sometimes stores absolute year and local time
|
|
1654
|
+
# (but sometimes year since 2000 and UTC time in same video!)
|
|
1655
|
+
require Time::Local;
|
|
1656
|
+
my $time = Image::ExifTool::TimeLocal($sec,$min,$hr,$day,$mon-1,$yr);
|
|
1657
|
+
($sec,$min,$hr,$day,$mon,$yr) = gmtime($time);
|
|
1658
|
+
$yr += 1900;
|
|
1659
|
+
++$mon;
|
|
1660
|
+
$et->WarnOnce('Converting GPSDateTime to UTC based on local time zone',1);
|
|
1661
|
+
}
|
|
1662
|
+
$lat = GetFloat($dataPt, 0x2c);
|
|
1663
|
+
$lon = GetFloat($dataPt, 0x30);
|
|
1664
|
+
$spd = GetFloat($dataPt, 0x34) * $knotsToKph;
|
|
1665
|
+
$trk = GetFloat($dataPt, 0x38);
|
|
1666
|
+
# (may be all zeros or int16u counting from 1 to 6 if not valid)
|
|
1667
|
+
my $tmp = substr($$dataPt, 60, 12);
|
|
1668
|
+
if ($tmp ne "\0\0\0\0\0\0\0\0\0\0\0\0" and $tmp ne "\x01\0\x02\0\x03\0\x04\0\x05\0\x06\0") {
|
|
1669
|
+
@acc = map { SignedInt32 / 256 } unpack('V3', $tmp);
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
} else {
|
|
1673
|
+
|
|
1674
|
+
$debug and $et->FoundTag(GPSType => '3b');
|
|
1675
|
+
# decode freeGPS from E-ACE B44 dashcam
|
|
1676
|
+
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 03 00 00 [..@.freeGPS ....]
|
|
1677
|
+
# 0010: 08 00 00 00 22 00 00 00 01 00 00 00 18 00 00 00 [...."...........]
|
|
1678
|
+
# 0020: 08 00 00 00 10 00 00 00 41 4e 45 00 67 4e 69 69 [........ANE.gNii]
|
|
1679
|
+
# 0030: 5a 38 4a 54 74 48 63 61 36 74 77 3d 00 00 00 00 [Z8JTtHca6tw=....]
|
|
1680
|
+
# 0040: 68 74 75 69 5a 4d 4a 53 73 58 55 58 37 4e 6f 3d [htuiZMJSsXUX7No=]
|
|
1681
|
+
# 0050: 00 00 00 00 64 3b ac 41 e1 3a 1d 43 2b 01 00 00 [....d;.A.:.C+...]
|
|
1682
|
+
# 0060: fd ff ff ff 43 00 00 00 32 4a 37 31 50 70 55 48 [....C...2J71PpUH]
|
|
1683
|
+
# 0070: 37 69 68 66 00 00 00 00 00 00 00 00 00 00 00 00 [7ihf............]
|
|
1684
|
+
# (16-byte string at 0x68 is base64 encoded and encrypted 'luckychip' string)
|
|
1685
|
+
$spd = GetFloat($dataPt, 0x54) * $knotsToKph;
|
|
1686
|
+
$trk = GetFloat($dataPt, 0x58);
|
|
1687
|
+
@acc = map SignedInt32, unpack('x92V3', $$dataPt);
|
|
1688
|
+
# (accelerometer scaling is roughly 1G=250-300, but it varies depending on the axis,
|
|
1689
|
+
# so leave the values as raw. The axes are positive acceleration up,left,forward)
|
|
1690
|
+
if ($notEnc) { # (not encrypted)
|
|
1691
|
+
($lat = $lt) =~ s/\0+$//;
|
|
1692
|
+
($lon = $ln) =~ s/\0+$//;
|
|
1693
|
+
} else {
|
|
1694
|
+
# decode base64 strings
|
|
1695
|
+
require Image::ExifTool::XMP;
|
|
1696
|
+
$_ = ${Image::ExifTool::XMP::DecodeBase64($_)} foreach ($lt, $ln);
|
|
1697
|
+
# try various keys to decrypt lat/lon
|
|
1698
|
+
my ($i, $ch, $key) = (0, 'a', $luckyKeys[0]);
|
|
1699
|
+
for (; $i<20; ++$i) {
|
|
1700
|
+
$i and ($key = $luckyKeys[1]) =~ s/#/$ch/g, ++$ch;
|
|
1701
|
+
($lat = DecryptLucky($lt, $key)) =~ /^\d{1,4}\.\d+$/ or undef($lat), next;
|
|
1702
|
+
($lon = DecryptLucky($ln, $key)) =~ /^\d{1,5}\.\d+$/ or undef($lon), next;
|
|
1703
|
+
last;
|
|
1704
|
+
}
|
|
1705
|
+
$lon or $et->WarnOnce('Unknown encryption for latitude/longitude');
|
|
1706
|
+
}
|
|
1626
1707
|
}
|
|
1627
1708
|
|
|
1628
1709
|
} elsif ($$dataPt =~ /^.{21}\0\0\0A([NS])([EW])/s) {
|
|
@@ -1683,7 +1764,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1683
1764
|
$trk -= 360 if $trk >= 360;
|
|
1684
1765
|
undef @acc;
|
|
1685
1766
|
} else {
|
|
1686
|
-
|
|
1767
|
+
@acc = map { SignedInt32 / 1000 } @acc; # (NC)
|
|
1687
1768
|
}
|
|
1688
1769
|
|
|
1689
1770
|
} elsif ($$dataPt =~ /^.{60}4W`b]S</s and length($$dataPt) >= 140) {
|
|
@@ -1787,7 +1868,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1787
1868
|
return 0;
|
|
1788
1869
|
}
|
|
1789
1870
|
# (not sure about acc scaling)
|
|
1790
|
-
|
|
1871
|
+
@acc = map { SignedInt32 / 1000 } @acc;
|
|
1791
1872
|
$lon = GetFloat($dataPt, 0x5c);
|
|
1792
1873
|
$lat = GetFloat($dataPt, 0x60);
|
|
1793
1874
|
$spd = GetFloat($dataPt, 0x64) * $knotsToKph;
|
|
@@ -1932,7 +2013,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1932
2013
|
# 0x7c - int32s[3] accelerometer * 1000
|
|
1933
2014
|
($latRef, $lonRef) = ($1, $2);
|
|
1934
2015
|
($hr,$min,$sec,$yr,$mon,$day,@acc) = unpack('x48V3x52V6', $$dataPt);
|
|
1935
|
-
|
|
2016
|
+
@acc = map { SignedInt32 / 1000 } @acc;
|
|
1936
2017
|
$lat = GetDouble($dataPt, 0x40);
|
|
1937
2018
|
$lon = GetDouble($dataPt, 0x50);
|
|
1938
2019
|
$spd = GetDouble($dataPt, 0x60) * $knotsToKph;
|
|
@@ -1948,8 +2029,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1948
2029
|
$lon = abs(GetFloat(\$dat, 8)); # (abs just to be safe)
|
|
1949
2030
|
$spd = GetFloat(\$dat, 12) * $knotsToKph;
|
|
1950
2031
|
$trk = GetFloat(\$dat, 16);
|
|
1951
|
-
@acc = unpack('x20V3', $dat);
|
|
1952
|
-
map { $_ = $_ - 4294967296 if $_ >= 0x80000000 } @acc;
|
|
2032
|
+
@acc = map SignedInt32, unpack('x20V3', $dat);
|
|
1953
2033
|
ConvertLatLon($lat, $lon);
|
|
1954
2034
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
|
1955
2035
|
$et->HandleTag($tagTbl, GPSLatitude => $lat * (substr($dat,1,1) eq 'S' ? -1 : 1));
|
|
@@ -1983,7 +2063,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1983
2063
|
$lon = abs(GetDouble($dataPt, 48)); # (abs just to be safe)
|
|
1984
2064
|
$spd = GetDouble($dataPt, 64) * $knotsToKph;
|
|
1985
2065
|
$trk = GetDouble($dataPt, 72);
|
|
1986
|
-
|
|
2066
|
+
@acc = map { SignedInt32 / 1000 } @acc; # (NC)
|
|
1987
2067
|
# (not necessary to read RMC sentence because we already have it all)
|
|
1988
2068
|
|
|
1989
2069
|
} elsif ($$dataPt =~ /^.{72}A[NS][EW]\0/s) {
|
|
@@ -2117,7 +2197,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
2117
2197
|
$day < 1 or $day > 31 or
|
|
2118
2198
|
$hr > 59 or $min > 59 or $sec > 600;
|
|
2119
2199
|
# change lat/lon to signed integer and divide by 1e7
|
|
2120
|
-
|
|
2200
|
+
($lat, $lon) = map { SignedInt32 / 1e7 } $lat, $lon;
|
|
2121
2201
|
$trk -= 0x10000 if $trk >= 0x8000; # make it signed
|
|
2122
2202
|
$trk /= 100;
|
|
2123
2203
|
$trk += 360 if $trk < 0;
|
|
@@ -22,7 +22,7 @@ use vars qw($VERSION %samsungLensTypes);
|
|
|
22
22
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
23
23
|
use Image::ExifTool::Exif;
|
|
24
24
|
|
|
25
|
-
$VERSION = '1.
|
|
25
|
+
$VERSION = '1.58';
|
|
26
26
|
|
|
27
27
|
sub WriteSTMN($$$);
|
|
28
28
|
sub ProcessINFO($$$);
|
|
@@ -957,7 +957,7 @@ my %formatMinMax = (
|
|
|
957
957
|
Samsung models such as the Galaxy S4 and Tab S, and from the 'sefd' atom in
|
|
958
958
|
HEIC images from models such as the S10+.
|
|
959
959
|
},
|
|
960
|
-
'0x0001-name' => 'EmbeddedImageName', # ("DualShot_1","DualShot_2")
|
|
960
|
+
'0x0001-name' => 'EmbeddedImageName', # ("DualShot_1","DualShot_2","SingleShot")
|
|
961
961
|
'0x0001' => [
|
|
962
962
|
{
|
|
963
963
|
Name => 'EmbeddedImage',
|
|
@@ -970,6 +970,7 @@ my %formatMinMax = (
|
|
|
970
970
|
Groups => { 2 => 'Preview' },
|
|
971
971
|
Binary => 1,
|
|
972
972
|
},
|
|
973
|
+
# (have also seen the string "BOKEH" here (SM-A226B)
|
|
973
974
|
],
|
|
974
975
|
'0x0100-name' => 'EmbeddedAudioFileName', # ("SoundShot_000")
|
|
975
976
|
'0x0100' => { Name => 'EmbeddedAudioFile', Groups => { 2 => 'Audio' }, Binary => 1 },
|
|
@@ -1265,6 +1266,7 @@ my %formatMinMax = (
|
|
|
1265
1266
|
'0x0b40' => { # (SM-N975X front camera)
|
|
1266
1267
|
Name => 'SingleShotMeta',
|
|
1267
1268
|
SubDirectory => { TagTable => 'Image::ExifTool::Samsung::SingleShotMeta' },
|
|
1269
|
+
# (have also see the string "BOKEH_INFO" here (SM-A226B)
|
|
1268
1270
|
},
|
|
1269
1271
|
# 0x0b41-name - seen 'SingeShot_DepthMap_1' (Yes, "Singe") (SM-N975X front camera)
|
|
1270
1272
|
'0x0b41' => { Name => 'SingleShotDepthMap', Binary => 1 },
|
|
@@ -1493,7 +1495,7 @@ sub ProcessSamsungMeta($$$)
|
|
|
1493
1495
|
my $pos = $$dirInfo{DirStart};
|
|
1494
1496
|
my $end = $$dirInfo{DirLen} + $pos;
|
|
1495
1497
|
unless ($pos + 8 <= $end and substr($$dataPt, $pos, 4) eq 'DOFS') {
|
|
1496
|
-
$et->Warn("Unrecognized $dirName data");
|
|
1498
|
+
$et->Warn("Unrecognized $dirName data", 1);
|
|
1497
1499
|
return 0;
|
|
1498
1500
|
}
|
|
1499
1501
|
my $ver = Get32u($dataPt, $pos + 4);
|