exiftool-vendored.pl 12.54.0 → 12.56.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/Changes +34 -4
- package/bin/MANIFEST +5 -0
- package/bin/META.json +1 -1
- package/bin/META.yml +1 -1
- package/bin/README +19 -19
- package/bin/arg_files/xmp2exif.args +4 -1
- package/bin/exiftool +28 -28
- package/bin/fmt_files/kml.fmt +3 -0
- package/bin/fmt_files/kml_track.fmt +6 -3
- package/bin/lib/Image/ExifTool/BuildTagLookup.pm +7 -5
- package/bin/lib/Image/ExifTool/Canon.pm +8 -2
- package/bin/lib/Image/ExifTool/Exif.pm +31 -2
- package/bin/lib/Image/ExifTool/FlashPix.pm +69 -8
- package/bin/lib/Image/ExifTool/FujiFilm.pm +3 -1
- package/bin/lib/Image/ExifTool/Geotag.pm +13 -4
- package/bin/lib/Image/ExifTool/InfiRay.pm +227 -0
- package/bin/lib/Image/ExifTool/JPEG.pm +40 -6
- package/bin/lib/Image/ExifTool/Matroska.pm +4 -4
- package/bin/lib/Image/ExifTool/Nikon.pm +187 -384
- package/bin/lib/Image/ExifTool/OpenEXR.pm +32 -15
- package/bin/lib/Image/ExifTool/PNG.pm +80 -2
- package/bin/lib/Image/ExifTool/QuickTime.pm +19 -4
- package/bin/lib/Image/ExifTool/QuickTimeStream.pl +127 -39
- package/bin/lib/Image/ExifTool/README +3 -0
- package/bin/lib/Image/ExifTool/Real.pm +2 -2
- package/bin/lib/Image/ExifTool/Sony.pm +5 -1
- package/bin/lib/Image/ExifTool/TagLookup.pm +4544 -4525
- package/bin/lib/Image/ExifTool/TagNames.pod +229 -21
- package/bin/lib/Image/ExifTool/VCard.pm +19 -5
- package/bin/lib/Image/ExifTool.pm +56 -15
- package/bin/lib/Image/ExifTool.pod +51 -50
- package/bin/perl-Image-ExifTool.spec +18 -18
- package/bin/pp_build_exe.args +7 -6
- package/package.json +3 -3
|
@@ -81,12 +81,15 @@ my %processByMetaFormat = (
|
|
|
81
81
|
ctbx => 1, # ('marl' in GM videos)
|
|
82
82
|
);
|
|
83
83
|
|
|
84
|
-
# data lengths for each INSV record type
|
|
84
|
+
# data lengths for each INSV/INSP record type
|
|
85
85
|
my %insvDataLen = (
|
|
86
|
+
0x200 => 0, # PreivewImage (any size) (a duplicate of PreviewImage in APP2 of INSP files)
|
|
86
87
|
0x300 => 0, # accelerometer (could be either 20 or 56 bytes)
|
|
87
88
|
0x400 => 16, # exposure (ref 6)
|
|
88
89
|
0x600 => 8, # timestamps (ref 6)
|
|
89
90
|
0x700 => 53, # GPS
|
|
91
|
+
# 0x900 => 48, # ? (Insta360 X3)
|
|
92
|
+
# 0xb00 => 10, # ? (Insta360 X3)
|
|
90
93
|
);
|
|
91
94
|
|
|
92
95
|
# limit the default amount of data we read for some record types
|
|
@@ -102,7 +105,7 @@ my %insvLimit = (
|
|
|
102
105
|
The tags below are extracted from timed metadata in QuickTime and other
|
|
103
106
|
formats of video files when the ExtractEmbedded option is used. Although
|
|
104
107
|
most of these tags are combined into the single table below, ExifTool
|
|
105
|
-
currently reads
|
|
108
|
+
currently reads 66 different formats of timed GPS metadata from video files.
|
|
106
109
|
},
|
|
107
110
|
VARS => { NO_ID => 1 },
|
|
108
111
|
GPSLatitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', RawConv => '$$self{FoundGPSLatitude} = 1; $val' },
|
|
@@ -880,9 +883,10 @@ sub HandleTextTags($$$)
|
|
|
880
883
|
#------------------------------------------------------------------------------
|
|
881
884
|
# Process subtitle 'text'
|
|
882
885
|
# Inputs: 0) ExifTool ref, 1) data ref or dirInfo ref, 2) tag table ref
|
|
883
|
-
|
|
886
|
+
# 3) flag set if text was already stored
|
|
887
|
+
sub Process_text($$$;$)
|
|
884
888
|
{
|
|
885
|
-
my ($et, $dataPt, $tagTbl) = @_;
|
|
889
|
+
my ($et, $dataPt, $tagTbl, $handled) = @_;
|
|
886
890
|
my %tags;
|
|
887
891
|
|
|
888
892
|
return if $$et{NoMoreTextDecoding};
|
|
@@ -938,6 +942,16 @@ sub Process_text($$$)
|
|
|
938
942
|
$tags{GPSSatellites} = $10 if defined $10;
|
|
939
943
|
$tags{GPSDOP} = $11 if defined $11;
|
|
940
944
|
$tags{GPSAltitude} = $12 if defined $12;
|
|
945
|
+
# ($G and $GS are ref https://exiftool.org/forum/index.php?topic=13115.msg71743#msg71743)
|
|
946
|
+
} elsif ($tag eq 'G' and $dat =~ /:(\d{4})-(\d{2})-(\d{2}) (\d{2}:\d{2}:\d{2})-([NS])(\d+\.\d+)-([EW])(\d+\.\d+)-S(\d+)/) {
|
|
947
|
+
$tags{GPSDateTime} = "$1:$2:$3 $4";
|
|
948
|
+
$tags{GPSLatitude} = $6 * ($5 eq 'S' ? -1 : 1);
|
|
949
|
+
$tags{GPSLongitude} = $8 * ($7 eq 'W' ? -1 : 1);
|
|
950
|
+
$tags{GPSSpeed} = $9;
|
|
951
|
+
} elsif ($tag eq 'GS' and $dat =~ /:([-+]?\d+),([-+]?\d+),([-+]?\d+)/) {
|
|
952
|
+
# scale and re-arrange to match gsensor output from Win app (forum11665)
|
|
953
|
+
my @acc = ( ($2+2432)/1000, ($3 + 361)/1000, ($1-3708)/1000 );
|
|
954
|
+
$tags{Accelerometer} = "@acc";
|
|
941
955
|
} elsif ($tag eq 'BEGINGSENSOR' and $dat =~ /^:([-+]\d+\.\d+):([-+]\d+\.\d+):([-+]\d+\.\d+)/) {
|
|
942
956
|
$tags{Accelerometer} = "$1 $2 $3";
|
|
943
957
|
} elsif ($tag eq 'TIME' and $dat =~ /^:(\d+)/) {
|
|
@@ -946,7 +960,7 @@ sub Process_text($$$)
|
|
|
946
960
|
$tags{Text} = $dat if length $dat;
|
|
947
961
|
$tags{done} = 1;
|
|
948
962
|
} elsif ($tag ne 'END') {
|
|
949
|
-
$tags{Text} = "\$$tag$dat";
|
|
963
|
+
$tags{Text} = "\$$tag$dat" unless $handled;
|
|
950
964
|
}
|
|
951
965
|
}
|
|
952
966
|
%tags and HandleTextTags($et, $tagTbl, \%tags), return;
|
|
@@ -1234,6 +1248,7 @@ Sample: for ($i=0; ; ) {
|
|
|
1234
1248
|
($type eq 'sbtl' and $metaFormat eq 'tx3g' and $buff =~ /^..PNDM/s))
|
|
1235
1249
|
{
|
|
1236
1250
|
|
|
1251
|
+
my $handled;
|
|
1237
1252
|
FoundSomething($et, $tagTbl, $time[$i], $dur[$i]);
|
|
1238
1253
|
unless ($buff =~ /^\$BEGIN/) {
|
|
1239
1254
|
# remove ending "encd" box if it exists
|
|
@@ -1273,9 +1288,10 @@ Sample: for ($i=0; ; ) {
|
|
|
1273
1288
|
}
|
|
1274
1289
|
unless (defined $val) {
|
|
1275
1290
|
$et->HandleTag($tagTbl, Text => $buff); # just store any other text
|
|
1291
|
+
$handled = 1;
|
|
1276
1292
|
}
|
|
1277
1293
|
}
|
|
1278
|
-
Process_text($et, \$buff, $tagTbl);
|
|
1294
|
+
Process_text($et, \$buff, $tagTbl, $handled);
|
|
1279
1295
|
|
|
1280
1296
|
} elsif ($processByMetaFormat{$type}) {
|
|
1281
1297
|
|
|
@@ -1371,6 +1387,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1371
1387
|
|
|
1372
1388
|
if (substr($$dataPt,18,8) eq "\xaa\xaa\xf2\xe1\xf0\xee\x54\x54") {
|
|
1373
1389
|
|
|
1390
|
+
$debug and $et->FoundTag(GPSType => '1A');
|
|
1374
1391
|
# (this is very similar to the encrypted text format)
|
|
1375
1392
|
# decode encrypted ASCII-based GPS (DashCam Azdome GS63H, ref 5)
|
|
1376
1393
|
# header looks like this in my sample:
|
|
@@ -1425,10 +1442,10 @@ sub ProcessFreeGPS($$$)
|
|
|
1425
1442
|
} elsif ($buf2 =~ /^.{173}([-+]\d{3})([-+]\d{3})([-+]\d{3})/s) { # (Azdome)
|
|
1426
1443
|
@acc = ($1/100, $2/100, $3/100);
|
|
1427
1444
|
}
|
|
1428
|
-
$debug and $et->FoundTag(GPSType => '1A');
|
|
1429
1445
|
|
|
1430
1446
|
} elsif ($$dataPt =~ /^.{52}(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/s) {
|
|
1431
1447
|
|
|
1448
|
+
$debug and $et->FoundTag(GPSType => '1B');
|
|
1432
1449
|
# decode NMEA-format GPS data (NextBase 512GW dashcam, ref PH)
|
|
1433
1450
|
# header looks like this in my sample:
|
|
1434
1451
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 40 01 00 00 [....freeGPS @...]
|
|
@@ -1454,10 +1471,10 @@ sub ProcessFreeGPS($$$)
|
|
|
1454
1471
|
# change to signed integer and divide by 256
|
|
1455
1472
|
map { $_ = $_ - 4294967296 if $_ >= 0x80000000; $_ /= 256 } @acc;
|
|
1456
1473
|
}
|
|
1457
|
-
$debug and $et->FoundTag(GPSType => '1B');
|
|
1458
1474
|
|
|
1459
1475
|
} elsif ($$dataPt =~ /^.{37}\0\0\0A([NS])([EW])/s) {
|
|
1460
1476
|
|
|
1477
|
+
$debug and $et->FoundTag(GPSType => '1C');
|
|
1461
1478
|
# decode freeGPS from ViofoA119v3 dashcam (similar to Novatek GPS format)
|
|
1462
1479
|
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 03 00 00 [..@.freeGPS ....]
|
|
1463
1480
|
# 0010: 05 00 00 00 2f 00 00 00 03 00 00 00 13 00 00 00 [..../...........]
|
|
@@ -1489,10 +1506,10 @@ sub ProcessFreeGPS($$$)
|
|
|
1489
1506
|
map { $_ = $_ - 4294967296 if $_ >= 0x80000000; $_ /= 256 } @acc;
|
|
1490
1507
|
}
|
|
1491
1508
|
SetByteOrder('MM');
|
|
1492
|
-
$debug and $et->FoundTag(GPSType => '1C');
|
|
1493
1509
|
|
|
1494
1510
|
} elsif ($$dataPt =~ /^.{21}\0\0\0A([NS])([EW])/s) {
|
|
1495
1511
|
|
|
1512
|
+
$debug and $et->FoundTag(GPSType => '1D');
|
|
1496
1513
|
# also decode 'gpmd' chunk from Kingslim D4 dashcam videos
|
|
1497
1514
|
# 0000: 0a 00 00 00 0b 00 00 00 07 00 00 00 e5 07 00 00 [................]
|
|
1498
1515
|
# 0010: 06 00 00 00 03 00 00 00 41 4e 57 31 91 52 83 45 [........ANW1.R.E]
|
|
@@ -1518,10 +1535,10 @@ sub ProcessFreeGPS($$$)
|
|
|
1518
1535
|
$acc[1] = GetFloat($dataPt, 0x30);
|
|
1519
1536
|
$acc[2] = GetFloat($dataPt, 0x34);
|
|
1520
1537
|
SetByteOrder('MM');
|
|
1521
|
-
$debug and $et->FoundTag(GPSType => '1D');
|
|
1522
1538
|
|
|
1523
1539
|
} elsif ($$dataPt =~ /^.{60}A\0{3}.{4}([NS])\0{3}.{4}([EW])\0{3}/s) {
|
|
1524
1540
|
|
|
1541
|
+
$debug and $et->FoundTag(GPSType => '1E');
|
|
1525
1542
|
# decode freeGPS from Akaso dashcam
|
|
1526
1543
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 60 00 00 00 [....freeGPS `...]
|
|
1527
1544
|
# 0010: 78 2e 78 78 00 00 00 00 00 00 00 00 00 00 00 00 [x.xx............]
|
|
@@ -1539,10 +1556,10 @@ sub ProcessFreeGPS($$$)
|
|
|
1539
1556
|
$trk = GetFloat($dataPt, 0x54) + 180; # (why is this off by 180?)
|
|
1540
1557
|
$trk -= 360 if $trk >= 360;
|
|
1541
1558
|
SetByteOrder('MM');
|
|
1542
|
-
$debug and $et->FoundTag(GPSType => '1E');
|
|
1543
1559
|
|
|
1544
1560
|
} elsif ($$dataPt =~ /^.{60}4W`b]S</s and length($$dataPt) >= 140) {
|
|
1545
1561
|
|
|
1562
|
+
$debug and $et->FoundTag(GPSType => '1F');
|
|
1546
1563
|
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 01 00 00 [..@.freeGPS ....]
|
|
1547
1564
|
# 0010: 5a 58 53 42 4e 58 59 53 00 00 00 00 00 00 00 00 [ZXSBNXYS........]
|
|
1548
1565
|
# 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
|
@@ -1557,10 +1574,10 @@ sub ProcessFreeGPS($$$)
|
|
|
1557
1574
|
$yr += ($yr >= 70 ? 1900 : 2000);
|
|
1558
1575
|
$spd = $9 * $knotsToKph if length $9;
|
|
1559
1576
|
$trk = $10 if length $10;
|
|
1560
|
-
$debug and $et->FoundTag(GPSType => '1F');
|
|
1561
1577
|
|
|
1562
1578
|
} elsif ($$dataPt =~ /^.{64}[\x01-\x0c]\0{3}[\x01-\x1f]\0{3}A[NS][EW]\0{5}/s) {
|
|
1563
1579
|
|
|
1580
|
+
$debug and $et->FoundTag(GPSType => '1G');
|
|
1564
1581
|
# Akaso V1 dascham
|
|
1565
1582
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 78 00 00 00 [....freeGPS x...]
|
|
1566
1583
|
# 0010: 59 6e 64 41 6b 61 73 6f 43 61 72 00 00 00 00 00 [YndAkasoCar.....]
|
|
@@ -1601,10 +1618,10 @@ sub ProcessFreeGPS($$$)
|
|
|
1601
1618
|
|
|
1602
1619
|
SetByteOrder('MM');
|
|
1603
1620
|
#my $serialNum = substr($$dataPt, 0x68, 20);
|
|
1604
|
-
$debug and $et->FoundTag(GPSType => '1G');
|
|
1605
1621
|
|
|
1606
1622
|
} elsif ($$dataPt =~ /^.{12}\xac\0\0\0.{44}(.{72})/s) {
|
|
1607
1623
|
|
|
1624
|
+
$debug and $et->FoundTag(GPSType => '1H');
|
|
1608
1625
|
# EACHPAI dash cam
|
|
1609
1626
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 ac 00 00 00 [....freeGPS ....]
|
|
1610
1627
|
# 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
|
@@ -1624,10 +1641,10 @@ sub ProcessFreeGPS($$$)
|
|
|
1624
1641
|
# bytes 7-12 are the timestamp in ASCII HHMMSS after xor-ing with 0x70
|
|
1625
1642
|
substr($time,7,6) = pack 'C*', map { $_ ^= 0x70 } unpack 'C*', substr($time,7,6);
|
|
1626
1643
|
# (other values are currently unknown)
|
|
1627
|
-
$debug and $et->FoundTag(GPSType => '1H');
|
|
1628
1644
|
|
|
1629
1645
|
} elsif ($$dataPt =~ /^.{64}A([NS])([EW])\0/s) {
|
|
1630
1646
|
|
|
1647
|
+
$debug and $et->FoundTag(GPSType => '1I');
|
|
1631
1648
|
# Vantrue S1 dashcam
|
|
1632
1649
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 78 00 00 00 [....freeGPS x...]
|
|
1633
1650
|
# 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
|
@@ -1650,10 +1667,10 @@ sub ProcessFreeGPS($$$)
|
|
|
1650
1667
|
$trk = GetFloat($dataPt, 0x68);
|
|
1651
1668
|
$alt = GetFloat($dataPt, 0x6c);
|
|
1652
1669
|
SetByteOrder('MM');
|
|
1653
|
-
$debug and $et->FoundTag(GPSType => '1I');
|
|
1654
1670
|
|
|
1655
1671
|
} else {
|
|
1656
1672
|
|
|
1673
|
+
$debug and $et->FoundTag(GPSType => '1J');
|
|
1657
1674
|
# decode binary GPS format (Viofo A119S, ref 2)
|
|
1658
1675
|
# header looks like this in my sample:
|
|
1659
1676
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 4c 00 00 00 [....freeGPS L...]
|
|
@@ -1687,7 +1704,6 @@ sub ProcessFreeGPS($$$)
|
|
|
1687
1704
|
$yr += 2000 if $yr < 2000;
|
|
1688
1705
|
$spd *= $knotsToKph; # convert speed to km/h
|
|
1689
1706
|
# ($trk is not confirmed; may be GPSImageDirection, ref PH)
|
|
1690
|
-
$debug and $et->FoundTag(GPSType => '1J');
|
|
1691
1707
|
}
|
|
1692
1708
|
#
|
|
1693
1709
|
# save tag values extracted by above code
|
|
@@ -1734,6 +1750,7 @@ sub ProcessFreeGPS2($$$)
|
|
|
1734
1750
|
|
|
1735
1751
|
if (substr($$dataPt,0x45,3) eq 'ATC') {
|
|
1736
1752
|
|
|
1753
|
+
$debug and $et->FoundTag(GPSType => '2A');
|
|
1737
1754
|
# header looks like this: (sample 1)
|
|
1738
1755
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 38 06 00 00 [....freeGPS 8...]
|
|
1739
1756
|
# 0010: 49 51 53 32 30 31 33 30 33 30 36 42 00 00 00 00 [IQS20130306B....]
|
|
@@ -1841,11 +1858,11 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1841
1858
|
}
|
|
1842
1859
|
# save position of most recent record (needed when parsing the next freeGPS block)
|
|
1843
1860
|
$$et{FreeGPS2}{RecentRecPos} = $lastRecPos;
|
|
1844
|
-
$debug and $et->FoundTag(GPSType => '2A');
|
|
1845
1861
|
return 1;
|
|
1846
1862
|
|
|
1847
1863
|
} elsif ($$dataPt =~ /^.{60}A\0.{10}([NS])\0.{14}([EW])\0/s) {
|
|
1848
1864
|
|
|
1865
|
+
$debug and $et->FoundTag(GPSType => '2B');
|
|
1849
1866
|
# header looks like this in my sample:
|
|
1850
1867
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 08 01 00 00 [....freeGPS ....]
|
|
1851
1868
|
# 0010: 32 30 31 33 30 38 31 35 2e 30 31 00 00 00 00 00 [20130815.01.....]
|
|
@@ -1873,7 +1890,6 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1873
1890
|
$lon = GetDouble($dataPt, 0x50);
|
|
1874
1891
|
$spd = GetDouble($dataPt, 0x60) * $knotsToKph;
|
|
1875
1892
|
$trk = GetDouble($dataPt, 0x68);
|
|
1876
|
-
$debug and $et->FoundTag(GPSType => '2B');
|
|
1877
1893
|
|
|
1878
1894
|
} elsif ($$dataPt =~ /^.{72}A([NS])([EW])/s) {
|
|
1879
1895
|
|
|
@@ -1900,6 +1916,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1900
1916
|
($latRef, $lonRef) = ($1, $2);
|
|
1901
1917
|
($hr,$min,$sec,$yr,$mon,$day) = unpack('x48V6', $$dataPt);
|
|
1902
1918
|
if (substr($$dataPt, 16, 3) eq 'IQS') {
|
|
1919
|
+
$debug and $et->FoundTag(GPSType => '2C');
|
|
1903
1920
|
# Type 3b (ref PH)
|
|
1904
1921
|
# header looks like this in my sample:
|
|
1905
1922
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 4c 00 00 00 [....freeGPS L...]
|
|
@@ -1910,20 +1927,20 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1910
1927
|
$lon = abs Get32s($dataPt, 0x50) / 1e7;
|
|
1911
1928
|
$spd = Get32s($dataPt, 0x54) / 100 * $mpsToKph;
|
|
1912
1929
|
$alt = GetFloat($dataPt, 0x58) / 1000; # (NC)
|
|
1913
|
-
$debug and $et->FoundTag(GPSType => '2C');
|
|
1914
1930
|
|
|
1915
1931
|
} else {
|
|
1932
|
+
$debug and $et->FoundTag(GPSType => '2D');
|
|
1916
1933
|
# Type 3 (ref 2)
|
|
1917
1934
|
# (no sample with this format)
|
|
1918
1935
|
$lat = GetFloat($dataPt, 0x4c);
|
|
1919
1936
|
$lon = GetFloat($dataPt, 0x50);
|
|
1920
1937
|
$spd = GetFloat($dataPt, 0x54) * $knotsToKph;
|
|
1921
1938
|
$trk = GetFloat($dataPt, 0x58);
|
|
1922
|
-
$debug and $et->FoundTag(GPSType => '2D');
|
|
1923
1939
|
}
|
|
1924
1940
|
|
|
1925
1941
|
} elsif ($$dataPt =~ /^.{60}A\0.{6}([NS])\0.{6}([EW])\0/s and $dirLen >= 112) {
|
|
1926
1942
|
|
|
1943
|
+
$debug and $et->FoundTag(GPSType => '2E');
|
|
1927
1944
|
# header looks like this in my sample (unknown dashcam, "Anticlock 2 2020_1125_1455_007.MOV"):
|
|
1928
1945
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 68 00 00 00 [....freeGPS h...]
|
|
1929
1946
|
# 0010: 32 30 31 33 30 33 32 35 41 00 00 00 00 00 00 00 [20130325A.......]
|
|
@@ -1940,10 +1957,10 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1940
1957
|
$lon = GetFloat($dataPt, 0x48);
|
|
1941
1958
|
$spd = GetFloat($dataPt, 0x50);
|
|
1942
1959
|
$trk = GetFloat($dataPt, 0x54);
|
|
1943
|
-
$debug and $et->FoundTag(GPSType => '2E');
|
|
1944
1960
|
|
|
1945
1961
|
} elsif ($$dataPt =~ /^.{16}A([NS])([EW])\0/s) {
|
|
1946
1962
|
|
|
1963
|
+
$debug and $et->FoundTag(GPSType => '2F');
|
|
1947
1964
|
# INNOVV MP4 video (same format as INNOVV TS)
|
|
1948
1965
|
while ($$dataPt =~ /(A[NS][EW]\0.{28})/g) {
|
|
1949
1966
|
my $dat = $1;
|
|
@@ -1961,11 +1978,36 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1961
1978
|
$et->HandleTag($tagTbl, GPSTrack => $trk);
|
|
1962
1979
|
$et->HandleTag($tagTbl, Accelerometer => "@acc");
|
|
1963
1980
|
}
|
|
1964
|
-
$debug and $et->FoundTag(GPSType => '2F');
|
|
1965
1981
|
return 1;
|
|
1966
1982
|
|
|
1983
|
+
} elsif ($$dataPt =~ /^.{28}A.{11}([NS]).{15}([EW])/s) {
|
|
1984
|
+
|
|
1985
|
+
$debug and $et->FoundTag(GPSType => '2G');
|
|
1986
|
+
# Vantrue N4 dashcam
|
|
1987
|
+
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 03 00 00 [..@.freeGPS ....]
|
|
1988
|
+
# 0010: 0d 00 00 00 16 00 00 00 1e 00 00 00 41 00 00 00 [............A...]
|
|
1989
|
+
# 0020: 2c b7 b4 1a 5a 71 b2 40 4e 00 00 00 00 00 00 00 [,...Zq.@N.......]
|
|
1990
|
+
# 0030: fb ae 08 fe 77 f6 89 40 45 00 00 00 00 00 00 00 [....w..@E.......]
|
|
1991
|
+
# 0040: be 9f 1a 2f dd 84 36 40 5c 8f c2 f5 28 fc 68 40 [.../..6@\...(.h@]
|
|
1992
|
+
# 0050: 16 00 00 00 0c 00 00 00 0e 00 00 00 f2 fb ff ff [................]
|
|
1993
|
+
# 0060: 42 00 00 00 02 00 00 00 20 24 47 4e 52 4d 43 2c [B....... $GNRMC,]
|
|
1994
|
+
# 0070: 31 33 32 32 33 30 2e 30 30 30 2c 41 2c 34 37 32 [132230.000,A,472]
|
|
1995
|
+
# 0080: 31 2e 33 35 31 39 37 2c 4e 2c 30 30 38 33 30 2e [1.35197,N,00830.]
|
|
1996
|
+
# 0090: 38 30 38 35 39 2c 45 2c 32 32 2e 35 31 39 2c 31 [80859,E,22.519,1]
|
|
1997
|
+
# 00a0: 39 39 2e 38 38 2c 31 34 31 32 32 32 2c 2c 2c 41 [99.88,141222,,,A]
|
|
1998
|
+
# 00b0: 2a 37 35 0d 0a 00 00 00 00 00 00 00 00 00 00 00 [*75.............]
|
|
1999
|
+
($latRef, $lonRef) = ($1, $2);
|
|
2000
|
+
($hr,$min,$sec,$yr,$mon,$day,@acc) = unpack('x16V3x52V3V3',$$dataPt);
|
|
2001
|
+
$lat = abs(GetDouble($dataPt, 32)); # (abs just to be safe)
|
|
2002
|
+
$lon = abs(GetDouble($dataPt, 48)); # (abs just to be safe)
|
|
2003
|
+
$spd = GetDouble($dataPt, 64) * $knotsToKph;
|
|
2004
|
+
$trk = GetDouble($dataPt, 72);
|
|
2005
|
+
map { $_ = $_ - 4294967296 if $_ >= 0x80000000; $_ /= 1000 } @acc; # (NC)
|
|
2006
|
+
# (not necessary to read RMC sentence because we already have it all)
|
|
2007
|
+
|
|
1967
2008
|
} else {
|
|
1968
2009
|
|
|
2010
|
+
$debug and $et->FoundTag(GPSType => '2H');
|
|
1969
2011
|
# (look for binary GPS as stored by NextBase 512G, ref PH)
|
|
1970
2012
|
# header looks like this in my sample:
|
|
1971
2013
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 78 01 00 00 [....freeGPS x...]
|
|
@@ -2008,7 +2050,6 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
2008
2050
|
$et->HandleTag($tagTbl, GPSTrack => $trk);
|
|
2009
2051
|
last if $pos += 0x20 > length($$dataPt) - 0x1e;
|
|
2010
2052
|
}
|
|
2011
|
-
$debug and $et->FoundTag(GPSType => '2G');
|
|
2012
2053
|
return $$et{DOC_NUM} ? 1 : 0; # return 0 if nothing extracted
|
|
2013
2054
|
}
|
|
2014
2055
|
#
|
|
@@ -2025,9 +2066,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
2025
2066
|
$et->HandleTag($tagTbl, GPSLongitude => $lon * ($lonRef eq 'W' ? -1 : 1));
|
|
2026
2067
|
$et->HandleTag($tagTbl, GPSSpeed => $spd) if defined $spd; # (now in km/h)
|
|
2027
2068
|
$et->HandleTag($tagTbl, GPSTrack => $trk) if defined $trk;
|
|
2028
|
-
if
|
|
2029
|
-
$et->HandleTag($tagTbl, GPSAltitude => $alt);
|
|
2030
|
-
}
|
|
2069
|
+
$et->HandleTag($tagTbl, GPSAltitude => $alt) if defined $alt;
|
|
2031
2070
|
$et->HandleTag($tagTbl, Accelerometer => "@acc") if @acc;
|
|
2032
2071
|
return 1;
|
|
2033
2072
|
}
|
|
@@ -2322,6 +2361,49 @@ sub Process_gsen($$$)
|
|
|
2322
2361
|
return 1;
|
|
2323
2362
|
}
|
|
2324
2363
|
|
|
2364
|
+
#------------------------------------------------------------------------------
|
|
2365
|
+
# Process Kenwood drv-a301w dashcam 'udta' atom (ref PH)
|
|
2366
|
+
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
|
|
2367
|
+
# Returns: 1 on success
|
|
2368
|
+
# Sample data:
|
|
2369
|
+
# 0000: 56 49 44 45 4f 55 55 55 55 55 55 55 55 55 55 55 [VIDEOUUUUUUUUUUU]
|
|
2370
|
+
# 0010: 55 55 55 55 55 55 55 55 55 55 55 fe fe 32 30 32 [UUUUUUUUUUU..202]
|
|
2371
|
+
# 0020: 33 30 31 30 37 31 31 31 39 31 34 2e 32 30 32 33 [30107111914.2023]
|
|
2372
|
+
# 0030: 30 31 30 37 31 31 31 39 31 35 03 4e 34 37 33 37 [0107111915.N4737]
|
|
2373
|
+
# 0040: 37 30 35 33 57 31 32 32 30 39 39 30 31 34 2b 30 [7053W122099014+0]
|
|
2374
|
+
# 0050: 30 35 38 30 30 30 2b 30 30 36 2b 30 30 39 2b 30 [058000+006+009+0]
|
|
2375
|
+
# 0060: 30 34 2b 30 30 32 2b 30 30 39 2b 30 30 35 2b 30 [04+002+009+005+0]
|
|
2376
|
+
sub ProcessKenwood($$$)
|
|
2377
|
+
{
|
|
2378
|
+
my ($et, $dirInfo, $tagTbl) = @_;
|
|
2379
|
+
my $dataPt = $$dirInfo{DataPt};
|
|
2380
|
+
my $dirLen = $$dirInfo{DirLen};
|
|
2381
|
+
while ($$dataPt =~ /\xfe\xfe([^\xfe]+)/g) {
|
|
2382
|
+
my $dat = $1;
|
|
2383
|
+
next unless $dat =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})./gs;
|
|
2384
|
+
my $time = "$1:$2:$3 $4:$5:$6"; # (likely local time zone, but not confirmed)
|
|
2385
|
+
# ignore second date (what is this for?)
|
|
2386
|
+
next unless $dat =~ /\G(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})./gs;
|
|
2387
|
+
next unless $dat =~ /\G([NS])(\d+)([EW])(\d+)/g;
|
|
2388
|
+
my ($lat, $lon) = ($2/1e4, $4/1e4);
|
|
2389
|
+
ConvertLatLon($lat, $lon);
|
|
2390
|
+
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
|
2391
|
+
$et->HandleTag($tagTbl, GPSDateTime => $time);
|
|
2392
|
+
$et->HandleTag($tagTbl, GPSLatitude => $lat * ($1 eq 'S' ? -1 : 1));
|
|
2393
|
+
$et->HandleTag($tagTbl, GPSLongitude => $lon * ($3 eq 'W' ? -1 : 1));
|
|
2394
|
+
next unless $dat =~ /\G([-+]\d{4})(\d+)/g;
|
|
2395
|
+
$et->HandleTag($tagTbl, GPSAltitude => $1 + 0); # (NC, educated guess)
|
|
2396
|
+
$et->HandleTag($tagTbl, GPSSpeed => $2); # (km/h)
|
|
2397
|
+
my @acc;
|
|
2398
|
+
while ($dat =~ /\G([-+]\d+)([-+]\d+)([-+]\d+)/g) {
|
|
2399
|
+
push @acc, $1/1000, $2/1000, $3/1000;
|
|
2400
|
+
}
|
|
2401
|
+
$et->HandleTag($tagTbl, Accelerometer => "@acc") if @acc;
|
|
2402
|
+
}
|
|
2403
|
+
delete $$et{DOC_NUM};
|
|
2404
|
+
return 1;
|
|
2405
|
+
}
|
|
2406
|
+
|
|
2325
2407
|
#------------------------------------------------------------------------------
|
|
2326
2408
|
# Process RIFF-format trailer written by Auto-Vox dashcam (ref PH)
|
|
2327
2409
|
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
|
|
@@ -2679,7 +2761,6 @@ sub ProcessInsta360($;$)
|
|
|
2679
2761
|
my ($id, $len) = unpack('vV', $buff);
|
|
2680
2762
|
($epos -= $len) + $trailerLen < 0 and last;
|
|
2681
2763
|
$raf->Seek($epos, 2) or last;
|
|
2682
|
-
my $dlen = $insvDataLen{$id};
|
|
2683
2764
|
if ($verbose) {
|
|
2684
2765
|
$et->VPrint(0, sprintf("Insta360 Record 0x%x (offset 0x%x, %d bytes):\n", $id, $fileEnd + $epos, $len));
|
|
2685
2766
|
}
|
|
@@ -2692,20 +2773,25 @@ sub ProcessInsta360($;$)
|
|
|
2692
2773
|
# 2. 20 byte records
|
|
2693
2774
|
# 0000: c1 d8 d9 0b 00 00 00 00 f5 83 14 80 df 7f fe 7f [................]
|
|
2694
2775
|
# 0010: fe 7f 01 80
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2776
|
+
my $dlen = $insvDataLen{$id};
|
|
2777
|
+
if (defined $dlen and not $dlen) {
|
|
2778
|
+
if ($id == 0x300) {
|
|
2779
|
+
if ($len % 20 and not $len % 56) {
|
|
2780
|
+
$dlen = 56;
|
|
2781
|
+
} elsif ($len % 56 and not $len % 20) {
|
|
2782
|
+
$dlen = 20;
|
|
2783
|
+
} else {
|
|
2784
|
+
if ($raf->Read($buff, 20) == 20) {
|
|
2785
|
+
if (substr($buff, 16, 3) eq "\0\0\0") {
|
|
2786
|
+
$dlen = 56;
|
|
2787
|
+
} else {
|
|
2788
|
+
$dlen = 20;
|
|
2789
|
+
}
|
|
2706
2790
|
}
|
|
2791
|
+
$raf->Seek($epos, 2) or last;
|
|
2707
2792
|
}
|
|
2708
|
-
|
|
2793
|
+
} elsif ($id == 0x200) {
|
|
2794
|
+
$dlen = $len;
|
|
2709
2795
|
}
|
|
2710
2796
|
}
|
|
2711
2797
|
# limit the number of records we read if necessary
|
|
@@ -2719,6 +2805,8 @@ sub ProcessInsta360($;$)
|
|
|
2719
2805
|
if ($dlen) {
|
|
2720
2806
|
if ($len % $dlen) {
|
|
2721
2807
|
$et->Warn(sprintf('Unexpected Insta360 record 0x%x length',$id));
|
|
2808
|
+
} elsif ($id == 0x200) {
|
|
2809
|
+
$et->FoundTag(PreviewImage => $buff);
|
|
2722
2810
|
} elsif ($id == 0x300) {
|
|
2723
2811
|
for ($p=0; $p<$len; $p+=$dlen) {
|
|
2724
2812
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
|
@@ -3,6 +3,9 @@ File: Image/ExifTool/README
|
|
|
3
3
|
|
|
4
4
|
Description: ExifTool support modules documentation
|
|
5
5
|
|
|
6
|
+
Note: This documentation is a reference to be used by developers when
|
|
7
|
+
adding new tags to ExifTool.
|
|
8
|
+
|
|
6
9
|
The ExifTool support modules are loaded by ExifTool to allow processing of
|
|
7
10
|
various meta information formats.
|
|
8
11
|
|
|
@@ -16,7 +16,7 @@ use vars qw($VERSION);
|
|
|
16
16
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
17
17
|
use Image::ExifTool::Canon;
|
|
18
18
|
|
|
19
|
-
$VERSION = '1.
|
|
19
|
+
$VERSION = '1.07';
|
|
20
20
|
|
|
21
21
|
sub ProcessRealMeta($$$);
|
|
22
22
|
sub ProcessRealProperties($$$);
|
|
@@ -608,7 +608,7 @@ sub ProcessReal($$)
|
|
|
608
608
|
} else {
|
|
609
609
|
last if $tag eq 'DATA'; # stop normal parsing at DATA tag
|
|
610
610
|
}
|
|
611
|
-
if ($size & 0x80000000) {
|
|
611
|
+
if ($size & 0x80000000 or $size < 10) {
|
|
612
612
|
$et->Warn('Bad chunk header');
|
|
613
613
|
last;
|
|
614
614
|
}
|
|
@@ -34,7 +34,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
|
34
34
|
use Image::ExifTool::Exif;
|
|
35
35
|
use Image::ExifTool::Minolta;
|
|
36
36
|
|
|
37
|
-
$VERSION = '3.
|
|
37
|
+
$VERSION = '3.57';
|
|
38
38
|
|
|
39
39
|
sub ProcessSRF($$$);
|
|
40
40
|
sub ProcessSR2($$$);
|
|
@@ -160,6 +160,7 @@ sub PrintInvLensSpec($;$$);
|
|
|
160
160
|
32875 => 'Sony FE 24-70mm F2.8 GM II', #JR
|
|
161
161
|
32876 => 'Sony E 11mm F1.8', #JR
|
|
162
162
|
32877 => 'Sony E 15mm F1.4 G', #JR
|
|
163
|
+
32878 => 'Sony FE 20-70mm F4 G', #JR
|
|
163
164
|
|
|
164
165
|
# (comment this out so LensID will report the LensModel, which is more useful)
|
|
165
166
|
# 32952 => 'Metabones Canon EF Speed Booster Ultra', #JR (corresponds to 184, but 'Advanced' mode, LensMount reported as E-mount)
|
|
@@ -191,6 +192,7 @@ sub PrintInvLensSpec($;$$);
|
|
|
191
192
|
49235 => 'Zeiss Loxia 85mm F2.4', #JR
|
|
192
193
|
49236 => 'Zeiss Loxia 25mm F2.4', #JR
|
|
193
194
|
|
|
195
|
+
49456 => 'Tamron E 18-200mm F3.5-6.3 Di III VC', #FrancoisPiette
|
|
194
196
|
49457 => 'Tamron 28-75mm F2.8 Di III RXD', #JR (Model A036)
|
|
195
197
|
49458 => 'Tamron 17-28mm F2.8 Di III RXD', #JR (Model A046)
|
|
196
198
|
49459 => 'Tamron 35mm F2.8 Di III OSD M1:2', #IB (Model F053)
|
|
@@ -256,6 +258,8 @@ sub PrintInvLensSpec($;$$);
|
|
|
256
258
|
50533 => 'Sigma 16-28mm F2.8 DG DN | C', #JR (022)
|
|
257
259
|
50534 => 'Sigma 20mm F1.4 DG DN | A', #JR (022)
|
|
258
260
|
50535 => 'Sigma 24mm F1.4 DG DN | A', #JR (022)
|
|
261
|
+
50536 => 'Sigma 60-600mm F4.5-6.3 DG DN OS | S', #JR (023)
|
|
262
|
+
50539 => 'Sigma 50mm F1.4 DG DN | A', #JR (023)
|
|
259
263
|
|
|
260
264
|
50992 => 'Voigtlander SUPER WIDE-HELIAR 15mm F4.5 III', #JR
|
|
261
265
|
50993 => 'Voigtlander HELIAR-HYPER WIDE 10mm F5.6', #IB
|