exiftool_vendored 12.42.0 → 12.52.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 +226 -6
- data/bin/MANIFEST +14 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +45 -44
- data/bin/config_files/acdsee.config +2 -1
- data/bin/config_files/frameCount.config +56 -0
- data/bin/config_files/tiff_version.config +1 -1
- data/bin/exiftool +116 -97
- data/bin/fmt_files/gpx.fmt +3 -0
- data/bin/fmt_files/gpx_wpt.fmt +3 -0
- data/bin/lib/Image/ExifTool/Apple.pm +16 -3
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +23 -12
- data/bin/lib/Image/ExifTool/Canon.pm +66 -37
- data/bin/lib/Image/ExifTool/CanonRaw.pm +8 -1
- data/bin/lib/Image/ExifTool/CanonVRD.pm +7 -8
- data/bin/lib/Image/ExifTool/Casio.pm +3 -3
- data/bin/lib/Image/ExifTool/DJI.pm +2 -1
- data/bin/lib/Image/ExifTool/DarwinCore.pm +13 -1
- data/bin/lib/Image/ExifTool/EXE.pm +9 -1
- data/bin/lib/Image/ExifTool/Exif.pm +17 -12
- data/bin/lib/Image/ExifTool/FLAC.pm +17 -3
- data/bin/lib/Image/ExifTool/FLIR.pm +9 -7
- data/bin/lib/Image/ExifTool/FlashPix.pm +26 -3
- data/bin/lib/Image/ExifTool/FujiFilm.pm +51 -4
- data/bin/lib/Image/ExifTool/GPS.pm +31 -5
- data/bin/lib/Image/ExifTool/Geotag.pm +36 -8
- data/bin/lib/Image/ExifTool/ICC_Profile.pm +3 -2
- data/bin/lib/Image/ExifTool/ICO.pm +143 -0
- data/bin/lib/Image/ExifTool/ID3.pm +6 -6
- data/bin/lib/Image/ExifTool/IPTC.pm +5 -1
- data/bin/lib/Image/ExifTool/JPEG.pm +1 -0
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +24 -3
- data/bin/lib/Image/ExifTool/LNK.pm +5 -2
- data/bin/lib/Image/ExifTool/Lang/de.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/fr.pm +6015 -759
- data/bin/lib/Image/ExifTool/Lang/sk.pm +1927 -0
- data/bin/lib/Image/ExifTool/M2TS.pm +98 -8
- data/bin/lib/Image/ExifTool/MIE.pm +9 -3
- data/bin/lib/Image/ExifTool/MISB.pm +494 -0
- data/bin/lib/Image/ExifTool/MakerNotes.pm +3 -1
- data/bin/lib/Image/ExifTool/Matroska.pm +272 -48
- data/bin/lib/Image/ExifTool/Motorola.pm +8 -2
- data/bin/lib/Image/ExifTool/Nikon.pm +746 -382
- data/bin/lib/Image/ExifTool/NikonCustom.pm +139 -106
- data/bin/lib/Image/ExifTool/NikonSettings.pm +5 -3
- data/bin/lib/Image/ExifTool/Olympus.pm +6 -4
- data/bin/lib/Image/ExifTool/PNG.pm +8 -1
- data/bin/lib/Image/ExifTool/Panasonic.pm +21 -4
- data/bin/lib/Image/ExifTool/PanasonicRaw.pm +25 -5
- data/bin/lib/Image/ExifTool/Parrot.pm +96 -2
- data/bin/lib/Image/ExifTool/Pentax.pm +7 -2
- data/bin/lib/Image/ExifTool/Photoshop.pm +29 -3
- data/bin/lib/Image/ExifTool/QuickTime.pm +166 -13
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +161 -22
- data/bin/lib/Image/ExifTool/README +15 -4
- data/bin/lib/Image/ExifTool/RIFF.pm +106 -9
- data/bin/lib/Image/ExifTool/Samsung.pm +2 -2
- data/bin/lib/Image/ExifTool/Sigma.pm +27 -1
- data/bin/lib/Image/ExifTool/SigmaRaw.pm +37 -13
- data/bin/lib/Image/ExifTool/Sony.pm +75 -47
- data/bin/lib/Image/ExifTool/TagInfoXML.pm +13 -6
- data/bin/lib/Image/ExifTool/TagLookup.pm +4791 -4519
- data/bin/lib/Image/ExifTool/TagNames.pod +2056 -1446
- data/bin/lib/Image/ExifTool/Text.pm +3 -4
- data/bin/lib/Image/ExifTool/Torrent.pm +2 -3
- data/bin/lib/Image/ExifTool/Validate.pm +3 -3
- data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +7 -0
- data/bin/lib/Image/ExifTool/WriteExif.pl +100 -23
- data/bin/lib/Image/ExifTool/WriteIPTC.pl +2 -6
- data/bin/lib/Image/ExifTool/WritePhotoshop.pl +5 -5
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +12 -7
- data/bin/lib/Image/ExifTool/WriteRIFF.pl +359 -0
- data/bin/lib/Image/ExifTool/WriteXMP.pl +15 -1
- data/bin/lib/Image/ExifTool/Writer.pl +46 -18
- data/bin/lib/Image/ExifTool/XMP.pm +78 -59
- data/bin/lib/Image/ExifTool/XMP2.pl +19 -4
- data/bin/lib/Image/ExifTool/ZIP.pm +19 -7
- data/bin/lib/Image/ExifTool.pm +146 -38
- data/bin/lib/Image/ExifTool.pod +83 -69
- data/bin/perl-Image-ExifTool.spec +43 -43
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +10 -4
|
@@ -26,6 +26,9 @@ sub ProcessFreeGPS($$$);
|
|
|
26
26
|
sub ProcessFreeGPS2($$$);
|
|
27
27
|
sub Process360Fly($$$);
|
|
28
28
|
sub ProcessFMAS($$$);
|
|
29
|
+
sub ProcessCAMM($$$);
|
|
30
|
+
|
|
31
|
+
my $debug; # set to 1 for extra debugging messages
|
|
29
32
|
|
|
30
33
|
# QuickTime data types that have ExifTool equivalents
|
|
31
34
|
# (ref https://developer.apple.com/library/content/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW35)
|
|
@@ -80,7 +83,7 @@ my %processByMetaFormat = (
|
|
|
80
83
|
|
|
81
84
|
# data lengths for each INSV record type
|
|
82
85
|
my %insvDataLen = (
|
|
83
|
-
0x300 =>
|
|
86
|
+
0x300 => 0, # accelerometer (could be either 20 or 56 bytes)
|
|
84
87
|
0x400 => 16, # exposure (ref 6)
|
|
85
88
|
0x600 => 8, # timestamps (ref 6)
|
|
86
89
|
0x700 => 53, # GPS
|
|
@@ -99,7 +102,7 @@ my %insvLimit = (
|
|
|
99
102
|
The tags below are extracted from timed metadata in QuickTime and other
|
|
100
103
|
formats of video files when the ExtractEmbedded option is used. Although
|
|
101
104
|
most of these tags are combined into the single table below, ExifTool
|
|
102
|
-
currently reads
|
|
105
|
+
currently reads 62 different formats of timed GPS metadata from video files.
|
|
103
106
|
},
|
|
104
107
|
VARS => { NO_ID => 1 },
|
|
105
108
|
GPSLatitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', RawConv => '$$self{FoundGPSLatitude} = 1; $val' },
|
|
@@ -234,7 +237,7 @@ my %insvLimit = (
|
|
|
234
237
|
camm => [{
|
|
235
238
|
Name => 'camm0',
|
|
236
239
|
# (according to the spec. the first 2 bytes are reserved and should be zero,
|
|
237
|
-
# but I have
|
|
240
|
+
# but I have samples where these bytes are non-zero, so allow anything here)
|
|
238
241
|
Condition => '$$valPt =~ /^..\0\0/s',
|
|
239
242
|
SubDirectory => {
|
|
240
243
|
TagTable => 'Image::ExifTool::QuickTime::camm0',
|
|
@@ -316,7 +319,7 @@ my %insvLimit = (
|
|
|
316
319
|
|
|
317
320
|
# tags found in 'camm' type 0 timed metadata (ref 4)
|
|
318
321
|
%Image::ExifTool::QuickTime::camm0 = (
|
|
319
|
-
PROCESS_PROC => \&
|
|
322
|
+
PROCESS_PROC => \&ProcessCAMM,
|
|
320
323
|
GROUPS => { 2 => 'Location' },
|
|
321
324
|
FIRST_ENTRY => 0,
|
|
322
325
|
NOTES => q{
|
|
@@ -334,7 +337,7 @@ my %insvLimit = (
|
|
|
334
337
|
|
|
335
338
|
# tags found in 'camm' type 1 timed metadata (ref 4)
|
|
336
339
|
%Image::ExifTool::QuickTime::camm1 = (
|
|
337
|
-
PROCESS_PROC => \&
|
|
340
|
+
PROCESS_PROC => \&ProcessCAMM,
|
|
338
341
|
GROUPS => { 2 => 'Camera' },
|
|
339
342
|
FIRST_ENTRY => 0,
|
|
340
343
|
4 => {
|
|
@@ -353,7 +356,7 @@ my %insvLimit = (
|
|
|
353
356
|
|
|
354
357
|
# tags found in 'camm' type 2 timed metadata (ref PH, Insta360Pro)
|
|
355
358
|
%Image::ExifTool::QuickTime::camm2 = (
|
|
356
|
-
PROCESS_PROC => \&
|
|
359
|
+
PROCESS_PROC => \&ProcessCAMM,
|
|
357
360
|
GROUPS => { 2 => 'Location' },
|
|
358
361
|
FIRST_ENTRY => 0,
|
|
359
362
|
4 => {
|
|
@@ -365,7 +368,7 @@ my %insvLimit = (
|
|
|
365
368
|
|
|
366
369
|
# tags found in 'camm' type 3 timed metadata (ref PH, Insta360Pro)
|
|
367
370
|
%Image::ExifTool::QuickTime::camm3 = (
|
|
368
|
-
PROCESS_PROC => \&
|
|
371
|
+
PROCESS_PROC => \&ProcessCAMM,
|
|
369
372
|
GROUPS => { 2 => 'Location' },
|
|
370
373
|
FIRST_ENTRY => 0,
|
|
371
374
|
4 => {
|
|
@@ -377,7 +380,7 @@ my %insvLimit = (
|
|
|
377
380
|
|
|
378
381
|
# tags found in 'camm' type 4 timed metadata (ref 4)
|
|
379
382
|
%Image::ExifTool::QuickTime::camm4 = (
|
|
380
|
-
PROCESS_PROC => \&
|
|
383
|
+
PROCESS_PROC => \&ProcessCAMM,
|
|
381
384
|
GROUPS => { 2 => 'Location' },
|
|
382
385
|
FIRST_ENTRY => 0,
|
|
383
386
|
4 => {
|
|
@@ -389,7 +392,7 @@ my %insvLimit = (
|
|
|
389
392
|
|
|
390
393
|
# tags found in 'camm' type 5 timed metadata (ref 4)
|
|
391
394
|
%Image::ExifTool::QuickTime::camm5 = (
|
|
392
|
-
PROCESS_PROC => \&
|
|
395
|
+
PROCESS_PROC => \&ProcessCAMM,
|
|
393
396
|
GROUPS => { 2 => 'Location' },
|
|
394
397
|
FIRST_ENTRY => 0,
|
|
395
398
|
4 => {
|
|
@@ -414,7 +417,7 @@ my %insvLimit = (
|
|
|
414
417
|
|
|
415
418
|
# tags found in 'camm' type 6 timed metadata (ref PH/4, Insta360)
|
|
416
419
|
%Image::ExifTool::QuickTime::camm6 = (
|
|
417
|
-
PROCESS_PROC => \&
|
|
420
|
+
PROCESS_PROC => \&ProcessCAMM,
|
|
418
421
|
GROUPS => { 2 => 'Location' },
|
|
419
422
|
FIRST_ENTRY => 0,
|
|
420
423
|
0x04 => {
|
|
@@ -480,7 +483,7 @@ my %insvLimit = (
|
|
|
480
483
|
|
|
481
484
|
# tags found in 'camm' type 7 timed metadata (ref 4)
|
|
482
485
|
%Image::ExifTool::QuickTime::camm7 = (
|
|
483
|
-
PROCESS_PROC => \&
|
|
486
|
+
PROCESS_PROC => \&ProcessCAMM,
|
|
484
487
|
GROUPS => { 2 => 'Location' },
|
|
485
488
|
FIRST_ENTRY => 0,
|
|
486
489
|
4 => {
|
|
@@ -896,10 +899,15 @@ sub Process_text($$$)
|
|
|
896
899
|
my $time = "$1:$2:$3";
|
|
897
900
|
if ($$et{LastTime}) {
|
|
898
901
|
if ($$et{LastTime} eq $time) {
|
|
902
|
+
# combine with the previous NMEA sentence
|
|
899
903
|
$$et{DOC_NUM} = $$et{LastDoc};
|
|
900
904
|
} elsif (%tags) {
|
|
905
|
+
# handle existing tags and start a new document
|
|
906
|
+
# (see https://exiftool.org/forum/index.php?msg=75422)
|
|
901
907
|
HandleTextTags($et, $tagTbl, \%tags);
|
|
902
|
-
|
|
908
|
+
undef %tags;
|
|
909
|
+
# increment document number and update document count if necessary
|
|
910
|
+
$$et{DOC_COUNT} < ++$$et{DOC_NUM} and $$et{DOC_COUNT} = $$et{DOC_NUM};
|
|
903
911
|
}
|
|
904
912
|
}
|
|
905
913
|
$$et{LastTime} = $time;
|
|
@@ -918,7 +926,8 @@ sub Process_text($$$)
|
|
|
918
926
|
$$et{DOC_NUM} = $$et{LastDoc};
|
|
919
927
|
} elsif (%tags) {
|
|
920
928
|
HandleTextTags($et, $tagTbl, \%tags);
|
|
921
|
-
|
|
929
|
+
undef %tags;
|
|
930
|
+
$$et{DOC_COUNT} < ++$$et{DOC_NUM} and $$et{DOC_COUNT} = $$et{DOC_NUM};
|
|
922
931
|
}
|
|
923
932
|
}
|
|
924
933
|
$$et{LastTime} = $time;
|
|
@@ -1416,6 +1425,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1416
1425
|
} elsif ($buf2 =~ /^.{173}([-+]\d{3})([-+]\d{3})([-+]\d{3})/s) { # (Azdome)
|
|
1417
1426
|
@acc = ($1/100, $2/100, $3/100);
|
|
1418
1427
|
}
|
|
1428
|
+
$debug and $et->FoundTag(GPSType => '1A');
|
|
1419
1429
|
|
|
1420
1430
|
} elsif ($$dataPt =~ /^.{52}(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/s) {
|
|
1421
1431
|
|
|
@@ -1444,6 +1454,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1444
1454
|
# change to signed integer and divide by 256
|
|
1445
1455
|
map { $_ = $_ - 4294967296 if $_ >= 0x80000000; $_ /= 256 } @acc;
|
|
1446
1456
|
}
|
|
1457
|
+
$debug and $et->FoundTag(GPSType => '1B');
|
|
1447
1458
|
|
|
1448
1459
|
} elsif ($$dataPt =~ /^.{37}\0\0\0A([NS])([EW])/s) {
|
|
1449
1460
|
|
|
@@ -1454,13 +1465,31 @@ sub ProcessFreeGPS($$$)
|
|
|
1454
1465
|
# 0030: f1 47 40 46 66 66 d2 41 85 eb 83 41 00 00 00 00 [.G@Fff.A...A....]
|
|
1455
1466
|
($latRef, $lonRef) = ($1, $2);
|
|
1456
1467
|
($hr,$min,$sec,$yr,$mon,$day) = unpack('x16V6', $$dataPt);
|
|
1457
|
-
$yr
|
|
1468
|
+
if ($yr < 2000) {
|
|
1469
|
+
$yr += 2000;
|
|
1470
|
+
} else {
|
|
1471
|
+
# Kenwood dashcam sometimes stores absolute year and local time
|
|
1472
|
+
# (but sometimes year since 2000 and UTC time in same video!)
|
|
1473
|
+
require Time::Local;
|
|
1474
|
+
my $time = Image::ExifTool::TimeLocal($sec,$min,$hr,$day,$mon-1,$yr-1900);
|
|
1475
|
+
($sec,$min,$hr,$day,$mon,$yr) = gmtime($time);
|
|
1476
|
+
$yr += 1900;
|
|
1477
|
+
++$mon;
|
|
1478
|
+
$et->WarnOnce('Converting GPSDateTime to UTC based on local time zone',1);
|
|
1479
|
+
}
|
|
1458
1480
|
SetByteOrder('II');
|
|
1459
1481
|
$lat = GetFloat($dataPt, 0x2c);
|
|
1460
1482
|
$lon = GetFloat($dataPt, 0x30);
|
|
1461
1483
|
$spd = GetFloat($dataPt, 0x34) * $knotsToKph; # (convert knots to km/h)
|
|
1462
1484
|
$trk = GetFloat($dataPt, 0x38);
|
|
1485
|
+
# (may be all zeros or int16u counting from 1 to 6 if not valid)
|
|
1486
|
+
my $tmp = substr($$dataPt, 60, 12);
|
|
1487
|
+
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") {
|
|
1488
|
+
@acc = unpack('V3', $tmp);
|
|
1489
|
+
map { $_ = $_ - 4294967296 if $_ >= 0x80000000; $_ /= 256 } @acc;
|
|
1490
|
+
}
|
|
1463
1491
|
SetByteOrder('MM');
|
|
1492
|
+
$debug and $et->FoundTag(GPSType => '1C');
|
|
1464
1493
|
|
|
1465
1494
|
} elsif ($$dataPt =~ /^.{21}\0\0\0A([NS])([EW])/s) {
|
|
1466
1495
|
|
|
@@ -1489,6 +1518,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1489
1518
|
$acc[1] = GetFloat($dataPt, 0x30);
|
|
1490
1519
|
$acc[2] = GetFloat($dataPt, 0x34);
|
|
1491
1520
|
SetByteOrder('MM');
|
|
1521
|
+
$debug and $et->FoundTag(GPSType => '1D');
|
|
1492
1522
|
|
|
1493
1523
|
} elsif ($$dataPt =~ /^.{60}A\0{3}.{4}([NS])\0{3}.{4}([EW])\0{3}/s) {
|
|
1494
1524
|
|
|
@@ -1509,6 +1539,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1509
1539
|
$trk = GetFloat($dataPt, 0x54) + 180; # (why is this off by 180?)
|
|
1510
1540
|
$trk -= 360 if $trk >= 360;
|
|
1511
1541
|
SetByteOrder('MM');
|
|
1542
|
+
$debug and $et->FoundTag(GPSType => '1E');
|
|
1512
1543
|
|
|
1513
1544
|
} elsif ($$dataPt =~ /^.{60}4W`b]S</s and length($$dataPt) >= 140) {
|
|
1514
1545
|
|
|
@@ -1526,8 +1557,9 @@ sub ProcessFreeGPS($$$)
|
|
|
1526
1557
|
$yr += ($yr >= 70 ? 1900 : 2000);
|
|
1527
1558
|
$spd = $9 * $knotsToKph if length $9;
|
|
1528
1559
|
$trk = $10 if length $10;
|
|
1560
|
+
$debug and $et->FoundTag(GPSType => '1F');
|
|
1529
1561
|
|
|
1530
|
-
} elsif ($$dataPt =~ /^.{64}[\x01-\x0c]\0{3}[\x01-\x1f]\0{3}A[NS][EW]\0/s) {
|
|
1562
|
+
} elsif ($$dataPt =~ /^.{64}[\x01-\x0c]\0{3}[\x01-\x1f]\0{3}A[NS][EW]\0{5}/s) {
|
|
1531
1563
|
|
|
1532
1564
|
# Akaso V1 dascham
|
|
1533
1565
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 78 00 00 00 [....freeGPS x...]
|
|
@@ -1569,6 +1601,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1569
1601
|
|
|
1570
1602
|
SetByteOrder('MM');
|
|
1571
1603
|
#my $serialNum = substr($$dataPt, 0x68, 20);
|
|
1604
|
+
$debug and $et->FoundTag(GPSType => '1G');
|
|
1572
1605
|
|
|
1573
1606
|
} elsif ($$dataPt =~ /^.{12}\xac\0\0\0.{44}(.{72})/s) {
|
|
1574
1607
|
|
|
@@ -1591,6 +1624,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1591
1624
|
# bytes 7-12 are the timestamp in ASCII HHMMSS after xor-ing with 0x70
|
|
1592
1625
|
substr($time,7,6) = pack 'C*', map { $_ ^= 0x70 } unpack 'C*', substr($time,7,6);
|
|
1593
1626
|
# (other values are currently unknown)
|
|
1627
|
+
$debug and $et->FoundTag(GPSType => '1H');
|
|
1594
1628
|
|
|
1595
1629
|
} elsif ($$dataPt =~ /^.{64}A([NS])([EW])\0/s) {
|
|
1596
1630
|
|
|
@@ -1616,6 +1650,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1616
1650
|
$trk = GetFloat($dataPt, 0x68);
|
|
1617
1651
|
$alt = GetFloat($dataPt, 0x6c);
|
|
1618
1652
|
SetByteOrder('MM');
|
|
1653
|
+
$debug and $et->FoundTag(GPSType => '1I');
|
|
1619
1654
|
|
|
1620
1655
|
} else {
|
|
1621
1656
|
|
|
@@ -1624,6 +1659,9 @@ sub ProcessFreeGPS($$$)
|
|
|
1624
1659
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 4c 00 00 00 [....freeGPS L...]
|
|
1625
1660
|
# 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
|
1626
1661
|
# 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
|
1662
|
+
# 0030: 10 00 00 00 2d 00 00 00 14 00 00 00 11 00 00 00 [....-...........]
|
|
1663
|
+
# 0040: 0c 00 00 00 1f 00 00 00 41 4e 45 00 5d 9a a9 45 [........ANE.]..E]
|
|
1664
|
+
# 0050: ab 1e e5 44 ec 51 f0 40 b8 5e a5 43 00 00 00 00 [...D.Q.@.^.C....]
|
|
1627
1665
|
# (records are same structure as Type 3 Novatek GPS in ProcessFreeGPS2() below)
|
|
1628
1666
|
($hr,$min,$sec,$yr,$mon,$day,$stat,$latRef,$lonRef,$lat,$lon,$spd,$trk) =
|
|
1629
1667
|
unpack('x48V6a1a1a1x1V4', $$dataPt);
|
|
@@ -1649,6 +1687,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1649
1687
|
$yr += 2000 if $yr < 2000;
|
|
1650
1688
|
$spd *= $knotsToKph; # convert speed to km/h
|
|
1651
1689
|
# ($trk is not confirmed; may be GPSImageDirection, ref PH)
|
|
1690
|
+
$debug and $et->FoundTag(GPSType => '1J');
|
|
1652
1691
|
}
|
|
1653
1692
|
#
|
|
1654
1693
|
# save tag values extracted by above code
|
|
@@ -1802,6 +1841,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1802
1841
|
}
|
|
1803
1842
|
# save position of most recent record (needed when parsing the next freeGPS block)
|
|
1804
1843
|
$$et{FreeGPS2}{RecentRecPos} = $lastRecPos;
|
|
1844
|
+
$debug and $et->FoundTag(GPSType => '2A');
|
|
1805
1845
|
return 1;
|
|
1806
1846
|
|
|
1807
1847
|
} elsif ($$dataPt =~ /^.{60}A\0.{10}([NS])\0.{14}([EW])\0/s) {
|
|
@@ -1833,6 +1873,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1833
1873
|
$lon = GetDouble($dataPt, 0x50);
|
|
1834
1874
|
$spd = GetDouble($dataPt, 0x60) * $knotsToKph;
|
|
1835
1875
|
$trk = GetDouble($dataPt, 0x68);
|
|
1876
|
+
$debug and $et->FoundTag(GPSType => '2B');
|
|
1836
1877
|
|
|
1837
1878
|
} elsif ($$dataPt =~ /^.{72}A([NS])([EW])/s) {
|
|
1838
1879
|
|
|
@@ -1869,6 +1910,8 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1869
1910
|
$lon = abs Get32s($dataPt, 0x50) / 1e7;
|
|
1870
1911
|
$spd = Get32s($dataPt, 0x54) / 100 * $mpsToKph;
|
|
1871
1912
|
$alt = GetFloat($dataPt, 0x58) / 1000; # (NC)
|
|
1913
|
+
$debug and $et->FoundTag(GPSType => '2C');
|
|
1914
|
+
|
|
1872
1915
|
} else {
|
|
1873
1916
|
# Type 3 (ref 2)
|
|
1874
1917
|
# (no sample with this format)
|
|
@@ -1876,6 +1919,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1876
1919
|
$lon = GetFloat($dataPt, 0x50);
|
|
1877
1920
|
$spd = GetFloat($dataPt, 0x54) * $knotsToKph;
|
|
1878
1921
|
$trk = GetFloat($dataPt, 0x58);
|
|
1922
|
+
$debug and $et->FoundTag(GPSType => '2D');
|
|
1879
1923
|
}
|
|
1880
1924
|
|
|
1881
1925
|
} elsif ($$dataPt =~ /^.{60}A\0.{6}([NS])\0.{6}([EW])\0/s and $dirLen >= 112) {
|
|
@@ -1896,6 +1940,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1896
1940
|
$lon = GetFloat($dataPt, 0x48);
|
|
1897
1941
|
$spd = GetFloat($dataPt, 0x50);
|
|
1898
1942
|
$trk = GetFloat($dataPt, 0x54);
|
|
1943
|
+
$debug and $et->FoundTag(GPSType => '2E');
|
|
1899
1944
|
|
|
1900
1945
|
} elsif ($$dataPt =~ /^.{16}A([NS])([EW])\0/s) {
|
|
1901
1946
|
|
|
@@ -1916,6 +1961,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1916
1961
|
$et->HandleTag($tagTbl, GPSTrack => $trk);
|
|
1917
1962
|
$et->HandleTag($tagTbl, Accelerometer => "@acc");
|
|
1918
1963
|
}
|
|
1964
|
+
$debug and $et->FoundTag(GPSType => '2F');
|
|
1919
1965
|
return 1;
|
|
1920
1966
|
|
|
1921
1967
|
} else {
|
|
@@ -1962,6 +2008,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1962
2008
|
$et->HandleTag($tagTbl, GPSTrack => $trk);
|
|
1963
2009
|
last if $pos += 0x20 > length($$dataPt) - 0x1e;
|
|
1964
2010
|
}
|
|
2011
|
+
$debug and $et->FoundTag(GPSType => '2G');
|
|
1965
2012
|
return $$et{DOC_NUM} ? 1 : 0; # return 0 if nothing extracted
|
|
1966
2013
|
}
|
|
1967
2014
|
#
|
|
@@ -2530,7 +2577,7 @@ sub ProcessTTAD($$$)
|
|
|
2530
2577
|
# (I think "5" may be the number of satellites. seen: 5,6,7 - PH)
|
|
2531
2578
|
FoundSomething($et, $tagTbl, $sampleTime / 1000);
|
|
2532
2579
|
my $t = GetDouble($dataPt, $pos);
|
|
2533
|
-
$et->HandleTag($tagTbl, GPSDateTime => Image::ExifTool::ConvertUnixTime($t,undef,3).'Z');
|
|
2580
|
+
$et->HandleTag($tagTbl, GPSDateTime => Image::ExifTool::ConvertUnixTime($t,undef,3) . 'Z');
|
|
2534
2581
|
$et->HandleTag($tagTbl, GPSLatitude => GetDouble($dataPt, $pos+0x1c));
|
|
2535
2582
|
$et->HandleTag($tagTbl, GPSLongitude => GetDouble($dataPt, $pos+0x24));
|
|
2536
2583
|
$et->HandleTag($tagTbl, GPSAltitude => GetDouble($dataPt, $pos+0x14));
|
|
@@ -2621,8 +2668,33 @@ sub ProcessInsta360($;$)
|
|
|
2621
2668
|
if ($verbose) {
|
|
2622
2669
|
$et->VPrint(0, sprintf("Insta360 Record 0x%x (offset 0x%x, %d bytes):\n", $id, $fileEnd + $epos, $len));
|
|
2623
2670
|
}
|
|
2671
|
+
# there are 2 types of record 0x300:
|
|
2672
|
+
# 1. 56 byte records
|
|
2673
|
+
# 0000: 4a f7 02 00 00 00 00 00 00 00 00 00 00 1e e7 3f [J..............?]
|
|
2674
|
+
# 0010: 00 00 00 00 00 b2 ef bf 00 00 00 00 00 70 c1 bf [.............p..]
|
|
2675
|
+
# 0020: 00 00 00 e0 91 5c 8c bf 00 00 00 20 8f ff 87 bf [.....\..... ....]
|
|
2676
|
+
# 0030: 00 00 00 00 88 7f c9 bf
|
|
2677
|
+
# 2. 20 byte records
|
|
2678
|
+
# 0000: c1 d8 d9 0b 00 00 00 00 f5 83 14 80 df 7f fe 7f [................]
|
|
2679
|
+
# 0010: fe 7f 01 80
|
|
2680
|
+
if ($id == 0x300) {
|
|
2681
|
+
if ($len % 20 and not $len % 56) {
|
|
2682
|
+
$dlen = 56;
|
|
2683
|
+
} elsif ($len % 56 and not $len % 20) {
|
|
2684
|
+
$dlen = 20;
|
|
2685
|
+
} else {
|
|
2686
|
+
if ($raf->Read($buff, 20) == 20) {
|
|
2687
|
+
if (substr($buff, 16, 3) eq "\0\0\0") {
|
|
2688
|
+
$dlen = 56;
|
|
2689
|
+
} else {
|
|
2690
|
+
$dlen = 20;
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
$raf->Seek($epos, 2) or last;
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2624
2696
|
# limit the number of records we read if necessary
|
|
2625
|
-
if ($insvLimit{$id} and $len > $insvLimit{$id}[1] * $dlen and
|
|
2697
|
+
if ($dlen and $insvLimit{$id} and $len > $insvLimit{$id}[1] * $dlen and
|
|
2626
2698
|
$et->Warn("Insta360 $insvLimit{$id}[0] data is huge. Processing only the first $insvLimit{$id}[1] records",2))
|
|
2627
2699
|
{
|
|
2628
2700
|
$len = $insvLimit{$id}[1] * $dlen;
|
|
@@ -2630,11 +2702,18 @@ sub ProcessInsta360($;$)
|
|
|
2630
2702
|
$raf->Read($buff, $len) == $len or last;
|
|
2631
2703
|
$et->VerboseDump(\$buff) if $verbose > 2;
|
|
2632
2704
|
if ($dlen) {
|
|
2633
|
-
$len % $dlen
|
|
2634
|
-
|
|
2705
|
+
if ($len % $dlen) {
|
|
2706
|
+
$et->Warn(sprintf('Unexpected Insta360 record 0x%x length',$id));
|
|
2707
|
+
} elsif ($id == 0x300) {
|
|
2635
2708
|
for ($p=0; $p<$len; $p+=$dlen) {
|
|
2636
2709
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
|
2637
|
-
my @a
|
|
2710
|
+
my @a;
|
|
2711
|
+
if ($dlen == 56) {
|
|
2712
|
+
@a = map { GetDouble(\$buff, $p + 8 * $_) } 1..6;
|
|
2713
|
+
} else {
|
|
2714
|
+
@a = unpack("x${p}x8v6", $buff);
|
|
2715
|
+
map { $_ = ($_ - 0x8000) / 1000 } @a;
|
|
2716
|
+
}
|
|
2638
2717
|
$et->HandleTag($tagTbl, TimeCode => sprintf('%.3f', Get64u(\$buff, $p) / 1000));
|
|
2639
2718
|
$et->HandleTag($tagTbl, Accelerometer => "@a[0..2]"); # (NC)
|
|
2640
2719
|
$et->HandleTag($tagTbl, AngularVelocity => "@a[3..5]"); # (NC)
|
|
@@ -2699,6 +2778,66 @@ sub ProcessInsta360($;$)
|
|
|
2699
2778
|
return 1;
|
|
2700
2779
|
}
|
|
2701
2780
|
|
|
2781
|
+
#------------------------------------------------------------------------------
|
|
2782
|
+
# Process CAMM metadata (ref PH)
|
|
2783
|
+
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
|
|
2784
|
+
# Returns: 1 on success
|
|
2785
|
+
sub ProcessCAMM($$$)
|
|
2786
|
+
{
|
|
2787
|
+
my ($et, $dirInfo, $tagTbl) = @_;
|
|
2788
|
+
my $dataPt = $$dirInfo{DataPt};
|
|
2789
|
+
my $pos = $$dirInfo{DirStart} || 0;
|
|
2790
|
+
my $end = $pos + ($$dirInfo{DirLen} || length($$dataPt) - $pos);
|
|
2791
|
+
# camm record size for each type, including 4-byte header
|
|
2792
|
+
my %size = ( 1 => 12, 2 => 16, 3 => 16, 4 => 16, 5 => 28, 6 => 60, 7 => 16 );
|
|
2793
|
+
my $rtnVal = 0;
|
|
2794
|
+
while ($pos + 4 < $end) {
|
|
2795
|
+
my $type = Get16u($dataPt, $pos + 2);
|
|
2796
|
+
my $size = $size{$type} or $et->WarnOnce("Unknown camm record type $type"), last;
|
|
2797
|
+
$pos + $size > $end and $et->WarnOnce("Truncated camm record $type"), last;
|
|
2798
|
+
my $tagTbl = GetTagTable("Image::ExifTool::QuickTime::camm$type");
|
|
2799
|
+
$$dirInfo{DirStart} = $pos;
|
|
2800
|
+
$$dirInfo{DirLen} = $size;
|
|
2801
|
+
$et->ProcessBinaryData($dirInfo, $tagTbl) and $rtnVal = 1;
|
|
2802
|
+
# not sure if this is according to specification, but I have seen multiple
|
|
2803
|
+
# camm records all in a single sample, so step forward to process the next one
|
|
2804
|
+
$pos += $size;
|
|
2805
|
+
}
|
|
2806
|
+
return $rtnVal;
|
|
2807
|
+
}
|
|
2808
|
+
|
|
2809
|
+
#------------------------------------------------------------------------------
|
|
2810
|
+
# Process Garmin GPS 'uuid' atom (ref PH)
|
|
2811
|
+
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
|
|
2812
|
+
# Returns: 1 on success
|
|
2813
|
+
# Note: This format is used by the Garmin DriveAssist 51, but the DriveAssist 50
|
|
2814
|
+
# uses a completely different format. :(
|
|
2815
|
+
sub ProcessGarminGPS($$$)
|
|
2816
|
+
{
|
|
2817
|
+
my ($et, $dirInfo, $tagTbl) = @_;
|
|
2818
|
+
my $dataPt = $$dirInfo{DataPt};
|
|
2819
|
+
my $dataLen = length $$dataPt;
|
|
2820
|
+
my $pos = 33;
|
|
2821
|
+
my $epoch = (66 * 365 + 17) * 24 * 3600; # time is relative to Jan 1, 1904
|
|
2822
|
+
my $scl = 180 / (32768 * 65536); # scaling factor for lat/lon
|
|
2823
|
+
$et->VerboseDir('GarminGPS');
|
|
2824
|
+
while ($pos + 20 <= $dataLen) {
|
|
2825
|
+
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
|
2826
|
+
my $time = Image::ExifTool::ConvertUnixTime(Get32u($dataPt, $pos) - $epoch) . 'Z';
|
|
2827
|
+
my $lat = Get32s($dataPt, $pos + 12) * $scl;
|
|
2828
|
+
my $lon = Get32s($dataPt, $pos + 16) * $scl;
|
|
2829
|
+
my $spd = Get16u($dataPt, $pos + 4); # (in mph)
|
|
2830
|
+
$et->HandleTag($tagTbl, 'GPSDateTime', $time);
|
|
2831
|
+
$et->HandleTag($tagTbl, 'GPSLatitude', $lat);
|
|
2832
|
+
$et->HandleTag($tagTbl, 'GPSLongitude', $lon);
|
|
2833
|
+
$et->HandleTag($tagTbl, 'GPSSpeed', $spd);
|
|
2834
|
+
$et->HandleTag($tagTbl, 'GPSSpeedRef', 'M');
|
|
2835
|
+
$pos += 20;
|
|
2836
|
+
}
|
|
2837
|
+
delete $$et{DOC_NUM};
|
|
2838
|
+
return 1;
|
|
2839
|
+
}
|
|
2840
|
+
|
|
2702
2841
|
#------------------------------------------------------------------------------
|
|
2703
2842
|
# Process 360Fly 'uuid' atom containing sensor data
|
|
2704
2843
|
# (ref https://github.com/JamesHeinrich/getID3/blob/master/getid3/module.audio-video.quicktime.php)
|
|
@@ -2776,9 +2915,9 @@ sub ScanMediaData($)
|
|
|
2776
2915
|
my ($pos, $buf2) = (0, '');
|
|
2777
2916
|
|
|
2778
2917
|
# don't rescan for freeGPS if we already found embedded metadata
|
|
2779
|
-
my $dataPos = $$et{
|
|
2918
|
+
my $dataPos = $$et{MediaDataOffset};
|
|
2780
2919
|
if ($dataPos and not $$et{DOC_COUNT}) {
|
|
2781
|
-
$dataLen = $$et{
|
|
2920
|
+
$dataLen = $$et{MediaDataSize};
|
|
2782
2921
|
if ($dataLen) {
|
|
2783
2922
|
if ($raf->Seek($dataPos, 0)) {
|
|
2784
2923
|
$$et{FreeGPS2} = { }; # initialize variable space for FreeGPS2()
|
|
@@ -395,7 +395,9 @@ numerical, and generated automatically otherwise.
|
|
|
395
395
|
be accessible.
|
|
396
396
|
|
|
397
397
|
'Hidden' - set to hide tag from the TagName documentation.
|
|
398
|
-
Also suppresses verbose output of a BinaryData tag.
|
|
398
|
+
Also suppresses verbose output of a BinaryData tag. The
|
|
399
|
+
RawConv of a Hidden tag should return undef so the tag value
|
|
400
|
+
is not seen by the user.
|
|
399
401
|
|
|
400
402
|
'IsComposite' - flag set for Composite tags
|
|
401
403
|
|
|
@@ -531,7 +533,8 @@ numerical, and generated automatically otherwise.
|
|
|
531
533
|
SubIFD's where the PutFirst flag is valid.
|
|
532
534
|
|
|
533
535
|
'Unknown' - this is an unknown tag (only extracted when the
|
|
534
|
-
Unknown option is set).
|
|
536
|
+
Unknown option is set). This is set to 2 for Unknown tags in
|
|
537
|
+
binary tables (extracted when Unknown is 2).
|
|
535
538
|
|
|
536
539
|
'WriteNothing' - flag indicating that nothing is actually
|
|
537
540
|
written when this tag is set. It is a fake writable tag that
|
|
@@ -638,7 +641,8 @@ numerical, and generated automatically otherwise.
|
|
|
638
641
|
expression, a code reference or a list reference. In this
|
|
639
642
|
expression, $self, $val and $tag may be used as with
|
|
640
643
|
ValueConv, but if ValueConv was defined then $val is the
|
|
641
|
-
ValueConv value instead of the Raw value.
|
|
644
|
+
ValueConv value instead of the Raw value. Composite tags
|
|
645
|
+
may also use the @val, @prt and @raw lists. The returned value
|
|
642
646
|
should always be defined. Note that the print conversion is
|
|
643
647
|
only done if the PrintConv option is enabled (which it is by
|
|
644
648
|
default), and if the result of the ValueConv is not a scalar
|
|
@@ -717,7 +721,7 @@ numerical, and generated automatically otherwise.
|
|
|
717
721
|
condition exists, then a 'true' condition is assumed. The
|
|
718
722
|
expression may use $self to access the ExifTool object. The
|
|
719
723
|
first 128 bytes of the raw data value are accessible through
|
|
720
|
-
the reference $valPt for EXIF, Jpeg2000, QuickTime and
|
|
724
|
+
the reference $valPt for EXIF, Jpeg2000, QuickTime, FLAC and
|
|
721
725
|
BinaryData tags only (note that for BinaryData tags, the raw
|
|
722
726
|
data of $$valPt is always 'undef' type, and may not be used
|
|
723
727
|
when writing except for SubDirectory tags). EXIF tags (and
|
|
@@ -964,6 +968,10 @@ numerical, and generated automatically otherwise.
|
|
|
964
968
|
OtherLang : [reserved] Used internally by QuickTime module to store a list
|
|
965
969
|
of tag ID's for alternate-language tags based on this one.
|
|
966
970
|
|
|
971
|
+
ParentTagInfo : [reserved] Used internally to store a reference to the tag
|
|
972
|
+
information hash of the parent structure for flattened
|
|
973
|
+
structure tags.
|
|
974
|
+
|
|
967
975
|
RootTagInfo : [reserved] Used internally to store a reference to the tag
|
|
968
976
|
information hash of the top-level structure for flattened
|
|
969
977
|
structure tags.
|
|
@@ -975,6 +983,9 @@ numerical, and generated automatically otherwise.
|
|
|
975
983
|
alternate language tags (eg. 'fr'). Only used with formats
|
|
976
984
|
which support alternate languages (eg. XMP, MIE, etc).
|
|
977
985
|
|
|
986
|
+
AddedUnknown : [reserved] Used internally to mark Unknown tags that were
|
|
987
|
+
added to the table at run time.
|
|
988
|
+
|
|
978
989
|
SubDirectory { If it exists, this specifies the start of a new subdirectory.
|
|
979
990
|
It contains a collection of variables which specify the type
|
|
980
991
|
and location of the subdirectory. Note that ValueConv and
|