exiftool-vendored.pl 13.37.0 → 13.40.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 +41 -3
- package/bin/MANIFEST +7 -0
- package/bin/META.json +1 -1
- package/bin/META.yml +1 -1
- package/bin/README +49 -47
- package/bin/config_files/local_time.config +55 -0
- package/bin/exiftool +83 -70
- package/bin/lib/Image/ExifTool/BMP.pm +1 -1
- package/bin/lib/Image/ExifTool/BuildTagLookup.pm +2 -2
- package/bin/lib/Image/ExifTool/DJI.pm +256 -20
- package/bin/lib/Image/ExifTool/DSF.pm +138 -0
- package/bin/lib/Image/ExifTool/EXE.pm +3 -1
- package/bin/lib/Image/ExifTool/Font.pm +386 -118
- package/bin/lib/Image/ExifTool/Geolocation.pm +10 -7
- package/bin/lib/Image/ExifTool/Geotag.pm +21 -2
- package/bin/lib/Image/ExifTool/GoPro.pm +6 -3
- package/bin/lib/Image/ExifTool/Google.pm +16 -6
- package/bin/lib/Image/ExifTool/ID3.pm +11 -10
- package/bin/lib/Image/ExifTool/LNK.pm +63 -2
- package/bin/lib/Image/ExifTool/M2TS.pm +32 -23
- package/bin/lib/Image/ExifTool/MIEUnits.pod +1 -1
- package/bin/lib/Image/ExifTool/OOXML.pm +3 -2
- package/bin/lib/Image/ExifTool/Olympus.pm +3 -1
- package/bin/lib/Image/ExifTool/Pentax.pm +7 -2
- package/bin/lib/Image/ExifTool/QuickTime.pm +3 -3
- package/bin/lib/Image/ExifTool/QuickTimeStream.pl +44 -35
- package/bin/lib/Image/ExifTool/Sony.pm +19 -14
- package/bin/lib/Image/ExifTool/TagLookup.pm +35 -1
- package/bin/lib/Image/ExifTool/TagNames.pod +1383 -1217
- package/bin/lib/Image/ExifTool/WavPack.pm +144 -0
- package/bin/lib/Image/ExifTool/XMP.pm +12 -7
- package/bin/lib/Image/ExifTool/XMP2.pl +11 -5
- package/bin/lib/Image/ExifTool.pm +46 -26
- package/bin/lib/Image/ExifTool.pod +64 -56
- package/bin/perl-Image-ExifTool.spec +47 -46
- package/package.json +4 -4
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
# 2024/11/26 - PH Also write GPSMeasureMode and GPSDOP
|
|
21
21
|
# 2024/11/05 - PH Added support for Google Maps "Export timeline data"
|
|
22
22
|
# JSON format
|
|
23
|
+
# 2025/09/22 - PH Added ability to read Columbus CSV log files
|
|
23
24
|
#
|
|
24
25
|
# References: 1) http://www.topografix.com/GPX/1/1/
|
|
25
26
|
# 2) http://www.gpsinformation.org/dale/nmea.htm#GSA
|
|
@@ -34,7 +35,7 @@ use vars qw($VERSION);
|
|
|
34
35
|
use Image::ExifTool qw(:Public);
|
|
35
36
|
use Image::ExifTool::GPS;
|
|
36
37
|
|
|
37
|
-
$VERSION = '1.
|
|
38
|
+
$VERSION = '1.83';
|
|
38
39
|
|
|
39
40
|
sub JITTER() { return 2 } # maximum time jitter
|
|
40
41
|
|
|
@@ -1344,6 +1345,23 @@ Category: foreach $category (qw{pos track alt orient atemp err dop}) {
|
|
|
1344
1345
|
if (defined $dop) {
|
|
1345
1346
|
$et->SetNewValue(GPSMeasureMode => $mm, %opts);
|
|
1346
1347
|
$et->SetNewValue(GPSDOP => $dop, %opts);
|
|
1348
|
+
# also set GPSHPositioningError if specified
|
|
1349
|
+
my $hposErr = $$et{OPTIONS}{GeoHPosErr};
|
|
1350
|
+
if ($hposErr) {
|
|
1351
|
+
$hposErr =~ s/gpsdop/GPSDOP/i;
|
|
1352
|
+
my $GPSDOP = $dop;
|
|
1353
|
+
local $SIG{'__WARN__'} = \&Image::ExifTool::SetWarning;
|
|
1354
|
+
undef $Image::ExifTool::evalWarning;
|
|
1355
|
+
#### eval GeoHPosErr ($GPSDOP)
|
|
1356
|
+
$hposErr = eval $hposErr;
|
|
1357
|
+
my $err = Image::ExifTool::GetWarning() || $@;
|
|
1358
|
+
if ($err) {
|
|
1359
|
+
$err = Image::ExifTool::CleanWarning($err);
|
|
1360
|
+
$et->Warn("Error calculating GPSHPositioningError: $err", 1);
|
|
1361
|
+
} else {
|
|
1362
|
+
$et->SetNewValue(GPSHPositioningError => $hposErr, %opts);
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1347
1365
|
}
|
|
1348
1366
|
}
|
|
1349
1367
|
unless ($xmp) {
|
|
@@ -1557,7 +1575,8 @@ This module loads GPS track logs, interpolates to determine position based
|
|
|
1557
1575
|
on time, and sets new GPS values for geotagging images. Currently supported
|
|
1558
1576
|
formats are GPX, NMEA RMC/GGA/GLL/GSA/ZDA, KML, IGC, Garmin XML and TCX,
|
|
1559
1577
|
Magellan PMGNTRK, Honeywell PTNTHPR, Bramor gEO, Winplus Beacon text,
|
|
1560
|
-
GPS/IMU CSV, DJI CSV
|
|
1578
|
+
GPS/IMU CSV, DJI/Columbus/ExifTool CSV format and 3 different Google JSON
|
|
1579
|
+
formats.
|
|
1561
1580
|
|
|
1562
1581
|
Methods in this module should not be called directly. Instead, the Geotag
|
|
1563
1582
|
feature is accessed by writing the values of the ExifTool Geotag, Geosync
|
|
@@ -17,7 +17,7 @@ use vars qw($VERSION);
|
|
|
17
17
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
18
18
|
use Image::ExifTool::QuickTime;
|
|
19
19
|
|
|
20
|
-
$VERSION = '1.
|
|
20
|
+
$VERSION = '1.15';
|
|
21
21
|
|
|
22
22
|
sub ProcessGoPro($$$);
|
|
23
23
|
sub ProcessString($$$);
|
|
@@ -251,7 +251,8 @@ my %noYes = ( N => 'No', Y => 'Yes' );
|
|
|
251
251
|
Notes => 'gyroscope readings in rad/s',
|
|
252
252
|
Binary => 1,
|
|
253
253
|
},
|
|
254
|
-
|
|
254
|
+
LOGS => 'HealthLogs',
|
|
255
|
+
HCTL => 'HorizonControl', #3
|
|
255
256
|
HDRV => { Name => 'HDRVideo', PrintConv => \%noYes }, #3/PH (NC)
|
|
256
257
|
# HFLG (APP6) - seen: 0
|
|
257
258
|
HSGT => 'HindsightSettings', #3
|
|
@@ -409,6 +410,7 @@ my %noYes = ( N => 'No', Y => 'Yes' );
|
|
|
409
410
|
},
|
|
410
411
|
# TOCK => { Name => 'OutTime', Unknown => 1, ValueConv => '$val/1000' }, #1 (gpmd)
|
|
411
412
|
TSMP => { Name => 'TotalSamples', Unknown => 1 }, #2 (gpmd)
|
|
413
|
+
TIMO => 'TimeOffset',
|
|
412
414
|
TYPE => { Name => 'StructureType', Unknown => 1 }, #2 (gpmd,GPMF - eg 'LLLllfFff', fmt c)
|
|
413
415
|
TZON => { # (GPMF) - seen: 60 (fmt s)
|
|
414
416
|
Name => 'TimeZone',
|
|
@@ -469,7 +471,8 @@ my %noYes = ( N => 'No', Y => 'Yes' );
|
|
|
469
471
|
AALP => { Name => 'AudioLevel', Notes => 'dBFS' },
|
|
470
472
|
GPSA => 'GPSAltitudeSystem', # (eg. 'MSLV')
|
|
471
473
|
GRAV => { Name => 'GravityVector', Binary => 1 },
|
|
472
|
-
|
|
474
|
+
# DISP - Disparity track
|
|
475
|
+
HUES => 'PredominantHue',
|
|
473
476
|
IORI => { Name => 'ImageOrientation', Binary => 1, Notes => 'quaternions 0-1' },
|
|
474
477
|
# LRVO - ? Part of LRV Frame Skip
|
|
475
478
|
# LRVS - ? Part of LRV Frame Skip
|
|
@@ -512,11 +512,20 @@ my %sAppInfo = (
|
|
|
512
512
|
GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
|
|
513
513
|
TAG_PREFIX => 'HDRPlusMakerNote',
|
|
514
514
|
PROCESS_PROC => \&ProcessHDRP,
|
|
515
|
-
VARS => {
|
|
515
|
+
VARS => {
|
|
516
|
+
ID_FMT => 'str',
|
|
517
|
+
SORT_PROC => sub {
|
|
518
|
+
my ($a,$b) = @_;
|
|
519
|
+
$a =~ s/(\d+)/sprintf("%.3d",$1)/eg;
|
|
520
|
+
$b =~ s/(\d+)/sprintf("%.3d",$1)/eg;
|
|
521
|
+
return $a cmp $b;
|
|
522
|
+
},
|
|
523
|
+
},
|
|
516
524
|
NOTES => q{
|
|
517
525
|
Google protobuf-format HDR-Plus maker notes. Tag ID's are hierarchical
|
|
518
526
|
protobuf field numbers. Stored as base64-encoded, encrypted and gzipped
|
|
519
|
-
Protobuf data.
|
|
527
|
+
Protobuf data. Much of this metadata is still unknown, but is extracted
|
|
528
|
+
using the Unknown option.
|
|
520
529
|
},
|
|
521
530
|
'1-1' => 'ImageName',
|
|
522
531
|
'1-2' => { Name => 'ImageData', Format => 'undef', Binary => 1 },
|
|
@@ -693,8 +702,8 @@ sub ProcessHDRP($$$)
|
|
|
693
702
|
my $i = 0;
|
|
694
703
|
while ($i < @words) {
|
|
695
704
|
# (messy, but handle all 64-bit arithmetic with 32-bit backward
|
|
696
|
-
# compatibility
|
|
697
|
-
# rotate the key
|
|
705
|
+
# compatibility, so no bit operations on any number > 0xffffffff)
|
|
706
|
+
# rotate the key for each new 64-bit word
|
|
698
707
|
# $key ^= $key >> 12;
|
|
699
708
|
$lo ^= $lo >> 12 | ($hi & 0xfff) << 20;
|
|
700
709
|
$hi ^= $hi >> 12;
|
|
@@ -715,7 +724,8 @@ sub ProcessHDRP($$$)
|
|
|
715
724
|
$c[$j+$k] += $a[$j] * $b[$k];
|
|
716
725
|
}
|
|
717
726
|
}
|
|
718
|
-
# (we only
|
|
727
|
+
# (we will only retain the low 64-bits of the key, so
|
|
728
|
+
# don't bother finishing the calculation of the upper bits)
|
|
719
729
|
for ($j=6; $j>=3; --$j) {
|
|
720
730
|
while ($c[$j] > 0xffffffff) {
|
|
721
731
|
++$c[$j-2];
|
|
@@ -726,7 +736,7 @@ sub ProcessHDRP($$$)
|
|
|
726
736
|
}
|
|
727
737
|
$hi = ($c[3] << 16) + $c[4];
|
|
728
738
|
$lo = ($c[5] << 16) + $c[6];
|
|
729
|
-
# apply the
|
|
739
|
+
# apply the key to this 64-bit word
|
|
730
740
|
$words[$i++] ^= $lo;
|
|
731
741
|
$words[$i++] ^= $hi;
|
|
732
742
|
}
|
|
@@ -18,7 +18,7 @@ use strict;
|
|
|
18
18
|
use vars qw($VERSION);
|
|
19
19
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
20
20
|
|
|
21
|
-
$VERSION = '1.
|
|
21
|
+
$VERSION = '1.64';
|
|
22
22
|
|
|
23
23
|
sub ProcessID3v2($$$);
|
|
24
24
|
sub ProcessPrivate($$$);
|
|
@@ -79,13 +79,13 @@ my %userTagName = (
|
|
|
79
79
|
VARS => { ID_FMT => 'none' },
|
|
80
80
|
PROCESS_PROC => \&ProcessID3Dir, # (used to process 'id3 ' chunk in WAV files)
|
|
81
81
|
NOTES => q{
|
|
82
|
-
ExifTool extracts ID3 and Lyrics3 information from MP3, MPEG, WAV, AIFF,
|
|
83
|
-
OGG, FLAC, APE, MPC and RealAudio files. ID3v2 tags which support
|
|
84
|
-
languages (eg. Comment and Lyrics) are extracted by specifying the
|
|
85
|
-
followed by a dash ('-'), then a 3-character ISO 639-2 language
|
|
86
|
-
"Comment-spa"). See L<https://id3.org/> for the official ID3
|
|
87
|
-
and L<http://www.loc.gov/standards/iso639-2/php/code_list.php>
|
|
88
|
-
ISO 639-2 language codes.
|
|
82
|
+
ExifTool extracts ID3 and Lyrics3 information from MP3, MPEG, WAV, WV, AIFF,
|
|
83
|
+
OGG, FLAC, APE, DSF, MPC and RealAudio files. ID3v2 tags which support
|
|
84
|
+
multiple languages (eg. Comment and Lyrics) are extracted by specifying the
|
|
85
|
+
tag name, followed by a dash ('-'), then a 3-character ISO 639-2 language
|
|
86
|
+
code (eg. "Comment-spa"). See L<https://id3.org/> for the official ID3
|
|
87
|
+
specification and L<http://www.loc.gov/standards/iso639-2/php/code_list.php>
|
|
88
|
+
for a list of ISO 639-2 language codes.
|
|
89
89
|
},
|
|
90
90
|
ID3v1 => {
|
|
91
91
|
Name => 'ID3v1',
|
|
@@ -1437,6 +1437,7 @@ sub ProcessID3($$)
|
|
|
1437
1437
|
|
|
1438
1438
|
# allow this to be called with either RAF or DataPt
|
|
1439
1439
|
my $raf = $$dirInfo{RAF} || File::RandomAccess->new($$dirInfo{DataPt});
|
|
1440
|
+
my $dataPos = $$dirInfo{DataPos} || 0;
|
|
1440
1441
|
my ($buff, %id3Header, %id3Trailer, $hBuff, $tBuff, $eBuff, $tagTablePtr);
|
|
1441
1442
|
my $rtnVal = 0;
|
|
1442
1443
|
my $hdrEnd = 0;
|
|
@@ -1486,7 +1487,7 @@ sub ProcessID3($$)
|
|
|
1486
1487
|
}
|
|
1487
1488
|
%id3Header = (
|
|
1488
1489
|
DataPt => \$hBuff,
|
|
1489
|
-
DataPos => $pos,
|
|
1490
|
+
DataPos => $dataPos + $pos,
|
|
1490
1491
|
DirStart => 0,
|
|
1491
1492
|
DirLen => length($hBuff),
|
|
1492
1493
|
Version => $vers,
|
|
@@ -1511,7 +1512,7 @@ sub ProcessID3($$)
|
|
|
1511
1512
|
$trailSize = 128;
|
|
1512
1513
|
%id3Trailer = (
|
|
1513
1514
|
DataPt => \$tBuff,
|
|
1514
|
-
DataPos => $raf->Tell() - 128,
|
|
1515
|
+
DataPos => $dataPos + $raf->Tell() - 128,
|
|
1515
1516
|
DirStart => 0,
|
|
1516
1517
|
DirLen => length($tBuff),
|
|
1517
1518
|
);
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
# Description: Read meta information from MS Shell Link files
|
|
5
5
|
#
|
|
6
6
|
# Revisions: 2009/09/19 - P. Harvey Created
|
|
7
|
+
# 2025/10/20 - PH Added .URL file support
|
|
7
8
|
#
|
|
8
9
|
# References: 1) http://msdn.microsoft.com/en-us/library/dd871305(PROT.10).aspx
|
|
9
10
|
# 2) http://www.i2s-lab.com/Papers/The_Windows_Shortcut_File_Format.pdf
|
|
@@ -17,7 +18,7 @@ use vars qw($VERSION);
|
|
|
17
18
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
18
19
|
use Image::ExifTool::Microsoft;
|
|
19
20
|
|
|
20
|
-
$VERSION = '1.
|
|
21
|
+
$VERSION = '1.12';
|
|
21
22
|
|
|
22
23
|
sub ProcessItemID($$$);
|
|
23
24
|
sub ProcessLinkInfo($$$);
|
|
@@ -447,6 +448,39 @@ sub ProcessLinkInfo($$$);
|
|
|
447
448
|
},
|
|
448
449
|
);
|
|
449
450
|
|
|
451
|
+
%Image::ExifTool::LNK::INI = (
|
|
452
|
+
GROUPS => { 2 => 'Document' },
|
|
453
|
+
VARS => { ID_FMT => 'none' },
|
|
454
|
+
NOTES => 'Tags found in INI-format Windows .URL files.',
|
|
455
|
+
URL => { },
|
|
456
|
+
IconFile => { },
|
|
457
|
+
IconIndex => { },
|
|
458
|
+
WorkingDirectory => { },
|
|
459
|
+
HotKey => { },
|
|
460
|
+
ShowCommand => { PrintConv => { 1 => 'Normal', 2 => 'Minimized', 3 => 'Maximized' } },
|
|
461
|
+
Modified => {
|
|
462
|
+
Groups => { 2 => 'Time' },
|
|
463
|
+
Format => 'int64u',
|
|
464
|
+
Groups => { 2 => 'Time' },
|
|
465
|
+
# convert time from 100-ns intervals since Jan 1, 1601 (NC)
|
|
466
|
+
RawConv => q{
|
|
467
|
+
my $dat = pack('H*', $val);
|
|
468
|
+
return undef if length $dat < 8;
|
|
469
|
+
my ($lo, $hi) = unpack('V2', $dat);
|
|
470
|
+
return undef unless $lo or $hi;
|
|
471
|
+
return $hi * 4294967296 + $lo;
|
|
472
|
+
},
|
|
473
|
+
ValueConv => '$val=$val/1e7-11644473600; ConvertUnixTime($val,1)',
|
|
474
|
+
PrintConv => '$self->ConvertDateTime($val)',
|
|
475
|
+
},
|
|
476
|
+
Author => { Groups => { 2 => 'Author' } },
|
|
477
|
+
WhatsNew => { },
|
|
478
|
+
Comment => { },
|
|
479
|
+
Desc => { },
|
|
480
|
+
Roamed => { Notes => '1 if synced across multiple devices' },
|
|
481
|
+
IDList => { },
|
|
482
|
+
);
|
|
483
|
+
|
|
450
484
|
#------------------------------------------------------------------------------
|
|
451
485
|
# Extract null-terminated ASCII or Unicode string from buffer
|
|
452
486
|
# Inputs: 0) buffer ref, 1) start position, 2) flag for unicode string
|
|
@@ -588,6 +622,27 @@ sub ProcessLinkInfo($$$)
|
|
|
588
622
|
return 1;
|
|
589
623
|
}
|
|
590
624
|
|
|
625
|
+
#------------------------------------------------------------------------------
|
|
626
|
+
# Extract information from a INI-format file
|
|
627
|
+
# Inputs: 0) ExifTool object reference, 1) dirInfo reference
|
|
628
|
+
# Returns: 1 on success, 0 if this wasn't a valid INI file
|
|
629
|
+
sub ProcessINI($$)
|
|
630
|
+
{
|
|
631
|
+
my ($et, $dirInfo) = @_;
|
|
632
|
+
my $raf = $$dirInfo{RAF};
|
|
633
|
+
my $buff;
|
|
634
|
+
local $/ = "\x0d\x0a";
|
|
635
|
+
my $tagTablePtr = GetTagTable('Image::ExifTool::LNK::INI');
|
|
636
|
+
while ($raf->ReadLine($buff)) {
|
|
637
|
+
if ($buff =~ /^\[(.*?)\]/) {
|
|
638
|
+
$et->VPrint(0, "$1 section:\n");
|
|
639
|
+
} elsif ($buff =~ /^\s*(\w+)=(.*)\x0d\x0a$/) {
|
|
640
|
+
$et->HandleTag($tagTablePtr, $1, $2, MakeTagInfo => 1);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
return 1;
|
|
644
|
+
}
|
|
645
|
+
|
|
591
646
|
#------------------------------------------------------------------------------
|
|
592
647
|
# Extract information from a MS Shell Link (Windows shortcut) file
|
|
593
648
|
# Inputs: 0) ExifTool object reference, 1) dirInfo reference
|
|
@@ -600,7 +655,13 @@ sub ProcessLNK($$)
|
|
|
600
655
|
|
|
601
656
|
# read LNK file header
|
|
602
657
|
$raf->Read($buff, 0x4c) == 0x4c or return 0;
|
|
603
|
-
$buff =~ /^.{4}\x01\x14\x02\0{5}\xc0\0{6}\x46/s
|
|
658
|
+
unless ($buff =~ /^.{4}\x01\x14\x02\0{5}\xc0\0{6}\x46/s) {
|
|
659
|
+
# check for INI-format LNK file (eg. .URL file)
|
|
660
|
+
return undef unless $buff =~ /^\[[InternetShortcut\][\x0d\x0a]/;
|
|
661
|
+
$raf->Seek(0,0) or return 0;
|
|
662
|
+
$et->SetFileType('URL', 'application/x-mswinurl');
|
|
663
|
+
return ProcessINI($et, $dirInfo);
|
|
664
|
+
};
|
|
604
665
|
$len = unpack('V', $buff);
|
|
605
666
|
$len >= 0x4c or return 0;
|
|
606
667
|
if ($len > 0x4c) {
|
|
@@ -32,7 +32,7 @@ use strict;
|
|
|
32
32
|
use vars qw($VERSION);
|
|
33
33
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
34
34
|
|
|
35
|
-
$VERSION = '1.
|
|
35
|
+
$VERSION = '1.31';
|
|
36
36
|
|
|
37
37
|
# program map table "stream_type" lookup (ref 6/1/9)
|
|
38
38
|
my %streamType = (
|
|
@@ -322,7 +322,7 @@ sub ParsePID($$$$$)
|
|
|
322
322
|
if ($$et{OPTIONS}{ExtractEmbedded}) {
|
|
323
323
|
$more = 1;
|
|
324
324
|
} elsif (not $$et{OPTIONS}{Validate}) {
|
|
325
|
-
$et->Warn('The ExtractEmbedded option may find more tags in the video data',
|
|
325
|
+
$et->Warn('The ExtractEmbedded option may find more tags in the video data',7);
|
|
326
326
|
}
|
|
327
327
|
} elsif ($type == 0x81 or $type == 0x87 or $type == 0x91) {
|
|
328
328
|
# AC-3 audio
|
|
@@ -557,31 +557,40 @@ sub ProcessM2TS($$)
|
|
|
557
557
|
{
|
|
558
558
|
my ($et, $dirInfo) = @_;
|
|
559
559
|
my $raf = $$dirInfo{RAF};
|
|
560
|
-
my ($buff, $
|
|
560
|
+
my ($buff, $j, $eof, $pLen, $readSize);
|
|
561
561
|
my (%pmt, %pidType, %data, %sectLen, %packLen, %fromStart);
|
|
562
562
|
my ($startTime, $endTime, $fwdTime, $backScan, $maxBack);
|
|
563
563
|
my $verbose = $et->Options('Verbose');
|
|
564
564
|
my $out = $et->Options('TextOut');
|
|
565
565
|
|
|
566
|
-
# read
|
|
567
|
-
return 0 unless $raf->Read($buff,
|
|
566
|
+
# read enough to guarantee 2 sync bytes
|
|
567
|
+
return 0 unless $raf->Read($buff, 383) == 383;
|
|
568
568
|
# test for magic number (sync byte is the only thing we can safely check)
|
|
569
|
-
return 0 unless $buff =~ /^(
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
569
|
+
return 0 unless $buff =~ /^(.{0,190}?)\x47(.{187}|.{191})\x47/s;
|
|
570
|
+
my $tcLen = length($2) - 187; # (length of timecode = 0 or 4 bytes)
|
|
571
|
+
my $start = length($1) - $tcLen;
|
|
572
|
+
# we may need to try the validation twice to handle the edge case
|
|
573
|
+
# where the first byte of a timecode is 0x47 and we were fooled
|
|
574
|
+
# into thinking there was no timecode
|
|
575
|
+
Try: for (;;) {
|
|
576
|
+
$start += 192 if $start < 0; # (if all or part of first timecode was missing)
|
|
577
|
+
$pLen = 188 + $tcLen;
|
|
578
|
+
$readSize = 64 * $pLen; # size of our read buffer
|
|
579
|
+
$raf->Seek($start, 0); # rewind to start
|
|
580
|
+
$raf->Read($buff, $readSize) >= $pLen * 4 or return 0; # require at least 4 packets
|
|
581
|
+
# validate the sync byte in the next 3 packets
|
|
582
|
+
for ($j=1; $j<4; ++$j) {
|
|
583
|
+
next if substr($buff, $tcLen + $pLen * $j, 1) eq 'G'; # (0x47)
|
|
584
|
+
return 0 if $tcLen;
|
|
585
|
+
$tcLen = 4;
|
|
586
|
+
$start -= 4;
|
|
587
|
+
next Try;
|
|
588
|
+
}
|
|
589
|
+
last; # success!
|
|
583
590
|
}
|
|
584
|
-
|
|
591
|
+
# (use M2T instead of M2TS just as an indicator that there is no timecode)
|
|
592
|
+
$et->SetFileType($tcLen ? 'M2TS' : 'M2T');
|
|
593
|
+
$et->Warn("File doesn't begin with the start of a packet") if $start;
|
|
585
594
|
SetByteOrder('MM');
|
|
586
595
|
my $tagTablePtr = GetTagTable('Image::ExifTool::M2TS::Main');
|
|
587
596
|
|
|
@@ -667,7 +676,7 @@ sub ProcessM2TS($$)
|
|
|
667
676
|
}
|
|
668
677
|
$pEnd += $pLen;
|
|
669
678
|
# decode the packet prefix
|
|
670
|
-
$pos += $
|
|
679
|
+
$pos += $tcLen;
|
|
671
680
|
my $prefix = unpack("x${pos}N", $buff); # (use unpack instead of Get32u for speed)
|
|
672
681
|
# validate sync byte
|
|
673
682
|
unless (($prefix & 0xff000000) == 0x47000000) {
|
|
@@ -685,9 +694,9 @@ sub ProcessM2TS($$)
|
|
|
685
694
|
if ($verbose > 1) {
|
|
686
695
|
my $i = ($raf->Tell() - length($buff) + $pEnd) / $pLen - 1;
|
|
687
696
|
print $out "Transport packet $i:\n";
|
|
688
|
-
$et->VerboseDump(\$buff, Len => $pLen, Addr => $i * $pLen, Start => $pos - $
|
|
697
|
+
$et->VerboseDump(\$buff, Len => $pLen, Addr => $i * $pLen, Start => $pos - $tcLen);
|
|
689
698
|
my $str = $pidName{$pid} ? " ($pidName{$pid})" : ' <not in Program Map Table!>';
|
|
690
|
-
printf $out " Timecode: 0x%.4x\n", Get32u(\$buff, $pos - $
|
|
699
|
+
printf $out " Timecode: 0x%.4x\n", Get32u(\$buff, $pos - $tcLen) if $pLen == 192;
|
|
691
700
|
printf $out " Packet ID: 0x%.4x$str\n", $pid;
|
|
692
701
|
printf $out " Start Flag: %s\n", $payload_unit_start_indicator ? 'Yes' : 'No';
|
|
693
702
|
}
|
|
@@ -172,7 +172,7 @@ strings.
|
|
|
172
172
|
hp_C homeopathic potency of centesimal series (homeopathic potency)
|
|
173
173
|
hp_X homeopathic potency of decimal series (homeopathic potency)
|
|
174
174
|
HPF high power field (view area in microscope)
|
|
175
|
-
Hz
|
|
175
|
+
Hz Hertz (frequency)
|
|
176
176
|
in inch, international (length)
|
|
177
177
|
in_br inch, British (length)
|
|
178
178
|
in_us inch, U.S. (length)
|
|
@@ -14,7 +14,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
|
14
14
|
use Image::ExifTool::XMP;
|
|
15
15
|
use Image::ExifTool::ZIP;
|
|
16
16
|
|
|
17
|
-
$VERSION = '1.
|
|
17
|
+
$VERSION = '1.10';
|
|
18
18
|
|
|
19
19
|
# test for recognized OOXML document extensions
|
|
20
20
|
my %isOOXML = (
|
|
@@ -27,6 +27,7 @@ my %isOOXML = (
|
|
|
27
27
|
XLAM => 1,
|
|
28
28
|
XLSX => 1, XLSM => 1, XLSB => 1,
|
|
29
29
|
XLTX => 1, XLTM => 1,
|
|
30
|
+
VSDX => 1,
|
|
30
31
|
);
|
|
31
32
|
|
|
32
33
|
# generate reverse lookup for file type based on MIME
|
|
@@ -57,7 +58,7 @@ my @vectorVals;
|
|
|
57
58
|
VARS => { ID_FMT => 'none' },
|
|
58
59
|
NOTES => q{
|
|
59
60
|
The Office Open XML (OOXML) format was introduced with Microsoft Office 2007
|
|
60
|
-
and is used by file types such as DOCX, PPTX and
|
|
61
|
+
and is used by file types such as DOCX, PPTX, XLSX and VSDX. These are
|
|
61
62
|
essentially ZIP archives containing XML files. The table below lists some
|
|
62
63
|
tags which have been observed in OOXML documents, but ExifTool will extract
|
|
63
64
|
any tags found from XML files of the OOXML document properties ("docProps")
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
# 25) Karsten Gieselmann private communication (OM series)
|
|
32
32
|
# IB) Iliah Borg private communication (LibRaw)
|
|
33
33
|
# NJ) Niels Kristian Bech Jensen private communication
|
|
34
|
+
# KG) Karsten Gieselmann private communication
|
|
34
35
|
#------------------------------------------------------------------------------
|
|
35
36
|
|
|
36
37
|
package Image::ExifTool::Olympus;
|
|
@@ -41,7 +42,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
|
41
42
|
use Image::ExifTool::Exif;
|
|
42
43
|
use Image::ExifTool::APP12;
|
|
43
44
|
|
|
44
|
-
$VERSION = '2.
|
|
45
|
+
$VERSION = '2.92';
|
|
45
46
|
|
|
46
47
|
sub PrintLensInfo($$$);
|
|
47
48
|
|
|
@@ -201,6 +202,7 @@ my %olympusLensTypes = (
|
|
|
201
202
|
# Other makes
|
|
202
203
|
'24 01 10' => 'Venus Optics Laowa 50mm F2.8 2x Macro', #DonKomarechka
|
|
203
204
|
'f7 03 10' => 'LAOWA C&D-Dreamer MFT 7.5mm F2.0', #forum3833
|
|
205
|
+
'f7 10 10' => 'LAOWA C&D-Dreamer MFT 6.0mm F2.0', #KG
|
|
204
206
|
);
|
|
205
207
|
|
|
206
208
|
# lookup for Olympus camera types (ref PH)
|
|
@@ -59,7 +59,7 @@ use Image::ExifTool::Exif;
|
|
|
59
59
|
use Image::ExifTool::GPS;
|
|
60
60
|
use Image::ExifTool::HP;
|
|
61
61
|
|
|
62
|
-
$VERSION = '3.
|
|
62
|
+
$VERSION = '3.59';
|
|
63
63
|
|
|
64
64
|
sub CryptShutterCount($$);
|
|
65
65
|
sub PrintFilter($$$);
|
|
@@ -1947,7 +1947,8 @@ my %binaryDataAttrs = (
|
|
|
1947
1947
|
'0 28' => 'Quick Macro', # (Q)
|
|
1948
1948
|
'0 29' => 'Forest', # (Q)
|
|
1949
1949
|
'0 30' => 'Backlight Silhouette', # (Q)
|
|
1950
|
-
'0
|
|
1950
|
+
'0 31' => 'Max. Aperture Priority', #KG (Ricoh GR III)
|
|
1951
|
+
'0 32' => 'DOF', #PH (GR III) #KG ???? GR III 'DOF Priority (Deep)' is mapped to '0 2' ???
|
|
1951
1952
|
# AUTO PICT modes (auto-selected)
|
|
1952
1953
|
'1 4' => 'Auto PICT (Standard)', #13
|
|
1953
1954
|
'1 5' => 'Auto PICT (Portrait)', #7 (K100D)
|
|
@@ -1962,7 +1963,11 @@ my %binaryDataAttrs = (
|
|
|
1962
1963
|
'2 22' => 'Shallow DOF (HyP)', #PH (K-5)
|
|
1963
1964
|
'3 0' => 'Green Mode', #16
|
|
1964
1965
|
'4 0' => 'Shutter Speed Priority',
|
|
1966
|
+
'4 2' => 'Shutter Speed Priority 2', #KG Coding error? 'DOF Priority' in Tv makes no sense
|
|
1967
|
+
'4 31' => 'Shutter Speed Priority 31',#KG Coding error? 'Max Aperture' in Tv makes no sense
|
|
1965
1968
|
'5 0' => 'Aperture Priority',
|
|
1969
|
+
'5 2' => 'Aperture Priority 2', #KG Coding error? 'DOF Priority' in Av makes no sense
|
|
1970
|
+
'5 31' => 'Aperture Priority 31', #KG Coding error? 'DOF Priority' in Av makes no sense
|
|
1966
1971
|
'6 0' => 'Program Tv Shift',
|
|
1967
1972
|
'7 0' => 'Program Av Shift', #19
|
|
1968
1973
|
'8 0' => 'Manual',
|
|
@@ -49,7 +49,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
|
49
49
|
use Image::ExifTool::Exif;
|
|
50
50
|
use Image::ExifTool::GPS;
|
|
51
51
|
|
|
52
|
-
$VERSION = '3.
|
|
52
|
+
$VERSION = '3.22';
|
|
53
53
|
|
|
54
54
|
sub ProcessMOV($$;$);
|
|
55
55
|
sub ProcessKeys($$$);
|
|
@@ -10515,9 +10515,9 @@ ItemID: foreach $id (reverse sort { $a <=> $b } keys %$items) {
|
|
|
10515
10515
|
$et->Warn($warnStr);
|
|
10516
10516
|
}
|
|
10517
10517
|
}
|
|
10518
|
-
# tweak file type based on track content ("iso*" and "dash" ftyp only)
|
|
10518
|
+
# tweak file type based on track content ("iso*" and "dash" ftyp only ["mp42" added in 13.39])
|
|
10519
10519
|
if ($topLevel and $$et{FileType} and $$et{FileType} eq 'MP4' and
|
|
10520
|
-
$$et{save_ftyp} and $$et{HasHandler} and $$et{save_ftyp} =~ /^(iso|dash)/ and
|
|
10520
|
+
$$et{save_ftyp} and $$et{HasHandler} and $$et{save_ftyp} =~ /^(iso|dash|mp42)/ and
|
|
10521
10521
|
$$et{HasHandler}{soun} and not $$et{HasHandler}{vide})
|
|
10522
10522
|
{
|
|
10523
10523
|
$et->OverrideFileType('M4A', 'audio/mp4');
|
|
@@ -111,7 +111,7 @@ my %insvLimit = (
|
|
|
111
111
|
The tags below are extracted from timed metadata in QuickTime and other
|
|
112
112
|
formats of video files when the ExtractEmbedded option is used. Although
|
|
113
113
|
most of these tags are combined into the single table below, ExifTool
|
|
114
|
-
currently reads
|
|
114
|
+
currently reads 116 different types of timed GPS metadata from video files.
|
|
115
115
|
},
|
|
116
116
|
GPSLatitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', RawConv => '$$self{FoundGPSLatitude} = 1; $val' },
|
|
117
117
|
GPSLongitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")' },
|
|
@@ -984,7 +984,9 @@ sub SetGPSDateTime($$$;$)
|
|
|
984
984
|
}
|
|
985
985
|
$sampleTime -= $tzOff; # shift from local time to UTC
|
|
986
986
|
}
|
|
987
|
+
$$et{SET_GROUP0} = 'Composite';
|
|
987
988
|
$et->HandleTag($tagTbl, GPSDateTime => Image::ExifTool::ConvertUnixTime($sampleTime,0,3) . 'Z');
|
|
989
|
+
delete $$et{SET_GROUP0};
|
|
988
990
|
}
|
|
989
991
|
}
|
|
990
992
|
|
|
@@ -1004,6 +1006,28 @@ sub HandleTextTags($$$)
|
|
|
1004
1006
|
undef %$tags; # clear the hash
|
|
1005
1007
|
}
|
|
1006
1008
|
|
|
1009
|
+
#------------------------------------------------------------------------------
|
|
1010
|
+
# Handle new time in NMEA stream and store queued tags if necessary
|
|
1011
|
+
# Inputs: 0) ExifTool ref, 1) time string, 2) tag table ref, 3) tags hash
|
|
1012
|
+
sub HandleNewTime($$$$)
|
|
1013
|
+
{
|
|
1014
|
+
my ($et, $time, $tagTbl, $tags) = @_;
|
|
1015
|
+
if ($$et{LastTime}) {
|
|
1016
|
+
if ($$et{LastTime} eq $time) {
|
|
1017
|
+
# combine with the previous NMEA sentence
|
|
1018
|
+
$$et{DOC_NUM} = $$et{LastDoc};
|
|
1019
|
+
} elsif (%$tags) {
|
|
1020
|
+
# handle existing tags and start a new document
|
|
1021
|
+
# (see https://exiftool.org/forum/index.php?msg=75422)
|
|
1022
|
+
HandleTextTags($et, $tagTbl, $tags);
|
|
1023
|
+
# increment document number and update document count if necessary
|
|
1024
|
+
$$et{DOC_COUNT} < ++$$et{DOC_NUM} and $$et{DOC_COUNT} = $$et{DOC_NUM};
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
$$et{LastTime} = $time;
|
|
1028
|
+
$$et{LastDoc} = $$et{DOC_NUM};
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1007
1031
|
#------------------------------------------------------------------------------
|
|
1008
1032
|
# Process subtitle 'text'
|
|
1009
1033
|
# Inputs: 0) ExifTool ref, 1) data ref or dirInfo ref, 2) tag table ref
|
|
@@ -1030,41 +1054,18 @@ sub Process_text($$$;$)
|
|
|
1030
1054
|
next;
|
|
1031
1055
|
}
|
|
1032
1056
|
my $time = "$1:$2:$3";
|
|
1033
|
-
|
|
1034
|
-
if ($$et{LastTime} eq $time) {
|
|
1035
|
-
# combine with the previous NMEA sentence
|
|
1036
|
-
$$et{DOC_NUM} = $$et{LastDoc};
|
|
1037
|
-
} elsif (%tags) {
|
|
1038
|
-
# handle existing tags and start a new document
|
|
1039
|
-
# (see https://exiftool.org/forum/index.php?msg=75422)
|
|
1040
|
-
HandleTextTags($et, $tagTbl, \%tags);
|
|
1041
|
-
undef %tags;
|
|
1042
|
-
# increment document number and update document count if necessary
|
|
1043
|
-
$$et{DOC_COUNT} < ++$$et{DOC_NUM} and $$et{DOC_COUNT} = $$et{DOC_NUM};
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
$$et{LastTime} = $time;
|
|
1047
|
-
$$et{LastDoc} = $$et{DOC_NUM};
|
|
1057
|
+
HandleNewTime($et, $time, $tagTbl, \%tags);
|
|
1048
1058
|
my $year = $14 + ($14 >= 70 ? 1900 : 2000);
|
|
1049
|
-
my $
|
|
1050
|
-
|
|
1059
|
+
my $date = sprintf('%.4d:%.2d:%.2d', $year, $13, $12);
|
|
1060
|
+
$$et{LastDate} = $date;
|
|
1061
|
+
$tags{GPSDateTime} = "$date ${time}Z";
|
|
1051
1062
|
$tags{GPSLatitude} = (($4 || 0) + $5/60) * ($6 eq 'N' ? 1 : -1);
|
|
1052
1063
|
$tags{GPSLongitude} = (($7 || 0) + $8/60) * ($9 eq 'E' ? 1 : -1);
|
|
1053
1064
|
$tags{GPSSpeed} = $10 * $knotsToKph if length $10;
|
|
1054
1065
|
$tags{GPSTrack} = $11 if length $11;
|
|
1055
1066
|
} 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) {
|
|
1056
1067
|
my $time = "$1:$2:$3";
|
|
1057
|
-
|
|
1058
|
-
if ($$et{LastTime} eq $time) {
|
|
1059
|
-
$$et{DOC_NUM} = $$et{LastDoc};
|
|
1060
|
-
} elsif (%tags) {
|
|
1061
|
-
HandleTextTags($et, $tagTbl, \%tags);
|
|
1062
|
-
undef %tags;
|
|
1063
|
-
$$et{DOC_COUNT} < ++$$et{DOC_NUM} and $$et{DOC_COUNT} = $$et{DOC_NUM};
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
$$et{LastTime} = $time;
|
|
1067
|
-
$$et{LastDoc} = $$et{DOC_NUM};
|
|
1068
|
+
HandleNewTime($et, $time, $tagTbl, \%tags);
|
|
1068
1069
|
$tags{GPSTimeStamp} = $time;
|
|
1069
1070
|
$tags{GPSLatitude} = (($4 || 0) + $5/60) * ($6 eq 'N' ? 1 : -1);
|
|
1070
1071
|
$tags{GPSLongitude} = (($7 || 0) + $8/60) * ($9 eq 'E' ? 1 : -1);
|
|
@@ -1112,6 +1113,11 @@ sub Process_text($$$;$)
|
|
|
1112
1113
|
}
|
|
1113
1114
|
}
|
|
1114
1115
|
}
|
|
1116
|
+
if ($tags{GPSTimeStamp} and not $tags{GPSDateTime} and $$et{LastDate}) {
|
|
1117
|
+
# hack to fill in missing date for NextBase 662GW
|
|
1118
|
+
# (note: this doesn't necessarily handle day rollover properly)
|
|
1119
|
+
$tags{GPSDateTime} = "$$et{LastDate} $tags{GPSTimeStamp}Z";
|
|
1120
|
+
}
|
|
1115
1121
|
HandleTextTags($et, $tagTbl, \%tags);
|
|
1116
1122
|
return;
|
|
1117
1123
|
}
|
|
@@ -3488,14 +3494,17 @@ sub ProcessGarminGPS($$$)
|
|
|
3488
3494
|
while ($pos + 20 <= $dataLen) {
|
|
3489
3495
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
|
3490
3496
|
my $time = Image::ExifTool::ConvertUnixTime(Get32u($dataPt, $pos) - $epoch) . 'Z';
|
|
3491
|
-
my $lat = Get32s($dataPt, $pos + 12)
|
|
3492
|
-
my $lon = Get32s($dataPt, $pos + 16)
|
|
3497
|
+
my $lat = Get32s($dataPt, $pos + 12);
|
|
3498
|
+
my $lon = Get32s($dataPt, $pos + 16);
|
|
3493
3499
|
my $spd = Get16u($dataPt, $pos + 4); # (in mph)
|
|
3494
3500
|
$et->HandleTag($tagTbl, 'GPSDateTime', $time);
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3501
|
+
# skip bad GPS fixes
|
|
3502
|
+
if ($lat != -2147483648 or $lon != -2147483648) {
|
|
3503
|
+
$et->HandleTag($tagTbl, 'GPSLatitude', $lat * $scl);
|
|
3504
|
+
$et->HandleTag($tagTbl, 'GPSLongitude', $lon * $scl);
|
|
3505
|
+
$et->HandleTag($tagTbl, 'GPSSpeed', $spd);
|
|
3506
|
+
$et->HandleTag($tagTbl, 'GPSSpeedRef', 'M');
|
|
3507
|
+
}
|
|
3499
3508
|
$pos += 20;
|
|
3500
3509
|
}
|
|
3501
3510
|
delete $$et{DOC_NUM};
|