exiftool-vendored.pl 12.62.0 → 12.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/Changes +76 -1
- package/bin/MANIFEST +4 -0
- package/bin/META.json +5 -3
- package/bin/META.yml +5 -3
- package/bin/Makefile.PL +7 -1
- package/bin/README +50 -46
- package/bin/config_files/guano.config +161 -0
- package/bin/exiftool +108 -75
- package/bin/lib/Image/ExifTool/7Z.pm +793 -0
- package/bin/lib/Image/ExifTool/Apple.pm +14 -7
- package/bin/lib/Image/ExifTool/BigTIFF.pm +8 -1
- package/bin/lib/Image/ExifTool/Canon.pm +4 -1
- package/bin/lib/Image/ExifTool/CanonRaw.pm +4 -4
- package/bin/lib/Image/ExifTool/CanonVRD.pm +4 -1
- package/bin/lib/Image/ExifTool/Exif.pm +31 -14
- package/bin/lib/Image/ExifTool/FlashPix.pm +8 -2
- package/bin/lib/Image/ExifTool/FujiFilm.pm +3 -3
- package/bin/lib/Image/ExifTool/GPS.pm +5 -2
- package/bin/lib/Image/ExifTool/Geotag.pm +4 -1
- package/bin/lib/Image/ExifTool/Jpeg2000.pm +226 -28
- package/bin/lib/Image/ExifTool/Lang/fr.pm +1467 -202
- package/bin/lib/Image/ExifTool/MPF.pm +2 -1
- package/bin/lib/Image/ExifTool/Matroska.pm +16 -1
- package/bin/lib/Image/ExifTool/MinoltaRaw.pm +2 -2
- package/bin/lib/Image/ExifTool/Nikon.pm +939 -31
- package/bin/lib/Image/ExifTool/NikonCustom.pm +874 -63
- package/bin/lib/Image/ExifTool/PDF.pm +23 -5
- package/bin/lib/Image/ExifTool/PLIST.pm +8 -1
- package/bin/lib/Image/ExifTool/PNG.pm +6 -6
- package/bin/lib/Image/ExifTool/PhaseOne.pm +5 -5
- package/bin/lib/Image/ExifTool/QuickTime.pm +91 -30
- package/bin/lib/Image/ExifTool/QuickTimeStream.pl +20 -19
- package/bin/lib/Image/ExifTool/README +2 -2
- package/bin/lib/Image/ExifTool/RIFF.pm +11 -9
- package/bin/lib/Image/ExifTool/Samsung.pm +227 -227
- package/bin/lib/Image/ExifTool/Shortcuts.pm +2 -1
- package/bin/lib/Image/ExifTool/SigmaRaw.pm +4 -4
- package/bin/lib/Image/ExifTool/Sony.pm +229 -30
- package/bin/lib/Image/ExifTool/TagLookup.pm +4757 -4633
- package/bin/lib/Image/ExifTool/TagNames.pod +706 -18
- package/bin/lib/Image/ExifTool/Validate.pm +17 -1
- package/bin/lib/Image/ExifTool/WriteExif.pl +9 -7
- package/bin/lib/Image/ExifTool/WriteQuickTime.pl +21 -9
- package/bin/lib/Image/ExifTool/WriteXMP.pl +2 -2
- package/bin/lib/Image/ExifTool/Writer.pl +35 -12
- package/bin/lib/Image/ExifTool/XMP.pm +14 -2
- package/bin/lib/Image/ExifTool/XMP2.pl +32 -0
- package/bin/lib/Image/ExifTool/XMPStruct.pl +96 -28
- package/bin/lib/Image/ExifTool/ZIP.pm +5 -5
- package/bin/lib/Image/ExifTool.pm +176 -128
- package/bin/lib/Image/ExifTool.pod +109 -53
- package/bin/perl-Image-ExifTool.spec +44 -44
- package/bin/pp_build_exe.args +7 -4
- package/package.json +3 -3
|
@@ -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.57';
|
|
25
25
|
|
|
26
26
|
sub FetchObject($$$$);
|
|
27
27
|
sub ExtractObject($$;$$);
|
|
@@ -109,7 +109,18 @@ my %supportedFilter = (
|
|
|
109
109
|
Title => { },
|
|
110
110
|
Author => { Groups => { 2 => 'Author' } },
|
|
111
111
|
Subject => { },
|
|
112
|
-
Keywords => {
|
|
112
|
+
Keywords => {
|
|
113
|
+
List => 'string', # this is a string list
|
|
114
|
+
Notes => q{
|
|
115
|
+
stored as a string but treated as a comma- or semicolon-separated list of
|
|
116
|
+
items when reading if the string contains commas or semicolons, whichever is
|
|
117
|
+
more numerous, otherwise it is treated a space-separated list of items.
|
|
118
|
+
Written as a comma-separated list. The list behaviour may be defeated by
|
|
119
|
+
setting the API NoPDFList option. Note that the corresponding
|
|
120
|
+
XMP-pdf:Keywords tag is not treated as a list, so the NoPDFList option
|
|
121
|
+
should be used when copying between these two.
|
|
122
|
+
},
|
|
123
|
+
},
|
|
113
124
|
Creator => { },
|
|
114
125
|
Producer => { },
|
|
115
126
|
CreationDate => {
|
|
@@ -1754,6 +1765,7 @@ sub ExpandArray($)
|
|
|
1754
1765
|
# 4) nesting depth, 5) dictionary capture type
|
|
1755
1766
|
sub ProcessDict($$$$;$$)
|
|
1756
1767
|
{
|
|
1768
|
+
local $_;
|
|
1757
1769
|
my ($et, $tagTablePtr, $dict, $xref, $nesting, $type) = @_;
|
|
1758
1770
|
my $verbose = $et->Options('Verbose');
|
|
1759
1771
|
my $unknown = $$tagTablePtr{EXTRACT_UNKNOWN};
|
|
@@ -2017,10 +2029,16 @@ sub ProcessDict($$$$;$$)
|
|
|
2017
2029
|
}
|
|
2018
2030
|
if ($$tagInfo{List} and not $$et{OPTIONS}{NoPDFList}) {
|
|
2019
2031
|
# separate tokens in comma or whitespace delimited lists
|
|
2020
|
-
my
|
|
2021
|
-
|
|
2022
|
-
|
|
2032
|
+
my $comma = $val =~ tr/,/,/;
|
|
2033
|
+
my $semi = $val =~ tr/;/;/;
|
|
2034
|
+
my $split;
|
|
2035
|
+
if ($comma or $semi) {
|
|
2036
|
+
$split = $comma > $semi ? ',+\\s*' : ';+\\s*';
|
|
2037
|
+
} else {
|
|
2038
|
+
$split = ' ';
|
|
2023
2039
|
}
|
|
2040
|
+
my @values = split $split, $val;
|
|
2041
|
+
$et->FoundTag($tagInfo, $_) foreach @values;
|
|
2024
2042
|
} else {
|
|
2025
2043
|
# a simple tag value
|
|
2026
2044
|
$et->FoundTag($tagInfo, $val);
|
|
@@ -21,7 +21,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
|
21
21
|
use Image::ExifTool::XMP;
|
|
22
22
|
use Image::ExifTool::GPS;
|
|
23
23
|
|
|
24
|
-
$VERSION = '1.
|
|
24
|
+
$VERSION = '1.11';
|
|
25
25
|
|
|
26
26
|
sub ExtractObject($$;$);
|
|
27
27
|
sub Get24u($$);
|
|
@@ -288,6 +288,12 @@ sub ExtractObject($$;$)
|
|
|
288
288
|
my $obj = ExtractObject($et, $plistInfo, $tag);
|
|
289
289
|
next if not defined $obj;
|
|
290
290
|
unless ($tagTablePtr) {
|
|
291
|
+
# make sure this is a valid structure field name
|
|
292
|
+
if (not defined $key or $key !~ /^[-_a-zA-Z0-9]+$/) {
|
|
293
|
+
$key = "Tag$i"; # (generate fake tag name if it had illegal characters)
|
|
294
|
+
} elsif ($key !~ /^[_a-zA-Z]/) {
|
|
295
|
+
$key = "_$key"; # (must begin with alpha or underline)
|
|
296
|
+
}
|
|
291
297
|
$$val{$key} = $obj if defined $obj;
|
|
292
298
|
next;
|
|
293
299
|
}
|
|
@@ -298,6 +304,7 @@ sub ExtractObject($$;$)
|
|
|
298
304
|
my $name = $tag;
|
|
299
305
|
$name =~ s/([^A-Za-z])([a-z])/$1\u$2/g; # capitalize words
|
|
300
306
|
$name =~ tr/-_a-zA-Z0-9//dc; # remove illegal characters
|
|
307
|
+
$name = "Tag$name" if length($name) < 2 or $name =~ /^[-0-9]/;
|
|
301
308
|
$tagInfo = { Name => ucfirst($name), List => 1 };
|
|
302
309
|
if ($$plistInfo{DateFormat}) {
|
|
303
310
|
$$tagInfo{Groups}{2} = 'Time';
|
|
@@ -36,7 +36,7 @@ use strict;
|
|
|
36
36
|
use vars qw($VERSION $AUTOLOAD %stdCase);
|
|
37
37
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
38
38
|
|
|
39
|
-
$VERSION = '1.
|
|
39
|
+
$VERSION = '1.64';
|
|
40
40
|
|
|
41
41
|
sub ProcessPNG_tEXt($$$);
|
|
42
42
|
sub ProcessPNG_iTXt($$$);
|
|
@@ -1374,7 +1374,7 @@ sub ProcessPNG($$)
|
|
|
1374
1374
|
my $datCount = 0;
|
|
1375
1375
|
my $datBytes = 0;
|
|
1376
1376
|
my $fastScan = $et->Options('FastScan');
|
|
1377
|
-
my $
|
|
1377
|
+
my $hash = $$et{ImageDataHash};
|
|
1378
1378
|
my ($n, $sig, $err, $hbuf, $dbuf, $cbuf);
|
|
1379
1379
|
my ($wasHdr, $wasEnd, $wasDat, $doTxt, @txtOffset);
|
|
1380
1380
|
|
|
@@ -1454,7 +1454,7 @@ sub ProcessPNG($$)
|
|
|
1454
1454
|
if ($datCount and $chunk ne $datChunk) {
|
|
1455
1455
|
my $s = $datCount > 1 ? 's' : '';
|
|
1456
1456
|
print $out "$fileType $datChunk ($datCount chunk$s, total $datBytes bytes)\n";
|
|
1457
|
-
print $out "$$et{INDENT}(
|
|
1457
|
+
print $out "$$et{INDENT}(ImageDataHash: $datBytes bytes of $datChunk data)\n" if $hash;
|
|
1458
1458
|
$datCount = $datBytes = 0;
|
|
1459
1459
|
}
|
|
1460
1460
|
}
|
|
@@ -1541,8 +1541,8 @@ sub ProcessPNG($$)
|
|
|
1541
1541
|
}
|
|
1542
1542
|
# skip over data chunks if possible/necessary
|
|
1543
1543
|
} elsif (not $validate or $len > $chunkSizeLimit) {
|
|
1544
|
-
if ($
|
|
1545
|
-
$et->
|
|
1544
|
+
if ($hash) {
|
|
1545
|
+
$et->ImageDataHash($raf, $len);
|
|
1546
1546
|
$raf->Read($cbuf, 4) == 4 or $et->Warn('Truncated data'), last;
|
|
1547
1547
|
} else {
|
|
1548
1548
|
$raf->Seek($len + 4, 1) or $et->Warn('Seek error'), last;
|
|
@@ -1565,7 +1565,7 @@ sub ProcessPNG($$)
|
|
|
1565
1565
|
$et->Warn("Corrupted $fileType image") unless $wasEnd;
|
|
1566
1566
|
last;
|
|
1567
1567
|
}
|
|
1568
|
-
$
|
|
1568
|
+
$hash->add($dbuf) if $hash and $datChunk; # add to hash if necessary
|
|
1569
1569
|
if ($verbose or $validate or ($outfile and not $fastScan)) {
|
|
1570
1570
|
# check CRC when in verbose mode (since we don't care about speed)
|
|
1571
1571
|
my $crc = CalculateCRC(\$hbuf, undef, 4);
|
|
@@ -15,7 +15,7 @@ use vars qw($VERSION);
|
|
|
15
15
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
16
16
|
use Image::ExifTool::Exif;
|
|
17
17
|
|
|
18
|
-
$VERSION = '1.
|
|
18
|
+
$VERSION = '1.09';
|
|
19
19
|
|
|
20
20
|
sub WritePhaseOne($$$);
|
|
21
21
|
sub ProcessPhaseOne($$$);
|
|
@@ -585,7 +585,7 @@ sub ProcessPhaseOne($$$)
|
|
|
585
585
|
my $dirLen = $$dirInfo{DirLen} || $$dirInfo{DataLen} - $dirStart;
|
|
586
586
|
my $binary = $et->Options('Binary');
|
|
587
587
|
my $verbose = $et->Options('Verbose');
|
|
588
|
-
my $
|
|
588
|
+
my $hash = $$et{ImageDataHash};
|
|
589
589
|
my $htmlDump = $$et{HTML_DUMP};
|
|
590
590
|
|
|
591
591
|
return 0 if $dirLen < 12;
|
|
@@ -678,16 +678,16 @@ sub ProcessPhaseOne($$$)
|
|
|
678
678
|
}
|
|
679
679
|
}
|
|
680
680
|
}
|
|
681
|
-
if ($
|
|
681
|
+
if ($hash and $tagInfo and $$tagInfo{IsImageData}) {
|
|
682
682
|
my ($pos, $len) = ($valuePtr, $size);
|
|
683
683
|
while ($len) {
|
|
684
684
|
my $n = $len > 65536 ? 65536 : $len;
|
|
685
685
|
my $tmp = substr($$dataPt, $pos, $n);
|
|
686
|
-
$
|
|
686
|
+
$hash->add($tmp);
|
|
687
687
|
$len -= $n;
|
|
688
688
|
$pos += $n;
|
|
689
689
|
}
|
|
690
|
-
$et->VPrint(0, "$$et{INDENT}(
|
|
690
|
+
$et->VPrint(0, "$$et{INDENT}(ImageDataHash: $size bytes of PhaseOne:$$tagInfo{Name})\n");
|
|
691
691
|
}
|
|
692
692
|
my %parms = (
|
|
693
693
|
DirName => $ifdType,
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
# 25) https://cconcolato.github.io/mp4ra/atoms.html
|
|
38
38
|
# 26) https://github.com/SamsungVR/android_upload_sdk/blob/master/SDKLib/src/main/java/com/samsung/msca/samsungvr/sdk/UserVideo.java
|
|
39
39
|
# 27) https://exiftool.org/forum/index.php?topic=11517.0
|
|
40
|
+
# 28) https://docs.mp3tag.de/mapping/
|
|
40
41
|
#------------------------------------------------------------------------------
|
|
41
42
|
|
|
42
43
|
package Image::ExifTool::QuickTime;
|
|
@@ -47,7 +48,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
|
47
48
|
use Image::ExifTool::Exif;
|
|
48
49
|
use Image::ExifTool::GPS;
|
|
49
50
|
|
|
50
|
-
$VERSION = '2.
|
|
51
|
+
$VERSION = '2.87';
|
|
51
52
|
|
|
52
53
|
sub ProcessMOV($$;$);
|
|
53
54
|
sub ProcessKeys($$$);
|
|
@@ -224,6 +225,9 @@ my %ftypLookup = (
|
|
|
224
225
|
'crx ' => 'Canon Raw (.CRX)', #PH (CR3 or CRM; use Canon CompressorVersion to decide)
|
|
225
226
|
);
|
|
226
227
|
|
|
228
|
+
# use extension to determine file type
|
|
229
|
+
my %useExt = ( GLV => 'MP4' );
|
|
230
|
+
|
|
227
231
|
# information for int32u date/time tags (time zero is Jan 1, 1904)
|
|
228
232
|
my %timeInfo = (
|
|
229
233
|
Notes => 'converted from UTC to local time if the QuickTimeUTC option is set',
|
|
@@ -447,8 +451,8 @@ my %dupDirOK = ( ipco => 1, '----' => 1 );
|
|
|
447
451
|
my %eeStd = ( stco => 'stbl', co64 => 'stbl', stsz => 'stbl', stz2 => 'stbl',
|
|
448
452
|
stsc => 'stbl', stts => 'stbl' );
|
|
449
453
|
|
|
450
|
-
# atoms required for generating
|
|
451
|
-
my %
|
|
454
|
+
# atoms required for generating ImageDataHash
|
|
455
|
+
my %hashBox = ( vide => { %eeStd }, soun => { %eeStd } );
|
|
452
456
|
|
|
453
457
|
# boxes and their containers for the various handler types that we want to save
|
|
454
458
|
# when the ExtractEmbedded is enabled (currently only the 'gps ' container name is
|
|
@@ -1006,7 +1010,8 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
1006
1010
|
0 => 'Monoscopic',
|
|
1007
1011
|
1 => 'Stereoscopic Top-Bottom',
|
|
1008
1012
|
2 => 'Stereoscopic Left-Right',
|
|
1009
|
-
3 => 'Stereoscopic Stereo-Custom',
|
|
1013
|
+
3 => 'Stereoscopic Stereo-Custom',
|
|
1014
|
+
4 => 'Stereoscopic Right-Left',
|
|
1010
1015
|
},
|
|
1011
1016
|
},
|
|
1012
1017
|
sv3d => {
|
|
@@ -2070,8 +2075,8 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
2070
2075
|
ValueConv => 'substr($val, 4)',
|
|
2071
2076
|
ValueConvInv => '"\0\0\0\x01$val"',
|
|
2072
2077
|
},
|
|
2073
|
-
# hmtp - "\0\0\0\x01"
|
|
2074
|
-
# vrin - "\0\0\0\x01" followed by 8 bytes of zero
|
|
2078
|
+
# hmtp - 412 bytes: "\0\0\0\x01" then maybe "\0\0\0\x64" and the rest zeros
|
|
2079
|
+
# vrin - 12 bytes: "\0\0\0\x01" followed by 8 bytes of zero
|
|
2075
2080
|
# ---- GoPro ---- (ref PH)
|
|
2076
2081
|
GoPr => 'GoProType', # (Hero3+)
|
|
2077
2082
|
FIRM => { Name => 'FirmwareVersion', Avoid => 1 }, # (Hero4)
|
|
@@ -2867,6 +2872,25 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
2867
2872
|
Name => 'AV1Configuration',
|
|
2868
2873
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::AV1Config' },
|
|
2869
2874
|
},
|
|
2875
|
+
clli => {
|
|
2876
|
+
Name => 'ContentLightLevel',
|
|
2877
|
+
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ContentLightLevel' },
|
|
2878
|
+
},
|
|
2879
|
+
# ref https://nokiatech.github.io/heif/technical.html
|
|
2880
|
+
# cclv - Content Color Volume
|
|
2881
|
+
# mdcv - Mastering Display Color Volume
|
|
2882
|
+
# rrtp - Required reference types
|
|
2883
|
+
# crtt - Creation time information
|
|
2884
|
+
# mdft - Modification time information
|
|
2885
|
+
# udes - User description
|
|
2886
|
+
# altt - Accessibility text
|
|
2887
|
+
# aebr - Auto exposure information
|
|
2888
|
+
# wbbr - White balance information
|
|
2889
|
+
# fobr - Focus information
|
|
2890
|
+
# afbr - Flash exposure information
|
|
2891
|
+
# dobr - Depth of field information
|
|
2892
|
+
# pano - Panorama information
|
|
2893
|
+
# iscl - Image Scaling
|
|
2870
2894
|
);
|
|
2871
2895
|
|
|
2872
2896
|
# ref https://aomediacodec.github.io/av1-spec/av1-spec.pdf
|
|
@@ -2901,8 +2925,8 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
2901
2925
|
1 => 'BT.709',
|
|
2902
2926
|
2 => 'Unspecified',
|
|
2903
2927
|
3 => 'For future use (3)',
|
|
2904
|
-
4 => 'BT.470 System M (historical)',
|
|
2905
|
-
5 => 'BT.470 System B, G (historical)',
|
|
2928
|
+
4 => 'BT.470 System M (historical)', # Gamma 2.2? (ref forum14960)
|
|
2929
|
+
5 => 'BT.470 System B, G (historical)', # Gamma 2.8? (ref forum14960)
|
|
2906
2930
|
6 => 'BT.601',
|
|
2907
2931
|
7 => 'SMPTE 240 M',
|
|
2908
2932
|
8 => 'Linear',
|
|
@@ -3128,6 +3152,16 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
3128
3152
|
},
|
|
3129
3153
|
);
|
|
3130
3154
|
|
|
3155
|
+
# ref https://android.googlesource.com/platform/frameworks/av/+/master/media/libstagefright/MPEG4Writer.cpp
|
|
3156
|
+
%Image::ExifTool::QuickTime::ContentLightLevel = (
|
|
3157
|
+
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
|
3158
|
+
GROUPS => { 2 => 'Video' },
|
|
3159
|
+
FIRST_ENTRY => 0,
|
|
3160
|
+
FORMAT => 'int16u',
|
|
3161
|
+
0 => 'MaxContentLightLevel',
|
|
3162
|
+
1 => 'MaxPicAverageLightLevel',
|
|
3163
|
+
);
|
|
3164
|
+
|
|
3131
3165
|
%Image::ExifTool::QuickTime::ItemRef = (
|
|
3132
3166
|
PROCESS_PROC => \&ProcessMOV,
|
|
3133
3167
|
WRITE_PROC => \&WriteQuickTime,
|
|
@@ -3363,8 +3397,9 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
3363
3397
|
},
|
|
3364
3398
|
albm => { Name => 'Album', Avoid => 1 }, #(ffmpeg source)
|
|
3365
3399
|
apID => 'AppleStoreAccount',
|
|
3366
|
-
atID => {
|
|
3367
|
-
|
|
3400
|
+
atID => {
|
|
3401
|
+
# (ref 10 called this AlbumTitleID or TVSeries)
|
|
3402
|
+
Name => 'ArtistID', #28 (or Track ID ref https://gist.github.com/maf654321/2b44c7b15d798f0c52ee)
|
|
3368
3403
|
Format => 'int32u',
|
|
3369
3404
|
Writable => 'int32s', #27
|
|
3370
3405
|
},
|
|
@@ -3375,6 +3410,7 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
3375
3410
|
Format => 'int32u',
|
|
3376
3411
|
Writable => 'int32s', #27
|
|
3377
3412
|
},
|
|
3413
|
+
cmID => 'ComposerID', #28 (need sample to get format)
|
|
3378
3414
|
cprt => { Name => 'Copyright', Groups => { 2 => 'Author' } },
|
|
3379
3415
|
dscp => { Name => 'Description', Avoid => 1 },
|
|
3380
3416
|
desc => { Name => 'Description', Avoid => 1 }, #7
|
|
@@ -6067,10 +6103,10 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
6067
6103
|
PrintConv => { 0 => 'No', 1 => 'Yes' },
|
|
6068
6104
|
},
|
|
6069
6105
|
perf => 'Performer',
|
|
6070
|
-
plID => {
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6106
|
+
plID => {
|
|
6107
|
+
# (ref 10 called this PlayListID or TVSeason)
|
|
6108
|
+
Name => 'AlbumID', #28
|
|
6109
|
+
Format => 'int64u',
|
|
6074
6110
|
Writable => 'int32s', #27
|
|
6075
6111
|
},
|
|
6076
6112
|
purd => 'PurchaseDate', #7
|
|
@@ -6532,6 +6568,7 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
6532
6568
|
'rating.user' => 'UserRating', # (Canon ELPH 510 HS)
|
|
6533
6569
|
'collection.user' => 'UserCollection', #22
|
|
6534
6570
|
'Encoded_With' => 'EncodedWith',
|
|
6571
|
+
'content.identifier' => 'ContentIdentifier', #forum14874
|
|
6535
6572
|
#
|
|
6536
6573
|
# the following tags aren't in the com.apple.quicktime namespace:
|
|
6537
6574
|
#
|
|
@@ -7187,7 +7224,7 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
7187
7224
|
#
|
|
7188
7225
|
# AudioFormat Offset Child atoms
|
|
7189
7226
|
# ----------- ------ ----------------
|
|
7190
|
-
# mp4a 52 * wave, chan, esds, SA3D(Insta360 spherical video params?,also GoPro Max)
|
|
7227
|
+
# mp4a 52 * wave, chan, esds, SA3D(Insta360 spherical video params?,also GoPro Max and Garmin VIRB 360)
|
|
7191
7228
|
# in24 52 wave, chan
|
|
7192
7229
|
# "ms\0\x11" 52 wave
|
|
7193
7230
|
# sowt 52 chan
|
|
@@ -7220,11 +7257,14 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
7220
7257
|
chan => {
|
|
7221
7258
|
Name => 'AudioChannelLayout',
|
|
7222
7259
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ChannelLayout' },
|
|
7223
|
-
}
|
|
7260
|
+
},
|
|
7261
|
+
SA3D => { # written by Garmin VIRB360
|
|
7262
|
+
Name => 'SpatialAudio',
|
|
7263
|
+
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::SpatialAudio' },
|
|
7264
|
+
},
|
|
7224
7265
|
# alac - 28 bytes
|
|
7225
7266
|
# adrm - AAX DRM atom? 148 bytes
|
|
7226
7267
|
# aabd - AAX unknown 17kB (contains 'aavd' strings)
|
|
7227
|
-
# SA3D - written by Garmin VIRB360
|
|
7228
7268
|
);
|
|
7229
7269
|
|
|
7230
7270
|
# AMR decode config box (ref 3)
|
|
@@ -7572,6 +7612,20 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
|
7572
7612
|
# (arbitrarily decode only first 8 channels)
|
|
7573
7613
|
);
|
|
7574
7614
|
|
|
7615
|
+
# spatial audio (ref https://github.com/google/spatial-media/blob/master/docs/spatial-audio-rfc.md)
|
|
7616
|
+
%Image::ExifTool::QuickTime::SpatialAudio = (
|
|
7617
|
+
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
|
7618
|
+
GROUPS => { 2 => 'Audio' },
|
|
7619
|
+
NOTES => 'Spatial Audio tags.',
|
|
7620
|
+
0 => 'SpatialAudioVersion',
|
|
7621
|
+
1 => { Name => 'AmbisonicType', PrintConv => { 0 => 'Periphonic' } },
|
|
7622
|
+
2 => { Name => 'AmbisonicOrder', Format => 'int32u' },
|
|
7623
|
+
6 => { Name => 'AmbisonicChannelOrdering', PrintConv => { 0 => 'ACN' } },
|
|
7624
|
+
7 => { Name => 'AmbisonicNormalization', PrintConv => { 0 => 'SN3D' } },
|
|
7625
|
+
8 => { Name => 'AmbisonicChannels', Format => 'int32u' },
|
|
7626
|
+
12 => { Name => 'AmbisonicChannelMap', Format => 'int32u[$val{8}]' },
|
|
7627
|
+
);
|
|
7628
|
+
|
|
7575
7629
|
# scheme type atom
|
|
7576
7630
|
# ref http://xhelmboyx.tripod.com/formats/mp4-layout.txt
|
|
7577
7631
|
%Image::ExifTool::QuickTime::SchemeType = (
|
|
@@ -8787,15 +8841,15 @@ sub HandleItemInfo($)
|
|
|
8787
8841
|
$et->VPrint(0, "$$et{INDENT} [snip $snip bytes]\n") if $snip;
|
|
8788
8842
|
}
|
|
8789
8843
|
}
|
|
8790
|
-
# do
|
|
8791
|
-
if ($isImageData{$type} and $$et{
|
|
8792
|
-
my $
|
|
8844
|
+
# do hash of AVIF "av01" and HEIC image data
|
|
8845
|
+
if ($isImageData{$type} and $$et{ImageDataHash}) {
|
|
8846
|
+
my $hash = $$et{ImageDataHash};
|
|
8793
8847
|
my $tot = 0;
|
|
8794
8848
|
foreach $extent (@{$$item{Extents}}) {
|
|
8795
8849
|
$raf->Seek($$extent[1] + $base, 0) or $et->Warn("Seek error in $type image data"), last;
|
|
8796
|
-
$tot += $et->
|
|
8850
|
+
$tot += $et->ImageDataHash($raf, $$extent[2], "$type image", 1);
|
|
8797
8851
|
}
|
|
8798
|
-
$et->VPrint(0, "$$et{INDENT}(
|
|
8852
|
+
$et->VPrint(0, "$$et{INDENT}(ImageDataHash: $tot bytes of $type data)\n") if $tot;
|
|
8799
8853
|
}
|
|
8800
8854
|
next unless $name;
|
|
8801
8855
|
# assemble the data for this item
|
|
@@ -9285,6 +9339,9 @@ sub ProcessMOV($$;$)
|
|
|
9285
9339
|
}
|
|
9286
9340
|
}
|
|
9287
9341
|
$fileType or $fileType = 'MP4'; # default to MP4
|
|
9342
|
+
# set file type from extension if appropriate
|
|
9343
|
+
my $ext = $$et{FILE_EXT};
|
|
9344
|
+
$fileType = $ext if $ext and $useExt{$ext} and $fileType eq $useExt{$ext};
|
|
9288
9345
|
$et->SetFileType($fileType, $mimeLookup{$fileType} || 'video/mp4');
|
|
9289
9346
|
# temporarily set ExtractEmbedded option for CRX files
|
|
9290
9347
|
$saveOptions{ExtractEmbedded} = $et->Options(ExtractEmbedded => 1) if $fileType eq 'CRX';
|
|
@@ -9299,8 +9356,8 @@ sub ProcessMOV($$;$)
|
|
|
9299
9356
|
$$raf{NoBuffer} = 1 if $fast; # disable buffering in FastScan mode
|
|
9300
9357
|
|
|
9301
9358
|
my $ee = $$et{OPTIONS}{ExtractEmbedded};
|
|
9302
|
-
my $
|
|
9303
|
-
if ($ee or $
|
|
9359
|
+
my $hash = $$et{ImageDataHash};
|
|
9360
|
+
if ($ee or $hash) {
|
|
9304
9361
|
$unkOpt = $$et{OPTIONS}{Unknown};
|
|
9305
9362
|
require 'Image/ExifTool/QuickTimeStream.pl';
|
|
9306
9363
|
}
|
|
@@ -9382,7 +9439,7 @@ sub ProcessMOV($$;$)
|
|
|
9382
9439
|
# set flag to store additional information for ExtractEmbedded option
|
|
9383
9440
|
my $handlerType = $$et{HandlerType};
|
|
9384
9441
|
if ($eeBox{$handlerType} and $eeBox{$handlerType}{$tag}) {
|
|
9385
|
-
if ($ee or $
|
|
9442
|
+
if ($ee or $hash) {
|
|
9386
9443
|
# (there is another 'gps ' box with a track log that doesn't contain offsets)
|
|
9387
9444
|
if ($tag ne 'gps ' or $eeBox{$handlerType}{$tag} eq $dirID) {
|
|
9388
9445
|
$eeTag = 1;
|
|
@@ -9394,7 +9451,7 @@ sub ProcessMOV($$;$)
|
|
|
9394
9451
|
} elsif ($ee and $ee > 1 and $eeBox2{$handlerType} and $eeBox2{$handlerType}{$tag}) {
|
|
9395
9452
|
$eeTag = 1;
|
|
9396
9453
|
$$et{OPTIONS}{Unknown} = 1;
|
|
9397
|
-
} elsif ($
|
|
9454
|
+
} elsif ($hash and $hashBox{$handlerType} and $hashBox{$handlerType}{$tag}) {
|
|
9398
9455
|
$eeTag = 1;
|
|
9399
9456
|
$$et{OPTIONS}{Unknown} = 1;
|
|
9400
9457
|
}
|
|
@@ -9466,13 +9523,17 @@ sub ProcessMOV($$;$)
|
|
|
9466
9523
|
my $items = $$et{ItemInfo};
|
|
9467
9524
|
my ($id, $prop, $docNum, $lowest);
|
|
9468
9525
|
my $primary = $$et{PrimaryItem} || 0;
|
|
9469
|
-
ItemID: foreach $id (keys %$items) {
|
|
9526
|
+
ItemID: foreach $id (reverse sort { $a <=> $b } keys %$items) {
|
|
9470
9527
|
next unless $$items{$id}{Association};
|
|
9471
9528
|
my $item = $$items{$id};
|
|
9472
9529
|
foreach $prop (@{$$item{Association}}) {
|
|
9473
9530
|
next unless $prop == $index;
|
|
9474
9531
|
if ($id == $primary or (not $dontInherit{$tag} and
|
|
9475
|
-
(
|
|
9532
|
+
(($$item{RefersTo} and $$item{RefersTo}{$primary}) or
|
|
9533
|
+
# hack: assume Item 1 is from the main image (eg. hvc1 data)
|
|
9534
|
+
# to hack the case where the primary item (ie. main image)
|
|
9535
|
+
# doesn't directly reference this property
|
|
9536
|
+
(not $$item{RefersTo} and $id == 1))))
|
|
9476
9537
|
{
|
|
9477
9538
|
# this is associated with the primary item or an item describing
|
|
9478
9539
|
# the primary item, so consider this part of the main document
|
|
@@ -9483,7 +9544,7 @@ ItemID: foreach $id (keys %$items) {
|
|
|
9483
9544
|
# this property is already associated with an item that has
|
|
9484
9545
|
# an ExifTool document number, so use the lowest associated DocNum
|
|
9485
9546
|
$docNum = $$item{DocNum} if not defined $docNum or $docNum > $$item{DocNum};
|
|
9486
|
-
}
|
|
9547
|
+
} else {
|
|
9487
9548
|
# keep track of the lowest associated item ID
|
|
9488
9549
|
$lowest = $id;
|
|
9489
9550
|
}
|
|
@@ -9629,7 +9690,7 @@ ItemID: foreach $id (keys %$items) {
|
|
|
9629
9690
|
}
|
|
9630
9691
|
if ($tag eq 'stbl') {
|
|
9631
9692
|
# process sample data when exiting SampleTable box if extracting embedded
|
|
9632
|
-
ProcessSamples($et) if $ee or $
|
|
9693
|
+
ProcessSamples($et) if $ee or $hash;
|
|
9633
9694
|
} elsif ($tag eq 'minf') {
|
|
9634
9695
|
$$et{HandlerType} = ''; # reset handler type at end of media info box
|
|
9635
9696
|
}
|
|
@@ -1128,14 +1128,14 @@ sub Process_text($$$;$)
|
|
|
1128
1128
|
# Inputs: 0) ExifTool ref
|
|
1129
1129
|
# Notes: Also accesses ExifTool RAF*, SET_GROUP1, HandlerType, MetaFormat,
|
|
1130
1130
|
# ee*, and avcC elements (* = must exist)
|
|
1131
|
-
# - may be called either due to ExtractEmbedded option, or
|
|
1132
|
-
# -
|
|
1131
|
+
# - may be called either due to ExtractEmbedded option, or ImageDataHash requested
|
|
1132
|
+
# - hash includes only video and audio data
|
|
1133
1133
|
sub ProcessSamples($)
|
|
1134
1134
|
{
|
|
1135
1135
|
my $et = shift;
|
|
1136
1136
|
my ($raf, $ee) = @$et{qw(RAF ee)};
|
|
1137
|
-
my ($i, $buff, $pos, $hdrLen, $hdrFmt, @time, @dur, $oldIndent, $
|
|
1138
|
-
my ($mdatOffset, $mdatSize); # (for range-checking samples when
|
|
1137
|
+
my ($i, $buff, $pos, $hdrLen, $hdrFmt, @time, @dur, $oldIndent, $hash);
|
|
1138
|
+
my ($mdatOffset, $mdatSize); # (for range-checking samples when hash is done)
|
|
1139
1139
|
|
|
1140
1140
|
return unless $ee;
|
|
1141
1141
|
delete $$et{ee}; # use only once
|
|
@@ -1144,22 +1144,22 @@ sub ProcessSamples($)
|
|
|
1144
1144
|
my $type = $$et{HandlerType} || '';
|
|
1145
1145
|
if ($type eq 'vide') {
|
|
1146
1146
|
# only process specific types of video streams
|
|
1147
|
-
$
|
|
1147
|
+
$hash = $$et{ImageDataHash};
|
|
1148
1148
|
# only process specific video types if ExtractEmbedded was used
|
|
1149
|
-
# (otherwise we are only here to calculate the audio/video
|
|
1149
|
+
# (otherwise we are only here to calculate the audio/video hash)
|
|
1150
1150
|
if ($eeOpt) {
|
|
1151
1151
|
if ($$ee{avcC}) { $type = 'avcC' }
|
|
1152
1152
|
elsif ($$ee{JPEG}) { $type = 'JPEG' }
|
|
1153
|
-
else { return unless $
|
|
1153
|
+
else { return unless $hash }
|
|
1154
1154
|
}
|
|
1155
1155
|
} elsif ($type eq 'soun') {
|
|
1156
|
-
$
|
|
1157
|
-
return unless $
|
|
1156
|
+
$hash = $$et{ImageDataHash};
|
|
1157
|
+
return unless $hash;
|
|
1158
1158
|
} else {
|
|
1159
|
-
return unless $eeOpt; # (don't do
|
|
1159
|
+
return unless $eeOpt; # (don't do hash on other types)
|
|
1160
1160
|
}
|
|
1161
1161
|
|
|
1162
|
-
my $
|
|
1162
|
+
my $hashSize = 0;
|
|
1163
1163
|
my ($start, $size) = @$ee{qw(start size)};
|
|
1164
1164
|
#
|
|
1165
1165
|
# determine sample start offsets from chunk offsets (stco) and sample-to-chunk table (stsc),
|
|
@@ -1213,7 +1213,7 @@ Sample: for ($i=0; ; ) {
|
|
|
1213
1213
|
++$iChunk;
|
|
1214
1214
|
}
|
|
1215
1215
|
@$start == @$size or $et->WarnOnce('Incorrect sample start/size count'), return;
|
|
1216
|
-
# process as chunks if we are only interested in calculating
|
|
1216
|
+
# process as chunks if we are only interested in calculating hash
|
|
1217
1217
|
if ($type eq 'soun' or $type eq 'vide') {
|
|
1218
1218
|
$start = $stco;
|
|
1219
1219
|
$size = \@chunkSize;
|
|
@@ -1232,7 +1232,7 @@ Sample: for ($i=0; ; ) {
|
|
|
1232
1232
|
$oldIndent = $$et{INDENT};
|
|
1233
1233
|
$$et{INDENT} = '';
|
|
1234
1234
|
}
|
|
1235
|
-
if ($
|
|
1235
|
+
if ($hash) {
|
|
1236
1236
|
$mdatSize = $$et{MediaDataSize};
|
|
1237
1237
|
$mdatOffset = $$et{MediaDataOffset} if defined $mdatSize;
|
|
1238
1238
|
}
|
|
@@ -1249,7 +1249,7 @@ Sample: for ($i=0; ; ) {
|
|
|
1249
1249
|
delete $$et{FoundGPSLatitude};
|
|
1250
1250
|
delete $$et{FoundGPSDateTime};
|
|
1251
1251
|
|
|
1252
|
-
# range check the sample data for
|
|
1252
|
+
# range check the sample data for hash if necessary
|
|
1253
1253
|
my $size = $$size[$i];
|
|
1254
1254
|
if (defined $mdatOffset) {
|
|
1255
1255
|
if ($$start[$i] < $mdatOffset) {
|
|
@@ -1268,9 +1268,9 @@ Sample: for ($i=0; ; ) {
|
|
|
1268
1268
|
next unless $n;
|
|
1269
1269
|
$size = $n;
|
|
1270
1270
|
}
|
|
1271
|
-
if ($
|
|
1272
|
-
$
|
|
1273
|
-
$
|
|
1271
|
+
if ($hash) {
|
|
1272
|
+
$hash->add($buff);
|
|
1273
|
+
$hashSize += length $buff;
|
|
1274
1274
|
}
|
|
1275
1275
|
if ($type eq 'avcC') {
|
|
1276
1276
|
next if length($buff) <= $hdrLen;
|
|
@@ -1378,7 +1378,7 @@ Sample: for ($i=0; ; ) {
|
|
|
1378
1378
|
DataPos => $$start[$i],
|
|
1379
1379
|
SampleTime => $time[$i],
|
|
1380
1380
|
SampleDuration => $dur[$i],
|
|
1381
|
-
}, $tagTbl)
|
|
1381
|
+
}, $tagTbl);
|
|
1382
1382
|
}
|
|
1383
1383
|
|
|
1384
1384
|
} elsif ($$tagTbl{$type}) {
|
|
@@ -1399,7 +1399,7 @@ Sample: for ($i=0; ; ) {
|
|
|
1399
1399
|
}
|
|
1400
1400
|
if ($verbose) {
|
|
1401
1401
|
my $str = $type eq 'soun' ? 'Audio' : 'Video';
|
|
1402
|
-
$et->VPrint(0, "$$et{INDENT}(
|
|
1402
|
+
$et->VPrint(0, "$$et{INDENT}(ImageDataHash: $hashSize bytes of $str data)\n") if $hashSize;
|
|
1403
1403
|
$$et{INDENT} = $oldIndent;
|
|
1404
1404
|
$et->VPrint(0, "--------------------------\n");
|
|
1405
1405
|
}
|
|
@@ -2904,6 +2904,7 @@ sub ProcessInsta360($;$)
|
|
|
2904
2904
|
# when the language is french? ie. "Ouest"?)
|
|
2905
2905
|
$a[7] eq 'O'))
|
|
2906
2906
|
{
|
|
2907
|
+
next if $a[3] eq 'V'; # void fixes don't have N/S E/W
|
|
2907
2908
|
$et->Warn('Unrecognized INSV GPS format');
|
|
2908
2909
|
last;
|
|
2909
2910
|
}
|
|
@@ -412,7 +412,7 @@ numerical, and generated automatically otherwise.
|
|
|
412
412
|
'IsComposite' - flag set for Composite tags
|
|
413
413
|
|
|
414
414
|
'IsImageData' - flag set if this is an image data offset to
|
|
415
|
-
be included in
|
|
415
|
+
be included in ImageDataHash calculation. Must have an
|
|
416
416
|
OffsetPair entry which is the ID of the corresponding size.
|
|
417
417
|
|
|
418
418
|
'IsOffset' - flag set if the tag represents an offset to some
|
|
@@ -637,7 +637,7 @@ numerical, and generated automatically otherwise.
|
|
|
637
637
|
RawConv instead to return undef if it is necessary to test the
|
|
638
638
|
value for validity, otherwise an undef tag may hide a
|
|
639
639
|
previously defined value when the Duplicates option is not
|
|
640
|
-
enabled.
|
|
640
|
+
enabled. If this isn't possible (as with Composite tags where
|
|
641
641
|
the converted values of the source tags are needed), set the
|
|
642
642
|
Priority to 0 to avoid taking priority over a valid tag. If
|
|
643
643
|
ValueConv is not specified, the Raw value is not converted.
|
|
@@ -30,7 +30,7 @@ use strict;
|
|
|
30
30
|
use vars qw($VERSION $AUTOLOAD);
|
|
31
31
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
32
32
|
|
|
33
|
-
$VERSION = '1.
|
|
33
|
+
$VERSION = '1.65';
|
|
34
34
|
|
|
35
35
|
sub ConvertTimecode($);
|
|
36
36
|
sub ProcessSGLT($$$);
|
|
@@ -38,7 +38,7 @@ sub ProcessSLLT($$$);
|
|
|
38
38
|
sub ProcessLucas($$$);
|
|
39
39
|
sub WriteRIFF($$);
|
|
40
40
|
|
|
41
|
-
# RIFF chunks containing image data (to include in
|
|
41
|
+
# RIFF chunks containing image data (to include in ImageDataHash digest)
|
|
42
42
|
my %isImageData = (
|
|
43
43
|
LIST_movi => 1, # (AVI: contains ##db, ##dc, ##wb)
|
|
44
44
|
data => 1, # (WAV)
|
|
@@ -652,6 +652,7 @@ my %code2charset = (
|
|
|
652
652
|
Name => 'Acidizer',
|
|
653
653
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Acidizer' },
|
|
654
654
|
},
|
|
655
|
+
guan => 'Guano', #forum14831
|
|
655
656
|
);
|
|
656
657
|
|
|
657
658
|
# the maker notes used by some digital cameras
|
|
@@ -1987,7 +1988,7 @@ sub ProcessRIFF($$)
|
|
|
1987
1988
|
my $unknown = $et->Options('Unknown');
|
|
1988
1989
|
my $validate = $et->Options('Validate');
|
|
1989
1990
|
my $ee = $et->Options('ExtractEmbedded');
|
|
1990
|
-
my $
|
|
1991
|
+
my $hash = $$et{ImageDataHash};
|
|
1991
1992
|
|
|
1992
1993
|
# verify this is a valid RIFF file
|
|
1993
1994
|
return 0 unless $raf->Read($buff, 12) == 12;
|
|
@@ -2045,6 +2046,7 @@ sub ProcessRIFF($$)
|
|
|
2045
2046
|
} else {
|
|
2046
2047
|
next;
|
|
2047
2048
|
}
|
|
2049
|
+
last;
|
|
2048
2050
|
}
|
|
2049
2051
|
# stop when we hit the audio data or AVI index or AVI movie data
|
|
2050
2052
|
# --> no more because Adobe Bridge stores XMP after this!!
|
|
@@ -2067,9 +2069,9 @@ sub ProcessRIFF($$)
|
|
|
2067
2069
|
# (in LIST_movi chunk: ##db = uncompressed DIB, ##dc = compressed DIB, ##wb = audio data)
|
|
2068
2070
|
if ($tagInfo or (($verbose or $unknown) and $tag !~ /^(data|idx1|LIST_movi|RIFF|\d{2}(db|dc|wb))$/)) {
|
|
2069
2071
|
$raf->Read($buff, $len2) == $len2 or $err=1, last;
|
|
2070
|
-
if ($
|
|
2071
|
-
$
|
|
2072
|
-
$et->VPrint(0, "$$et{INDENT}(
|
|
2072
|
+
if ($hash and $isImageData{$tag}) {
|
|
2073
|
+
$hash->add($buff);
|
|
2074
|
+
$et->VPrint(0, "$$et{INDENT}(ImageDataHash: '${tag}' chunk, $len2 bytes)\n");
|
|
2073
2075
|
}
|
|
2074
2076
|
my $setGroups;
|
|
2075
2077
|
if ($tagInfo and ref $tagInfo eq 'HASH' and $$tagInfo{SetGroups}) {
|
|
@@ -2099,10 +2101,10 @@ sub ProcessRIFF($$)
|
|
|
2099
2101
|
next; # (must not increment $pos)
|
|
2100
2102
|
} else {
|
|
2101
2103
|
my $rewind;
|
|
2102
|
-
# do
|
|
2103
|
-
if ($
|
|
2104
|
+
# do hash if required
|
|
2105
|
+
if ($hash and $isImageData{$tag}) {
|
|
2104
2106
|
$rewind = $raf->Tell();
|
|
2105
|
-
$et->
|
|
2107
|
+
$et->ImageDataHash($raf, $len2, "'${tag}' chunk");
|
|
2106
2108
|
}
|
|
2107
2109
|
if ($tag eq 'LIST_movi' and $ee) {
|
|
2108
2110
|
$raf->Seek($rewind, 0) or $err = 1, last if $rewind;
|