exiftool-vendored.exe 12.28.0 → 12.34.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/Changes +108 -5
- package/bin/exiftool_files/README +2 -2
- package/bin/exiftool_files/arg_files/xmp2exif.args +2 -1
- package/bin/exiftool_files/config_files/example.config +1 -1
- package/bin/exiftool_files/exiftool.pl +40 -26
- package/bin/exiftool_files/fmt_files/gpx.fmt +1 -1
- package/bin/exiftool_files/fmt_files/gpx_wpt.fmt +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/BuildTagLookup.pm +16 -3
- package/bin/exiftool_files/lib/Image/ExifTool/CBOR.pm +331 -0
- package/bin/exiftool_files/lib/Image/ExifTool/Canon.pm +35 -5
- package/bin/exiftool_files/lib/Image/ExifTool/Charset.pm +2 -0
- package/bin/exiftool_files/lib/Image/ExifTool/DPX.pm +13 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Exif.pm +98 -4
- package/bin/exiftool_files/lib/Image/ExifTool/FujiFilm.pm +1 -0
- package/bin/exiftool_files/lib/Image/ExifTool/Geotag.pm +13 -2
- package/bin/exiftool_files/lib/Image/ExifTool/GoPro.pm +16 -1
- package/bin/exiftool_files/lib/Image/ExifTool/ICC_Profile.pm +96 -4
- package/bin/exiftool_files/lib/Image/ExifTool/ID3.pm +15 -3
- package/bin/exiftool_files/lib/Image/ExifTool/JSON.pm +7 -3
- package/bin/exiftool_files/lib/Image/ExifTool/Jpeg2000.pm +60 -26
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/nl.pm +60 -59
- package/bin/exiftool_files/lib/Image/ExifTool/M2TS.pm +81 -14
- package/bin/exiftool_files/lib/Image/ExifTool/MacOS.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Nikon.pm +12 -3
- package/bin/exiftool_files/lib/Image/ExifTool/NikonSettings.pm +10 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Olympus.pm +8 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Other.pm +93 -0
- package/bin/exiftool_files/lib/Image/ExifTool/PDF.pm +11 -12
- package/bin/exiftool_files/lib/Image/ExifTool/PNG.pm +7 -6
- package/bin/exiftool_files/lib/Image/ExifTool/Panasonic.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Pentax.pm +2 -1
- package/bin/exiftool_files/lib/Image/ExifTool/QuickTime.pm +67 -9
- package/bin/exiftool_files/lib/Image/ExifTool/QuickTimeStream.pl +133 -119
- package/bin/exiftool_files/lib/Image/ExifTool/README +9 -2
- package/bin/exiftool_files/lib/Image/ExifTool/RIFF.pm +6 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Samsung.pm +47 -10
- package/bin/exiftool_files/lib/Image/ExifTool/Sony.pm +80 -32
- package/bin/exiftool_files/lib/Image/ExifTool/TagLookup.pm +139 -4
- package/bin/exiftool_files/lib/Image/ExifTool/TagNames.pod +224 -30
- package/bin/exiftool_files/lib/Image/ExifTool/WritePDF.pl +1 -0
- package/bin/exiftool_files/lib/Image/ExifTool/WritePNG.pl +2 -0
- package/bin/exiftool_files/lib/Image/ExifTool/WriteQuickTime.pl +17 -3
- package/bin/exiftool_files/lib/Image/ExifTool/Writer.pl +43 -0
- package/bin/exiftool_files/lib/Image/ExifTool/XMP.pm +21 -8
- package/bin/exiftool_files/lib/Image/ExifTool/XMP2.pl +4 -1
- package/bin/exiftool_files/lib/Image/ExifTool/XMPStruct.pl +3 -1
- package/bin/exiftool_files/lib/Image/ExifTool.pm +8892 -8839
- package/bin/exiftool_files/lib/Image/ExifTool.pod +24 -15
- package/package.json +3 -3
|
@@ -25,6 +25,7 @@ sub Process_mebx($$$);
|
|
|
25
25
|
sub ProcessFreeGPS($$$);
|
|
26
26
|
sub ProcessFreeGPS2($$$);
|
|
27
27
|
sub Process360Fly($$$);
|
|
28
|
+
sub ProcessFMAS($$$);
|
|
28
29
|
|
|
29
30
|
# QuickTime data types that have ExifTool equivalents
|
|
30
31
|
# (ref https://developer.apple.com/library/content/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW35)
|
|
@@ -98,15 +99,15 @@ my %insvLimit = (
|
|
|
98
99
|
The tags below are extracted from timed metadata in QuickTime and other
|
|
99
100
|
formats of video files when the ExtractEmbedded option is used. Although
|
|
100
101
|
most of these tags are combined into the single table below, ExifTool
|
|
101
|
-
currently reads
|
|
102
|
+
currently reads 57 different formats of timed GPS metadata from video files.
|
|
102
103
|
},
|
|
103
104
|
VARS => { NO_ID => 1 },
|
|
104
105
|
GPSLatitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', RawConv => '$$self{FoundGPSLatitude} = 1; $val' },
|
|
105
106
|
GPSLongitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")' },
|
|
106
107
|
GPSAltitude => { PrintConv => '(sprintf("%.4f", $val) + 0) . " m"' }, # round to 4 decimals
|
|
107
|
-
GPSSpeed => { PrintConv => 'sprintf("%.4f", $val) + 0'
|
|
108
|
+
GPSSpeed => { PrintConv => 'sprintf("%.4f", $val) + 0', Notes => 'in km/h unless GPSSpeedRef says otherwise' },
|
|
108
109
|
GPSSpeedRef => { PrintConv => { K => 'km/h', M => 'mph', N => 'knots' } },
|
|
109
|
-
GPSTrack => { PrintConv => 'sprintf("%.4f", $val) + 0'
|
|
110
|
+
GPSTrack => { PrintConv => 'sprintf("%.4f", $val) + 0', Notes => 'relative to true north unless GPSTrackRef says otherwise' },
|
|
110
111
|
GPSTrackRef => { PrintConv => { M => 'Magnetic North', T => 'True North' } },
|
|
111
112
|
GPSDateTime => {
|
|
112
113
|
Groups => { 2 => 'Time' },
|
|
@@ -181,6 +182,13 @@ my %insvLimit = (
|
|
|
181
182
|
TagTable => 'Image::ExifTool::QuickTime::Stream',
|
|
182
183
|
ProcessProc => \&Process_text,
|
|
183
184
|
},
|
|
185
|
+
},{
|
|
186
|
+
Name => 'gpmd_FMAS', # Vantrue N2S binary format
|
|
187
|
+
Condition => '$$valPt =~ /^FMAS\0\0\0\0/',
|
|
188
|
+
SubDirectory => {
|
|
189
|
+
TagTable => 'Image::ExifTool::QuickTime::Stream',
|
|
190
|
+
ProcessProc => \&ProcessFMAS,
|
|
191
|
+
},
|
|
184
192
|
},{
|
|
185
193
|
Name => 'gpmd_GoPro',
|
|
186
194
|
SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' },
|
|
@@ -901,14 +909,8 @@ sub Process_text($$$)
|
|
|
901
909
|
$tags{GPSDateTime} = $dateTime;
|
|
902
910
|
$tags{GPSLatitude} = (($4 || 0) + $5/60) * ($6 eq 'N' ? 1 : -1);
|
|
903
911
|
$tags{GPSLongitude} = (($7 || 0) + $8/60) * ($9 eq 'E' ? 1 : -1);
|
|
904
|
-
if
|
|
905
|
-
|
|
906
|
-
$tags{GPSSpeedRef} = 'K';
|
|
907
|
-
}
|
|
908
|
-
if (length $11) {
|
|
909
|
-
$tags{GPSTrack} = $11;
|
|
910
|
-
$tags{GPSTrackRef} = 'T';
|
|
911
|
-
}
|
|
912
|
+
$tags{GPSSpeed} = $10 * $knotsToKph if length $10;
|
|
913
|
+
$tags{GPSTrack} = $11 if length $11;
|
|
912
914
|
} elsif ($tag =~ /^[A-Z]{2}GGA$/ and $dat =~ /^,(\d{2})(\d{2})(\d+(?:\.\d*)?),(\d*?)(\d{1,2}\.\d+),([NS]),(\d*?)(\d{1,2}\.\d+),([EW]),[1-6]?,(\d+)?,(\.\d+|\d+\.?\d*)?,(-?\d+\.?\d*)?,M?/s) {
|
|
913
915
|
my $time = "$1:$2:$3";
|
|
914
916
|
if ($$et{LastTime}) {
|
|
@@ -988,10 +990,7 @@ sub Process_text($$$)
|
|
|
988
990
|
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 0x39, 5)));
|
|
989
991
|
$tags{GPSAltitude} = $val + 0 if $val =~ /^[-+]\d+$/;
|
|
990
992
|
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 0x3e, 3)));
|
|
991
|
-
if
|
|
992
|
-
$tags{GPSSpeed} = $val + 0;
|
|
993
|
-
$tags{GPSSpeedRef} = 'K';
|
|
994
|
-
}
|
|
993
|
+
$tags{GPSSpeed} = $val + 0 if $val =~ /^\d+$/;
|
|
995
994
|
if ($$dataPt =~ /^\0\0..\xaa\xaa/s) { # (BlueSkySea)
|
|
996
995
|
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 0xad, 12)));
|
|
997
996
|
# the first X,Y,Z accelerometer readings from the AccelerometerData
|
|
@@ -1022,10 +1021,7 @@ sub Process_text($$$)
|
|
|
1022
1021
|
$tags{GPSLatitude} = $2;
|
|
1023
1022
|
$tags{GPSLongitude} = $1;
|
|
1024
1023
|
$tags{GPSAltitude} = $1 if $$dataPt =~ /,\s*H\s+([-+]?\d+\.?\d*)m/;
|
|
1025
|
-
if
|
|
1026
|
-
$tags{GPSSpeed} = $1 * $mpsToKph;
|
|
1027
|
-
$tags{GPSSpeedRef} = 'K';
|
|
1028
|
-
}
|
|
1024
|
+
$tags{GPSSpeed} = $1 * $mpsToKph if $$dataPt =~ /,\s*H.S\s+([-+]?\d+\.?\d*)/;
|
|
1029
1025
|
$tags{Distance} = $1 * $mpsToKph if $$dataPt =~ /,\s*D\s+(\d+\.?\d*)m/;
|
|
1030
1026
|
$tags{VerticalSpeed} = $1 if $$dataPt =~ /,\s*V.S\s+([-+]?\d+\.?\d*)/;
|
|
1031
1027
|
$tags{FNumber} = $1 if $$dataPt =~ /\bF\/(\d+\.?\d*)/;
|
|
@@ -1086,14 +1082,8 @@ sub Process_text($$$)
|
|
|
1086
1082
|
$tags{GPSDateTime} = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2dZ', $year, $14, $13, $1, $2, $3);
|
|
1087
1083
|
$tags{GPSLatitude} = (($5 || 0) + $6/60) * ($7 eq 'N' ? 1 : -1);
|
|
1088
1084
|
$tags{GPSLongitude} = (($8 || 0) + $9/60) * ($10 eq 'E' ? 1 : -1);
|
|
1089
|
-
if
|
|
1090
|
-
|
|
1091
|
-
$tags{GPSSpeedRef} = 'K';
|
|
1092
|
-
}
|
|
1093
|
-
if (length $12) {
|
|
1094
|
-
$tags{GPSTrack} = $12;
|
|
1095
|
-
$tags{GPSTrackRef} = 'T';
|
|
1096
|
-
}
|
|
1085
|
+
$tags{GPSSpeed} = $11 * $knotsToKph if length $11;
|
|
1086
|
+
$tags{GPSTrack} = $12 if length $12;
|
|
1097
1087
|
}
|
|
1098
1088
|
$tags{GSensor} = $1 if $$dataPt =~ /\bgsensori,(.*?)(;|$)/;
|
|
1099
1089
|
$tags{Car} = $1 if $$dataPt =~ /\bCAR,(.*?)(;|$)/;
|
|
@@ -1230,7 +1220,10 @@ sub ProcessSamples($)
|
|
|
1230
1220
|
$et->VPrint(1, "${hdr}, Sample ".($i+1).' of '.scalar(@$start)." ($size bytes)\n");
|
|
1231
1221
|
$et->VerboseDump(\$buff, Addr => $$start[$i]);
|
|
1232
1222
|
}
|
|
1233
|
-
if ($type eq 'text'
|
|
1223
|
+
if ($type eq 'text' or
|
|
1224
|
+
# (PNDM is normally 'text', but was sbtl/tx3g in concatenated Garmin sample output_3videos.mp4)
|
|
1225
|
+
($type eq 'sbtl' and $metaFormat eq 'tx3g' and $buff =~ /^..PNDM/s))
|
|
1226
|
+
{
|
|
1234
1227
|
|
|
1235
1228
|
FoundSomething($et, $tagTbl, $time[$i], $dur[$i]);
|
|
1236
1229
|
unless ($buff =~ /^\$BEGIN/) {
|
|
@@ -1265,8 +1258,7 @@ sub ProcessSamples($)
|
|
|
1265
1258
|
next if length($buff) < 20 + $n;
|
|
1266
1259
|
$et->HandleTag($tagTbl, GPSLatitude => Get32s(\$buff, 12+$n) * 180/0x80000000);
|
|
1267
1260
|
$et->HandleTag($tagTbl, GPSLongitude => Get32s(\$buff, 16+$n) * 180/0x80000000);
|
|
1268
|
-
$et->HandleTag($tagTbl, GPSSpeed
|
|
1269
|
-
$et->HandleTag($tagTbl, GPSSpeedRef => 'K');
|
|
1261
|
+
$et->HandleTag($tagTbl, GPSSpeed => Get16u(\$buff, 8+$n) * $mphToKph);
|
|
1270
1262
|
SetGPSDateTime($et, $tagTbl, $time[$i]);
|
|
1271
1263
|
next; # all done (don't store/process as text)
|
|
1272
1264
|
}
|
|
@@ -1339,6 +1331,19 @@ sub ProcessSamples($)
|
|
|
1339
1331
|
$$et{HandlerType} = $$et{HanderDesc} = '';
|
|
1340
1332
|
}
|
|
1341
1333
|
|
|
1334
|
+
#------------------------------------------------------------------------------
|
|
1335
|
+
# Convert latitude/longitude from DDDMM.MMMM format to decimal degrees
|
|
1336
|
+
# Inputs: 0) latitude, 1) longitude
|
|
1337
|
+
# Returns: lat/lon are changed in place
|
|
1338
|
+
# (note: this method works fine for negative coordinates)
|
|
1339
|
+
sub ConvertLatLon($$)
|
|
1340
|
+
{
|
|
1341
|
+
my $deg = int($_[0] / 100); # latitude
|
|
1342
|
+
$_[0] = $deg + ($_[0] - $deg * 100) / 60;
|
|
1343
|
+
$deg = int($_[1] / 100); # longitude
|
|
1344
|
+
$_[1] = $deg + ($_[1] - $deg * 100) / 60;
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1342
1347
|
#------------------------------------------------------------------------------
|
|
1343
1348
|
# Process "freeGPS " data blocks referenced by a 'gps ' (GPSDataList) atom
|
|
1344
1349
|
# Inputs: 0) ExifTool ref, 1) dirInfo ref {DataPt,SampleTime,SampleDuration}, 2) tagTable ref
|
|
@@ -1350,7 +1355,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1350
1355
|
my ($et, $dirInfo, $tagTbl) = @_;
|
|
1351
1356
|
my $dataPt = $$dirInfo{DataPt};
|
|
1352
1357
|
my $dirLen = length $$dataPt;
|
|
1353
|
-
my ($yr, $mon, $day, $hr, $min, $sec, $stat, $lbl);
|
|
1358
|
+
my ($yr, $mon, $day, $hr, $min, $sec, $stat, $lbl, $ddd);
|
|
1354
1359
|
my ($lat, $latRef, $lon, $lonRef, $spd, $trk, $alt, @acc, @xtra);
|
|
1355
1360
|
|
|
1356
1361
|
return 0 if $dirLen < 92;
|
|
@@ -1475,7 +1480,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1475
1480
|
$lat = GetFloat($dataPt, 0x1c);
|
|
1476
1481
|
$lon = GetFloat($dataPt, 0x20);
|
|
1477
1482
|
$et->VPrint(0, sprintf("Raw lat/lon = %.9f %.9f\n", $lat, $lon));
|
|
1478
|
-
$et->WarnOnce('GPSLatitude/Longitude
|
|
1483
|
+
$et->WarnOnce('GPSLatitude/Longitude encryption is not yet known, so these will be wrong');
|
|
1479
1484
|
$lat = abs $lat;
|
|
1480
1485
|
$lon = abs $lon;
|
|
1481
1486
|
$spd = GetFloat($dataPt, 0x24) * $knotsToKph; # (convert knots to km/h)
|
|
@@ -1505,6 +1510,23 @@ sub ProcessFreeGPS($$$)
|
|
|
1505
1510
|
$trk -= 360 if $trk >= 360;
|
|
1506
1511
|
SetByteOrder('MM');
|
|
1507
1512
|
|
|
1513
|
+
} elsif ($$dataPt =~ /^.{60}4W`b]S</s and length($$dataPt) >= 140) {
|
|
1514
|
+
|
|
1515
|
+
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 01 00 00 [..@.freeGPS ....]
|
|
1516
|
+
# 0010: 5a 58 53 42 4e 58 59 53 00 00 00 00 00 00 00 00 [ZXSBNXYS........]
|
|
1517
|
+
# 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
|
1518
|
+
# 0030: 00 00 00 00 00 00 00 00 00 00 00 00 34 57 60 62 [............4W`b]
|
|
1519
|
+
# 0040: 5d 53 3c 41 44 45 41 41 42 3e 40 40 3c 51 3c 45 []S<ADEAAB>@@<Q<E]
|
|
1520
|
+
# 0050: 41 40 43 3e 41 47 49 48 44 3c 5e 3c 40 41 46 43 [A@C>AGIHD<^<@AFC]
|
|
1521
|
+
# 0060: 42 3e 49 49 40 42 45 3c 55 3c 45 47 3e 45 43 41 [B>II@BE<U<EG>ECA]
|
|
1522
|
+
# decipher $GPRMC by subtracting 16 from each character value
|
|
1523
|
+
$_ = pack 'C*', map { $_>=16 and $_-=16 } unpack('x60C80', $$dataPt);
|
|
1524
|
+
return 0 unless /[A-Z]{2}RMC,(\d{2})(\d{2})(\d+(\.\d*)?),A?,(\d*?\d{1,2}\.\d+),([NS]),(\d*?\d{1,2}\.\d+),([EW]),(\d*\.?\d*),(\d*\.?\d*),(\d{2})(\d{2})(\d+)/;
|
|
1525
|
+
($yr,$mon,$day,$hr,$min,$sec,$lat,$latRef,$lon,$lonRef) = ($13,$12,$11,$1,$2,$3,$5,$6,$7,$8);
|
|
1526
|
+
$yr += ($yr >= 70 ? 1900 : 2000);
|
|
1527
|
+
$spd = $9 * $knotsToKph if length $9;
|
|
1528
|
+
$trk = $10 if length $10;
|
|
1529
|
+
|
|
1508
1530
|
} elsif ($$dataPt =~ /^.{16}YndAkasoCar/s) {
|
|
1509
1531
|
|
|
1510
1532
|
# Akaso V1 dascham
|
|
@@ -1523,13 +1545,17 @@ sub ProcessFreeGPS($$$)
|
|
|
1523
1545
|
return 0 unless $stat eq 'A' and ($latRef eq 'N' or $latRef eq 'S') and
|
|
1524
1546
|
($lonRef eq 'E' or $lonRef eq 'W');
|
|
1525
1547
|
|
|
1526
|
-
$et->WarnOnce(
|
|
1548
|
+
$et->WarnOnce('GPSLatitude/Longitude encryption is not yet known, so these will be wrong');
|
|
1527
1549
|
# (see https://exiftool.org/forum/index.php?topic=11320.0)
|
|
1528
|
-
return 1;
|
|
1529
1550
|
|
|
1530
1551
|
SetByteOrder('II');
|
|
1552
|
+
|
|
1553
|
+
$spd = GetFloat($dataPt, 0x60);
|
|
1554
|
+
$trk = GetFloat($dataPt, 0x64) + 180; # (why is this off by 180?)
|
|
1531
1555
|
$lat = GetDouble($dataPt, 0x50); # latitude is here, but encrypted somehow
|
|
1532
1556
|
$lon = GetDouble($dataPt, 0x58); # longitude is here, but encrypted somehow
|
|
1557
|
+
$ddd = 1; # don't convert until we know what the format is
|
|
1558
|
+
|
|
1533
1559
|
SetByteOrder('MM');
|
|
1534
1560
|
#my $serialNum = substr($$dataPt, 0x68, 20);
|
|
1535
1561
|
|
|
@@ -1593,10 +1619,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1593
1619
|
#
|
|
1594
1620
|
FoundSomething($et, $tagTbl, $$dirInfo{SampleTime}, $$dirInfo{SampleDuration});
|
|
1595
1621
|
# lat/long are in DDDMM.MMMM format
|
|
1596
|
-
|
|
1597
|
-
$lat = $deg + ($lat - $deg * 100) / 60;
|
|
1598
|
-
$deg = int($lon / 100);
|
|
1599
|
-
$lon = $deg + ($lon - $deg * 100) / 60;
|
|
1622
|
+
ConvertLatLon($lat, $lon) unless $ddd;
|
|
1600
1623
|
$sec = '0' . $sec unless $sec =~ /^\d{2}/; # pad integer part of seconds to 2 digits
|
|
1601
1624
|
if (defined $yr) {
|
|
1602
1625
|
my $time = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%sZ',$yr,$mon,$day,$hr,$min,$sec);
|
|
@@ -1608,14 +1631,8 @@ sub ProcessFreeGPS($$$)
|
|
|
1608
1631
|
$et->HandleTag($tagTbl, GPSLatitude => $lat * ($latRef eq 'S' ? -1 : 1));
|
|
1609
1632
|
$et->HandleTag($tagTbl, GPSLongitude => $lon * ($lonRef eq 'W' ? -1 : 1));
|
|
1610
1633
|
$et->HandleTag($tagTbl, GPSAltitude => $alt) if defined $alt;
|
|
1611
|
-
if
|
|
1612
|
-
|
|
1613
|
-
$et->HandleTag($tagTbl, GPSSpeedRef => 'K');
|
|
1614
|
-
}
|
|
1615
|
-
if (defined $trk) {
|
|
1616
|
-
$et->HandleTag($tagTbl, GPSTrack => $trk);
|
|
1617
|
-
$et->HandleTag($tagTbl, GPSTrackRef => 'T');
|
|
1618
|
-
}
|
|
1634
|
+
$et->HandleTag($tagTbl, GPSSpeed => $spd) if defined $spd;
|
|
1635
|
+
$et->HandleTag($tagTbl, GPSTrack => $trk) if defined $trk;
|
|
1619
1636
|
while (@xtra) {
|
|
1620
1637
|
my $tag = shift @xtra;
|
|
1621
1638
|
$et->HandleTag($tagTbl, $tag => shift @xtra);
|
|
@@ -1734,9 +1751,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1734
1751
|
$et->HandleTag($tagTbl, GPSLatitude => Get32s(\$b, 0x10) / 1e7);
|
|
1735
1752
|
$et->HandleTag($tagTbl, GPSLongitude => Get32s(\$b, 0x18) / 1e7);
|
|
1736
1753
|
$et->HandleTag($tagTbl, GPSSpeed => Get32s(\$b, 0x20) / 100 * $mpsToKph);
|
|
1737
|
-
$et->HandleTag($tagTbl, GPSSpeedRef => 'K');
|
|
1738
1754
|
$et->HandleTag($tagTbl, GPSTrack => $trk);
|
|
1739
|
-
$et->HandleTag($tagTbl, GPSTrackRef => 'T');
|
|
1740
1755
|
$et->HandleTag($tagTbl, GPSAltitude => Get32s(\$b, 0x28) / 1000);
|
|
1741
1756
|
$lastRecPos = $recPos;
|
|
1742
1757
|
$foundNew = 1;
|
|
@@ -1857,17 +1872,12 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1857
1872
|
$trk = GetFloat(\$dat, 16);
|
|
1858
1873
|
@acc = unpack('x20V3', $dat);
|
|
1859
1874
|
map { $_ = $_ - 4294967296 if $_ >= 0x80000000 } @acc;
|
|
1860
|
-
|
|
1861
|
-
$lat = $deg + ($lat - $deg * 100) / 60;
|
|
1862
|
-
$deg = int($lon / 100);
|
|
1863
|
-
$lon = $deg + ($lon - $deg * 100) / 60;
|
|
1875
|
+
ConvertLatLon($lat, $lon);
|
|
1864
1876
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
|
1865
1877
|
$et->HandleTag($tagTbl, GPSLatitude => $lat * (substr($dat,1,1) eq 'S' ? -1 : 1));
|
|
1866
1878
|
$et->HandleTag($tagTbl, GPSLongitude => $lon * (substr($dat,2,1) eq 'W' ? -1 : 1));
|
|
1867
1879
|
$et->HandleTag($tagTbl, GPSSpeed => $spd);
|
|
1868
|
-
$et->HandleTag($tagTbl, GPSSpeedRef => 'K');
|
|
1869
1880
|
$et->HandleTag($tagTbl, GPSTrack => $trk);
|
|
1870
|
-
$et->HandleTag($tagTbl, GPSTrackRef => 'T');
|
|
1871
1881
|
$et->HandleTag($tagTbl, Accelerometer => "@acc");
|
|
1872
1882
|
}
|
|
1873
1883
|
return 1;
|
|
@@ -1913,9 +1923,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1913
1923
|
$et->HandleTag($tagTbl, GPSLatitude => $lat);
|
|
1914
1924
|
$et->HandleTag($tagTbl, GPSLongitude => $lon);
|
|
1915
1925
|
$et->HandleTag($tagTbl, GPSSpeed => $spd / 100 * $mpsToKph);
|
|
1916
|
-
$et->HandleTag($tagTbl, GPSSpeedRef => 'K');
|
|
1917
1926
|
$et->HandleTag($tagTbl, GPSTrack => $trk);
|
|
1918
|
-
$et->HandleTag($tagTbl, GPSTrackRef => 'T');
|
|
1919
1927
|
last if $pos += 0x20 > length($$dataPt) - 0x1e;
|
|
1920
1928
|
}
|
|
1921
1929
|
return $$et{DOC_NUM} ? 1 : 0; # return 0 if nothing extracted
|
|
@@ -1928,23 +1936,12 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1928
1936
|
$yr += 2000 if $yr < 2000;
|
|
1929
1937
|
my $time = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2dZ', $yr, $mon, $day, $hr, $min, $sec);
|
|
1930
1938
|
# convert from DDMM.MMMMMM to DD.DDDDDD format if necessary
|
|
1931
|
-
unless
|
|
1932
|
-
my $deg = int($lat / 100);
|
|
1933
|
-
$lat = $deg + ($lat - $deg * 100) / 60;
|
|
1934
|
-
$deg = int($lon / 100);
|
|
1935
|
-
$lon = $deg + ($lon - $deg * 100) / 60;
|
|
1936
|
-
}
|
|
1939
|
+
ConvertLatLon($lat, $lon) unless $ddd;
|
|
1937
1940
|
$et->HandleTag($tagTbl, GPSDateTime => $time);
|
|
1938
1941
|
$et->HandleTag($tagTbl, GPSLatitude => $lat * ($latRef eq 'S' ? -1 : 1));
|
|
1939
1942
|
$et->HandleTag($tagTbl, GPSLongitude => $lon * ($lonRef eq 'W' ? -1 : 1));
|
|
1940
|
-
if
|
|
1941
|
-
|
|
1942
|
-
$et->HandleTag($tagTbl, GPSSpeedRef => 'K');
|
|
1943
|
-
}
|
|
1944
|
-
if (defined $trk) {
|
|
1945
|
-
$et->HandleTag($tagTbl, GPSTrack => $trk);
|
|
1946
|
-
$et->HandleTag($tagTbl, GPSTrackRef => 'T');
|
|
1947
|
-
}
|
|
1943
|
+
$et->HandleTag($tagTbl, GPSSpeed => $spd) if defined $spd; # (now in km/h)
|
|
1944
|
+
$et->HandleTag($tagTbl, GPSTrack => $trk) if defined $trk;
|
|
1948
1945
|
if (defined $alt) {
|
|
1949
1946
|
$et->HandleTag($tagTbl, GPSAltitude => $alt);
|
|
1950
1947
|
}
|
|
@@ -1952,6 +1949,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1952
1949
|
return 1;
|
|
1953
1950
|
}
|
|
1954
1951
|
|
|
1952
|
+
|
|
1955
1953
|
#------------------------------------------------------------------------------
|
|
1956
1954
|
# Extract embedded information referenced from a track
|
|
1957
1955
|
# Inputs: 0) ExifTool ref, 1) tag name, 2) data ref
|
|
@@ -2036,16 +2034,12 @@ sub ParseTag($$$)
|
|
|
2036
2034
|
SetGPSDateTime($et, $tagTbl, $a[2]);
|
|
2037
2035
|
my $lat = $a[5] / 1e3;
|
|
2038
2036
|
my $lon = $a[7] / 1e3;
|
|
2039
|
-
|
|
2040
|
-
$lat =
|
|
2041
|
-
$
|
|
2042
|
-
$lon = $deg + ($lon - $deg * 100) / 60;
|
|
2043
|
-
$lat = -$lat if $a[4] eq 'S';
|
|
2044
|
-
$lon = -$lon if $a[6] eq 'W';
|
|
2037
|
+
ConvertLatLon($lat, $lon);
|
|
2038
|
+
$lat = -abs($lat) if $a[4] eq 'S';
|
|
2039
|
+
$lon = -abs($lon) if $a[6] eq 'W';
|
|
2045
2040
|
$et->HandleTag($tagTbl, GPSLatitude => $lat);
|
|
2046
2041
|
$et->HandleTag($tagTbl, GPSLongitude => $lon);
|
|
2047
|
-
$et->HandleTag($tagTbl, GPSSpeed
|
|
2048
|
-
$et->HandleTag($tagTbl, GPSSpeedRef => 'K');
|
|
2042
|
+
$et->HandleTag($tagTbl, GPSSpeed => $a[3] / 1e3);
|
|
2049
2043
|
$pos += 36;
|
|
2050
2044
|
}
|
|
2051
2045
|
SetByteOrder('MM');
|
|
@@ -2107,9 +2101,9 @@ sub Process_mebx($$$)
|
|
|
2107
2101
|
|
|
2108
2102
|
# parse using information from 'keys' table (eg. Apple iPhone7+ hevc 'Core Media Data Handler')
|
|
2109
2103
|
$et->VerboseDir('mebx', undef, length $$dataPt);
|
|
2110
|
-
my $pos
|
|
2111
|
-
|
|
2112
|
-
|
|
2104
|
+
my ($pos, $len);
|
|
2105
|
+
for ($pos=0; $pos+8<length($$dataPt); $pos+=$len) {
|
|
2106
|
+
$len = Get32u($dataPt, $pos);
|
|
2113
2107
|
last if $len < 8 or $pos + $len > length $$dataPt;
|
|
2114
2108
|
my $id = substr($$dataPt, $pos+4, 4);
|
|
2115
2109
|
my $info = $$ee{'keys'}{$id};
|
|
@@ -2132,7 +2126,6 @@ sub Process_mebx($$$)
|
|
|
2132
2126
|
} else {
|
|
2133
2127
|
$et->WarnOnce('No key information for mebx ID ' . PrintableTagID($id,1));
|
|
2134
2128
|
}
|
|
2135
|
-
$pos += $len;
|
|
2136
2129
|
}
|
|
2137
2130
|
return 1;
|
|
2138
2131
|
}
|
|
@@ -2188,20 +2181,14 @@ sub Process_gps0($$$)
|
|
|
2188
2181
|
my $lat = GetDouble($dataPt, $pos);
|
|
2189
2182
|
my $lon = GetDouble($dataPt, $pos+8);
|
|
2190
2183
|
next if abs($lat) > 9000 or abs($lon) > 18000;
|
|
2191
|
-
|
|
2192
|
-
my $deg = int($lat / 100);
|
|
2193
|
-
$lat = $deg + ($lat - $deg * 100) / 60;
|
|
2194
|
-
$deg = int($lon / 100);
|
|
2195
|
-
$lon = $deg + ($lon - $deg * 100) / 60;
|
|
2184
|
+
ConvertLatLon($lat, $lon);
|
|
2196
2185
|
my @a = unpack('C*', substr($$dataPt, $pos+22, 6)); # unpack date/time
|
|
2197
2186
|
$a[0] += 2000;
|
|
2198
2187
|
$et->HandleTag($tagTbl, GPSDateTime => sprintf("%.4d:%.2d:%.2d %.2d:%.2d:%.2dZ", @a));
|
|
2199
2188
|
$et->HandleTag($tagTbl, GPSLatitude => $lat);
|
|
2200
2189
|
$et->HandleTag($tagTbl, GPSLongitude => $lon);
|
|
2201
2190
|
$et->HandleTag($tagTbl, GPSSpeed => Get16u($dataPt, $pos+0x14));
|
|
2202
|
-
$et->HandleTag($tagTbl, GPSSpeedRef => 'K');
|
|
2203
2191
|
$et->HandleTag($tagTbl, GPSTrack => Get8u($dataPt, $pos+0x1c) * 2); # (NC)
|
|
2204
|
-
$et->HandleTag($tagTbl, GPSTrackRef => 'T');
|
|
2205
2192
|
$et->HandleTag($tagTbl, GPSAltitude => Get32s($dataPt, $pos + 0x10));
|
|
2206
2193
|
# yet to be decoded:
|
|
2207
2194
|
# 0x1d - int8u[3] seen: "1 1 0"
|
|
@@ -2290,10 +2277,7 @@ sub ProcessRIFFTrailer($$$)
|
|
|
2290
2277
|
my $lat = GetDouble(\$buff, $pos+4);
|
|
2291
2278
|
my $lon = GetDouble(\$buff, $pos+12);
|
|
2292
2279
|
$et->Warn('Bad gps0 record') and last if abs($lat) > 9000 or abs($lon) > 18000;
|
|
2293
|
-
|
|
2294
|
-
$lat = $deg + ($lat - $deg * 100) / 60;
|
|
2295
|
-
$deg = int($lon / 100);
|
|
2296
|
-
$lon = $deg + ($lon - $deg * 100) / 60;
|
|
2280
|
+
ConvertLatLon($lat, $lon);
|
|
2297
2281
|
$lat = -$lat if Get8u(\$buff, $pos+0x21) == 2; # wild guess
|
|
2298
2282
|
$lon = -$lon if Get8u(\$buff, $pos+0x22) == 2; # wild guess
|
|
2299
2283
|
my @a = unpack('C*', substr($buff, $pos+26, 6)); # unpack date/time
|
|
@@ -2303,9 +2287,7 @@ sub ProcessRIFFTrailer($$$)
|
|
|
2303
2287
|
$et->HandleTag($tagTbl, GPSLatitude => $lat);
|
|
2304
2288
|
$et->HandleTag($tagTbl, GPSLongitude => $lon);
|
|
2305
2289
|
$et->HandleTag($tagTbl, GPSSpeed => Get16u(\$buff, $pos+0x18) * $knotsToKph);
|
|
2306
|
-
$et->HandleTag($tagTbl, GPSSpeedRef => 'K');
|
|
2307
2290
|
$et->HandleTag($tagTbl, GPSTrack => Get8u(\$buff, $pos+0x20) * 2);
|
|
2308
|
-
$et->HandleTag($tagTbl, GPSTrackRef => 'T');
|
|
2309
2291
|
}
|
|
2310
2292
|
} elsif ($tag eq 'gsen') {
|
|
2311
2293
|
# (similar to record decoded in Process_gsen)
|
|
@@ -2359,17 +2341,11 @@ sub ProcessNMEA($$$)
|
|
|
2359
2341
|
$et->HandleTag($tagTbl, GPSDateTime => $fix{dat});
|
|
2360
2342
|
$et->HandleTag($tagTbl, GPSLatitude => $fix{lat});
|
|
2361
2343
|
$et->HandleTag($tagTbl, GPSLongitude => $fix{lon});
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
}
|
|
2366
|
-
|
|
2367
|
-
$et->HandleTag($tagTbl, GPSTrack => $fix{trk});
|
|
2368
|
-
$et->HandleTag($tagTbl, GPSTrackRef => 'T');
|
|
2369
|
-
}
|
|
2370
|
-
$et->HandleTag($tagTbl, GPSAltitude => $fix{alt}) if defined $fix{alt};
|
|
2371
|
-
$et->HandleTag($tagTbl, GPSSatellites => $fix{nsats}+0) if defined $fix{nsats};
|
|
2372
|
-
$et->HandleTag($tagTbl, GPSDOP => $fix{hdop}) if defined $fix{hdop};
|
|
2344
|
+
$et->HandleTag($tagTbl, GPSSpeed => $fix{spd} * $knotsToKph) if defined $fix{spd};
|
|
2345
|
+
$et->HandleTag($tagTbl, GPSTrack => $fix{trk}) if defined $fix{trk};
|
|
2346
|
+
$et->HandleTag($tagTbl, GPSAltitude => $fix{alt}) if defined $fix{alt};
|
|
2347
|
+
$et->HandleTag($tagTbl, GPSSatellites=> $fix{nsats}+0) if defined $fix{nsats};
|
|
2348
|
+
$et->HandleTag($tagTbl, GPSDOP => $fix{hdop}) if defined $fix{hdop};
|
|
2373
2349
|
}
|
|
2374
2350
|
undef %fix;
|
|
2375
2351
|
}
|
|
@@ -2523,9 +2499,7 @@ sub ProcessTTAD($$$)
|
|
|
2523
2499
|
$et->HandleTag($tagTbl, GPSLongitude => GetDouble($dataPt, $pos+0x24));
|
|
2524
2500
|
$et->HandleTag($tagTbl, GPSAltitude => GetDouble($dataPt, $pos+0x14));
|
|
2525
2501
|
$et->HandleTag($tagTbl, GPSSpeed => GetDouble($dataPt, $pos+0x0c) * $mpsToKph);
|
|
2526
|
-
$et->HandleTag($tagTbl, GPSSpeedRef => 'K');
|
|
2527
2502
|
$et->HandleTag($tagTbl, GPSTrack => GetDouble($dataPt, $pos+0x30));
|
|
2528
|
-
$et->HandleTag($tagTbl, GPSTrackRef => 'T');
|
|
2529
2503
|
if ($unknown) {
|
|
2530
2504
|
my @a = map { GetDouble($dataPt, $pos+0x38+8*$_) } 0..2;
|
|
2531
2505
|
$et->HandleTag($tagTbl, Unknown03 => "@a");
|
|
@@ -2645,21 +2619,26 @@ sub ProcessInsta360($;$)
|
|
|
2645
2619
|
my $tmp = substr($buff, $p, $dlen);
|
|
2646
2620
|
my @a = unpack('VVvaa8aa8aa8a8a8', $tmp);
|
|
2647
2621
|
next unless $a[3] eq 'A'; # (ignore void fixes)
|
|
2648
|
-
|
|
2649
|
-
|
|
2622
|
+
unless (($a[5] eq 'N' or $a[5] eq 'S') and # (quick validation)
|
|
2623
|
+
($a[7] eq 'E' or $a[7] eq 'W' or
|
|
2624
|
+
# (odd, but I've seen "O" instead of "W". Perhaps
|
|
2625
|
+
# when the language is french? ie. "Ouest"?)
|
|
2626
|
+
$a[7] eq 'O'))
|
|
2627
|
+
{
|
|
2628
|
+
$et->Warn('Unrecognized INSV GPS format');
|
|
2629
|
+
last;
|
|
2630
|
+
}
|
|
2650
2631
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
|
2651
2632
|
$a[$_] = GetDouble(\$a[$_], 0) foreach 4,6,8,9,10;
|
|
2652
2633
|
$a[4] = -abs($a[4]) if $a[5] eq 'S'; # (abs just in case it was already signed)
|
|
2653
|
-
$a[6] = -abs($a[6]) if $a[7]
|
|
2654
|
-
$et->HandleTag($tagTbl, GPSDateTime
|
|
2655
|
-
$et->HandleTag($tagTbl, GPSLatitude
|
|
2634
|
+
$a[6] = -abs($a[6]) if $a[7] ne 'E';
|
|
2635
|
+
$et->HandleTag($tagTbl, GPSDateTime => Image::ExifTool::ConvertUnixTime($a[0]) . 'Z');
|
|
2636
|
+
$et->HandleTag($tagTbl, GPSLatitude => $a[4]);
|
|
2656
2637
|
$et->HandleTag($tagTbl, GPSLongitude => $a[6]);
|
|
2657
|
-
$et->HandleTag($tagTbl, GPSSpeed
|
|
2658
|
-
$et->HandleTag($tagTbl,
|
|
2659
|
-
$et->HandleTag($tagTbl,
|
|
2660
|
-
$et->HandleTag($tagTbl,
|
|
2661
|
-
$et->HandleTag($tagTbl, GPSAltitude => $a[10]);
|
|
2662
|
-
$et->HandleTag($tagTbl, Unknown02 => "@a[1,2]") if $unknown; # millisecond counter (https://exiftool.org/forum/index.php?topic=9884.msg65143#msg65143)
|
|
2638
|
+
$et->HandleTag($tagTbl, GPSSpeed => $a[8] * $mpsToKph);
|
|
2639
|
+
$et->HandleTag($tagTbl, GPSTrack => $a[9]);
|
|
2640
|
+
$et->HandleTag($tagTbl, GPSAltitude => $a[10]);
|
|
2641
|
+
$et->HandleTag($tagTbl, Unknown02 => "@a[1,2]") if $unknown; # millisecond counter (https://exiftool.org/forum/index.php?topic=9884.msg65143#msg65143)
|
|
2663
2642
|
}
|
|
2664
2643
|
}
|
|
2665
2644
|
} elsif ($id == 0x101) {
|
|
@@ -2715,6 +2694,41 @@ sub Process360Fly($$$)
|
|
|
2715
2694
|
return 1;
|
|
2716
2695
|
}
|
|
2717
2696
|
|
|
2697
|
+
#------------------------------------------------------------------------------
|
|
2698
|
+
# Process GPS from Vantrue N2S dashcam
|
|
2699
|
+
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
|
|
2700
|
+
# Returns: 1 on success
|
|
2701
|
+
sub ProcessFMAS($$$)
|
|
2702
|
+
{
|
|
2703
|
+
my ($et, $dirInfo, $tagTbl) = @_;
|
|
2704
|
+
my $dataPt = $$dirInfo{DataPt};
|
|
2705
|
+
return 0 unless $$dataPt =~ /^FMAS\0\0\0\0.{72}SAMM.{36}A/s and length($$dataPt) >= 160;
|
|
2706
|
+
$et->VerboseDir('FMAS', undef, length($$dataPt));
|
|
2707
|
+
# 0000: 46 4d 41 53 00 00 00 00 00 00 00 00 00 00 00 00 [FMAS............]
|
|
2708
|
+
# 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
|
2709
|
+
# 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
|
2710
|
+
# 0030: 02 08 01 08 06 08 02 04 07 02 06 00 00 00 00 00 [................]
|
|
2711
|
+
# 0040: 00 00 00 00 00 00 00 00 4f 46 4e 49 4d 4d 41 53 [........OFNIMMAS]
|
|
2712
|
+
# 0050: 53 41 4d 4d 01 00 00 00 00 00 00 00 00 00 00 00 [SAMM............]
|
|
2713
|
+
# 0060: e5 07 09 18 08 00 22 00 02 00 00 00 a1 82 8a bf [......".........]
|
|
2714
|
+
# 0070: 89 23 8e bd 0b 2c 30 bc 41 57 4e 51 16 00 a1 01 [.#...,0.AWNQ....]
|
|
2715
|
+
# 0080: 29 26 27 0c 4b 00 49 00 00 00 00 00 00 00 00 00 [)&'.K.I.........]
|
|
2716
|
+
# 0090: 00 00 00 00 00 00 00 00 00 52 00 00 00 00 00 00 [.........R......]
|
|
2717
|
+
my @a = unpack('x96vCCCCCCx16AAACCCvCCvvv',$$dataPt);
|
|
2718
|
+
SetByteOrder('II');
|
|
2719
|
+
my $acc = ReadValue($dataPt, 0x6c, 'float', 3); # (looks like Z comes first in my sample)
|
|
2720
|
+
my $lon = $a[10] + ($a[11] + $a[13]/6000) / 60; # (why zero byte at $a[12]?)
|
|
2721
|
+
my $lat = $a[14] + ($a[15] + $a[16]/6000) / 60;
|
|
2722
|
+
$et->HandleTag($tagTbl, GPSDateTime => sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d', @a[0..5]));
|
|
2723
|
+
$et->HandleTag($tagTbl, GPSLatitude => $lat * ($a[9] eq 'S' ? -1 : 1));
|
|
2724
|
+
$et->HandleTag($tagTbl, GPSLongitude => $lon * ($a[8] eq 'W' ? -1 : 1));
|
|
2725
|
+
$et->HandleTag($tagTbl, GPSSpeed => $a[17] * $mphToKph); # convert mph -> kph
|
|
2726
|
+
$et->HandleTag($tagTbl, GPSTrack => $a[18]);
|
|
2727
|
+
$et->HandleTag($tagTbl, Accelerometer=> $acc);
|
|
2728
|
+
SetByteOrder('MM');
|
|
2729
|
+
return 1;
|
|
2730
|
+
}
|
|
2731
|
+
|
|
2718
2732
|
#------------------------------------------------------------------------------
|
|
2719
2733
|
# Scan media data for "freeGPS" metadata if not found already (ref PH)
|
|
2720
2734
|
# Inputs: 0) ExifTool ref
|
|
@@ -408,6 +408,9 @@ numerical, and generated automatically otherwise.
|
|
|
408
408
|
to be evaluated. Expression may access $val and $et,
|
|
409
409
|
and is evaluated only when reading.
|
|
410
410
|
|
|
411
|
+
'iTXt' - [PNG TextualData tags only] flag to write tag as PNG
|
|
412
|
+
iTXt chunk even if it contains no special characters.
|
|
413
|
+
|
|
411
414
|
'List' - flag indicating that duplicate entries of this tag
|
|
412
415
|
are allowed, and will be accumulated in a list. Note that for
|
|
413
416
|
XMP information, 3 different types of lists are supported and
|
|
@@ -447,6 +450,10 @@ numerical, and generated automatically otherwise.
|
|
|
447
450
|
may be written if the tag already exists. By default, all
|
|
448
451
|
MakerNotes tags are permanent unless otherwise specified.
|
|
449
452
|
|
|
453
|
+
'PreservePadding' - [QuickTime only] flag to preserve the
|
|
454
|
+
original size of the QuickTime atom by padding with nulls when
|
|
455
|
+
writing with the QuickTimePad option.
|
|
456
|
+
|
|
450
457
|
'PrintHex' - specifies that unknown PrintConv values should
|
|
451
458
|
be printed in hex (eg. 'Unknown (0x1)'). Also causes
|
|
452
459
|
numerical tag values to be printed in hex in the HTML tag name
|
|
@@ -471,9 +478,9 @@ numerical, and generated automatically otherwise.
|
|
|
471
478
|
tags in IFD1 of JPEG images which default to priority 0.
|
|
472
479
|
|
|
473
480
|
'Protected' - bit mask to protect tags from writing:
|
|
474
|
-
Bit 0x01 indicates an '
|
|
481
|
+
Bit 0x01 indicates an 'Unsafe' tag, which is not set via
|
|
475
482
|
SetNewValuesFromFile() unless specified explicitly.
|
|
476
|
-
Bit 0x02 indicates a '
|
|
483
|
+
Bit 0x02 indicates a 'Protected' tag, which should not be set
|
|
477
484
|
directly by the user.
|
|
478
485
|
|
|
479
486
|
'PutFirst' - [EXIF only] flag to place this value before IFD0
|
|
@@ -30,7 +30,7 @@ use strict;
|
|
|
30
30
|
use vars qw($VERSION);
|
|
31
31
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
32
32
|
|
|
33
|
-
$VERSION = '1.
|
|
33
|
+
$VERSION = '1.59';
|
|
34
34
|
|
|
35
35
|
sub ConvertTimecode($);
|
|
36
36
|
sub ProcessSGLT($$$);
|
|
@@ -527,6 +527,10 @@ my %code2charset = (
|
|
|
527
527
|
Name => 'Text',
|
|
528
528
|
Notes => 'streamed text, extracted when the ExtractEmbedded option is used',
|
|
529
529
|
},
|
|
530
|
+
'id3 ' => {
|
|
531
|
+
Name => 'ID3',
|
|
532
|
+
SubDirectory => { TagTable => 'Image::ExifTool::ID3::Main' },
|
|
533
|
+
},
|
|
530
534
|
#
|
|
531
535
|
# WebP-specific tags
|
|
532
536
|
#
|
|
@@ -818,6 +822,7 @@ my %code2charset = (
|
|
|
818
822
|
ILGT => 'Lightness',
|
|
819
823
|
IMED => 'Medium',
|
|
820
824
|
INAM => 'Title',
|
|
825
|
+
ITRK => 'TrackNumber',
|
|
821
826
|
IPLT => 'NumColors',
|
|
822
827
|
IPRD => 'Product',
|
|
823
828
|
ISBJ => 'Subject',
|