exiftool_vendored 12.60.0 → 12.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|