exiftool_vendored 12.60.0 → 12.61.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 +23 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +2 -2
- data/bin/exiftool +54 -29
- 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 +15 -6
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +51 -21
- data/bin/lib/Image/ExifTool/Sony.pm +16 -10
- data/bin/lib/Image/ExifTool/TagNames.pod +1 -0
- data/bin/lib/Image/ExifTool/WritePDF.pl +7 -8
- data/bin/lib/Image/ExifTool/XMP.pm +13 -4
- data/bin/lib/Image/ExifTool.pm +62 -28
- data/bin/perl-Image-ExifTool.spec +1 -1
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e42c8004f68374320f592b26a0d8ceaa0d44e09331c9be1f66986d2fe94ad7d0
|
4
|
+
data.tar.gz: eab311e1d2c27c522ed174ae054adc3d44e31c91992fdacbb6c6fb02e965da20
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27e28a24360bd3651900c9db4b30ddff5517d777a8d6fa9723b80e758b71947697ca80e2149107be7ed6aac3c8b9ae37364d16126ddb2ee1a6c8aeaf8034e11a
|
7
|
+
data.tar.gz: 4845253fe922519e454c45d5e35e89b75a242ddf21183de8a6f5a32417d5cf814280161e46d2c722934175b4293f83ee1b0a2878bc6ea1c6fbd139cd105a6b25
|
data/bin/Changes
CHANGED
@@ -7,6 +7,29 @@ RSS feed: https://exiftool.org/rss.xml
|
|
7
7
|
Note: The most recent production release is Version 12.60. (Other versions are
|
8
8
|
considered development releases, and are not uploaded to MetaCPAN.)
|
9
9
|
|
10
|
+
Apr. 24, 2023 - Version 12.61
|
11
|
+
|
12
|
+
- Added ImageDataMD5 support for J2C and JXL images
|
13
|
+
- Added support for PDF 2.0 (specification is finally freely available)
|
14
|
+
- Added ability to extract timed Accelerometer data from Azdome GS63H MP4
|
15
|
+
videos which don't contain GPS
|
16
|
+
- Added some new Sony lenses (thanks Jos Roost)
|
17
|
+
- Decode some new tags for the Sony ZV-E1 (thanks Jos Roost)
|
18
|
+
- Decode more tags for the Nikon Z30 (thanks Xavier)
|
19
|
+
- Enhanced -fileNUM option to allow tags from the main file to be used in the
|
20
|
+
file name string
|
21
|
+
- Validate sample offset and size when calculating ImageDataMD5 for MP4 videos
|
22
|
+
(note: may change ImageDataMD5 value for videos where audio data runs past
|
23
|
+
end of media data)
|
24
|
+
- Return error when attempting to write a fragmented JXL file
|
25
|
+
- Improved robustness for determining image size for corrupted JPEG
|
26
|
+
- Patched to allow Insta360 GPS records of unexpected length and tweaked
|
27
|
+
verification algorithm to determine validity of these records
|
28
|
+
- Fixed bug introduced in 12.57 where -progress:%f gave runtime warnings
|
29
|
+
- Fixed "--" option to ignore subsequent -common_args option
|
30
|
+
- Fixed incorrect ImageDataMD5 for Sony A100 ARW images
|
31
|
+
- Fixed problem reading new XMP-et:OriginalImageMD5 tag
|
32
|
+
|
10
33
|
Apr. 5, 2023 - Version 12.60 (production release)
|
11
34
|
|
12
35
|
- Added a new Sony FileFormat value
|
data/bin/META.json
CHANGED
data/bin/META.yml
CHANGED
data/bin/README
CHANGED
@@ -107,8 +107,8 @@ your home directory, then you would type the following commands in a
|
|
107
107
|
terminal window to extract and run ExifTool:
|
108
108
|
|
109
109
|
cd ~/Desktop
|
110
|
-
gzip -dc Image-ExifTool-12.
|
111
|
-
cd Image-ExifTool-12.
|
110
|
+
gzip -dc Image-ExifTool-12.61.tar.gz | tar -xf -
|
111
|
+
cd Image-ExifTool-12.61
|
112
112
|
./exiftool t/images/ExifTool.jpg
|
113
113
|
|
114
114
|
Note: These commands extract meta information from one of the test images.
|
data/bin/exiftool
CHANGED
@@ -11,7 +11,7 @@ use strict;
|
|
11
11
|
use warnings;
|
12
12
|
require 5.004;
|
13
13
|
|
14
|
-
my $version = '12.
|
14
|
+
my $version = '12.61';
|
15
15
|
|
16
16
|
# add our 'lib' directory to the include list BEFORE 'use Image::ExifTool'
|
17
17
|
BEGIN {
|
@@ -365,13 +365,14 @@ sub Cleanup() {
|
|
365
365
|
|
366
366
|
# isolate arguments common to all commands
|
367
367
|
if (grep /^-common_args$/i, @ARGV) {
|
368
|
-
my (@newArgs, $common);
|
368
|
+
my (@newArgs, $common, $end);
|
369
369
|
foreach (@ARGV) {
|
370
|
-
if (/^-common_args$/i) {
|
370
|
+
if (/^-common_args$/i and not $end) {
|
371
371
|
$common = 1;
|
372
372
|
} elsif ($common) {
|
373
373
|
push @commonArgs, $_;
|
374
374
|
} else {
|
375
|
+
$end = 1 if $_ eq '--';
|
375
376
|
push @newArgs, $_;
|
376
377
|
}
|
377
378
|
}
|
@@ -1951,23 +1952,31 @@ sub GetImageInfo($$)
|
|
1951
1952
|
my (@foundTags, $info, $file, $ind, $g8);
|
1952
1953
|
|
1953
1954
|
# set window title for this file if necessary
|
1954
|
-
if (defined $windowTitle
|
1955
|
-
|
1956
|
-
|
1957
|
-
|
1958
|
-
|
1959
|
-
|
1960
|
-
|
1961
|
-
|
1962
|
-
|
1963
|
-
|
1964
|
-
|
1965
|
-
|
1966
|
-
|
1967
|
-
|
1968
|
-
|
1969
|
-
|
1970
|
-
|
1955
|
+
if (defined $windowTitle) {
|
1956
|
+
if ($progressCount >= $progressNext) {
|
1957
|
+
my $prog = $progressMax ? "$progressCount/$progressMax" : '0/0';
|
1958
|
+
my $title = $windowTitle;
|
1959
|
+
my ($num, $denom) = split '/', $prog;
|
1960
|
+
my $frac = $num / ($denom || 1);
|
1961
|
+
my $n = $title =~ s/%(\d+)b/%b/ ? $1 : 20; # length of bar
|
1962
|
+
my $bar = int($frac * $n + 0.5);
|
1963
|
+
my %lkup = (
|
1964
|
+
b => ('I' x $bar) . ('.' x ($n - $bar)),
|
1965
|
+
f => $orig,
|
1966
|
+
p => int(100 * $frac + 0.5),
|
1967
|
+
r => $prog,
|
1968
|
+
'%'=> '%',
|
1969
|
+
);
|
1970
|
+
$title =~ s/%([%bfpr])/$lkup{$1}/eg;
|
1971
|
+
SetWindowTitle($title);
|
1972
|
+
if (defined $progressMax) {
|
1973
|
+
undef $progressNext;
|
1974
|
+
} else {
|
1975
|
+
$progressNext += $progressIncr;
|
1976
|
+
}
|
1977
|
+
}
|
1978
|
+
# ($progressMax is not defined for "-progress:%f")
|
1979
|
+
++$progressCount unless defined $progressMax;
|
1971
1980
|
}
|
1972
1981
|
unless (length $orig or $outOpt) {
|
1973
1982
|
Warn qq(Error: Zero-length file name - ""\n);
|
@@ -1993,7 +2002,11 @@ sub GetImageInfo($$)
|
|
1993
2002
|
}
|
1994
2003
|
# set alternate file names
|
1995
2004
|
foreach $g8 (sort keys %altFile) {
|
1996
|
-
my $altName =
|
2005
|
+
my $altName = $orig;
|
2006
|
+
# must double any '$' symbols in the original file name because
|
2007
|
+
# they are used for tag names in a -fileNUM argument
|
2008
|
+
$altName =~ s/\$/\$\$/g;
|
2009
|
+
$altName = FilenameSPrintf($altFile{$g8}, $altName);
|
1997
2010
|
$et->SetAlternateFile($g8, $altName);
|
1998
2011
|
}
|
1999
2012
|
|
@@ -2536,6 +2549,7 @@ TAG: foreach $tag (@foundTags) {
|
|
2536
2549
|
$xtra .= " et:table='${table}'";
|
2537
2550
|
$xtra .= " et:index='${index}'" if defined $index;
|
2538
2551
|
}
|
2552
|
+
# Note: New $xtra attributes must be added to %ignoreEtProp in XMP.pm!
|
2539
2553
|
my $lastVal = $val;
|
2540
2554
|
for ($valNum=0; $valNum<2; ++$valNum) {
|
2541
2555
|
$val = FormatXML($val, $ind, $group);
|
@@ -3700,7 +3714,7 @@ sub ProcessFiles($;$)
|
|
3700
3714
|
if (defined $progressMax) {
|
3701
3715
|
unless (defined $progressNext) {
|
3702
3716
|
$progressNext = $progressCount + $progressIncr;
|
3703
|
-
$progressNext -= $progressNext % $progressIncr;
|
3717
|
+
$progressNext -= $progressNext % $progressIncr; # (show even multiples)
|
3704
3718
|
$progressNext = $progressMax if $progressNext > $progressMax;
|
3705
3719
|
}
|
3706
3720
|
++$progressCount;
|
@@ -4479,7 +4493,7 @@ sub Progress($$)
|
|
4479
4493
|
my ($file, $msg) = @_;
|
4480
4494
|
if (defined $progStr) {
|
4481
4495
|
print $file $msg, $progStr, "\n";
|
4482
|
-
undef $progressNext;
|
4496
|
+
undef $progressNext if defined $progressMax;
|
4483
4497
|
}
|
4484
4498
|
}
|
4485
4499
|
|
@@ -4669,7 +4683,7 @@ L<Tag operations|/Tag operations>
|
|
4669
4683
|
-TAG or --TAG Extract or exclude specified tag
|
4670
4684
|
-TAG[+-^]=[VALUE] Write new value for tag
|
4671
4685
|
-TAG[+-]<=DATFILE Write tag value from contents of file
|
4672
|
-
-TAG[+-]<SRCTAG
|
4686
|
+
-[+]TAG[+-]<SRCTAG Copy tag value (see -tagsFromFile)
|
4673
4687
|
|
4674
4688
|
-tagsFromFile SRCFILE Copy tag values from file
|
4675
4689
|
-x TAG (-exclude) Exclude specified tag
|
@@ -5541,7 +5555,7 @@ with this command:
|
|
5541
5555
|
|
5542
5556
|
produces output like this:
|
5543
5557
|
|
5544
|
-
-- Generated by ExifTool 12.
|
5558
|
+
-- Generated by ExifTool 12.61 --
|
5545
5559
|
File: a.jpg - 2003:10:31 15:44:19
|
5546
5560
|
(f/5.6, 1/60s, ISO 100)
|
5547
5561
|
File: b.jpg - 2006:05:23 11:57:38
|
@@ -6544,11 +6558,22 @@ option no longer suppresses the output "{readyNUM}" message.
|
|
6544
6558
|
|
6545
6559
|
=item B<-file>I<NUM> I<ALTFILE>
|
6546
6560
|
|
6547
|
-
Read tags from an alternate source file.
|
6561
|
+
Read tags from an alternate source file. Among other things, this allows
|
6562
|
+
tags from different files to be compared and combined using the B<-if> and
|
6563
|
+
B<-p> options. Tags from alternate files are accessed via the corresponding
|
6548
6564
|
family 8 group name (eg. C<File1:TAG> for the B<-file1> option, C<File2:TAG>
|
6549
|
-
for B<-file2>, etc). I<ALTFILE> may contain filename formatting codes
|
6550
|
-
|
6551
|
-
|
6565
|
+
for B<-file2>, etc). I<ALTFILE> may contain filename formatting codes like
|
6566
|
+
the B<-w> option (%d, %f, etc) , and/or tag names with a leading C<$> symbol
|
6567
|
+
in the same way as the B<-p> option (so any other dollar symbol in the file
|
6568
|
+
name must be doubled, eg. C<money$$.jpg>). For example, assuming that the
|
6569
|
+
OriginalFileName tag has been set in the edited file, a command to copy
|
6570
|
+
Rights from the original file could look like this:
|
6571
|
+
|
6572
|
+
exiftool -file1 '$originalfilename' '-rights<file1:rights' edited.jpg
|
6573
|
+
|
6574
|
+
Tag names in a B<-fileNUM> argument may access any tag from the original
|
6575
|
+
file except for Composite tags, and any tag from earlier (alphabetically
|
6576
|
+
sorted) B<-fileNUM> options (including Composite tags).
|
6552
6577
|
|
6553
6578
|
=item B<-list_dir>
|
6554
6579
|
|
@@ -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);
|
@@ -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' } },
|
@@ -20827,6 +20827,7 @@ WX350/WX500, ILCE-1/7/7C/7R/7S/7M2/7M3/7RM2/7RM3/7RM4/7SM2/7SM3/9/9M2/5000/
|
|
20827
20827
|
|
20828
20828
|
Index1 Tag Name Writable
|
20829
20829
|
------ -------- --------
|
20830
|
+
994 ISOInfo Sony ISOInfo
|
20830
20831
|
1102 ISOInfo Sony ISOInfo
|
20831
20832
|
1176 ISOInfo Sony ISOInfo
|
20832
20833
|
1181 ISOInfo Sony ISOInfo
|
@@ -23,7 +23,7 @@ my $beginComment = '%BeginExifToolUpdate';
|
|
23
23
|
my $endComment = '%EndExifToolUpdate ';
|
24
24
|
|
25
25
|
my $keyExt; # crypt key extension
|
26
|
-
my $pdfVer; # version of PDF file we are
|
26
|
+
my $pdfVer; # version of PDF file we are writing (highest Version in Root dictionaries)
|
27
27
|
|
28
28
|
# internal tags used in dictionary objects
|
29
29
|
my %myDictTags = (
|
@@ -297,15 +297,11 @@ sub WritePDF($$)
|
|
297
297
|
$$newTool{PDF_CAPTURE} = \%capture;
|
298
298
|
my $info = $newTool->ImageInfo($raf, 'XMP', 'PDF:*', 'Error', 'Warning');
|
299
299
|
# not a valid PDF file unless we got a version number
|
300
|
-
|
301
|
-
my $vers = $newTool->GetInfo('PDF:PDFVersion');
|
302
|
-
# take highest version number if multiple versions in an incremental save
|
303
|
-
($pdfVer) = sort { $b <=> $a } values %$vers;
|
300
|
+
$pdfVer = $$newTool{PDFVersion};
|
304
301
|
$pdfVer or $et->Error('Missing PDF:PDFVersion'), return 0;
|
305
302
|
# check version number
|
306
|
-
if ($pdfVer >
|
307
|
-
$et->
|
308
|
-
# (so writing by ExifTool is based on trial and error)
|
303
|
+
if ($pdfVer > 2.0) {
|
304
|
+
$et->Error("Writing PDF $pdfVer is untested", 1) and return 0;
|
309
305
|
}
|
310
306
|
# fail if we had any serious errors while extracting information
|
311
307
|
if ($capture{Error} or $$info{Error}) {
|
@@ -412,6 +408,9 @@ sub WritePDF($$)
|
|
412
408
|
my $tagID;
|
413
409
|
foreach $tagID (sort keys %$newTags) {
|
414
410
|
my $tagInfo = $$newTags{$tagID};
|
411
|
+
if ($pdfVer >= 2.0 and not $$tagInfo{PDF2}) {
|
412
|
+
next if $et->Warn("Writing PDF:$$tagInfo{Name} is deprecated for PDF 2.0 documents",2);
|
413
|
+
}
|
415
414
|
my $nvHash = $et->GetNewValueHash($tagInfo);
|
416
415
|
my (@vals, $deleted);
|
417
416
|
my $tag = $$tagInfo{Name};
|
@@ -248,7 +248,11 @@ my %boolConv = (
|
|
248
248
|
|
249
249
|
# XMP namespaces which we don't want to contribute to generated EXIF tag names
|
250
250
|
# (Note: namespaces with non-standard prefixes aren't currently ignored)
|
251
|
-
my %ignoreNamespace = ( 'x'=>1, rdf=>1, xmlns=>1, xml=>1, svg=>1,
|
251
|
+
my %ignoreNamespace = ( 'x'=>1, rdf=>1, xmlns=>1, xml=>1, svg=>1, office=>1 );
|
252
|
+
|
253
|
+
# ExifTool properties that don't generate tag names (et:tagid is historic)
|
254
|
+
my %ignoreEtProp = ( 'et:desc'=>1, 'et:prt'=>1, 'et:val'=>1 , 'et:id'=>1, 'et:tagid'=>1,
|
255
|
+
'et:toolkit'=>1, 'et:table'=>1, 'et:index'=>1 );
|
252
256
|
|
253
257
|
# XMP properties to ignore (set dynamically via dirInfo IgnoreProp)
|
254
258
|
my %ignoreProp;
|
@@ -2850,7 +2854,7 @@ sub GetXMPTagID($;$$)
|
|
2850
2854
|
# split name into namespace and property name
|
2851
2855
|
# (Note: namespace can be '' for property qualifiers)
|
2852
2856
|
my ($ns, $nm) = ($prop =~ /(.*?):(.*)/) ? ($1, $2) : ('', $prop);
|
2853
|
-
if ($ignoreNamespace{$ns} or $ignoreProp{$prop}) {
|
2857
|
+
if ($ignoreNamespace{$ns} or $ignoreProp{$prop} or $ignoreEtProp{$prop}) {
|
2854
2858
|
# special case: don't ignore rdf numbered items
|
2855
2859
|
# (not technically allowed in XMP, but used in RDF/XML)
|
2856
2860
|
unless ($prop =~ /^rdf:(_\d+)$/) {
|
@@ -3420,7 +3424,10 @@ NoLoop:
|
|
3420
3424
|
my %grps = ( 0 => $1, 1 => $2 );
|
3421
3425
|
# apply a little magic to recover original group names
|
3422
3426
|
# from this exiftool-written RDF/XML file
|
3423
|
-
if ($grps{1}
|
3427
|
+
if ($grps{1} eq 'System') {
|
3428
|
+
$grps{1} = 'XML-System';
|
3429
|
+
$grps{0} = 'XML';
|
3430
|
+
} elsif ($grps{1} =~ /^\d/) {
|
3424
3431
|
# URI's with only family 0 are internal tags from the source file,
|
3425
3432
|
# so change the group name to avoid confusion with tags from this file
|
3426
3433
|
$grps{1} = "XML-$grps{0}";
|
@@ -3888,7 +3895,9 @@ sub ParseXMPElement($$$;$$$$)
|
|
3888
3895
|
}
|
3889
3896
|
}
|
3890
3897
|
my $shortVal = $attrs{$shortName};
|
3891
|
-
|
3898
|
+
# Note: $prop is the containing property in this loop (not the shorthand property)
|
3899
|
+
# so $ignoreProp ignores all attributes of the ignored property
|
3900
|
+
if ($ignoreNamespace{$ns} or $ignoreProp{$prop} or $ignoreEtProp{$propName}) {
|
3892
3901
|
$ignored = $propName;
|
3893
3902
|
# handle special attributes (extract as tags only once if not empty)
|
3894
3903
|
if (ref $recognizedAttrs{$propName} and $shortVal) {
|
data/bin/lib/Image/ExifTool.pm
CHANGED
@@ -29,7 +29,7 @@ use vars qw($VERSION $RELEASE @ISA @EXPORT_OK %EXPORT_TAGS $AUTOLOAD @fileTypes
|
|
29
29
|
%jpegMarker %specialTags %fileTypeLookup $testLen $exeDir
|
30
30
|
%static_vars);
|
31
31
|
|
32
|
-
$VERSION = '12.
|
32
|
+
$VERSION = '12.61';
|
33
33
|
$RELEASE = '';
|
34
34
|
@ISA = qw(Exporter);
|
35
35
|
%EXPORT_TAGS = (
|
@@ -1826,10 +1826,10 @@ my %systemTagsNotes = (
|
|
1826
1826
|
ImageDataMD5 => {
|
1827
1827
|
Notes => q{
|
1828
1828
|
MD5 of image data. Generated only if specifically requested for JPEG and
|
1829
|
-
TIFF-based images, PNG, CRW, CR3, MRW, RAF, X3F and AVIF images,
|
1830
|
-
videos, and some RIFF-based files. The MD5 includes the main image
|
1831
|
-
plus JpgFromRaw/OtherImage for some formats, but does not include
|
1832
|
-
ThumbnailImage or PreviewImage. Includes video and audio data for MOV/MP4.
|
1829
|
+
TIFF-based images, PNG, CRW, CR3, MRW, RAF, X3F, JP2, JXL and AVIF images,
|
1830
|
+
MOV/MP4 videos, and some RIFF-based files. The MD5 includes the main image
|
1831
|
+
data, plus JpgFromRaw/OtherImage for some formats, but does not include
|
1832
|
+
ThumbnailImage or PreviewImage. Includes video and audio data for MOV/MP4.
|
1833
1833
|
The L<XMP-et:OriginalImageMD5 tag|XMP.html#ExifTool> provides a place to
|
1834
1834
|
store these values in the file.
|
1835
1835
|
},
|
@@ -2503,23 +2503,6 @@ sub ExtractInfo($;@)
|
|
2503
2503
|
}
|
2504
2504
|
}
|
2505
2505
|
++$$self{FILE_SEQUENCE}; # count files read
|
2506
|
-
# extract information from alternate files if necessary
|
2507
|
-
my ($g8, $altExifTool);
|
2508
|
-
foreach $g8 (keys %{$$self{ALT_EXIFTOOL}}) {
|
2509
|
-
$altExifTool = $$self{ALT_EXIFTOOL}{$g8};
|
2510
|
-
next if $$altExifTool{DID_EXTRACT}; # avoid extracting twice
|
2511
|
-
$$altExifTool{OPTIONS} = $$self{OPTIONS};
|
2512
|
-
$$altExifTool{GLOBAL_TIME_OFFSET} = $$self{GLOBAL_TIME_OFFSET};
|
2513
|
-
$$altExifTool{REQ_TAG_LOOKUP} = $$self{REQ_TAG_LOOKUP};
|
2514
|
-
$altExifTool->ExtractInfo($$altExifTool{ALT_FILE});
|
2515
|
-
# set family 8 group name for all tags
|
2516
|
-
foreach (keys %{$$altExifTool{VALUE}}) {
|
2517
|
-
my $ex = $$altExifTool{TAG_EXTRA}{$_};
|
2518
|
-
$ex or $ex = $$altExifTool{TAG_EXTRA}{$_} = { };
|
2519
|
-
$$ex{G8} = $g8;
|
2520
|
-
}
|
2521
|
-
$$altExifTool{DID_EXTRACT} = 1;
|
2522
|
-
}
|
2523
2506
|
}
|
2524
2507
|
|
2525
2508
|
my $filename = $$self{FILENAME}; # image file name ('' if already open)
|
@@ -2661,6 +2644,7 @@ sub ExtractInfo($;@)
|
|
2661
2644
|
if ($isDir or (defined $stat[2] and ($stat[2] & 0170000) == 0040000)) {
|
2662
2645
|
$self->FoundTag('FileType', 'DIR');
|
2663
2646
|
$self->FoundTag('FileTypeExtension', '');
|
2647
|
+
$self->ExtractAltInfo();
|
2664
2648
|
$self->BuildCompositeTags() if $$options{Composite};
|
2665
2649
|
$raf->Close() if $raf;
|
2666
2650
|
return 1;
|
@@ -2679,6 +2663,7 @@ sub ExtractInfo($;@)
|
|
2679
2663
|
} else {
|
2680
2664
|
$self->Error('Unknown file type');
|
2681
2665
|
}
|
2666
|
+
$self->ExtractAltInfo();
|
2682
2667
|
$self->BuildCompositeTags() if $fast == 4 and $$options{Composite};
|
2683
2668
|
last; # don't read the file
|
2684
2669
|
}
|
@@ -2845,6 +2830,7 @@ sub ExtractInfo($;@)
|
|
2845
2830
|
}
|
2846
2831
|
unless ($reEntry) {
|
2847
2832
|
$$self{PATH} = [ ]; # reset PATH
|
2833
|
+
$self->ExtractAltInfo();
|
2848
2834
|
# calculate Composite tags
|
2849
2835
|
$self->BuildCompositeTags() if $$options{Composite};
|
2850
2836
|
# do our HTML dump if requested
|
@@ -4067,6 +4053,42 @@ sub CombineInfo($;@)
|
|
4067
4053
|
return \%combinedInfo;
|
4068
4054
|
}
|
4069
4055
|
|
4056
|
+
#------------------------------------------------------------------------------
|
4057
|
+
# Read metadata from alternate files
|
4058
|
+
# Inputs: 0) ExifTool ref
|
4059
|
+
# Notes: This is called after reading the main file so the tags are available
|
4060
|
+
# for being used in the file name, but before building Composite tags
|
4061
|
+
# so tags from the alternate files may be used in the Composite tags
|
4062
|
+
sub ExtractAltInfo($)
|
4063
|
+
{
|
4064
|
+
my $self = shift;
|
4065
|
+
# extract information from alternate files if necessary
|
4066
|
+
my ($g8, $altExifTool);
|
4067
|
+
foreach $g8 (sort keys %{$$self{ALT_EXIFTOOL}}) {
|
4068
|
+
$altExifTool = $$self{ALT_EXIFTOOL}{$g8};
|
4069
|
+
next if $$altExifTool{DID_EXTRACT}; # avoid extracting twice
|
4070
|
+
$$altExifTool{OPTIONS} = $$self{OPTIONS};
|
4071
|
+
$$altExifTool{GLOBAL_TIME_OFFSET} = $$self{GLOBAL_TIME_OFFSET};
|
4072
|
+
$$altExifTool{REQ_TAG_LOOKUP} = $$self{REQ_TAG_LOOKUP};
|
4073
|
+
my $fileName = $$altExifTool{ALT_FILE};
|
4074
|
+
# allow tags from the main file to be used in the alternate file names
|
4075
|
+
# (eg. -file1 '$originalfilename')
|
4076
|
+
if ($fileName =~ /\$/) {
|
4077
|
+
my @tags = reverse sort keys %{$$self{VALUE}};
|
4078
|
+
$fileName = $self->InsertTagValues(\@tags, $fileName, 'Warn');
|
4079
|
+
next unless defined $fileName;
|
4080
|
+
}
|
4081
|
+
$altExifTool->ExtractInfo($fileName);
|
4082
|
+
# set family 8 group name for all tags
|
4083
|
+
foreach (keys %{$$altExifTool{VALUE}}) {
|
4084
|
+
my $ex = $$altExifTool{TAG_EXTRA}{$_};
|
4085
|
+
$ex or $ex = $$altExifTool{TAG_EXTRA}{$_} = { };
|
4086
|
+
$$ex{G8} = $g8;
|
4087
|
+
}
|
4088
|
+
$$altExifTool{DID_EXTRACT} = 1;
|
4089
|
+
}
|
4090
|
+
}
|
4091
|
+
|
4070
4092
|
#------------------------------------------------------------------------------
|
4071
4093
|
# Get tag table name
|
4072
4094
|
# Inputs: 0) ExifTool object reference, 1) tag key
|
@@ -6432,12 +6454,12 @@ sub ProcessJPEG($$)
|
|
6432
6454
|
my $htmlDump = $$self{HTML_DUMP};
|
6433
6455
|
my %dumpParms = ( Out => $out );
|
6434
6456
|
my ($ch, $s, $length, $md5, $md5size);
|
6435
|
-
my ($success, $wantTrailer, $trailInfo, $foundSOS, %jumbfChunk);
|
6457
|
+
my ($success, $wantTrailer, $trailInfo, $foundSOS, $gotSize, %jumbfChunk);
|
6436
6458
|
my (@iccChunk, $iccChunkCount, $iccChunksTotal, @flirChunk, $flirCount, $flirTotal);
|
6437
6459
|
my ($preview, $scalado, @dqt, $subSampling, $dumpEnd, %extendedXMP);
|
6438
6460
|
|
6439
|
-
# get pointer to MD5 object if it exists and we are the top-level JPEG
|
6440
|
-
if ($$self{FILE_TYPE}
|
6461
|
+
# get pointer to MD5 object if it exists and we are the top-level JPEG or JP2
|
6462
|
+
if ($$self{FILE_TYPE} =~ /^(JPEG|JP2)$/ and not $$self{DOC_NUM}) {
|
6441
6463
|
$md5 = $$self{ImageDataMD5};
|
6442
6464
|
$md5size = 0;
|
6443
6465
|
}
|
@@ -6561,7 +6583,8 @@ sub ProcessJPEG($$)
|
|
6561
6583
|
$self->HDump($segPos-4, $length+4, "[JPEG $markerName]", undef, 0x08);
|
6562
6584
|
$dumpEnd = $segPos + $length;
|
6563
6585
|
}
|
6564
|
-
next
|
6586
|
+
next if $length < 6 or $gotSize;
|
6587
|
+
$gotSize = 1; # (ignore subsequent SOF segments in probably corrupted JPEG)
|
6565
6588
|
# extract some useful information
|
6566
6589
|
my ($p, $h, $w, $n) = unpack('Cn2C', $$segDataPt);
|
6567
6590
|
my $sof = GetTagTable('Image::ExifTool::JPEG::SOF');
|
@@ -6751,6 +6774,11 @@ sub ProcessJPEG($$)
|
|
6751
6774
|
pop @$path;
|
6752
6775
|
$verbose and print $out "JPEG SOD\n";
|
6753
6776
|
$success = 1;
|
6777
|
+
if ($md5 and $$self{FILE_TYPE} eq 'JP2') {
|
6778
|
+
my $pos = $raf->Tell();
|
6779
|
+
$self->ImageDataMD5($raf, undef, 'SOD');
|
6780
|
+
$raf->Seek($pos, 0);
|
6781
|
+
}
|
6754
6782
|
next if $verbose > 2 or $htmlDump;
|
6755
6783
|
last; # all done parsing file
|
6756
6784
|
} elsif (defined $markerLenBytes{$marker}) {
|
@@ -7483,8 +7511,11 @@ sub ProcessJPEG($$)
|
|
7483
7511
|
}
|
7484
7512
|
} elsif ($marker == 0x51) { # SIZ (J2C)
|
7485
7513
|
my ($w, $h) = unpack('x2N2', $$segDataPt);
|
7486
|
-
|
7487
|
-
|
7514
|
+
unless ($gotSize) {
|
7515
|
+
$gotSize = 1;
|
7516
|
+
$self->FoundTag('ImageWidth', $w);
|
7517
|
+
$self->FoundTag('ImageHeight', $h);
|
7518
|
+
}
|
7488
7519
|
} elsif (($marker & 0xf0) != 0xe0) {
|
7489
7520
|
$dumpType = "$markerName segment";
|
7490
7521
|
$desc = "[JPEG $markerName]"; # (other known JPEG segments)
|
@@ -7824,6 +7855,9 @@ sub DoProcessTIFF($$;$)
|
|
7824
7855
|
if ($$self{TIFF_TYPE} eq 'TIFF') {
|
7825
7856
|
$self->FoundTag(PageCount => $$self{PageCount}) if $$self{MultiPage};
|
7826
7857
|
}
|
7858
|
+
if ($$self{ImageDataMD5} and $$self{A100DataOffset} and $raf->Seek($$self{A100DataOffset},0)) {
|
7859
|
+
$self->ImageDataMD5($raf, undef, 'A100');
|
7860
|
+
}
|
7827
7861
|
return 1;
|
7828
7862
|
}
|
7829
7863
|
#
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exiftool_vendored
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 12.
|
4
|
+
version: 12.61.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew McEachen
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
12
|
+
date: 2023-05-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: exiftool
|