exiftool_vendored 12.99.0 → 13.03.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/Changes +76 -3
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +2 -2
- data/bin/arg_files/exif2xmp.args +4 -0
- data/bin/arg_files/xmp2exif.args +4 -0
- data/bin/exiftool +121 -50
- data/bin/lib/Image/ExifTool/Apple.pm +2 -2
- data/bin/lib/Image/ExifTool/CBOR.pm +4 -1
- data/bin/lib/Image/ExifTool/Canon.pm +35 -26
- data/bin/lib/Image/ExifTool/Exif.pm +15 -9
- data/bin/lib/Image/ExifTool/FlashPix.pm +5 -9
- data/bin/lib/Image/ExifTool/GIF.pm +143 -92
- data/bin/lib/Image/ExifTool/Geolocation.dat +0 -0
- data/bin/lib/Image/ExifTool/Geotag.pm +6 -5
- data/bin/lib/Image/ExifTool/GoPro.pm +2 -2
- data/bin/lib/Image/ExifTool/JPEG.pm +9 -1
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +2 -2
- data/bin/lib/Image/ExifTool/LNK.pm +1 -1
- data/bin/lib/Image/ExifTool/M2TS.pm +2 -2
- data/bin/lib/Image/ExifTool/MIE.pm +9 -3
- data/bin/lib/Image/ExifTool/MacOS.pm +2 -1
- data/bin/lib/Image/ExifTool/Matroska.pm +10 -2
- data/bin/lib/Image/ExifTool/Nikon.pm +5 -2
- data/bin/lib/Image/ExifTool/PDF.pm +35 -4
- data/bin/lib/Image/ExifTool/PNG.pm +14 -3
- data/bin/lib/Image/ExifTool/PPM.pm +11 -2
- data/bin/lib/Image/ExifTool/PhaseOne.pm +2 -1
- data/bin/lib/Image/ExifTool/QuickTime.pm +6 -1
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +69 -7
- data/bin/lib/Image/ExifTool/RIFF.pm +7 -2
- data/bin/lib/Image/ExifTool/TagLookup.pm +5596 -5582
- data/bin/lib/Image/ExifTool/TagNames.pod +75 -21
- data/bin/lib/Image/ExifTool/Text.pm +3 -2
- data/bin/lib/Image/ExifTool/Validate.pm +2 -2
- data/bin/lib/Image/ExifTool/WriteRIFF.pl +13 -4
- data/bin/lib/Image/ExifTool/Writer.pl +42 -66
- data/bin/lib/Image/ExifTool/XMP.pm +19 -4
- data/bin/lib/Image/ExifTool/XMP2.pl +60 -0
- data/bin/lib/Image/ExifTool/XMPStruct.pl +1 -2
- data/bin/lib/Image/ExifTool.pm +204 -86
- data/bin/lib/Image/ExifTool.pod +58 -31
- data/bin/perl-Image-ExifTool.spec +1 -1
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +2 -2
@@ -11,7 +11,7 @@ use strict;
|
|
11
11
|
use vars qw($VERSION);
|
12
12
|
use Image::ExifTool qw(:DataAccess :Utils);
|
13
13
|
|
14
|
-
$VERSION = '1.
|
14
|
+
$VERSION = '1.37';
|
15
15
|
|
16
16
|
sub ProcessOcad($$$);
|
17
17
|
sub ProcessJPEG_HDR($$$);
|
@@ -228,6 +228,10 @@ sub ProcessJPEG_HDR($$$);
|
|
228
228
|
Name => 'InfiRayIsothermal',
|
229
229
|
Condition => '$$self{HasIJPEG}',
|
230
230
|
SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::Isothermal' },
|
231
|
+
}, {
|
232
|
+
Name => 'SEAL',
|
233
|
+
Condition => '$$valPt =~ /^SEAL\0/',
|
234
|
+
SubDirectory => { TagTable => 'Image::ExifTool::XMP::SEAL' },
|
231
235
|
}],
|
232
236
|
APP9 => [{
|
233
237
|
Name => 'MediaJukebox',
|
@@ -237,6 +241,10 @@ sub ProcessJPEG_HDR($$$);
|
|
237
241
|
Name => 'InfiRaySensor',
|
238
242
|
Condition => '$$self{HasIJPEG}',
|
239
243
|
SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::Sensor' },
|
244
|
+
}, {
|
245
|
+
Name => 'SEAL',
|
246
|
+
Condition => '$$valPt =~ /^SEAL\0/',
|
247
|
+
SubDirectory => { TagTable => 'Image::ExifTool::XMP::SEAL' },
|
240
248
|
}],
|
241
249
|
APP10 => {
|
242
250
|
Name => 'Comment',
|
@@ -16,7 +16,7 @@ use strict;
|
|
16
16
|
use vars qw($VERSION);
|
17
17
|
use Image::ExifTool qw(:DataAccess :Utils);
|
18
18
|
|
19
|
-
$VERSION = '1.
|
19
|
+
$VERSION = '1.42';
|
20
20
|
|
21
21
|
sub ProcessJpeg2000Box($$$);
|
22
22
|
sub ProcessJUMD($$$);
|
@@ -1338,7 +1338,7 @@ sub ProcessJpeg2000Box($$$)
|
|
1338
1338
|
if (defined $val) {
|
1339
1339
|
my $key = $et->FoundTag($tagInfo, $val);
|
1340
1340
|
# save Rational value
|
1341
|
-
$$et{
|
1341
|
+
$$et{TAG_EXTRA}{$key}{Rational} = $rational if defined $rational and defined $key;
|
1342
1342
|
}
|
1343
1343
|
} elsif ($outfile) {
|
1344
1344
|
my $boxhdr = pack('N', $boxLen + 8) . $boxID;
|
@@ -650,7 +650,7 @@ sub ProcessLNK($$)
|
|
650
650
|
my $mask = 0x04 << $i;
|
651
651
|
next unless $flags & $mask;
|
652
652
|
$raf->Read($buff, 2) or return 1;
|
653
|
-
$len = unpack('v', $buff);
|
653
|
+
$len = unpack('v', $buff) or next;
|
654
654
|
$len *= 2 if $flags & 0x80; # characters are 2 bytes if Unicode flag is set
|
655
655
|
$raf->Read($buff, $len) or return 1;
|
656
656
|
my $val;
|
@@ -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.26';
|
36
36
|
|
37
37
|
# program map table "stream_type" lookup (ref 6/1/9)
|
38
38
|
my %streamType = (
|
@@ -82,7 +82,7 @@ my %streamType = (
|
|
82
82
|
0x86 => 'DTS-HD Audio',
|
83
83
|
0x87 => 'E-AC-3 Audio',
|
84
84
|
0x8a => 'DTS Audio',
|
85
|
-
0x90 => '
|
85
|
+
0x90 => 'Presentation Graphic Stream (subtitle)', #https://en.wikipedia.org/wiki/Program-specific_information
|
86
86
|
0x91 => 'A52b/AC-3 Audio',
|
87
87
|
0x92 => 'DVD_SPU vls Subtitle',
|
88
88
|
0x94 => 'SDDS Audio',
|
@@ -14,7 +14,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
14
14
|
use Image::ExifTool::Exif;
|
15
15
|
use Image::ExifTool::GPS;
|
16
16
|
|
17
|
-
$VERSION = '1.
|
17
|
+
$VERSION = '1.55';
|
18
18
|
|
19
19
|
sub ProcessMIE($$);
|
20
20
|
sub ProcessMIEGroup($$$);
|
@@ -1596,9 +1596,10 @@ sub ProcessMIEGroup($$$)
|
|
1596
1596
|
} else {
|
1597
1597
|
# process MIE data format types
|
1598
1598
|
if ($tagInfo) {
|
1599
|
-
my $rational;
|
1599
|
+
my ($rational, $binVal);
|
1600
1600
|
# extract tag value
|
1601
1601
|
my $val = ReadMIEValue(\$value, 0, $formatStr, undef, $valLen, \$rational);
|
1602
|
+
$binVal = substr($value, 0, $valLen) if $$et{OPTIONS}{SaveBin};
|
1602
1603
|
unless (defined $val) {
|
1603
1604
|
$et->Warn("Error reading $tag value");
|
1604
1605
|
$val = '<err>';
|
@@ -1661,7 +1662,12 @@ sub ProcessMIEGroup($$$)
|
|
1661
1662
|
$val .= "($units)" if defined $units;
|
1662
1663
|
}
|
1663
1664
|
my $key = $et->FoundTag($tagInfo, $val);
|
1664
|
-
|
1665
|
+
if (defined $key) {
|
1666
|
+
my $ex = $$et{TAG_EXTRA}{$key};
|
1667
|
+
$$ex{Rational} = $rational if defined $rational;
|
1668
|
+
$$ex{BinVal} = $binVal if defined $binVal;
|
1669
|
+
$$ex{G6} = $formatStr if $$et{OPTIONS}{SaveFormat};
|
1670
|
+
}
|
1665
1671
|
}
|
1666
1672
|
} else {
|
1667
1673
|
# skip over unknown information or free bytes
|
@@ -12,7 +12,7 @@ use strict;
|
|
12
12
|
use vars qw($VERSION);
|
13
13
|
use Image::ExifTool qw(:DataAccess :Utils);
|
14
14
|
|
15
|
-
$VERSION = '1.
|
15
|
+
$VERSION = '1.14';
|
16
16
|
|
17
17
|
sub MDItemLocalTime($);
|
18
18
|
sub ProcessATTR($$$);
|
@@ -394,6 +394,7 @@ sub SetMacOSTags($$$)
|
|
394
394
|
if ($val =~ /[-+Z]/) {
|
395
395
|
my $time = Image::ExifTool::GetUnixTime($val, 1);
|
396
396
|
$val = Image::ExifTool::ConvertUnixTime($time, 1) if $time;
|
397
|
+
$val =~ s/[-+].*//; # remove time zone
|
397
398
|
}
|
398
399
|
$val =~ s{(\d{4}):(\d{2}):(\d{2})}{$2/$3/$1}; # reformat for setfile
|
399
400
|
$cmd = "/usr/bin/setfile -d '${val}' '${f}'";
|
@@ -15,7 +15,7 @@ use strict;
|
|
15
15
|
use vars qw($VERSION);
|
16
16
|
use Image::ExifTool qw(:DataAccess :Utils);
|
17
17
|
|
18
|
-
$VERSION = '1.
|
18
|
+
$VERSION = '1.17';
|
19
19
|
|
20
20
|
sub HandleStruct($$;$$$$);
|
21
21
|
|
@@ -685,6 +685,14 @@ my %uidInfo = (
|
|
685
685
|
Name => 'Projection',
|
686
686
|
SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Projection' },
|
687
687
|
},
|
688
|
+
#
|
689
|
+
# other
|
690
|
+
#
|
691
|
+
0x5345414c => { # ('SEAL' in hex)
|
692
|
+
Name => 'SEAL',
|
693
|
+
NotEBML => 1, # don't process SubDirectory as EBML elements
|
694
|
+
SubDirectory => { TagTable => 'Image::ExifTool::XMP::SEAL' },
|
695
|
+
},
|
688
696
|
);
|
689
697
|
|
690
698
|
# Spherical video v2 projection tags (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md)
|
@@ -1047,7 +1055,7 @@ sub ProcessMKV($$)
|
|
1047
1055
|
$seekInfoOnly = 1;
|
1048
1056
|
}
|
1049
1057
|
if ($tagInfo) {
|
1050
|
-
if ($$tagInfo{SubDirectory}) {
|
1058
|
+
if ($$tagInfo{SubDirectory} and not $$tagInfo{NotEBML}) {
|
1051
1059
|
# stop processing at first cluster unless we are using -v -U or -ee
|
1052
1060
|
# or there are Tags after this
|
1053
1061
|
if ($$tagInfo{Name} eq 'Cluster' and $processAll < 2) {
|
@@ -65,7 +65,7 @@ use Image::ExifTool::Exif;
|
|
65
65
|
use Image::ExifTool::GPS;
|
66
66
|
use Image::ExifTool::XMP;
|
67
67
|
|
68
|
-
$VERSION = '4.
|
68
|
+
$VERSION = '4.39';
|
69
69
|
|
70
70
|
sub LensIDConv($$$);
|
71
71
|
sub ProcessNikonAVI($$$);
|
@@ -13609,7 +13609,10 @@ sub ProcessNikonMOV($$$)
|
|
13609
13609
|
Size => $size,
|
13610
13610
|
Base => $$dirInfo{Base},
|
13611
13611
|
);
|
13612
|
-
|
13612
|
+
if ($key) {
|
13613
|
+
$$et{TAG_EXTRA}{$key}{Rational} = $rational if $rational;
|
13614
|
+
$$et{TAG_EXTRA}{$key}{BinVal} = substr($$dataPt, $pos, $size) if $$et{OPTIONS}{SaveBin};
|
13615
|
+
}
|
13613
13616
|
} elsif (exists $needTags{$tag}) {
|
13614
13617
|
$needTags{$tag} = ReadValue($dataPt, $pos, $fmtStr, $count, $size);
|
13615
13618
|
$$et{NikonSerialKey} = SerialKey($et, $needTags{0x110a431});
|
@@ -21,7 +21,7 @@ use vars qw($VERSION $AUTOLOAD $lastFetched);
|
|
21
21
|
use Image::ExifTool qw(:DataAccess :Utils);
|
22
22
|
require Exporter;
|
23
23
|
|
24
|
-
$VERSION = '1.
|
24
|
+
$VERSION = '1.60';
|
25
25
|
|
26
26
|
sub FetchObject($$$$);
|
27
27
|
sub ExtractObject($$;$$);
|
@@ -349,6 +349,7 @@ my %supportedFilter = (
|
|
349
349
|
# tags in PDF ICCBased, Cs1 and CS0 dictionaries
|
350
350
|
%Image::ExifTool::PDF::ICCBased = (
|
351
351
|
_stream => {
|
352
|
+
Name => 'ICC_Profile',
|
352
353
|
SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' },
|
353
354
|
},
|
354
355
|
);
|
@@ -470,6 +471,7 @@ my %supportedFilter = (
|
|
470
471
|
# tags in PDF AIMetaData dictionary
|
471
472
|
%Image::ExifTool::PDF::AIMetaData = (
|
472
473
|
_stream => {
|
474
|
+
Name => 'AIStream',
|
473
475
|
SubDirectory => { TagTable => 'Image::ExifTool::PostScript::Main' },
|
474
476
|
},
|
475
477
|
);
|
@@ -477,6 +479,7 @@ my %supportedFilter = (
|
|
477
479
|
# tags in PDF ImageResources dictionary
|
478
480
|
%Image::ExifTool::PDF::ImageResources = (
|
479
481
|
_stream => {
|
482
|
+
Name => 'PhotoshopStream',
|
480
483
|
SubDirectory => { TagTable => 'Image::ExifTool::Photoshop::Main' },
|
481
484
|
},
|
482
485
|
);
|
@@ -1595,9 +1598,13 @@ sub DecryptInit($$$)
|
|
1595
1598
|
$password = $et->Options('Password');
|
1596
1599
|
return 'Document is password protected (use Password option)' unless defined $password;
|
1597
1600
|
# make sure there is no UTF-8 flag on the password
|
1598
|
-
if ($] >= 5.006 and (
|
1601
|
+
if ($] >= 5.006 and ($$et{OPTIONS}{EncodeHangs} or
|
1602
|
+
eval { require Encode; Encode::is_utf8($password) } or $@))
|
1603
|
+
{
|
1604
|
+
local $SIG{'__WARN__'} = sub { };
|
1599
1605
|
# repack by hand if Encode isn't available
|
1600
|
-
$password = $@ ? pack('C*',unpack($] < 5.010000 ?
|
1606
|
+
$password = ($$et{OPTIONS}{EncodeHangs} or $@) ? pack('C*', unpack($] < 5.010000 ?
|
1607
|
+
'U0C*' : 'C0C*', $password)) : Encode::encode('utf8', $password);
|
1601
1608
|
}
|
1602
1609
|
} else {
|
1603
1610
|
return 'Incorrect password';
|
@@ -2157,6 +2164,20 @@ sub ProcessDict($$$$;$$)
|
|
2157
2164
|
last;
|
2158
2165
|
}
|
2159
2166
|
# decode stream if necessary
|
2167
|
+
if ($cryptInfo and ($$cryptInfo{_aesv2} or $$cryptInfo{_aesv3} and
|
2168
|
+
$$dict{Length} and $$dict{Length} > 10000) and not $$dict{_decrypted} and
|
2169
|
+
not $$et{PDF_CAPTURE}) # (capturing PDF for writing?)
|
2170
|
+
{
|
2171
|
+
my $type = $$dict{Type} || '';
|
2172
|
+
if ($type ne '/Metadata' or $$dict{Length} > 100000) {
|
2173
|
+
if ($$et{OPTIONS}{IgnoreMinorErrors}) {
|
2174
|
+
$et->WarnOnce("Decrypting large $$tagInfo{Name} (will be slow)");
|
2175
|
+
} else {
|
2176
|
+
$et->WarnOnce("Skipping large AES-encrypted $$tagInfo{Name}", 2);
|
2177
|
+
last;
|
2178
|
+
}
|
2179
|
+
}
|
2180
|
+
}
|
2160
2181
|
DecodeStream($et, $dict) or last;
|
2161
2182
|
if ($verbose > 2) {
|
2162
2183
|
$et->VPrint(2,"$$et{INDENT}$$et{DIR_NAME} stream data\n");
|
@@ -2233,7 +2254,17 @@ sub ReadPDF($$)
|
|
2233
2254
|
$raf->Read($buff, $len) == $len or return -3;
|
2234
2255
|
# find the LAST xref table in the file (may be multiple %%EOF marks,
|
2235
2256
|
# and comments between "startxref" and "%%EOF")
|
2236
|
-
$buff =~ /^.*startxref(\s+)(\d+)(\s+)(%[^\x0d\x0a]*\s+)
|
2257
|
+
$buff =~ /^.*startxref(\s+)(\d+)(\s+)((%[^\x0d\x0a]*\s+)*)%%EOF/s or return -4;
|
2258
|
+
# parse comments to read SEAL information
|
2259
|
+
if ($4) {
|
2260
|
+
my @com = split /[\x0d\x0d]+/, $4;
|
2261
|
+
foreach (@com) {
|
2262
|
+
/^(%+\s*)<seal seal=/ or next;
|
2263
|
+
my $dat = substr $_, length($1);
|
2264
|
+
my $tbl = GetTagTable('Image::ExifTool::XMP::SEAL');
|
2265
|
+
$et->ProcessDirectory({ DataPt => \$dat }, $tbl);
|
2266
|
+
}
|
2267
|
+
}
|
2237
2268
|
my $ws = $1 . $3;
|
2238
2269
|
my $xr = $2;
|
2239
2270
|
push @xrefOffsets, $xr, 'Main';
|
@@ -36,7 +36,7 @@ use strict;
|
|
36
36
|
use vars qw($VERSION $AUTOLOAD %stdCase);
|
37
37
|
use Image::ExifTool qw(:DataAccess :Utils);
|
38
38
|
|
39
|
-
$VERSION = '1.
|
39
|
+
$VERSION = '1.69';
|
40
40
|
|
41
41
|
sub ProcessPNG_tEXt($$$);
|
42
42
|
sub ProcessPNG_iTXt($$$);
|
@@ -371,6 +371,10 @@ my %noLeapFrog = ( SAVE => 1, SEEK => 1, IHDR => 1, JHDR => 1, IEND => 1, MEND =
|
|
371
371
|
IgnoreProp => { meta => 1 }, # ignore 'meta' container
|
372
372
|
},
|
373
373
|
},
|
374
|
+
seAl => {
|
375
|
+
Name => 'SEAL',
|
376
|
+
SubDirectory => { TagTable => 'Image::ExifTool::XMP::SEAL' },
|
377
|
+
},
|
374
378
|
# mkBF,mkTS,mkBS,mkBT ? - written by Adobe FireWorks
|
375
379
|
);
|
376
380
|
|
@@ -980,8 +984,15 @@ sub FoundPNG($$$$;$$$$)
|
|
980
984
|
my $processProc = $$subdir{ProcessProc};
|
981
985
|
# nothing more to do if writing and subdirectory is not writable
|
982
986
|
my $subTable = GetTagTable($$subdir{TagTable});
|
983
|
-
|
984
|
-
|
987
|
+
if ($outBuff and not $$subTable{WRITE_PROC}) {
|
988
|
+
if ($$et{DEL_GROUP}{$dirName}) {
|
989
|
+
# non-writable directories may be deleted as a group (eg. SEAL)
|
990
|
+
$et->VPrint(0, " Deleting $dirName\n");
|
991
|
+
$$outBuff = '';
|
992
|
+
++$$et{CHANGED};
|
993
|
+
}
|
994
|
+
return 1;
|
995
|
+
}
|
985
996
|
my %subdirInfo = (
|
986
997
|
DataPt => \$val,
|
987
998
|
DirStart => 0,
|
@@ -16,7 +16,7 @@ use strict;
|
|
16
16
|
use vars qw($VERSION);
|
17
17
|
use Image::ExifTool qw(:DataAccess :Utils);
|
18
18
|
|
19
|
-
$VERSION = '1.
|
19
|
+
$VERSION = '1.11';
|
20
20
|
|
21
21
|
#------------------------------------------------------------------------------
|
22
22
|
# Read or write information in a PPM/PGM/PBM image
|
@@ -29,7 +29,7 @@ sub ProcessPPM($$)
|
|
29
29
|
my $outfile = $$dirInfo{OutFile};
|
30
30
|
my $verbose = $et->Options('Verbose');
|
31
31
|
my $out = $et->Options('TextOut');
|
32
|
-
my ($buff, $num, $type, %info);
|
32
|
+
my ($buff, $num, $type, %info, $seal);
|
33
33
|
#
|
34
34
|
# read as much of the image as necessary to extract the header and comments
|
35
35
|
#
|
@@ -77,6 +77,7 @@ sub ProcessPPM($$)
|
|
77
77
|
if (defined $info{Comment}) {
|
78
78
|
$info{Comment} =~ s/^# ?//mg; # remove "# " at the start of each line
|
79
79
|
$info{Comment} =~ s/[\n\r]+$//; # remove trailing newline
|
80
|
+
$seal = 1 if $info{Comment} =~ /^<seal seal=/;
|
80
81
|
}
|
81
82
|
$et->SetFileType($type);
|
82
83
|
my $len = pos($buff);
|
@@ -91,6 +92,10 @@ sub ProcessPPM($$)
|
|
91
92
|
++$$et{CHANGED};
|
92
93
|
$et->VerboseValue('- Comment', $oldComment) if defined $oldComment;
|
93
94
|
$et->VerboseValue('+ Comment', $newComment) if defined $newComment;
|
95
|
+
} elsif ($seal and $$et{DEL_GROUP}{SEAL}) {
|
96
|
+
# delete SEAL comment
|
97
|
+
$et->VerboseValue('- Comment', $oldComment);
|
98
|
+
++$$et{CHANGED};
|
94
99
|
} else {
|
95
100
|
$newComment = $oldComment; # use existing comment
|
96
101
|
}
|
@@ -116,6 +121,10 @@ sub ProcessPPM($$)
|
|
116
121
|
print $out "$type header ($len bytes):\n";
|
117
122
|
$et->VerboseDump(\$buff, Len => $len);
|
118
123
|
}
|
124
|
+
if ($seal) {
|
125
|
+
$et->ProcessDirectory({ DataPt => \$info{Comment} }, GetTagTable('Image::ExifTool::XMP::SEAL'));
|
126
|
+
delete $info{Comment};
|
127
|
+
}
|
119
128
|
my $tag;
|
120
129
|
foreach $tag (qw{Comment ImageWidth ImageHeight MaxVal}) {
|
121
130
|
$et->FoundTag($tag, $info{$tag}) if defined $info{$tag};
|
@@ -15,7 +15,7 @@ use vars qw($VERSION);
|
|
15
15
|
use Image::ExifTool qw(:DataAccess :Utils);
|
16
16
|
use Image::ExifTool::Exif;
|
17
17
|
|
18
|
-
$VERSION = '1.
|
18
|
+
$VERSION = '1.11';
|
19
19
|
|
20
20
|
sub WritePhaseOne($$$);
|
21
21
|
sub ProcessPhaseOne($$$);
|
@@ -71,6 +71,7 @@ my @formatName = ( undef, 'string', 'int16s', undef, 'int32s' );
|
|
71
71
|
# >2 = compressed
|
72
72
|
# 5 = non-linear
|
73
73
|
PrintConv => { #PH
|
74
|
+
0 => 'Uncompressed', #https://github.com/darktable-org/darktable/issues/7308
|
74
75
|
1 => 'RAW 1', #? (encrypted)
|
75
76
|
2 => 'RAW 2', #? (encrypted)
|
76
77
|
3 => 'IIQ L', # (now "L14", ref IB)
|
@@ -48,7 +48,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
48
48
|
use Image::ExifTool::Exif;
|
49
49
|
use Image::ExifTool::GPS;
|
50
50
|
|
51
|
-
$VERSION = '3.
|
51
|
+
$VERSION = '3.05';
|
52
52
|
|
53
53
|
sub ProcessMOV($$;$);
|
54
54
|
sub ProcessKeys($$$);
|
@@ -902,6 +902,10 @@ my %userDefined = (
|
|
902
902
|
},
|
903
903
|
# '35AX'? - seen "AT" (Yada RoadCam Pro 4K dashcam)
|
904
904
|
cust => 'CustomInfo', # 70mai A810
|
905
|
+
SEAL => {
|
906
|
+
Name => 'SEAL',
|
907
|
+
SubDirectory => { TagTable => 'Image::ExifTool::XMP::SEAL' },
|
908
|
+
},
|
905
909
|
);
|
906
910
|
|
907
911
|
# stuff seen in 'skip' atom (70mai Pro Plus+ MP4 videos)
|
@@ -3097,6 +3101,7 @@ my %userDefined = (
|
|
3097
3101
|
10 => {
|
3098
3102
|
Name => 'VideoFullRangeFlag',
|
3099
3103
|
Mask => 0x80,
|
3104
|
+
PrintConv => { 0 => 'Limited', 1 => 'Full' },
|
3100
3105
|
},
|
3101
3106
|
);
|
3102
3107
|
|
@@ -591,8 +591,8 @@ my %insvLimit = (
|
|
591
591
|
GROUPS => { 2 => 'Location' },
|
592
592
|
FIRST_ENTRY => 0,
|
593
593
|
NOTES => q{
|
594
|
-
Tags extracted from the tx3g sbtl timed metadata of Yuneec drones,
|
595
|
-
subtitle text in some other videos.
|
594
|
+
Tags extracted from the tx3g sbtl timed metadata of Yuneec and Autel drones,
|
595
|
+
and subtitle text in some other videos.
|
596
596
|
},
|
597
597
|
Lat => {
|
598
598
|
Name => 'GPSLatitude',
|
@@ -619,6 +619,32 @@ my %insvLimit = (
|
|
619
619
|
PrintConv => '$self->ConvertDateTime($val)',
|
620
620
|
},
|
621
621
|
Text => { Groups => { 2 => 'Other' } },
|
622
|
+
# the following tags are extracted from Autel Evo II drone videos
|
623
|
+
GPSDateTime => {
|
624
|
+
Groups => { 2 => 'Time' },
|
625
|
+
Description => 'GPS Date/Time',
|
626
|
+
PrintConv => '$self->ConvertDateTime($val)',
|
627
|
+
},
|
628
|
+
HomeLat => {
|
629
|
+
Name => 'GPSHomeLatitude',
|
630
|
+
RawConv => '$$self{FoundGPSLatitude} = 1; $val',
|
631
|
+
PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
|
632
|
+
},
|
633
|
+
HomeLon => {
|
634
|
+
Name => 'GPSHomeLongitude',
|
635
|
+
PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
|
636
|
+
},
|
637
|
+
ISO => { },
|
638
|
+
SHUTTER => {
|
639
|
+
Name => 'ExposureTime',
|
640
|
+
ValueConv => '1 / $val',
|
641
|
+
PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
|
642
|
+
},
|
643
|
+
'F-NUM' => {
|
644
|
+
Name => 'FNumber',
|
645
|
+
PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)',
|
646
|
+
},
|
647
|
+
EV => 'ExposureCompensation',
|
622
648
|
);
|
623
649
|
|
624
650
|
%Image::ExifTool::QuickTime::INSV_MakerNotes = (
|
@@ -2361,7 +2387,7 @@ sub ParseTag($$$)
|
|
2361
2387
|
}
|
2362
2388
|
|
2363
2389
|
#------------------------------------------------------------------------------
|
2364
|
-
# Process Yuneec 'tx3g' sbtl metadata (ref PH)
|
2390
|
+
# Process Yuneec 'tx3g' and Autel sbtl metadata (ref PH)
|
2365
2391
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
|
2366
2392
|
# Returns: 1 on success
|
2367
2393
|
sub Process_tx3g($$$)
|
@@ -2369,13 +2395,49 @@ sub Process_tx3g($$$)
|
|
2369
2395
|
my ($et, $dirInfo, $tagTablePtr) = @_;
|
2370
2396
|
my $dataPt = $$dirInfo{DataPt};
|
2371
2397
|
return 0 if length $$dataPt < 2;
|
2372
|
-
pos($$dataPt) = 2; # skip 2-byte length word
|
2373
2398
|
$et->VerboseDir('tx3g', undef, length($$dataPt)-2);
|
2374
|
-
$
|
2375
|
-
|
2399
|
+
my $text = substr($$dataPt, 2); # remove 2-byte length word
|
2400
|
+
$et->HandleTag($tagTablePtr, 'Text', $text);
|
2401
|
+
if ($text =~ /^HOME\(/) {
|
2402
|
+
# --- sample text from Autel Evo II drone ---
|
2403
|
+
# HOME(W: 109.318642, N: 40.769371) 2023-09-12 10:28:07
|
2404
|
+
# GPS(W: 109.339287, N: 40.768574, 2371.76m)
|
2405
|
+
# HDR ISO:100 SHUTTER:1000 EV:-0.7 F-NUM:1.8
|
2406
|
+
# F.PRY (1.0\xc2\xb0, -3.7\xc2\xb0, -59.0\xc2\xb0), G.PRY (-51.1\xc2\xb0, 0.0\xc2\xb0, -58.9\xc2\xb0)
|
2407
|
+
my $line;
|
2408
|
+
foreach $line (split /\x0a/, $text) {
|
2409
|
+
if ($line =~ /^HOME\(([EW]):\s*(\d+\.\d+),\s*([NS]):\s*(\d+\.\d+)\)\s*(.*)/) {
|
2410
|
+
my ($lon, $lat, $time) = ($2, $4, $5);
|
2411
|
+
$lon = -$lon if $1 eq 'W';
|
2412
|
+
$lat = -$lat if $3 eq 'S';
|
2413
|
+
$time =~ tr/-/:/; # (likely local time zone, but not confirmed)
|
2414
|
+
$et->HandleTag($tagTablePtr, GPSDateTime => $time);
|
2415
|
+
$et->HandleTag($tagTablePtr, HomeLat => $lat);
|
2416
|
+
$et->HandleTag($tagTablePtr, HomeLon => $lon);
|
2417
|
+
} elsif ($line =~ /^GPS\(([EW]):\s*(\d+\.\d+),\s*([NS]):\s*(\d+\.\d+),\s*(.*)m/) {
|
2418
|
+
my ($lon, $lat, $alt) = ($2, $4, $5);
|
2419
|
+
$lon = -$lon if $1 eq 'W';
|
2420
|
+
$lat = -$lat if $3 eq 'S';
|
2421
|
+
$et->HandleTag($tagTablePtr, Lat => $lat);
|
2422
|
+
$et->HandleTag($tagTablePtr, Lon => $lon);
|
2423
|
+
$et->HandleTag($tagTablePtr, Alt => $alt);
|
2424
|
+
} elsif ($line =~ /^F\.PRY\s*\((-?[\d.]+)\xc2\xb0,\s*(-?[\d.]+)\xc2\xb0,\s*(-?[\d.]+)\xc2\xb0/) {
|
2425
|
+
$et->HandleTag($tagTablePtr, Yaw => $1);
|
2426
|
+
$et->HandleTag($tagTablePtr, Pitch => $2);
|
2427
|
+
$et->HandleTag($tagTablePtr, Roll => $3);
|
2428
|
+
if ($line =~ /G\.PRY\s*\((-?[\d.]+)\xc2\xb0,\s*(-?[\d.]+)\xc2\xb0,\s*(-?[\d.]+)\xc2\xb0/) {
|
2429
|
+
$et->HandleTag($tagTablePtr, GimYaw => $1);
|
2430
|
+
$et->HandleTag($tagTablePtr, GimPitch => $2);
|
2431
|
+
$et->HandleTag($tagTablePtr, GimRoll => $3);
|
2432
|
+
}
|
2433
|
+
} else {
|
2434
|
+
$et->HandleTag($tagTablePtr, $1, $2) while $line =~ /([-\w]+):([^:]*[^:\s])(\s|$)/sg;
|
2435
|
+
}
|
2436
|
+
}
|
2437
|
+
} elsif ($text =~ /^\w{3} (\d{4})-(\d{2})-(\d{2}) (\d{2}:\d{2}:\d{2}) ?([-+])(\d{2}):?(\d{2})$/s) {
|
2376
2438
|
$et->HandleTag($tagTablePtr, 'DateTime', "$1:$2:$3 $4$5$6:$7");
|
2377
2439
|
} else {
|
2378
|
-
$et->HandleTag($tagTablePtr, $1, $2) while
|
2440
|
+
$et->HandleTag($tagTablePtr, $1, $2) while $text =~ /(\w+):([^:]*[^:\s])(\s|$)/sg;
|
2379
2441
|
}
|
2380
2442
|
return 1;
|
2381
2443
|
}
|
@@ -30,7 +30,7 @@ use strict;
|
|
30
30
|
use vars qw($VERSION $AUTOLOAD);
|
31
31
|
use Image::ExifTool qw(:DataAccess :Utils);
|
32
32
|
|
33
|
-
$VERSION = '1.
|
33
|
+
$VERSION = '1.69';
|
34
34
|
|
35
35
|
sub ConvertTimecode($);
|
36
36
|
sub ProcessSGLT($$$);
|
@@ -664,6 +664,10 @@ my %code2charset = (
|
|
664
664
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Acidizer' },
|
665
665
|
},
|
666
666
|
guan => 'Guano', #forum14831
|
667
|
+
SEAL => {
|
668
|
+
Name => 'SEAL',
|
669
|
+
SubDirectory => { TagTable => 'Image::ExifTool::XMP::SEAL' },
|
670
|
+
},
|
667
671
|
);
|
668
672
|
|
669
673
|
# the maker notes used by some digital cameras
|
@@ -2120,7 +2124,8 @@ sub ProcessRIFF($$)
|
|
2120
2124
|
my $tagInfo = $$tagTbl{$tag};
|
2121
2125
|
# (in LIST_movi chunk: ##db = uncompressed DIB, ##dc = compressed DIB, ##wb = audio data)
|
2122
2126
|
if ($tagInfo or (($verbose or $unknown) and $tag !~ /^(data|idx1|LIST_movi|RIFF|\d{2}(db|dc|wb))$/)) {
|
2123
|
-
$raf->Read($buff, $len2)
|
2127
|
+
$raf->Read($buff, $len2) >= $len or $err=1, next;
|
2128
|
+
length($buff) == $len2 or $et->Warn("No padding on odd-sized $tag chunk");
|
2124
2129
|
if ($hash and $isImageData{$tag}) {
|
2125
2130
|
$hash->add($buff);
|
2126
2131
|
$et->VPrint(0, "$$et{INDENT}(ImageDataHash: '${tag}' chunk, $len2 bytes)\n");
|