exiftool_vendored 12.25.0 → 12.35.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 +174 -7
- data/bin/MANIFEST +11 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +44 -43
- data/bin/arg_files/xmp2exif.args +2 -1
- data/bin/config_files/convert_regions.config +25 -14
- data/bin/config_files/example.config +1 -1
- data/bin/exiftool +118 -92
- data/bin/fmt_files/gpx.fmt +1 -1
- data/bin/fmt_files/gpx_wpt.fmt +1 -1
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +16 -3
- data/bin/lib/Image/ExifTool/CBOR.pm +331 -0
- data/bin/lib/Image/ExifTool/Canon.pm +52 -20
- data/bin/lib/Image/ExifTool/Charset.pm +2 -0
- data/bin/lib/Image/ExifTool/DPX.pm +13 -2
- data/bin/lib/Image/ExifTool/Exif.pm +107 -8
- data/bin/lib/Image/ExifTool/FLIR.pm +33 -8
- data/bin/lib/Image/ExifTool/FlashPix.pm +35 -10
- data/bin/lib/Image/ExifTool/FujiFilm.pm +1 -0
- data/bin/lib/Image/ExifTool/Geotag.pm +13 -2
- data/bin/lib/Image/ExifTool/GoPro.pm +16 -1
- data/bin/lib/Image/ExifTool/ICC_Profile.pm +96 -4
- data/bin/lib/Image/ExifTool/ID3.pm +15 -3
- data/bin/lib/Image/ExifTool/JPEG.pm +68 -2
- data/bin/lib/Image/ExifTool/JSON.pm +7 -3
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +164 -36
- data/bin/lib/Image/ExifTool/LIF.pm +153 -0
- data/bin/lib/Image/ExifTool/Lang/nl.pm +60 -59
- data/bin/lib/Image/ExifTool/M2TS.pm +103 -7
- data/bin/lib/Image/ExifTool/MIE.pm +2 -1
- data/bin/lib/Image/ExifTool/MRC.pm +1 -1
- data/bin/lib/Image/ExifTool/MacOS.pm +2 -2
- data/bin/lib/Image/ExifTool/Nikon.pm +50 -6
- data/bin/lib/Image/ExifTool/NikonSettings.pm +10 -2
- data/bin/lib/Image/ExifTool/Olympus.pm +9 -2
- data/bin/lib/Image/ExifTool/Other.pm +93 -0
- data/bin/lib/Image/ExifTool/PDF.pm +11 -12
- data/bin/lib/Image/ExifTool/PNG.pm +7 -6
- data/bin/lib/Image/ExifTool/Panasonic.pm +14 -2
- data/bin/lib/Image/ExifTool/Pentax.pm +28 -5
- data/bin/lib/Image/ExifTool/Photoshop.pm +6 -0
- data/bin/lib/Image/ExifTool/QuickTime.pm +123 -25
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +203 -121
- data/bin/lib/Image/ExifTool/README +9 -2
- data/bin/lib/Image/ExifTool/RIFF.pm +7 -2
- data/bin/lib/Image/ExifTool/Samsung.pm +47 -10
- data/bin/lib/Image/ExifTool/Sony.pm +113 -42
- data/bin/lib/Image/ExifTool/TagLookup.pm +4599 -4451
- data/bin/lib/Image/ExifTool/TagNames.pod +276 -41
- data/bin/lib/Image/ExifTool/Torrent.pm +18 -11
- data/bin/lib/Image/ExifTool/WriteIPTC.pl +1 -1
- data/bin/lib/Image/ExifTool/WritePDF.pl +1 -0
- data/bin/lib/Image/ExifTool/WritePNG.pl +2 -0
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +21 -4
- data/bin/lib/Image/ExifTool/WriteXMP.pl +1 -1
- data/bin/lib/Image/ExifTool/Writer.pl +47 -2
- data/bin/lib/Image/ExifTool/XMP.pm +32 -12
- data/bin/lib/Image/ExifTool/XMP2.pl +5 -2
- data/bin/lib/Image/ExifTool/XMPStruct.pl +3 -1
- data/bin/lib/Image/ExifTool/ZISRAW.pm +121 -2
- data/bin/lib/Image/ExifTool.pm +153 -52
- data/bin/lib/Image/ExifTool.pod +70 -60
- data/bin/perl-Image-ExifTool.spec +43 -42
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +6 -3
@@ -0,0 +1,93 @@
|
|
1
|
+
#------------------------------------------------------------------------------
|
2
|
+
# File: Other.pm
|
3
|
+
#
|
4
|
+
# Description: Read meta information from other uncommon formats
|
5
|
+
#
|
6
|
+
# Revisions: 2021/07/16 - P. Harvey Created
|
7
|
+
#
|
8
|
+
# References: 1) PFM - http://www.pauldebevec.com/Research/HDR/PFM/
|
9
|
+
#------------------------------------------------------------------------------
|
10
|
+
|
11
|
+
package Image::ExifTool::Other;
|
12
|
+
|
13
|
+
use strict;
|
14
|
+
use vars qw($VERSION);
|
15
|
+
use Image::ExifTool qw(:DataAccess :Utils);
|
16
|
+
use Image::ExifTool::Exif;
|
17
|
+
|
18
|
+
$VERSION = '1.00';
|
19
|
+
|
20
|
+
# Other info
|
21
|
+
%Image::ExifTool::Other::PFM = (
|
22
|
+
GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' },
|
23
|
+
VARS => { NO_ID => 1 },
|
24
|
+
NOTES => q{
|
25
|
+
Tags extracted from Portable FloatMap images. See
|
26
|
+
L<http://www.pauldebevec.com/Research/HDR/PFM/> for the specification.
|
27
|
+
},
|
28
|
+
ColorSpace => { PrintConv => { PF => 'RGB', 'Pf' => 'Monochrome'} },
|
29
|
+
ImageWidth => { },
|
30
|
+
ImageHeight => { },
|
31
|
+
ByteOrder => { PrintConv => '$val > 0 ? "Big-endian" : "Little-endian"' },
|
32
|
+
);
|
33
|
+
|
34
|
+
#------------------------------------------------------------------------------
|
35
|
+
# Extract information from a Portable FloatMap image
|
36
|
+
# Inputs: 0) ExifTool object reference, 1) dirInfo reference
|
37
|
+
# Returns: 1 on success, 0 if this wasn't a valid PFM file
|
38
|
+
sub ProcessPFM2($$)
|
39
|
+
{
|
40
|
+
my ($et, $dirInfo) = @_;
|
41
|
+
my $raf = $$dirInfo{RAF};
|
42
|
+
my $buff;
|
43
|
+
return 0 unless $raf->Read($buff, 256) and $buff =~ /^(P[Ff])\x0a(\d+) (\d+)\x0a([-+0-9.]+)\x0a/;
|
44
|
+
$et->SetFileType('PFM', 'image/x-pfm');
|
45
|
+
my $tagTablePtr = GetTagTable('Image::ExifTool::Other::PFM');
|
46
|
+
$et->HandleTag($tagTablePtr, ColorSpace => $1);
|
47
|
+
$et->HandleTag($tagTablePtr, ImageWidth => $2);
|
48
|
+
$et->HandleTag($tagTablePtr, ImageHeight => $3);
|
49
|
+
$et->HandleTag($tagTablePtr, ByteOrder => $4);
|
50
|
+
# hack to set proper file description (extension is the same for Printer Font Metrics files)
|
51
|
+
$Image::ExifTool::static_vars{OverrideFileDescription}{PFM} = 'Portable FloatMap',
|
52
|
+
return 1;
|
53
|
+
}
|
54
|
+
|
55
|
+
1; # end
|
56
|
+
|
57
|
+
__END__
|
58
|
+
|
59
|
+
=head1 NAME
|
60
|
+
|
61
|
+
Image::ExifTool::Other - Read meta information from other uncommon formats
|
62
|
+
|
63
|
+
=head1 SYNOPSIS
|
64
|
+
|
65
|
+
This module is used by Image::ExifTool
|
66
|
+
|
67
|
+
=head1 DESCRIPTION
|
68
|
+
|
69
|
+
This module contains routines required by Image::ExifTool to extract
|
70
|
+
information from Portable FloatMap (PFM) images.
|
71
|
+
|
72
|
+
=head1 AUTHOR
|
73
|
+
|
74
|
+
Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
|
75
|
+
|
76
|
+
This library is free software; you can redistribute it and/or modify it
|
77
|
+
under the same terms as Perl itself.
|
78
|
+
|
79
|
+
=head1 REFERENCES
|
80
|
+
|
81
|
+
=over 4
|
82
|
+
|
83
|
+
=item PFM L<http://www.pauldebevec.com/Research/HDR/PFM/>
|
84
|
+
|
85
|
+
=back
|
86
|
+
|
87
|
+
=head1 SEE ALSO
|
88
|
+
|
89
|
+
L<Image::ExifTool::TagNames/Other Tags>,
|
90
|
+
L<Image::ExifTool(3pm)|Image::ExifTool>
|
91
|
+
|
92
|
+
=cut
|
93
|
+
|
@@ -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.54';
|
25
25
|
|
26
26
|
sub FetchObject($$$$);
|
27
27
|
sub ExtractObject($$;$$);
|
@@ -280,7 +280,12 @@ my %supportedFilter = (
|
|
280
280
|
ConvertToDict => 1,
|
281
281
|
},
|
282
282
|
Cs1 => {
|
283
|
-
SubDirectory => { TagTable => 'Image::ExifTool::PDF::
|
283
|
+
SubDirectory => { TagTable => 'Image::ExifTool::PDF::DefaultRGB' },
|
284
|
+
ConvertToDict => 1, # (just in case)
|
285
|
+
},
|
286
|
+
CS0 => {
|
287
|
+
SubDirectory => { TagTable => 'Image::ExifTool::PDF::DefaultRGB' },
|
288
|
+
ConvertToDict => 1, # (just in case)
|
284
289
|
},
|
285
290
|
);
|
286
291
|
|
@@ -291,14 +296,7 @@ my %supportedFilter = (
|
|
291
296
|
},
|
292
297
|
);
|
293
298
|
|
294
|
-
# tags in PDF Cs1
|
295
|
-
%Image::ExifTool::PDF::Cs1 = (
|
296
|
-
_stream => {
|
297
|
-
SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' },
|
298
|
-
},
|
299
|
-
);
|
300
|
-
|
301
|
-
# tags in PDF ICCBased dictionary
|
299
|
+
# tags in PDF ICCBased, Cs1 and CS0 dictionaries
|
302
300
|
%Image::ExifTool::PDF::ICCBased = (
|
303
301
|
_stream => {
|
304
302
|
SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' },
|
@@ -1989,16 +1987,17 @@ sub ProcessDict($$$$;$$)
|
|
1989
1987
|
} else {
|
1990
1988
|
$val = ReadPDFValue($val);
|
1991
1989
|
}
|
1992
|
-
# convert from UTF-16 (big endian) to UTF-8 or Latin if necessary
|
1993
|
-
# unless this is binary data (hex-encoded strings would not have been converted)
|
1994
1990
|
if (ref $val) {
|
1995
1991
|
if (ref $val eq 'ARRAY') {
|
1992
|
+
delete $$et{LIST_TAGS}{$tagInfo} if $$tagInfo{List};
|
1996
1993
|
my $v;
|
1997
1994
|
foreach $v (@$val) {
|
1998
1995
|
$et->FoundTag($tagInfo, $v);
|
1999
1996
|
}
|
2000
1997
|
}
|
2001
1998
|
} elsif (defined $val) {
|
1999
|
+
# convert from UTF-16 (big endian) to UTF-8 or Latin if necessary
|
2000
|
+
# unless this is binary data (hex-encoded strings would not have been converted)
|
2002
2001
|
my $format = $$tagInfo{Format} || $$tagInfo{Writable} || 'string';
|
2003
2002
|
$val = ConvertPDFDate($val) if $format eq 'date';
|
2004
2003
|
if (not $$tagInfo{Binary} and $val =~ /[\x18-\x1f\x80-\xff]/) {
|
@@ -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.59';
|
40
40
|
|
41
41
|
sub ProcessPNG_tEXt($$$);
|
42
42
|
sub ProcessPNG_iTXt($$$);
|
@@ -89,7 +89,7 @@ $Image::ExifTool::PNG::colorType = -1;
|
|
89
89
|
|
90
90
|
# data and text chunk types
|
91
91
|
my %isDatChunk = ( IDAT => 1, JDAT => 1, JDAA => 1 );
|
92
|
-
my %isTxtChunk = ( tEXt => 1, zTXt => 1, iTXt => 1 );
|
92
|
+
my %isTxtChunk = ( tEXt => 1, zTXt => 1, iTXt => 1, eXIf => 1 );
|
93
93
|
|
94
94
|
# chunks that we shouldn't move other chunks across (ref 3)
|
95
95
|
my %noLeapFrog = ( SAVE => 1, SEEK => 1, IHDR => 1, JHDR => 1, IEND => 1, MEND => 1,
|
@@ -478,6 +478,8 @@ my %unreg = ( Notes => 'unregistered' );
|
|
478
478
|
if the L<Compress|../ExifTool.html#Compress> option is used and Compress::Zlib is available. Raw profile
|
479
479
|
information is always created as compressed zTXt if Compress::Zlib is
|
480
480
|
available, or tEXt otherwise. Standard XMP is written as uncompressed iTXt.
|
481
|
+
User-defined tags may set an 'iTXt' flag in the tag definition to be written
|
482
|
+
only as iTXt.
|
481
483
|
|
482
484
|
Alternate languages are accessed by suffixing the tag name with a '-',
|
483
485
|
followed by an RFC 3066 language code (eg. "PNG:Comment-fr", or
|
@@ -1382,9 +1384,8 @@ sub ProcessPNG($$)
|
|
1382
1384
|
# to add it as a text profile chunk if this isn't successful
|
1383
1385
|
# (ie. if Compress::Zlib wasn't available)
|
1384
1386
|
Add_iCCP($et, $outfile);
|
1385
|
-
AddChunks($et, $outfile) or $err = 1;
|
1386
|
-
|
1387
|
-
AddChunks($et, $outfile, 'IFD0') if $chunk eq $endChunk;
|
1387
|
+
AddChunks($et, $outfile) or $err = 1; # add all text chunks
|
1388
|
+
AddChunks($et, $outfile, 'IFD0') or $err = 1; # and eXIf chunk
|
1388
1389
|
} elsif ($chunk eq 'PLTE') {
|
1389
1390
|
# iCCP chunk must come before PLTE (and IDAT, handled above)
|
1390
1391
|
# (ignore errors -- will add later as text profile if this fails)
|
@@ -1444,7 +1445,7 @@ sub ProcessPNG($$)
|
|
1444
1445
|
} else {
|
1445
1446
|
$msg = 'fixed';
|
1446
1447
|
}
|
1447
|
-
$et->WarnOnce("Text chunk(s) found after $$et{FileType} $wasDat ($msg)", 1);
|
1448
|
+
$et->WarnOnce("Text/EXIF chunk(s) found after $$et{FileType} $wasDat ($msg)", 1);
|
1448
1449
|
}
|
1449
1450
|
# read chunk data and CRC
|
1450
1451
|
unless ($raf->Read($dbuf,$len)==$len and $raf->Read($cbuf, 4)==4) {
|
@@ -37,7 +37,7 @@ use vars qw($VERSION %leicaLensTypes);
|
|
37
37
|
use Image::ExifTool qw(:DataAccess :Utils);
|
38
38
|
use Image::ExifTool::Exif;
|
39
39
|
|
40
|
-
$VERSION = '2.
|
40
|
+
$VERSION = '2.16';
|
41
41
|
|
42
42
|
sub ProcessLeicaLEIC($$$);
|
43
43
|
sub WhiteBalanceConv($;$$);
|
@@ -449,7 +449,7 @@ my %shootingMode = (
|
|
449
449
|
same as the number printed on the camera body
|
450
450
|
},
|
451
451
|
PrintConv => q{
|
452
|
-
return $val unless $val=~/^([A-Z]
|
452
|
+
return $val unless $val=~/^([A-Z][0-9A-Z]{2})(\d{2})(\d{2})(\d{2})(\d{4})/;
|
453
453
|
my $yr = $2 + ($2 < 70 ? 2000 : 1900);
|
454
454
|
return "($1) $yr:$3:$4 no. $5";
|
455
455
|
},
|
@@ -1423,6 +1423,18 @@ my %shootingMode = (
|
|
1423
1423
|
Name => 'NoiseReductionStrength',
|
1424
1424
|
Writable => 'rational64s',
|
1425
1425
|
},
|
1426
|
+
0xe4 => { #IB
|
1427
|
+
Name => 'LensTypeModel',
|
1428
|
+
Condition => '$format eq "int16u"',
|
1429
|
+
Writable => 'int16u',
|
1430
|
+
RawConv => q{
|
1431
|
+
return undef unless $val;
|
1432
|
+
require Image::ExifTool::Olympus; # (to load Composite LensID)
|
1433
|
+
return $val;
|
1434
|
+
},
|
1435
|
+
ValueConv => '$_=sprintf("%.4x",$val); s/(..)(..)/$2 $1/; $_',
|
1436
|
+
ValueConvInv => '$val =~ s/(..) (..)/$2$1/; hex($val)',
|
1437
|
+
},
|
1426
1438
|
0x0e00 => {
|
1427
1439
|
Name => 'PrintIM',
|
1428
1440
|
Description => 'Print Image Matching',
|
@@ -58,7 +58,7 @@ use Image::ExifTool::Exif;
|
|
58
58
|
use Image::ExifTool::GPS;
|
59
59
|
use Image::ExifTool::HP;
|
60
60
|
|
61
|
-
$VERSION = '3.
|
61
|
+
$VERSION = '3.39';
|
62
62
|
|
63
63
|
sub CryptShutterCount($$);
|
64
64
|
sub PrintFilter($$$);
|
@@ -340,6 +340,7 @@ sub DecodeAFPoints($$$$;$);
|
|
340
340
|
'8 64' => 'HD PENTAX-D FA* 50mm F1.4 SDM AW', #27
|
341
341
|
'8 65' => 'HD PENTAX-D FA 70-210mm F4 ED SDM WR', #PH
|
342
342
|
'8 66' => 'HD PENTAX-D FA 85mm F1.4 ED SDM AW', #James O'Neill
|
343
|
+
'8 195' => 'HD PENTAX DA* 16-50mm F2.8 ED PLM AW', #27
|
343
344
|
'8 196' => 'HD PENTAX-DA* 11-18mm F2.8 ED DC AW', #29
|
344
345
|
'8 197' => 'HD PENTAX-DA 55-300mm F4.5-6.3 ED PLM WR RE', #29
|
345
346
|
'8 198' => 'smc PENTAX-DA L 18-50mm F4-5.6 DC WR RE', #29
|
@@ -548,6 +549,7 @@ my %pentaxModelID = (
|
|
548
549
|
0x13222 => 'K-70', #29 (Ricoh)
|
549
550
|
0x1322c => 'KP', #29 (Ricoh)
|
550
551
|
0x13240 => 'K-1 Mark II', # (Ricoh)
|
552
|
+
0x13254 => 'K-3 Mark III', #IB (Ricoh)
|
551
553
|
0x13290 => 'WG-70', # (Ricoh)
|
552
554
|
);
|
553
555
|
|
@@ -2222,6 +2224,7 @@ my %binaryDataAttrs = (
|
|
2222
2224
|
17 => '17 (K-70)', #29
|
2223
2225
|
18 => '18 (KP)', #PH
|
2224
2226
|
19 => '19 (GR III)', #PH
|
2227
|
+
20 => '20 (K-3III)', #PH
|
2225
2228
|
},
|
2226
2229
|
},
|
2227
2230
|
0x0067 => { #PH (K-5)
|
@@ -2454,6 +2457,7 @@ my %binaryDataAttrs = (
|
|
2454
2457
|
'2 0' => 'Standard',
|
2455
2458
|
'3 0' => 'Fast',
|
2456
2459
|
# '1 108' - seen for GR III
|
2460
|
+
# '3 84' - seen for K-3III
|
2457
2461
|
},
|
2458
2462
|
},
|
2459
2463
|
0x007b => { #PH (K-5)
|
@@ -2597,8 +2601,9 @@ my %binaryDataAttrs = (
|
|
2597
2601
|
},
|
2598
2602
|
},
|
2599
2603
|
},
|
2600
|
-
0x0095 => { #31
|
2604
|
+
0x0095 => [{ #31
|
2601
2605
|
Name => 'SkinToneCorrection',
|
2606
|
+
Condition => '$count == 2',
|
2602
2607
|
Writable => 'int8s',
|
2603
2608
|
Count => 2,
|
2604
2609
|
PrintConv => {
|
@@ -2606,7 +2611,15 @@ my %binaryDataAttrs = (
|
|
2606
2611
|
'1 1' => 'On (type 1)',
|
2607
2612
|
'1 2' => 'On (type 2)',
|
2608
2613
|
},
|
2609
|
-
},
|
2614
|
+
},{
|
2615
|
+
Name => 'SkinToneCorrection',
|
2616
|
+
Condition => '$count == 3',
|
2617
|
+
Writable => 'int8s',
|
2618
|
+
Count => 3,
|
2619
|
+
PrintConv => {
|
2620
|
+
'0 0 0' => 'Off',
|
2621
|
+
},
|
2622
|
+
}],
|
2610
2623
|
0x0096 => { #31
|
2611
2624
|
Name => 'ClarityControl',
|
2612
2625
|
Writable => 'int8s',
|
@@ -2842,8 +2855,18 @@ my %binaryDataAttrs = (
|
|
2842
2855
|
# High: 0000000238c0e960fde0f9203140f5a0fce0f1e031403f00e600fb00f7803760f120fc60ef403460
|
2843
2856
|
# Very High:000000023d20e520fdc0f7203420f4c0fb60ee6036404400e120fae0f5403aa0f020fac0eb403a00
|
2844
2857
|
},
|
2845
|
-
|
2846
|
-
|
2858
|
+
0x021c => { #IB
|
2859
|
+
Name => 'ColorMatrixA2',
|
2860
|
+
Format => 'int16s',
|
2861
|
+
Writable => 'undef',
|
2862
|
+
Count => 9,
|
2863
|
+
},
|
2864
|
+
0x021d => { #IB
|
2865
|
+
Name => 'ColorMatrixB2',
|
2866
|
+
Format => 'int16s',
|
2867
|
+
Writable => 'undef',
|
2868
|
+
Count => 9,
|
2869
|
+
},
|
2847
2870
|
# 0x021e - undef[8] (K-5, Q)
|
2848
2871
|
0x021f => { #JD
|
2849
2872
|
Name => 'AFInfo',
|
@@ -988,6 +988,12 @@ sub ProcessPhotoshop($$$)
|
|
988
988
|
$size += 1 if $size & 0x01; # size is padded to an even # bytes
|
989
989
|
$pos += $size;
|
990
990
|
}
|
991
|
+
# warn about incorrect IPTCDigest
|
992
|
+
if ($$et{VALUE}{IPTCDigest} and $$et{VALUE}{CurrentIPTCDigest} and
|
993
|
+
$$et{VALUE}{IPTCDigest} ne $$et{VALUE}{CurrentIPTCDigest})
|
994
|
+
{
|
995
|
+
$et->WarnOnce('IPTCDigest is not current. XMP may be out of sync');
|
996
|
+
}
|
991
997
|
delete $$et{LOW_PRIORITY_DIR}{'*'};
|
992
998
|
return $success;
|
993
999
|
}
|
@@ -47,7 +47,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
47
47
|
use Image::ExifTool::Exif;
|
48
48
|
use Image::ExifTool::GPS;
|
49
49
|
|
50
|
-
$VERSION = '2.
|
50
|
+
$VERSION = '2.72';
|
51
51
|
|
52
52
|
sub ProcessMOV($$;$);
|
53
53
|
sub ProcessKeys($$$);
|
@@ -229,9 +229,10 @@ my %timeInfo = (
|
|
229
229
|
Writable => 1,
|
230
230
|
Permanent => 1,
|
231
231
|
DelValue => 0,
|
232
|
-
# It is not uncommon for brain-dead software to use the wrong time zero,
|
233
|
-
# so assume a time zero of Jan 1, 1970 if the date is before this
|
232
|
+
# It is not uncommon for brain-dead software to use the wrong time zero, it should be
|
233
|
+
# Jan 1, 1904, so assume a time zero of Jan 1, 1970 if the date is before this
|
234
234
|
# Note: This value will be in UTC if generated by a system that is aware of the time zone
|
235
|
+
# (also note: this code is duplicated for the CreateDate tag)
|
235
236
|
RawConv => q{
|
236
237
|
my $offset = (66 * 365 + 17) * 24 * 3600;
|
237
238
|
return $val - $offset if $val >= $offset or $$self{OPTIONS}{QuickTimeUTC};
|
@@ -481,6 +482,17 @@ my %eeBox2 = (
|
|
481
482
|
# (Pittasoft Blackview dashcam MP4 videos)
|
482
483
|
Condition => '$$valPt =~ /^\0\0..(cprt|sttm|ptnm|ptrh|thum|gps |3gf )/s',
|
483
484
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Pittasoft' },
|
485
|
+
},{
|
486
|
+
Name => 'ThumbnailImage',
|
487
|
+
# (DJI Zenmuse XT2 thermal camera)
|
488
|
+
Groups => { 2 => 'Preview' },
|
489
|
+
Condition => '$$valPt =~ /^.{4}mdat\xff\xd8\xff/s',
|
490
|
+
RawConv => q{
|
491
|
+
my $len = unpack('N', $val);
|
492
|
+
return undef if $len <= 8 or $len > length($val);
|
493
|
+
return substr($val, 8, $len-8);
|
494
|
+
},
|
495
|
+
Binary => 1,
|
484
496
|
},{
|
485
497
|
Unknown => 1,
|
486
498
|
Binary => 1,
|
@@ -557,6 +569,7 @@ my %eeBox2 = (
|
|
557
569
|
# *** this is where ExifTool writes XMP in MP4 videos (as per XMP spec) ***
|
558
570
|
Condition => '$$valPt=~/^\xbe\x7a\xcf\xcb\x97\xa9\x42\xe8\x9c\x71\x99\x94\x91\xe3\xaf\xac/',
|
559
571
|
WriteGroup => 'XMP', # (write main XMP tags here)
|
572
|
+
PreservePadding => 1,
|
560
573
|
SubDirectory => {
|
561
574
|
TagTable => 'Image::ExifTool::XMP::Main',
|
562
575
|
Start => 16,
|
@@ -606,6 +619,7 @@ my %eeBox2 = (
|
|
606
619
|
Name => 'PreviewImage',
|
607
620
|
Condition => '$$valPt=~/^\xea\xf4\x2b\x5e\x1c\x98\x4b\x88\xb9\xfb\xb7\xdc\x40\x6e\x4d\x16/',
|
608
621
|
Groups => { 2 => 'Preview' },
|
622
|
+
PreservePadding => 1,
|
609
623
|
# 0x00 - undef[16]: UUID
|
610
624
|
# 0x10 - int32u[2]: "0 1" (version and/or item count?)
|
611
625
|
# 0x18 - int32u: PRVW atom size
|
@@ -733,6 +747,11 @@ my %eeBox2 = (
|
|
733
747
|
Unknown => 1,
|
734
748
|
Binary => 1,
|
735
749
|
},
|
750
|
+
sefd => {
|
751
|
+
Name => 'SamsungTrailer',
|
752
|
+
SubDirectory => { TagTable => 'Image::ExifTool::Samsung::Trailer' },
|
753
|
+
},
|
754
|
+
# 'samn'? - seen in Vantrue N2S sample video
|
736
755
|
);
|
737
756
|
|
738
757
|
# MPEG-4 'ftyp' atom
|
@@ -1194,6 +1213,15 @@ my %eeBox2 = (
|
|
1194
1213
|
Name => 'CreateDate',
|
1195
1214
|
Groups => { 2 => 'Time' },
|
1196
1215
|
%timeInfo,
|
1216
|
+
RawConv => q{
|
1217
|
+
my $offset = (66 * 365 + 17) * 24 * 3600;
|
1218
|
+
if ($val >= $offset or $$self{OPTIONS}{QuickTimeUTC}) {
|
1219
|
+
$val -= $offset;
|
1220
|
+
} elsif ($val and not $$self{IsWriting}) {
|
1221
|
+
$self->WarnOnce('Patched incorrect time zero for QuickTime date/time tag',1);
|
1222
|
+
}
|
1223
|
+
return $$self{CreateDate} = $val;
|
1224
|
+
},
|
1197
1225
|
# this is int64u if MovieHeaderVersion == 1 (ref 13)
|
1198
1226
|
Hook => '$$self{MovieHeaderVersion} and $format = "int64u", $varSize += 4',
|
1199
1227
|
},
|
@@ -2254,6 +2282,12 @@ my %eeBox2 = (
|
|
2254
2282
|
# opax - 164 bytes unknown (center and affine arrays? ref 26)
|
2255
2283
|
# opai - 32 bytes (maybe contains a serial number starting at byte 16? - PH) (rgb gains, degamma, gamma? ref 26)
|
2256
2284
|
# intv - 16 bytes all zero
|
2285
|
+
# ---- Xaiomi ----
|
2286
|
+
mcvr => {
|
2287
|
+
Name => 'PreviewImage',
|
2288
|
+
Groups => { 2 => 'Preview' },
|
2289
|
+
Binary => 1,
|
2290
|
+
},
|
2257
2291
|
# ---- Unknown ----
|
2258
2292
|
# CDET - 128 bytes (unknown origin)
|
2259
2293
|
# mtyp - 4 bytes all zero (some drone video)
|
@@ -2691,6 +2725,7 @@ my %eeBox2 = (
|
|
2691
2725
|
colr => [{
|
2692
2726
|
Name => 'ICC_Profile',
|
2693
2727
|
Condition => '$$valPt =~ /^(prof|rICC)/',
|
2728
|
+
Permanent => 0, # (in QuickTime, this writes a zero-length box instead of deleting)
|
2694
2729
|
SubDirectory => {
|
2695
2730
|
TagTable => 'Image::ExifTool::ICC_Profile::Main',
|
2696
2731
|
Start => 4,
|
@@ -6281,6 +6316,10 @@ my %eeBox2 = (
|
|
6281
6316
|
'location.ISO6709' => {
|
6282
6317
|
Name => 'GPSCoordinates',
|
6283
6318
|
Groups => { 2 => 'Location' },
|
6319
|
+
Notes => q{
|
6320
|
+
Google Photos may ignore this if the coorinates have more than 5 digits
|
6321
|
+
after the decimal
|
6322
|
+
},
|
6284
6323
|
ValueConv => \&ConvertISO6709,
|
6285
6324
|
ValueConvInv => \&ConvInvISO6709,
|
6286
6325
|
PrintConv => \&PrintGPSCoordinates,
|
@@ -6425,10 +6464,11 @@ my %eeBox2 = (
|
|
6425
6464
|
# iTunes info ('----') atoms
|
6426
6465
|
%Image::ExifTool::QuickTime::iTunesInfo = (
|
6427
6466
|
PROCESS_PROC => \&ProcessMOV,
|
6428
|
-
GROUPS => { 2 => 'Audio' },
|
6467
|
+
GROUPS => { 1 => 'iTunes', 2 => 'Audio' },
|
6429
6468
|
NOTES => q{
|
6430
6469
|
ExifTool will extract any iTunesInfo tags that exist, even if they are not
|
6431
|
-
defined in this table.
|
6470
|
+
defined in this table. These tags belong to the family 1 "iTunes" group,
|
6471
|
+
and are not currently writable.
|
6432
6472
|
},
|
6433
6473
|
# 'mean'/'name'/'data' atoms form a triplet, but unfortunately
|
6434
6474
|
# I haven't been able to find any documentation on this.
|
@@ -6489,9 +6529,45 @@ my %eeBox2 = (
|
|
6489
6529
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::EncodingParams' },
|
6490
6530
|
},
|
6491
6531
|
# also heard about 'iTunPGAP', but I haven't seen a sample
|
6492
|
-
|
6493
|
-
|
6494
|
-
|
6532
|
+
# all tags below were added based on samples I have seen - PH
|
6533
|
+
DISCNUMBER => 'DiscNumber',
|
6534
|
+
TRACKNUMBER => 'TrackNumber',
|
6535
|
+
ARTISTS => 'Artists',
|
6536
|
+
CATALOGNUMBER => 'CatalogNumber',
|
6537
|
+
RATING => 'Rating',
|
6538
|
+
MEDIA => 'Media',
|
6539
|
+
SCRIPT => 'Script', # character set? (seen 'Latn')
|
6540
|
+
BARCODE => 'Barcode',
|
6541
|
+
LABEL => 'Label',
|
6542
|
+
MOOD => 'Mood',
|
6543
|
+
popularimeter => 'Popularimeter',
|
6544
|
+
'Dynamic Range (DR)'=> 'DynamicRange',
|
6545
|
+
initialkey => 'InitialKey',
|
6546
|
+
originalyear => 'OriginalYear',
|
6547
|
+
originaldate => 'OriginalDate',
|
6548
|
+
'~length' => 'Length', # play length? (ie. duration?)
|
6549
|
+
replaygain_track_gain=>'ReplayTrackGain',
|
6550
|
+
replaygain_track_peak=>'ReplayTrackPeak',
|
6551
|
+
'Volume Level (ReplayGain)'=> 'ReplayVolumeLevel',
|
6552
|
+
'Dynamic Range (R128)'=> 'DynamicRangeR128',
|
6553
|
+
'Volume Level (R128)' => 'VolumeLevelR128',
|
6554
|
+
'Peak Level (Sample)' => 'PeakLevelSample',
|
6555
|
+
'Peak Level (R128)' => 'PeakLevelR128',
|
6556
|
+
# also seen (many from forum12777):
|
6557
|
+
# 'MusicBrainz Album Release Country'
|
6558
|
+
# 'MusicBrainz Album Type'
|
6559
|
+
# 'MusicBrainz Album Status'
|
6560
|
+
# 'MusicBrainz Track Id'
|
6561
|
+
# 'MusicBrainz Release Track Id'
|
6562
|
+
# 'MusicBrainz Album Id'
|
6563
|
+
# 'MusicBrainz Album Artist Id'
|
6564
|
+
# 'MusicBrainz Artist Id'
|
6565
|
+
# 'Acoustid Id' (sic)
|
6566
|
+
# 'Tool Version'
|
6567
|
+
# 'Tool Name'
|
6568
|
+
# 'ISRC'
|
6569
|
+
# 'HDCD'
|
6570
|
+
# 'Waveform'
|
6495
6571
|
);
|
6496
6572
|
|
6497
6573
|
# iTunes audio encoding parameters
|
@@ -8860,20 +8936,28 @@ sub ProcessKeys($$$)
|
|
8860
8936
|
my $ns = substr($$dataPt, $pos + 4, 4);
|
8861
8937
|
my $tag = substr($$dataPt, $pos + 8, $len - 8);
|
8862
8938
|
$tag =~ s/\0.*//s; # truncate at null
|
8939
|
+
my $full = $tag;
|
8863
8940
|
$tag =~ s/^com\.(apple\.quicktime\.)?// if $ns eq 'mdta'; # remove apple quicktime domain
|
8864
8941
|
$tag = "Tag_$ns" unless $tag;
|
8865
|
-
|
8866
|
-
my $tagInfo
|
8867
|
-
|
8868
|
-
$tagInfo = $et->GetTagInfo($
|
8869
|
-
|
8942
|
+
my $short = $tag;
|
8943
|
+
my $tagInfo;
|
8944
|
+
for (;;) {
|
8945
|
+
$tagInfo = $et->GetTagInfo($tagTablePtr, $tag) and last;
|
8946
|
+
# also try ItemList and UserData tables
|
8947
|
+
$tagInfo = $et->GetTagInfo($itemList, $tag) and last;
|
8948
|
+
$tagInfo = $et->GetTagInfo($userData, $tag) and last;
|
8949
|
+
# (I have some samples where the tag is a reversed ItemList or UserData tag ID)
|
8950
|
+
if ($tag =~ /^\w{3}\xa9$/) {
|
8951
|
+
$tag = pack('N', unpack('V', $tag));
|
8952
|
+
$tagInfo = $et->GetTagInfo($itemList, $tag) and last;
|
8870
8953
|
$tagInfo = $et->GetTagInfo($userData, $tag);
|
8871
|
-
|
8872
|
-
|
8873
|
-
|
8874
|
-
|
8875
|
-
|
8954
|
+
last;
|
8955
|
+
}
|
8956
|
+
if ($tag eq $full) {
|
8957
|
+
$tag = $short;
|
8958
|
+
last;
|
8876
8959
|
}
|
8960
|
+
$tag = $full;
|
8877
8961
|
}
|
8878
8962
|
my ($newInfo, $msg);
|
8879
8963
|
if ($tagInfo) {
|
@@ -8914,6 +8998,7 @@ sub ProcessKeys($$$)
|
|
8914
8998
|
delete $$itemList{$id};
|
8915
8999
|
}
|
8916
9000
|
if ($newInfo) {
|
9001
|
+
$$newInfo{KeysID} = $tag; # save original ID for use in family 7 group name
|
8917
9002
|
AddTagToTable($itemList, $id, $newInfo);
|
8918
9003
|
$msg or $msg = '';
|
8919
9004
|
$out and print $out "$$et{INDENT}Added ItemList Tag $id = ($ns) $tag$msg\n";
|
@@ -9041,6 +9126,12 @@ sub ProcessMOV($$;$)
|
|
9041
9126
|
} else {
|
9042
9127
|
my $t = PrintableTagID($tag,2);
|
9043
9128
|
$et->VPrint(0,"$$et{INDENT}Tag '${t}' extends to end of file");
|
9129
|
+
if ($$tagTablePtr{"$tag-size"}) {
|
9130
|
+
my $pos = $raf->Tell();
|
9131
|
+
$raf->Seek(0, 2);
|
9132
|
+
$et->HandleTag($tagTablePtr, "$tag-size", $raf->Tell() - $pos);
|
9133
|
+
$et->HandleTag($tagTablePtr, "$tag-offset", $pos) if $$tagTablePtr{"$tag-offset"};
|
9134
|
+
}
|
9044
9135
|
}
|
9045
9136
|
last;
|
9046
9137
|
}
|
@@ -9267,6 +9358,7 @@ ItemID: foreach $id (keys %$items) {
|
|
9267
9358
|
Name => $name,
|
9268
9359
|
Description => $desc,
|
9269
9360
|
};
|
9361
|
+
$et->VPrint(0, $$et{INDENT}, "[adding QuickTime:$name]\n");
|
9270
9362
|
AddTagToTable($tagTablePtr, $tag, $tagInfo);
|
9271
9363
|
}
|
9272
9364
|
# ignore 8-byte header
|
@@ -9278,9 +9370,9 @@ ItemID: foreach $id (keys %$items) {
|
|
9278
9370
|
$val = \$buff;
|
9279
9371
|
}
|
9280
9372
|
}
|
9281
|
-
|
9373
|
+
$$tagInfo{List} = 1; # (allow any of these tags to have multiple data elements)
|
9374
|
+
$et->VerboseInfo($tag, $tagInfo, Value => $val) if $verbose;
|
9282
9375
|
} else {
|
9283
|
-
undef %triplet if $tag eq 'mean';
|
9284
9376
|
$triplet{$tag} = substr($val,4) if length($val) > 4;
|
9285
9377
|
undef $tagInfo; # don't store this tag
|
9286
9378
|
}
|
@@ -9346,7 +9438,7 @@ ItemID: foreach $id (keys %$items) {
|
|
9346
9438
|
for (;;) {
|
9347
9439
|
last if $pos + 16 > $size;
|
9348
9440
|
my ($len, $type, $flags, $ctry, $lang) = unpack("x${pos}Na4Nnn", $val);
|
9349
|
-
last if $pos + $len > $size;
|
9441
|
+
last if $pos + $len > $size or not $len;
|
9350
9442
|
my ($value, $langInfo, $oldDir);
|
9351
9443
|
my $format = $$tagInfo{Format};
|
9352
9444
|
if ($type eq 'data' and $len >= 16) {
|
@@ -9364,7 +9456,13 @@ ItemID: foreach $id (keys %$items) {
|
|
9364
9456
|
# (shouldn't be null terminated, but some software writes it anyway)
|
9365
9457
|
$value =~ s/\0$// unless $$tagInfo{Binary};
|
9366
9458
|
} else {
|
9367
|
-
|
9459
|
+
if (not $format) {
|
9460
|
+
$format = QuickTimeFormat($flags, $len);
|
9461
|
+
} elsif ($format =~ /^int\d+([us])$/) {
|
9462
|
+
# adjust integer to available length (but not int64)
|
9463
|
+
my $fmt = { 1=>'int8', 2=>'int16', 4=>'int32' }->{$len};
|
9464
|
+
$format = $fmt . $1 if defined $fmt;
|
9465
|
+
}
|
9368
9466
|
if ($format) {
|
9369
9467
|
$value = ReadValue(\$value, 0, $format, $$tagInfo{Count}, $len);
|
9370
9468
|
} elsif (not $$tagInfo{ValueConv}) {
|
@@ -9520,9 +9618,9 @@ ItemID: foreach $id (keys %$items) {
|
|
9520
9618
|
($size, $tag) = unpack('Na4', $buff);
|
9521
9619
|
++$index if defined $index;
|
9522
9620
|
}
|
9523
|
-
# tweak file type based on track content ("iso*" ftyp only)
|
9524
|
-
if ($$et{VALUE}{FileType} and $$et{VALUE}{FileType} eq 'MP4' and
|
9525
|
-
$$et{save_ftyp} and $$et{HasHandler} and $$et{save_ftyp} =~ /^iso/ and
|
9621
|
+
# tweak file type based on track content ("iso*" and "dash" ftyp only)
|
9622
|
+
if ($topLevel and $$et{VALUE}{FileType} and $$et{VALUE}{FileType} eq 'MP4' and
|
9623
|
+
$$et{save_ftyp} and $$et{HasHandler} and $$et{save_ftyp} =~ /^(iso|dash)/ and
|
9526
9624
|
$$et{HasHandler}{soun} and not $$et{HasHandler}{vide})
|
9527
9625
|
{
|
9528
9626
|
$et->OverrideFileType('M4A', 'audio/mp4');
|