exiftool_vendored 12.60.0 → 12.62.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 +35 -0
- data/bin/MANIFEST +7 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +45 -44
- data/bin/exiftool +100 -73
- data/bin/lib/Image/ExifTool/BMP.pm +0 -1
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +4 -4
- data/bin/lib/Image/ExifTool/FlashPix.pm +2 -1
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +31 -6
- data/bin/lib/Image/ExifTool/MinoltaRaw.pm +2 -2
- data/bin/lib/Image/ExifTool/Nikon.pm +3 -3
- data/bin/lib/Image/ExifTool/PDF.pm +17 -8
- data/bin/lib/Image/ExifTool/QuickTime.pm +10 -7
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +51 -21
- data/bin/lib/Image/ExifTool/Sony.pm +16 -10
- data/bin/lib/Image/ExifTool/TagLookup.pm +9 -0
- data/bin/lib/Image/ExifTool/TagNames.pod +34 -5
- data/bin/lib/Image/ExifTool/WPG.pm +296 -0
- data/bin/lib/Image/ExifTool/WritePDF.pl +7 -8
- data/bin/lib/Image/ExifTool/Writer.pl +12 -4
- data/bin/lib/Image/ExifTool/XMP.pm +17 -5
- data/bin/lib/Image/ExifTool/ZIP.pm +159 -41
- data/bin/lib/Image/ExifTool.pm +118 -50
- data/bin/lib/Image/ExifTool.pod +51 -42
- data/bin/perl-Image-ExifTool.spec +44 -43
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +3 -2
@@ -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.34';
|
20
20
|
|
21
21
|
sub ProcessJpeg2000Box($$$);
|
22
22
|
sub ProcessJUMD($$$);
|
@@ -34,6 +34,9 @@ my %resolutionUnit = (
|
|
34
34
|
6 => 'um',
|
35
35
|
);
|
36
36
|
|
37
|
+
# top-level boxes containing image data
|
38
|
+
my %isImageData = ( jp2c=>1, jbrd=>1, jxlp=>1, jxlc=>1 );
|
39
|
+
|
37
40
|
# map of where information is written in JPEG2000 image
|
38
41
|
my %jp2Map = (
|
39
42
|
IPTC => 'UUID-IPTC',
|
@@ -428,6 +431,7 @@ my %j2cMarker = (
|
|
428
431
|
# stuff seen in JPEG XL images:
|
429
432
|
#
|
430
433
|
# jbrd - JPEG Bitstream Reconstruction Data (allows lossless conversion back to original JPG)
|
434
|
+
# jxlp - partial JXL codestream
|
431
435
|
jxlc => {
|
432
436
|
Name => 'JXLCodestream',
|
433
437
|
Format => 'undef',
|
@@ -930,7 +934,7 @@ sub ProcessJpeg2000Box($$$)
|
|
930
934
|
my $raf = $$dirInfo{RAF};
|
931
935
|
my $outfile = $$dirInfo{OutFile};
|
932
936
|
my $dirEnd = $dirStart + $dirLen;
|
933
|
-
my ($err, $outBuff, $verbose, $doColour);
|
937
|
+
my ($err, $outBuff, $verbose, $doColour, $md5);
|
934
938
|
|
935
939
|
if ($outfile) {
|
936
940
|
unless ($raf) {
|
@@ -948,6 +952,8 @@ sub ProcessJpeg2000Box($$$)
|
|
948
952
|
# (must not set verbose flag when writing!)
|
949
953
|
$verbose = $$et{OPTIONS}{Verbose};
|
950
954
|
$et->VerboseDir($$dirInfo{DirName}) if $verbose;
|
955
|
+
# do MD5 if requested, but only for top-level image data
|
956
|
+
$md5 = $$et{ImageDataMD5} if $raf;
|
951
957
|
}
|
952
958
|
# loop through all contained boxes
|
953
959
|
my ($pos, $boxLen, $lastBox);
|
@@ -971,6 +977,11 @@ sub ProcessJpeg2000Box($$$)
|
|
971
977
|
}
|
972
978
|
$boxLen = unpack("x$pos N",$$dataPt); # (length includes header and data)
|
973
979
|
$boxID = substr($$dataPt, $pos+4, 4);
|
980
|
+
# (ftbl box contains flst boxes with absolute file offsets, not currently handled)
|
981
|
+
if ($outfile and $boxID eq 'ftbl') {
|
982
|
+
$et->Error("Can't yet handle fragmented JPX files");
|
983
|
+
return -1;
|
984
|
+
}
|
974
985
|
# remove old colr boxes if necessary
|
975
986
|
if ($doColour and $boxID eq 'colr') {
|
976
987
|
if ($doColour == 1) { # did we successfully write the new colr box?
|
@@ -1007,9 +1018,14 @@ sub ProcessJpeg2000Box($$$)
|
|
1007
1018
|
while ($raf->Read($buff, 65536)) {
|
1008
1019
|
Write($outfile, $buff) or $err = 1;
|
1009
1020
|
}
|
1010
|
-
}
|
1011
|
-
|
1012
|
-
|
1021
|
+
} else {
|
1022
|
+
if ($verbose) {
|
1023
|
+
my $msg = sprintf("offset 0x%.4x to end of file", $dataPos + $base + $pos);
|
1024
|
+
$et->VPrint(0, "$$et{INDENT}- Tag '${boxID}' ($msg)\n");
|
1025
|
+
}
|
1026
|
+
if ($md5 and $isImageData{$boxID}) {
|
1027
|
+
$et->ImageDataMD5($raf, undef, $boxID);
|
1028
|
+
}
|
1013
1029
|
}
|
1014
1030
|
last; # (ignore the rest of the file when reading)
|
1015
1031
|
}
|
@@ -1026,6 +1042,8 @@ sub ProcessJpeg2000Box($$$)
|
|
1026
1042
|
Write($outfile, $$dataPt) or $err = 1;
|
1027
1043
|
$raf->Read($buff,$boxLen) == $boxLen or $err = '', last;
|
1028
1044
|
Write($outfile, $buff) or $err = 1;
|
1045
|
+
} elsif ($md5 and $isImageData{$boxID}) {
|
1046
|
+
$et->ImageDataMD5($raf, $boxLen, $boxID);
|
1029
1047
|
} else {
|
1030
1048
|
$raf->Seek($boxLen, 1) or $err = 'Seek error', last;
|
1031
1049
|
}
|
@@ -1038,6 +1056,10 @@ sub ProcessJpeg2000Box($$$)
|
|
1038
1056
|
# read the box data
|
1039
1057
|
$dataPos = $raf->Tell() - $base;
|
1040
1058
|
$raf->Read($buff,$boxLen) == $boxLen or $err = '', last;
|
1059
|
+
if ($md5 and $isImageData{$boxID}) {
|
1060
|
+
$md5->add($buff);
|
1061
|
+
$et->VPrint(0, "$$et{INDENT}(ImageDataMD5: $boxLen bytes of $boxID data)\n");
|
1062
|
+
}
|
1041
1063
|
$valuePtr = 0;
|
1042
1064
|
$dataLen = $boxLen;
|
1043
1065
|
} elsif ($pos + $boxLen > $dirEnd) {
|
@@ -1311,7 +1333,7 @@ sub ProcessJP2($$)
|
|
1311
1333
|
}
|
1312
1334
|
|
1313
1335
|
#------------------------------------------------------------------------------
|
1314
|
-
# Read meta information
|
1336
|
+
# Read/write meta information in a JPEG XL image
|
1315
1337
|
# Inputs: 0) ExifTool object reference, 1) dirInfo reference
|
1316
1338
|
# Returns: 1 on success, 0 if this wasn't a valid JPEG XL file, -1 on write error
|
1317
1339
|
sub ProcessJXL($$)
|
@@ -1340,6 +1362,9 @@ sub ProcessJXL($$)
|
|
1340
1362
|
$$dirInfo{RAF} = new File::RandomAccess(\$buff);
|
1341
1363
|
} else {
|
1342
1364
|
$et->SetFileType('JXL Codestream','image/jxl', 'jxl');
|
1365
|
+
if ($$et{ImageDataMD5} and $raf->Seek(0,0)) {
|
1366
|
+
$et->ImageDataMD5($raf, undef, 'JXL');
|
1367
|
+
}
|
1343
1368
|
return ProcessJXLCodestream($et, \$hdr);
|
1344
1369
|
}
|
1345
1370
|
} else {
|
@@ -17,7 +17,7 @@ use vars qw($VERSION);
|
|
17
17
|
use Image::ExifTool qw(:DataAccess :Utils);
|
18
18
|
use Image::ExifTool::Minolta;
|
19
19
|
|
20
|
-
$VERSION = '1.
|
20
|
+
$VERSION = '1.18';
|
21
21
|
|
22
22
|
sub ProcessMRW($$;$);
|
23
23
|
sub WriteMRW($$;$);
|
@@ -489,7 +489,7 @@ sub ProcessMRW($$;$)
|
|
489
489
|
$err and $et->Error("MRW format error", $$et{TIFF_TYPE} eq 'ARW');
|
490
490
|
} else {
|
491
491
|
$err and $et->Warn("MRW format error");
|
492
|
-
$et->ImageDataMD5($raf, undef, 'raw');
|
492
|
+
$et->ImageDataMD5($raf, undef, 'raw') unless $$et{A100DataOffset};
|
493
493
|
}
|
494
494
|
return $rtnVal;
|
495
495
|
}
|
@@ -64,7 +64,7 @@ use Image::ExifTool::Exif;
|
|
64
64
|
use Image::ExifTool::GPS;
|
65
65
|
use Image::ExifTool::XMP;
|
66
66
|
|
67
|
-
$VERSION = '4.
|
67
|
+
$VERSION = '4.22';
|
68
68
|
|
69
69
|
sub LensIDConv($$$);
|
70
70
|
sub ProcessNikonAVI($$$);
|
@@ -2300,8 +2300,8 @@ my %base64coord = (
|
|
2300
2300
|
},
|
2301
2301
|
},
|
2302
2302
|
{ # (Z6_2 firmware version 1.00 and Z7II firmware versions 1.00 & 1.01, ref 28)
|
2303
|
-
# 0800=Z6/Z7 0801=Z50 0802=Z5 0803=Z6II/Z7II 0804=Zfc
|
2304
|
-
Condition => '$$valPt =~ /^080[
|
2303
|
+
# 0800=Z6/Z7 0801=Z50 0802=Z5 0803=Z6II/Z7II 0804=Zfc 0807=Z30
|
2304
|
+
Condition => '$$valPt =~ /^080[012347]/',
|
2305
2305
|
Name => 'ShotInfoZ7II',
|
2306
2306
|
SubDirectory => {
|
2307
2307
|
TagTable => 'Image::ExifTool::Nikon::ShotInfoZ7II',
|
@@ -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.56';
|
25
25
|
|
26
26
|
sub FetchObject($$$$);
|
27
27
|
sub ExtractObject($$;$$);
|
@@ -41,7 +41,7 @@ my $cryptStream; # flag that streams are encrypted
|
|
41
41
|
my $lastOffset; # last fetched object offset
|
42
42
|
my %streamObjs; # hash of stream objects
|
43
43
|
my %fetched; # dicts fetched in verbose mode (to avoid cyclical recursion)
|
44
|
-
my $pdfVer; # version of PDF file being processed
|
44
|
+
my $pdfVer; # version of PDF file being processed (from header)
|
45
45
|
|
46
46
|
# filters supported in DecodeStream()
|
47
47
|
my %supportedFilter = (
|
@@ -115,6 +115,7 @@ my %supportedFilter = (
|
|
115
115
|
CreationDate => {
|
116
116
|
Name => 'CreateDate',
|
117
117
|
Writable => 'date',
|
118
|
+
PDF2 => 1, # not deprecated in PDF 2.0
|
118
119
|
Groups => { 2 => 'Time' },
|
119
120
|
Shift => 'Time',
|
120
121
|
PrintConv => '$self->ConvertDateTime($val)',
|
@@ -123,6 +124,7 @@ my %supportedFilter = (
|
|
123
124
|
ModDate => {
|
124
125
|
Name => 'ModifyDate',
|
125
126
|
Writable => 'date',
|
127
|
+
PDF2 => 1, # not deprecated in PDF 2.0
|
126
128
|
Groups => { 2 => 'Time' },
|
127
129
|
Shift => 'Time',
|
128
130
|
PrintConv => '$self->ConvertDateTime($val)',
|
@@ -168,7 +170,10 @@ my %supportedFilter = (
|
|
168
170
|
Lang => 'Language',
|
169
171
|
PageLayout => { },
|
170
172
|
PageMode => { },
|
171
|
-
Version =>
|
173
|
+
Version => {
|
174
|
+
Name => 'PDFVersion',
|
175
|
+
RawConv => '$$self{PDFVersion} = $val if $$self{PDFVersion} < $val; $val',
|
176
|
+
},
|
172
177
|
);
|
173
178
|
|
174
179
|
# tags extracted from the PDF Encrypt dictionary
|
@@ -1754,7 +1759,7 @@ sub ProcessDict($$$$;$$)
|
|
1754
1759
|
my $unknown = $$tagTablePtr{EXTRACT_UNKNOWN};
|
1755
1760
|
my $embedded = (defined $unknown and not $unknown and $et->Options('ExtractEmbedded'));
|
1756
1761
|
my @tags = @{$$dict{_tags}};
|
1757
|
-
my ($next, %join);
|
1762
|
+
my ($next, %join, $validInfo);
|
1758
1763
|
my $index = 0;
|
1759
1764
|
|
1760
1765
|
$nesting = ($nesting || 0) + 1;
|
@@ -1775,6 +1780,7 @@ sub ProcessDict($$$$;$$)
|
|
1775
1780
|
last;
|
1776
1781
|
}
|
1777
1782
|
}
|
1783
|
+
$validInfo = ($et->Options('Validate') and $tagTablePtr eq \%Image::ExifTool::PDF::Info);
|
1778
1784
|
#
|
1779
1785
|
# extract information from all tags in the dictionary
|
1780
1786
|
#
|
@@ -1810,6 +1816,10 @@ sub ProcessDict($$$$;$$)
|
|
1810
1816
|
$isSubDoc = 1; # treat as a sub-document
|
1811
1817
|
}
|
1812
1818
|
}
|
1819
|
+
if ($validInfo and $$et{PDFVersion} >= 2.0 and (not $tagInfo or not $$tagInfo{PDF2})) {
|
1820
|
+
my $name = $tagInfo ? ":$$tagInfo{Name}" : " Info tag '${tag}'";
|
1821
|
+
$et->Warn("PDF$name is deprecated in PDF 2.0");
|
1822
|
+
}
|
1813
1823
|
if ($verbose) {
|
1814
1824
|
my ($val2, $extra);
|
1815
1825
|
if (ref $val eq 'SCALAR') {
|
@@ -2118,9 +2128,8 @@ sub ReadPDF($$)
|
|
2118
2128
|
$raf->Read($buff, 1024) >= 8 or return 0;
|
2119
2129
|
$buff =~ /^(\s*)%PDF-(\d+\.\d+)/ or return 0;
|
2120
2130
|
$$et{PDFBase} = length $1 and $et->Warn('PDF header is not at start of file',1);
|
2121
|
-
$pdfVer = $2;
|
2131
|
+
$pdfVer = $$et{PDFVersion} = $2;
|
2122
2132
|
$et->SetFileType(); # set the FileType tag
|
2123
|
-
$et->Warn("The PDF $pdfVer specification is held hostage by the ISO") if $pdfVer >= 2.0;
|
2124
2133
|
# store PDFVersion tag
|
2125
2134
|
my $tagTablePtr = GetTagTable('Image::ExifTool::PDF::Root');
|
2126
2135
|
$et->HandleTag($tagTablePtr, 'Version', $pdfVer);
|
@@ -2384,8 +2393,8 @@ This module is loaded automatically by Image::ExifTool when required.
|
|
2384
2393
|
This code reads meta information from PDF (Adobe Portable Document Format)
|
2385
2394
|
files. It supports object streams introduced in PDF-1.5 but only with a
|
2386
2395
|
limited set of Filter and Predictor algorithms, however all standard
|
2387
|
-
encryption methods through PDF-
|
2388
|
-
|
2396
|
+
encryption methods through PDF-2.0 are supported, including AESV2 (AES-128)
|
2397
|
+
and AESV3 (AES-256).
|
2389
2398
|
|
2390
2399
|
=head1 AUTHOR
|
2391
2400
|
|
@@ -47,7 +47,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
47
47
|
use Image::ExifTool::Exif;
|
48
48
|
use Image::ExifTool::GPS;
|
49
49
|
|
50
|
-
$VERSION = '2.
|
50
|
+
$VERSION = '2.85';
|
51
51
|
|
52
52
|
sub ProcessMOV($$;$);
|
53
53
|
sub ProcessKeys($$$);
|
@@ -470,6 +470,9 @@ my %eeBox2 = (
|
|
470
470
|
vide => { avcC => 'stsd' }, # (parses H264 video stream)
|
471
471
|
);
|
472
472
|
|
473
|
+
# image types in AVIF and HEIC files
|
474
|
+
my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
475
|
+
|
473
476
|
# QuickTime atoms
|
474
477
|
%Image::ExifTool::QuickTime::Main = (
|
475
478
|
PROCESS_PROC => \&ProcessMOV,
|
@@ -2884,7 +2887,7 @@ my %eeBox2 = (
|
|
2884
2887
|
7 => 'SMPTE 240',
|
2885
2888
|
8 => 'Generic film (color filters using illuminant C)',
|
2886
2889
|
9 => 'BT.2020, BT.2100',
|
2887
|
-
10 => 'SMPTE 428 (CIE
|
2890
|
+
10 => 'SMPTE 428 (CIE 1931 XYZ)', #forum14766
|
2888
2891
|
11 => 'SMPTE RP 431-2',
|
2889
2892
|
12 => 'SMPTE EG 432-1',
|
2890
2893
|
22 => 'EBU Tech. 3213-E',
|
@@ -8784,15 +8787,15 @@ sub HandleItemInfo($)
|
|
8784
8787
|
$et->VPrint(0, "$$et{INDENT} [snip $snip bytes]\n") if $snip;
|
8785
8788
|
}
|
8786
8789
|
}
|
8787
|
-
# do MD5 checksum of AVIF "av01" image data
|
8788
|
-
if ($type
|
8790
|
+
# do MD5 checksum of AVIF "av01" and HEIC image data
|
8791
|
+
if ($isImageData{$type} and $$et{ImageDataMD5}) {
|
8789
8792
|
my $md5 = $$et{ImageDataMD5};
|
8790
8793
|
my $tot = 0;
|
8791
8794
|
foreach $extent (@{$$item{Extents}}) {
|
8792
|
-
$raf->Seek($$extent[1] + $base, 0) or $et->Warn(
|
8793
|
-
$tot += $et->ImageDataMD5($raf, $$extent[2],
|
8795
|
+
$raf->Seek($$extent[1] + $base, 0) or $et->Warn("Seek error in $type image data"), last;
|
8796
|
+
$tot += $et->ImageDataMD5($raf, $$extent[2], "$type image", 1);
|
8794
8797
|
}
|
8795
|
-
$et->VPrint(0, "$$et{INDENT}(ImageDataMD5: $tot bytes of
|
8798
|
+
$et->VPrint(0, "$$et{INDENT}(ImageDataMD5: $tot bytes of $type data)\n") if $tot;
|
8796
8799
|
}
|
8797
8800
|
next unless $name;
|
8798
8801
|
# assemble the data for this item
|
@@ -28,7 +28,7 @@ sub Process360Fly($$$);
|
|
28
28
|
sub ProcessFMAS($$$);
|
29
29
|
sub ProcessCAMM($$$);
|
30
30
|
|
31
|
-
my $debug; # set to
|
31
|
+
my $debug; # set to 'tEST' (all caps) for extra debugging messages
|
32
32
|
|
33
33
|
# QuickTime data types that have ExifTool equivalents
|
34
34
|
# (ref https://developer.apple.com/library/content/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW35)
|
@@ -89,6 +89,7 @@ my %insvDataLen = (
|
|
89
89
|
0x600 => 8, # timestamps (ref 6)
|
90
90
|
0x700 => 53, # GPS
|
91
91
|
# 0x900 => 48, # ? (Insta360 X3)
|
92
|
+
# 0xa00 => 5?, # ? (Insta360 ONE RS)
|
92
93
|
# 0xb00 => 10, # ? (Insta360 X3)
|
93
94
|
);
|
94
95
|
|
@@ -1134,6 +1135,7 @@ sub ProcessSamples($)
|
|
1134
1135
|
my $et = shift;
|
1135
1136
|
my ($raf, $ee) = @$et{qw(RAF ee)};
|
1136
1137
|
my ($i, $buff, $pos, $hdrLen, $hdrFmt, @time, @dur, $oldIndent, $md5);
|
1138
|
+
my ($mdatOffset, $mdatSize); # (for range-checking samples when MD5 is done)
|
1137
1139
|
|
1138
1140
|
return unless $ee;
|
1139
1141
|
delete $$et{ee}; # use only once
|
@@ -1230,6 +1232,10 @@ Sample: for ($i=0; ; ) {
|
|
1230
1232
|
$oldIndent = $$et{INDENT};
|
1231
1233
|
$$et{INDENT} = '';
|
1232
1234
|
}
|
1235
|
+
if ($md5) {
|
1236
|
+
$mdatSize = $$et{MediaDataSize};
|
1237
|
+
$mdatOffset = $$et{MediaDataOffset} if defined $mdatSize;
|
1238
|
+
}
|
1233
1239
|
# get required information from avcC box if parsing video data
|
1234
1240
|
if ($type eq 'avcC') {
|
1235
1241
|
$hdrLen = (Get8u(\$$ee{avcC}, 4) & 0x03) + 1;
|
@@ -1243,10 +1249,25 @@ Sample: for ($i=0; ; ) {
|
|
1243
1249
|
delete $$et{FoundGPSLatitude};
|
1244
1250
|
delete $$et{FoundGPSDateTime};
|
1245
1251
|
|
1246
|
-
#
|
1252
|
+
# range check the sample data for MD5 if necessary
|
1247
1253
|
my $size = $$size[$i];
|
1248
|
-
|
1249
|
-
|
1254
|
+
if (defined $mdatOffset) {
|
1255
|
+
if ($$start[$i] < $mdatOffset) {
|
1256
|
+
$et->Warn("Sample $i for '${type}' data is before start of mdat");
|
1257
|
+
} elsif ($$start[$i] + $size > $mdatOffset + $mdatSize) {
|
1258
|
+
$et->Warn("Sample $i for '${type}' data runs off end of mdat");
|
1259
|
+
$size = $mdatOffset + $mdatSize - $$start[$i];
|
1260
|
+
$size = 0 if $size < 0;
|
1261
|
+
}
|
1262
|
+
}
|
1263
|
+
# read the sample data
|
1264
|
+
$raf->Seek($$start[$i], 0) or $et->WarnOnce("Seek error in $type data"), next;
|
1265
|
+
my $n = $raf->Read($buff, $size);
|
1266
|
+
unless ($n == $size) {
|
1267
|
+
$et->WarnOnce("Error reading $type data");
|
1268
|
+
next unless $n;
|
1269
|
+
$size = $n;
|
1270
|
+
}
|
1250
1271
|
if ($md5) {
|
1251
1272
|
$md5->add($buff);
|
1252
1273
|
$md5size += length $buff;
|
@@ -1455,16 +1476,15 @@ sub ProcessFreeGPS($$$)
|
|
1455
1476
|
$et->VerboseDump(\$buf2);
|
1456
1477
|
}
|
1457
1478
|
# (extract longitude as 9 digits, not 8, ref PH)
|
1458
|
-
|
1459
|
-
|
1460
|
-
|
1461
|
-
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1467
|
-
push @xtra, UserLabel => $lbl if length $lbl;
|
1479
|
+
if ($buf2 =~ /^.{8}(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2}).(.{15})([NS])(\d{8})([EW])(\d{9})(\d{8})?/s) {
|
1480
|
+
($yr,$mon,$day,$hr,$min,$sec,$lbl,$latRef,$lat,$lonRef,$lon,$spd) = ($1,$2,$3,$4,$5,$6,$7,$8,$9/1e4,$10,$11/1e4,$12);
|
1481
|
+
if (defined $spd) { # (Azdome)
|
1482
|
+
$spd += 0; # remove leading 0's
|
1483
|
+
} elsif ($buf2 =~ /^.{57}([-+]\d{4})(\d{3})/s) { # (EEEkit)
|
1484
|
+
# $alt = $1 + 0; (doesn't look right for my sample, but the Ambarella A12 text has this)
|
1485
|
+
$spd = $2 + 0;
|
1486
|
+
}
|
1487
|
+
}
|
1468
1488
|
# extract accelerometer data (ref PH)
|
1469
1489
|
if ($buf2 =~ /^.{65}(([-+]\d{3})([-+]\d{3})([-+]\d{3})([-+]\d{3})*)/s) {
|
1470
1490
|
$_ = $1;
|
@@ -1472,7 +1492,15 @@ sub ProcessFreeGPS($$$)
|
|
1472
1492
|
s/([-+])/ $1/g; s/^ //;
|
1473
1493
|
push @xtra, AccelerometerData => $_;
|
1474
1494
|
} elsif ($buf2 =~ /^.{173}([-+]\d{3})([-+]\d{3})([-+]\d{3})/s) { # (Azdome)
|
1495
|
+
# (Adzome may contain acc and date/time/label even if GPS doesn't exist)
|
1475
1496
|
@acc = ($1/100, $2/100, $3/100);
|
1497
|
+
if (not defined $yr and $buf2 =~ /^.{8}(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2}).(.{15})/s) {
|
1498
|
+
($yr,$mon,$day,$hr,$min,$sec,$lbl) = ($1,$2,$3,$4,$5,$6,$7);
|
1499
|
+
}
|
1500
|
+
}
|
1501
|
+
if (defined $lbl) {
|
1502
|
+
$lbl =~ s/\0.*//s; $lbl =~ s/\s+$//; # truncate at null and remove trailing spaces
|
1503
|
+
push @xtra, UserLabel => $lbl if length $lbl;
|
1476
1504
|
}
|
1477
1505
|
|
1478
1506
|
} elsif ($$dataPt =~ /^.{52}(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/s) {
|
@@ -1741,8 +1769,6 @@ sub ProcessFreeGPS($$$)
|
|
1741
1769
|
# save tag values extracted by above code
|
1742
1770
|
#
|
1743
1771
|
FoundSomething($et, $tagTbl, $$dirInfo{SampleTime}, $$dirInfo{SampleDuration});
|
1744
|
-
# lat/long are in DDDMM.MMMM format
|
1745
|
-
ConvertLatLon($lat, $lon) unless $ddd;
|
1746
1772
|
$sec = '0' . $sec unless $sec =~ /^\d{2}/; # pad integer part of seconds to 2 digits
|
1747
1773
|
if (defined $yr) {
|
1748
1774
|
my $time = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%sZ',$yr,$mon,$day,$hr,$min,$sec);
|
@@ -1751,8 +1777,12 @@ sub ProcessFreeGPS($$$)
|
|
1751
1777
|
my $time = sprintf('%.2d:%.2d:%sZ',$hr,$min,$sec);
|
1752
1778
|
$et->HandleTag($tagTbl, GPSTimeStamp => $time);
|
1753
1779
|
}
|
1754
|
-
|
1755
|
-
|
1780
|
+
if (defined $lat) {
|
1781
|
+
# lat/long are in DDDMM.MMMM format unless $ddd is set
|
1782
|
+
ConvertLatLon($lat, $lon) unless $ddd;
|
1783
|
+
$et->HandleTag($tagTbl, GPSLatitude => $lat * ($latRef eq 'S' ? -1 : 1));
|
1784
|
+
$et->HandleTag($tagTbl, GPSLongitude => $lon * ($lonRef eq 'W' ? -1 : 1));
|
1785
|
+
}
|
1756
1786
|
$et->HandleTag($tagTbl, GPSAltitude => $alt) if defined $alt;
|
1757
1787
|
$et->HandleTag($tagTbl, GPSSpeed => $spd) if defined $spd;
|
1758
1788
|
$et->HandleTag($tagTbl, GPSTrack => $trk) if defined $trk;
|
@@ -2835,7 +2865,7 @@ sub ProcessInsta360($;$)
|
|
2835
2865
|
$raf->Read($buff, $len) == $len or last;
|
2836
2866
|
$et->VerboseDump(\$buff) if $verbose > 2;
|
2837
2867
|
if ($dlen) {
|
2838
|
-
if ($len % $dlen) {
|
2868
|
+
if ($len % $dlen and $id != 0x700) { # (have seen one 0x700 record which was expected format but not multiple of 53 bytes)
|
2839
2869
|
$et->Warn(sprintf('Unexpected Insta360 record 0x%x length',$id));
|
2840
2870
|
} elsif ($id == 0x200) {
|
2841
2871
|
$et->FoundTag(PreviewImage => $buff);
|
@@ -2865,10 +2895,9 @@ sub ProcessInsta360($;$)
|
|
2865
2895
|
$et->HandleTag($tagTbl, VideoTimeStamp => sprintf('%.3f', Get64u(\$buff, $p) / 1000));
|
2866
2896
|
}
|
2867
2897
|
} elsif ($id == 0x700) {
|
2868
|
-
for ($p=0; $p
|
2898
|
+
for ($p=0; $p+$dlen<=$len; $p+=$dlen) {
|
2869
2899
|
my $tmp = substr($buff, $p, $dlen);
|
2870
2900
|
my @a = unpack('VVvaa8aa8aa8a8a8', $tmp);
|
2871
|
-
next unless $a[3] eq 'A'; # (ignore void fixes)
|
2872
2901
|
unless (($a[5] eq 'N' or $a[5] eq 'S') and # (quick validation)
|
2873
2902
|
($a[7] eq 'E' or $a[7] eq 'W' or
|
2874
2903
|
# (odd, but I've seen "O" instead of "W". Perhaps
|
@@ -2878,6 +2907,7 @@ sub ProcessInsta360($;$)
|
|
2878
2907
|
$et->Warn('Unrecognized INSV GPS format');
|
2879
2908
|
last;
|
2880
2909
|
}
|
2910
|
+
next unless $a[3] eq 'A'; # (ignore void fixes)
|
2881
2911
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
2882
2912
|
$a[$_] = GetDouble(\$a[$_], 0) foreach 4,6,8,9,10;
|
2883
2913
|
$a[4] = -abs($a[4]) if $a[5] eq 'S'; # (abs just in case it was already signed)
|
@@ -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.60';
|
38
38
|
|
39
39
|
sub ProcessSRF($$$);
|
40
40
|
sub ProcessSR2($$$);
|
@@ -161,6 +161,7 @@ sub PrintInvLensSpec($;$$);
|
|
161
161
|
32876 => 'Sony E 11mm F1.8', #JR
|
162
162
|
32877 => 'Sony E 15mm F1.4 G', #JR
|
163
163
|
32878 => 'Sony FE 20-70mm F4 G', #JR
|
164
|
+
32879 => 'Sony FE 50mm F1.4 GM', #JR
|
164
165
|
|
165
166
|
# (comment this out so LensID will report the LensModel, which is more useful)
|
166
167
|
# 32952 => 'Metabones Canon EF Speed Booster Ultra', #JR (corresponds to 184, but 'Advanced' mode, LensMount reported as E-mount)
|
@@ -259,7 +260,10 @@ sub PrintInvLensSpec($;$$);
|
|
259
260
|
50534 => 'Sigma 20mm F1.4 DG DN | A', #JR (022)
|
260
261
|
50535 => 'Sigma 24mm F1.4 DG DN | A', #JR (022)
|
261
262
|
50536 => 'Sigma 60-600mm F4.5-6.3 DG DN OS | S', #JR (023)
|
263
|
+
50537 => 'Sigma 50mm F2 DG DN | C', #JR (023)
|
264
|
+
50538 => 'Sigma 17mm F4 DG DN | C', #JR (023)
|
262
265
|
50539 => 'Sigma 50mm F1.4 DG DN | A', #JR (023)
|
266
|
+
50544 => 'Sigma 23mm F1.4 DC DN | C', #JR (023)
|
263
267
|
|
264
268
|
50992 => 'Voigtlander SUPER WIDE-HELIAR 15mm F4.5 III', #JR
|
265
269
|
50993 => 'Voigtlander HELIAR-HYPER WIDE 10mm F5.6', #IB
|
@@ -1165,7 +1169,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
|
|
1165
1169
|
},
|
1166
1170
|
},{
|
1167
1171
|
Name => 'AFAreaModeSetting',
|
1168
|
-
Condition => '$$self{Model} =~ /^(NEX-|ILCE-|ILME-|DSC-(RX10M4|RX100M6|RX100M7|RX100M5A|HX99|RX0M2))/',
|
1172
|
+
Condition => '$$self{Model} =~ /^(NEX-|ILCE-|ILME-|ZV-E|DSC-(RX10M4|RX100M6|RX100M7|RX100M5A|HX99|RX0M2))/',
|
1169
1173
|
Notes => 'NEX, ILCE and some DSC models',
|
1170
1174
|
RawConv => '$$self{AFAreaILCE} = $val',
|
1171
1175
|
DataMember => 'AFAreaILCE',
|
@@ -1201,7 +1205,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
|
|
1201
1205
|
# observed values in range (0 0) to (640 480), with center (320 240) often seen
|
1202
1206
|
# for NEX-5R/6, positions appear to be in an 11x9 grid
|
1203
1207
|
Name => 'FlexibleSpotPosition',
|
1204
|
-
Condition => '$$self{Model} =~ /^(NEX-|ILCE-|ILME-|DSC-(RX10M4|RX100M6|RX100M7|RX100M5A|HX99|RX0M2))/',
|
1208
|
+
Condition => '$$self{Model} =~ /^(NEX-|ILCE-|ILME-|ZV-E|DSC-(RX10M4|RX100M6|RX100M7|RX100M5A|HX99|RX0M2))/',
|
1205
1209
|
Writable => 'int16u',
|
1206
1210
|
Count => 2,
|
1207
1211
|
Notes => q{
|
@@ -1669,6 +1673,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
|
|
1669
1673
|
# 0x28 (e) for ILCE-7RM4/9M2, DSC-RX100M7, ZV-1/E10
|
1670
1674
|
# 0x31 (e) for ILCE-1/7M4/7SM3, ILME-FX3
|
1671
1675
|
# 0x32 (e) for ILCE-7RM5, ILME-FX30
|
1676
|
+
# 0x33 (e) for ZV-E1
|
1672
1677
|
# first byte decoded: 40, 204, 202, 27, 58, 62, 48, 215, 28, 106, 89 respectively
|
1673
1678
|
{
|
1674
1679
|
Name => 'Tag9400a',
|
@@ -1683,7 +1688,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
|
|
1683
1688
|
SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag9400b' },
|
1684
1689
|
},{
|
1685
1690
|
Name => 'Tag9400c',
|
1686
|
-
Condition => '$$valPt =~ /^[\x23\x24\x26\x28\x31\x32]/',
|
1691
|
+
Condition => '$$valPt =~ /^[\x23\x24\x26\x28\x31\x32\x33]/',
|
1687
1692
|
SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag9400c' },
|
1688
1693
|
},{
|
1689
1694
|
Name => 'Sony_0x9400',
|
@@ -1896,7 +1901,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
|
|
1896
1901
|
},
|
1897
1902
|
0x940c => [{
|
1898
1903
|
Name => 'Tag940c',
|
1899
|
-
Condition => '$$self{Model} =~ /^(NEX-|ILCE-|ILME-|Lunar|ZV-E10)\b/',
|
1904
|
+
Condition => '$$self{Model} =~ /^(NEX-|ILCE-|ILME-|Lunar|ZV-E10|ZV-E1)\b/',
|
1900
1905
|
SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag940c' },
|
1901
1906
|
},{
|
1902
1907
|
Name => 'Sony_0x940c',
|
@@ -2064,6 +2069,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
|
|
2064
2069
|
389 => 'ZV-1F', #IB
|
2065
2070
|
390 => 'ILCE-7RM5', #IB
|
2066
2071
|
391 => 'ILME-FX30', #JR
|
2072
|
+
393 => 'ZV-E1', #JR
|
2067
2073
|
},
|
2068
2074
|
},
|
2069
2075
|
0xb020 => { #2
|
@@ -8238,7 +8244,7 @@ my %isoSetting2010 = (
|
|
8238
8244
|
},
|
8239
8245
|
0x002a => [{
|
8240
8246
|
Name => 'Quality2',
|
8241
|
-
Condition => '$$self{Model} !~ /^(ILCE-(1|7M4|7RM5|7SM3)|ILME-FX3)\b/',
|
8247
|
+
Condition => '$$self{Model} !~ /^(ILCE-(1|7M4|7RM5|7SM3)|ILME-(FX3|FX30)|ZV-E1)\b/',
|
8242
8248
|
PrintConv => {
|
8243
8249
|
0 => 'JPEG',
|
8244
8250
|
1 => 'RAW',
|
@@ -8247,7 +8253,6 @@ my %isoSetting2010 = (
|
|
8247
8253
|
},
|
8248
8254
|
},{
|
8249
8255
|
Name => 'Quality2',
|
8250
|
-
Condition => '$$self{Model} =~ /^(ILCE-(1|7M4|7RM5|7SM3)|ILME-FX3)\b/',
|
8251
8256
|
PrintConv => {
|
8252
8257
|
1 => 'JPEG',
|
8253
8258
|
2 => 'RAW',
|
@@ -8258,13 +8263,13 @@ my %isoSetting2010 = (
|
|
8258
8263
|
}],
|
8259
8264
|
0x0047 => {
|
8260
8265
|
Name => 'SonyImageHeight',
|
8261
|
-
Condition => '$$self{Model} !~ /^(ILCE-(1|7M4|7RM5|7SM3)|ILME-FX3)\b/',
|
8266
|
+
Condition => '$$self{Model} !~ /^(ILCE-(1|7M4|7RM5|7SM3)|ILME-(FX3|FX30)|ZV-E1)\b/',
|
8262
8267
|
Format => 'int16u',
|
8263
8268
|
PrintConv => '$val > 0 ? 8*$val : "n.a."',
|
8264
8269
|
},
|
8265
8270
|
0x0053 => {
|
8266
8271
|
Name => 'ModelReleaseYear',
|
8267
|
-
Condition => '$$self{Model} !~ /^(ILCE-(1|7M4|7RM5|7SM3)|ILME-FX3)\b/',
|
8272
|
+
Condition => '$$self{Model} !~ /^(ILCE-(1|7M4|7RM5|7SM3)|ILME-(FX3|FX30)|ZV-E1)\b/',
|
8268
8273
|
Format => 'int8u',
|
8269
8274
|
PrintConv => 'sprintf("20%.2d", $val)',
|
8270
8275
|
},
|
@@ -8279,9 +8284,10 @@ my %isoSetting2010 = (
|
|
8279
8284
|
FIRST_ENTRY => 0,
|
8280
8285
|
GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
|
8281
8286
|
DATAMEMBER => [ 0 ],
|
8282
|
-
IS_SUBDIR => [ 0x044e, 0x0498, 0x049d, 0x04a1, 0x04a2, 0x059d, 0x0634, 0x0636, 0x064c, 0x0653, 0x0678, 0x06b8, 0x06de, 0x06e7 ],
|
8287
|
+
IS_SUBDIR => [ 0x03e2, 0x044e, 0x0498, 0x049d, 0x04a1, 0x04a2, 0x059d, 0x0634, 0x0636, 0x064c, 0x0653, 0x0678, 0x06b8, 0x06de, 0x06e7 ],
|
8283
8288
|
0x0000 => { Name => 'Ver9401', Hidden => 1, RawConv => '$$self{Ver9401} = $val; $$self{OPTIONS}{Unknown}<2 ? undef : $val' },
|
8284
8289
|
|
8290
|
+
0x03e2 => { Name => 'ISOInfo', Condition => '$$self{Ver9401} == 181', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } },
|
8285
8291
|
0x044e => { Name => 'ISOInfo', Condition => '$$self{Ver9401} == 178', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } },
|
8286
8292
|
0x0498 => { Name => 'ISOInfo', Condition => '$$self{Ver9401} == 148', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } },
|
8287
8293
|
0x049d => { Name => 'ISOInfo', Condition => '$$self{Ver9401} == 167', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } },
|
@@ -2498,6 +2498,9 @@ my %tagLookup = (
|
|
2498
2498
|
'energysavingmode' => { 238 => 0x648, 239 => 0x678 },
|
2499
2499
|
'engineer' => { 521 => 'engineer' },
|
2500
2500
|
'enhancedarktones' => { 280 => 0x8 },
|
2501
|
+
'enhancedenoisealreadyapplied' => { 491 => 'EnhanceDenoiseAlreadyApplied' },
|
2502
|
+
'enhancedenoiselumaamount' => { 491 => 'EnhanceDenoiseLumaAmount' },
|
2503
|
+
'enhancedenoiseversion' => { 491 => 'EnhanceDenoiseVersion' },
|
2501
2504
|
'enhancedetailsalreadyapplied' => { 491 => 'EnhanceDetailsAlreadyApplied' },
|
2502
2505
|
'enhancedetailsversion' => { 491 => 'EnhanceDetailsVersion' },
|
2503
2506
|
'enhancement' => { 112 => 0x16, 113 => 0x3016 },
|
@@ -9489,6 +9492,7 @@ my %tagExists = (
|
|
9489
9492
|
'imagefullheight' => 1,
|
9490
9493
|
'imagefullwidth' => 1,
|
9491
9494
|
'imageheader' => 1,
|
9495
|
+
'imageheightinches' => 1,
|
9492
9496
|
'imagehorizonpixelpack' => 1,
|
9493
9497
|
'imageid' => 1,
|
9494
9498
|
'imageinfo' => 1,
|
@@ -9522,6 +9526,7 @@ my %tagExists = (
|
|
9522
9526
|
'imagetoolbar' => 1,
|
9523
9527
|
'imageuidlist' => 1,
|
9524
9528
|
'imageversion' => 1,
|
9529
|
+
'imagewidthinches' => 1,
|
9525
9530
|
'imageworkstationmake' => 1,
|
9526
9531
|
'imagingdata' => 1,
|
9527
9532
|
'imdb' => 1,
|
@@ -11103,6 +11108,7 @@ my %tagExists = (
|
|
11103
11108
|
'rafdata' => 1,
|
11104
11109
|
'rafversion' => 1,
|
11105
11110
|
'rangeimagelocalset' => 1,
|
11111
|
+
'rarversion' => 1,
|
11106
11112
|
'rasterpadding' => 1,
|
11107
11113
|
'rate' => 1,
|
11108
11114
|
'rated' => 1,
|
@@ -11192,6 +11198,8 @@ my %tagExists = (
|
|
11192
11198
|
'recordingtimeyear' => 1,
|
11193
11199
|
'recordingtimeyearmonth' => 1,
|
11194
11200
|
'recordingtimeyearmonthday' => 1,
|
11201
|
+
'records' => 1,
|
11202
|
+
'recordsv2' => 1,
|
11195
11203
|
'rect' => 1,
|
11196
11204
|
'rectangleofinterest' => 1,
|
11197
11205
|
'red1header' => 1,
|
@@ -12468,6 +12476,7 @@ my %tagExists = (
|
|
12468
12476
|
'worldtime' => 1,
|
12469
12477
|
'worldtocamera' => 1,
|
12470
12478
|
'worldtondc' => 1,
|
12479
|
+
'wpgversion' => 1,
|
12471
12480
|
'wrapmodes' => 1,
|
12472
12481
|
'writername' => 1,
|
12473
12482
|
'writers' => 1,
|