exiftool_vendored 12.68.0 → 12.70.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 +63 -15
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +2 -2
- data/bin/exiftool +13 -13
- data/bin/lib/Image/ExifTool/CBOR.pm +18 -2
- data/bin/lib/Image/ExifTool/Canon.pm +68 -16
- data/bin/lib/Image/ExifTool/DJI.pm +3 -2
- data/bin/lib/Image/ExifTool/DNG.pm +25 -2
- data/bin/lib/Image/ExifTool/EXE.pm +54 -6
- data/bin/lib/Image/ExifTool/Exif.pm +175 -14
- data/bin/lib/Image/ExifTool/FujiFilm.pm +142 -20
- data/bin/lib/Image/ExifTool/GIF.pm +5 -1
- data/bin/lib/Image/ExifTool/ID3.pm +70 -7
- data/bin/lib/Image/ExifTool/InDesign.pm +1 -1
- data/bin/lib/Image/ExifTool/JPEG.pm +1 -1
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +30 -15
- data/bin/lib/Image/ExifTool/MakerNotes.pm +2 -2
- data/bin/lib/Image/ExifTool/Nikon.pm +58 -18
- data/bin/lib/Image/ExifTool/Olympus.pm +7 -1
- data/bin/lib/Image/ExifTool/PNG.pm +8 -13
- data/bin/lib/Image/ExifTool/Panasonic.pm +15 -2
- data/bin/lib/Image/ExifTool/PhotoMechanic.pm +2 -2
- data/bin/lib/Image/ExifTool/QuickTime.pm +32 -5
- data/bin/lib/Image/ExifTool/README +14 -5
- data/bin/lib/Image/ExifTool/RIFF.pm +60 -10
- data/bin/lib/Image/ExifTool/Sony.pm +95 -34
- data/bin/lib/Image/ExifTool/TagLookup.pm +6937 -6714
- data/bin/lib/Image/ExifTool/TagNames.pod +812 -332
- data/bin/lib/Image/ExifTool/Text.pm +4 -5
- data/bin/lib/Image/ExifTool/Validate.pm +23 -20
- data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +2 -2
- data/bin/lib/Image/ExifTool/WriteExif.pl +14 -4
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +1 -0
- data/bin/lib/Image/ExifTool/WriteRIFF.pl +31 -6
- data/bin/lib/Image/ExifTool/Writer.pl +40 -14
- data/bin/lib/Image/ExifTool/XMP.pm +67 -2
- data/bin/lib/Image/ExifTool/XMP2.pl +35 -0
- data/bin/lib/Image/ExifTool.pm +79 -40
- data/bin/lib/Image/ExifTool.pod +9 -3
- data/bin/perl-Image-ExifTool.spec +1 -1
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +2 -2
@@ -25,11 +25,10 @@ $VERSION = '1.04';
|
|
25
25
|
Although basic text files contain no metadata, the following tags are
|
26
26
|
determined from a simple analysis of the data in TXT and CSV files.
|
27
27
|
Statistics are generated only for 8-bit encodings, but the L<FastScan|../ExifTool.html#FastScan> (-fast)
|
28
|
-
option may be used to limit processing to the first 64
|
29
|
-
tags are not produced. To avoid long processing delays, ExifTool will
|
30
|
-
a minor warning and process only the first 64
|
31
|
-
|
32
|
-
option is used.
|
28
|
+
option may be used to limit processing to the first 64 KiB in which case
|
29
|
+
some tags are not produced. To avoid long processing delays, ExifTool will
|
30
|
+
issue a minor warning and process only the first 64 KiB of any file larger
|
31
|
+
than 20 MiB unless the L<IgnoreMinorErrors|../ExifTool.html#IgnoreMinorErrors> (-m) option is used.
|
33
32
|
},
|
34
33
|
MIMEEncoding => { Groups => { 2 => 'Other' } },
|
35
34
|
Newlines => {
|
@@ -17,7 +17,7 @@ package Image::ExifTool::Validate;
|
|
17
17
|
use strict;
|
18
18
|
use vars qw($VERSION %exifSpec);
|
19
19
|
|
20
|
-
$VERSION = '1.
|
20
|
+
$VERSION = '1.23';
|
21
21
|
|
22
22
|
use Image::ExifTool qw(:Utils);
|
23
23
|
use Image::ExifTool::Exif;
|
@@ -86,7 +86,7 @@ my %verCheck = (
|
|
86
86
|
GPS => { GPSVersionID => \%gpsVer },
|
87
87
|
);
|
88
88
|
|
89
|
-
# tags standard in various RAW file formats
|
89
|
+
# tags standard in various RAW file formats or IFD's
|
90
90
|
my %otherSpec = (
|
91
91
|
CR2 => { 0xc5d8 => 1, 0xc5d9 => 1, 0xc5e0 => 1, 0xc640 => 1, 0xc6dc => 1, 0xc6dd => 1 },
|
92
92
|
NEF => { 0x9216 => 1, 0x9217 => 1 },
|
@@ -103,6 +103,7 @@ my %otherSpec = (
|
|
103
103
|
SRW => { 0xa010 => 1, 0xa011 => 1, 0xa101 => 1, 0xa102 => 1 },
|
104
104
|
NRW => { 0x9216 => 1, 0x9217 => 1 },
|
105
105
|
X3F => { 0xa500 => 1 },
|
106
|
+
CameraIFD => { All => 1 }, # (exists in JPG and DNG of Leica Q3 images)
|
106
107
|
);
|
107
108
|
|
108
109
|
# standard format for tags (not necessary for exifSpec or GPS tags where Writable is defined)
|
@@ -142,20 +143,22 @@ my %stdFormat = (
|
|
142
143
|
# GeoTiff tags:
|
143
144
|
0x830e => 'double', 0x8482 => 'double', 0x87af => 'int16u', 0x87b1 => 'string',
|
144
145
|
0x8480 => 'double', 0x85d8 => 'double', 0x87b0 => 'double',
|
145
|
-
# DNG tags:
|
146
|
-
0xc615 => '(string|int8u)',
|
147
|
-
0xc61a => '(int16u|int32u|rational64u)',
|
148
|
-
0xc61d => 'int(16|32)u',
|
149
|
-
0xc61f => '(int16u|int32u|rational64u)',
|
150
|
-
0xc620 => '(int16u|int32u|rational64u)',
|
151
|
-
0xc628 => '(int16u|rational64u)',
|
152
|
-
0xc634 => 'int8u',
|
153
|
-
0xc640 => '',
|
154
|
-
0xc660 => '',
|
155
|
-
0xc68b => '(string|int8u)',
|
156
|
-
0xc68d => 'int(16|32)u',
|
157
|
-
0xc68e => 'int(16|32)u',
|
158
|
-
0xc6d2 => '',
|
146
|
+
# DNG tags: (use '' for non-DNG tags in the range 0xc612-0xcd48)
|
147
|
+
0xc615 => '(string|int8u)', 0xc6f4 => '(string|int8u)',
|
148
|
+
0xc61a => '(int16u|int32u|rational64u)', 0xc6f6 => '(string|int8u)',
|
149
|
+
0xc61d => 'int(16|32)u', 0xc6f8 => '(string|int8u)',
|
150
|
+
0xc61f => '(int16u|int32u|rational64u)', 0xc6fe => '(string|int8u)',
|
151
|
+
0xc620 => '(int16u|int32u|rational64u)', 0xc716 => '(string|int8u)',
|
152
|
+
0xc628 => '(int16u|rational64u)', 0xc717 => '(string|int8u)',
|
153
|
+
0xc634 => 'int8u', 0xc718 => '(string|int8u)',
|
154
|
+
0xc640 => '', 0xc71e => 'int(16|32)u',
|
155
|
+
0xc660 => '', 0xc71f => 'int(16|32)u',
|
156
|
+
0xc68b => '(string|int8u)', 0xc791 => 'int(16|32)u',
|
157
|
+
0xc68d => 'int(16|32)u', 0xc792 => 'int(16|32)u',
|
158
|
+
0xc68e => 'int(16|32)u', 0xc793 => '(int16u|int32u|rational64u)',
|
159
|
+
0xc6d2 => '', 0xcd43 => 'int(16|32)u',
|
160
|
+
0xc6d3 => '', 0xcd48 => '(string|int8u)',
|
161
|
+
|
159
162
|
# Exif 3.0 spec
|
160
163
|
0x10e => 'string|utf8', 0xa430 => 'string|utf8', 0xa439 => 'string|utf8',
|
161
164
|
0x10f => 'string|utf8', 0xa433 => 'string|utf8', 0xa43a => 'string|utf8',
|
@@ -430,7 +433,7 @@ sub ValidateExif($$$$$$$$)
|
|
430
433
|
my $stdFmt = $stdFormat{$ifd} || $stdFormat{IFD};
|
431
434
|
if (defined $$stdFmt{All} or ($tagTablePtr eq \%Image::ExifTool::Exif::Main and
|
432
435
|
($exifSpec{$tag} or $$stdFmt{$tag} or
|
433
|
-
($tag >= 0xc612 and $tag <=
|
436
|
+
($tag >= 0xc612 and $tag <= 0xcd48 and not defined $$stdFmt{$tag}))) or # (DNG tags)
|
434
437
|
$$tagTablePtr{SHORT_NAME} eq 'GPS::Main')
|
435
438
|
{
|
436
439
|
my $wgp = $$ti{WriteGroup} || $$tagTablePtr{WRITE_GROUP};
|
@@ -456,8 +459,8 @@ sub ValidateExif($$$$$$$$)
|
|
456
459
|
} elsif (not $otherSpec{$$et{FileType}} or
|
457
460
|
(not $otherSpec{$$et{FileType}}{$tag} and not $otherSpec{$$et{FileType}}{All}))
|
458
461
|
{
|
459
|
-
if ($tagTablePtr eq \%Image::ExifTool::Exif::Main or $$
|
460
|
-
$et->Warn(sprintf('Non-standard %s tag 0x%.4x %s', $ifd, $tag, $$ti{Name}), 1);
|
462
|
+
if ($tagTablePtr eq \%Image::ExifTool::Exif::Main or $$ti{Unknown}) {
|
463
|
+
$et->Warn(sprintf('Non-standard %s tag 0x%.4x %s', $ifd, $tag, $$ti{Name}), 1) unless $otherSpec{$ifd};
|
461
464
|
}
|
462
465
|
}
|
463
466
|
# change expected count from read Format to Writable size
|
@@ -478,7 +481,7 @@ sub ValidateExif($$$$$$$$)
|
|
478
481
|
} elsif (not $otherSpec{$$et{FileType}} or
|
479
482
|
(not $otherSpec{$$et{FileType}}{$tag} and not $otherSpec{$$et{FileType}}{All}))
|
480
483
|
{
|
481
|
-
$et->Warn(sprintf('Unknown %s tag 0x%.4x', $ifd, $tag), 1);
|
484
|
+
$et->Warn(sprintf('Unknown %s tag 0x%.4x', $ifd, $tag), 1) unless $otherSpec{$ifd};
|
482
485
|
}
|
483
486
|
}
|
484
487
|
|
@@ -142,7 +142,6 @@ sub SaveMakerNotes($)
|
|
142
142
|
}
|
143
143
|
# save position of maker notes for pointer fixups
|
144
144
|
$fixup->{Shift} += length($makerNotes);
|
145
|
-
$$et{MAKER_NOTE_FIXUP} = $fixup;
|
146
145
|
$$et{MAKER_NOTE_BYTE_ORDER} = GetByteOrder();
|
147
146
|
# add value data
|
148
147
|
$makerNotes .= $makerInfo->{ValBuff};
|
@@ -150,7 +149,8 @@ sub SaveMakerNotes($)
|
|
150
149
|
my $tagTablePtr = Image::ExifTool::GetTagTable('Image::ExifTool::Exif::Main');
|
151
150
|
my $tagInfo = $et->GetTagInfo($tagTablePtr, 0x927c, \$makerNotes);
|
152
151
|
# save the MakerNotes
|
153
|
-
$et->FoundTag($tagInfo, $makerNotes);
|
152
|
+
my $key = $et->FoundTag($tagInfo, $makerNotes);
|
153
|
+
$$et{TAG_EXTRA}{$key}{Fixup} = $fixup;
|
154
154
|
# save the garbage collection some work later
|
155
155
|
delete $makerInfo->{Entries};
|
156
156
|
delete $makerInfo->{ValBuff};
|
@@ -930,8 +930,16 @@ Entry: for (;;) {
|
|
930
930
|
}
|
931
931
|
}
|
932
932
|
unless ($success) {
|
933
|
-
|
934
|
-
|
933
|
+
my $wrn = sprintf("Error reading value for $name entry $index, ID 0x%.4x", $oldID);
|
934
|
+
my $truncOK;
|
935
|
+
if ($oldInfo and not $$oldInfo{Unknown}) {
|
936
|
+
$wrn .= " $$oldInfo{Name}";
|
937
|
+
$truncOK = $$oldInfo{TruncateOK};
|
938
|
+
}
|
939
|
+
return undef if $et->Error($wrn, $inMakerNotes || $truncOK);
|
940
|
+
unless ($truncOK) {
|
941
|
+
++$index; $oldID = $newID; next; # drop this tag
|
942
|
+
}
|
935
943
|
}
|
936
944
|
} elsif (not $invalidPreview) {
|
937
945
|
return undef if $et->Error("Bad $name offset for $tagStr", $inMakerNotes);
|
@@ -1094,6 +1102,8 @@ Entry: for (;;) {
|
|
1094
1102
|
# add, edit or delete this tag
|
1095
1103
|
shift @newTags; # remove from list
|
1096
1104
|
my $curInfo = $set{$newID};
|
1105
|
+
# don't allow MakerNotes to be added to ExifIFD of CR3 file
|
1106
|
+
next if $newID == 0x927c and $isNew > 0 and $$et{FileType} eq 'CR3';
|
1097
1107
|
unless ($curInfo or $$addDirs{$newID}) {
|
1098
1108
|
# we can finally get the specific tagInfo reference for this tag
|
1099
1109
|
# (because we can now evaluate the Condition statement since all
|
@@ -1429,8 +1439,8 @@ NoOverwrite: next if $isNew > 0;
|
|
1429
1439
|
if ($$et{DEL_GROUP}{MakerNotes} and
|
1430
1440
|
($$et{DEL_GROUP}{MakerNotes} != 2 or $isNew <= 0))
|
1431
1441
|
{
|
1432
|
-
if ($et->IsRawType()) {
|
1433
|
-
$et->
|
1442
|
+
if ($et->IsRawType() and not ($et->IsRawType() == 2 and $dirName eq 'ExifIFD')) {
|
1443
|
+
$et->Warn("Can't delete MakerNotes from $$et{FileType}",1);
|
1434
1444
|
} else {
|
1435
1445
|
if ($isNew <= 0) {
|
1436
1446
|
++$$et{CHANGED};
|
@@ -19,6 +19,8 @@ my %webpMap = (
|
|
19
19
|
'XMP ' => 'RIFF', # (the RIFF chunk name is 'XMP ')
|
20
20
|
EXIF => 'RIFF',
|
21
21
|
ICCP => 'RIFF',
|
22
|
+
C2PA => 'RIFF',
|
23
|
+
JUMBF => 'C2PA',
|
22
24
|
XMP => 'XMP ',
|
23
25
|
IFD0 => 'EXIF',
|
24
26
|
IFD1 => 'IFD0',
|
@@ -66,6 +68,7 @@ sub WriteRIFF($$)
|
|
66
68
|
$et->InitWriteDirs(\%webpMap);
|
67
69
|
my $addDirs = $$et{ADD_DIRS};
|
68
70
|
my $editDirs = $$et{EDIT_DIRS};
|
71
|
+
$$addDirs{IFD0} = 'EXIF' if $$addDirs{EXIF}; # set flag to add IFD0 if adding EXIF (don't ask)
|
69
72
|
my ($createVP8X, $deleteVP8X);
|
70
73
|
|
71
74
|
# write header
|
@@ -142,6 +145,17 @@ sub WriteRIFF($$)
|
|
142
145
|
}
|
143
146
|
# RIFF chunks are padded to an even number of bytes
|
144
147
|
my $len2 = $len + ($len & 0x01);
|
148
|
+
# handle incorrect "XMP\0" chunk ID written by Google software
|
149
|
+
if ($tag eq "XMP\0") {
|
150
|
+
if ($$et{DEL_GROUP}{XMP}) {
|
151
|
+
# just ignore this chunk if deleting XMP
|
152
|
+
$raf->Seek($len2, 1) or $et->Error('Seek error'), last;
|
153
|
+
++$$et{CHANGED};
|
154
|
+
next;
|
155
|
+
} else {
|
156
|
+
$et->Warn('Incorrect XMP tag ID',1) if $pass;
|
157
|
+
}
|
158
|
+
}
|
145
159
|
# edit/add/delete necessary metadata chunks (EXIF must come before XMP)
|
146
160
|
if ($$editDirs{$tag} or $tag eq '' or ($tag eq 'XMP ' and $$addDirs{EXIF})) {
|
147
161
|
my $handledTag;
|
@@ -156,13 +170,12 @@ sub WriteRIFF($$)
|
|
156
170
|
#
|
157
171
|
# add/edit/delete EXIF/XMP/ICCP (note: EXIF must come before XMP, and ICCP is written elsewhere)
|
158
172
|
#
|
159
|
-
my %dirName = ( EXIF => 'IFD0', 'XMP ' => 'XMP', ICCP => 'ICC_Profile' );
|
160
|
-
my %tblName = ( EXIF => 'Exif', 'XMP ' => 'XMP', ICCP => 'ICC_Profile' );
|
173
|
+
my %dirName = ( EXIF => 'IFD0', 'XMP ' => 'XMP', ICCP => 'ICC_Profile', C2PA => 'JUMBF' );
|
174
|
+
my %tblName = ( EXIF => 'Exif', 'XMP ' => 'XMP', ICCP => 'ICC_Profile', C2PA => 'Jpeg2000' );
|
161
175
|
my $dir;
|
162
|
-
foreach $dir ('EXIF', 'XMP ', 'ICCP' ) {
|
176
|
+
foreach $dir ('EXIF', 'XMP ', 'ICCP', 'C2PA' ) {
|
163
177
|
next unless $tag eq $dir or ($$addDirs{$dir} and
|
164
178
|
($tag eq '' or ($tag eq 'XMP ' and $dir eq 'EXIF')));
|
165
|
-
delete $$addDirs{$dir}; # (don't try to add again)
|
166
179
|
my $start;
|
167
180
|
unless ($pass) {
|
168
181
|
# write the EXIF and save the result for the next pass
|
@@ -170,8 +183,15 @@ sub WriteRIFF($$)
|
|
170
183
|
if ($tag eq 'EXIF') {
|
171
184
|
# (only need to set directory $start for EXIF)
|
172
185
|
if ($buff =~ /^Exif\0\0/) {
|
173
|
-
|
174
|
-
|
186
|
+
if ($$et{DEL_GROUP}{EXIF}) {
|
187
|
+
# remove incorrect header if rewriting anyway
|
188
|
+
$buff = substr($buff, 6);
|
189
|
+
$len -= 6;
|
190
|
+
$len2 -= 6;
|
191
|
+
} else {
|
192
|
+
$et->Warn('Improper EXIF header',1) unless $pass;
|
193
|
+
$start = 6;
|
194
|
+
}
|
175
195
|
} else {
|
176
196
|
$start = 0;
|
177
197
|
}
|
@@ -189,11 +209,16 @@ sub WriteRIFF($$)
|
|
189
209
|
Parent => $dir,
|
190
210
|
DirName => $dirName{$dir},
|
191
211
|
);
|
212
|
+
# must pass the TagInfo to enable deletion of C2PA information
|
213
|
+
if (ref $Image::ExifTool::RIFF::Main{$dir} eq 'HASH') {
|
214
|
+
$dirInfo{TagInfo} = $Image::ExifTool::RIFF::Main{$dir};
|
215
|
+
}
|
192
216
|
my $tagTablePtr = GetTagTable("Image::ExifTool::$tblName{$dir}::Main");
|
193
217
|
# (override writeProc for EXIF because it has the TIFF header)
|
194
218
|
my $writeProc = $dir eq 'EXIF' ? \&Image::ExifTool::WriteTIFF : undef;
|
195
219
|
$dirDat{$dir} = $et->WriteDirectory(\%dirInfo, $tagTablePtr, $writeProc);
|
196
220
|
}
|
221
|
+
delete $$addDirs{$dir}; # (don't try to add again)
|
197
222
|
if (defined $dirDat{$dir}) {
|
198
223
|
if ($dir eq $tag) {
|
199
224
|
$handledTag = 1; # set flag indicating we edited this tag
|
@@ -122,9 +122,9 @@ my %writableType = (
|
|
122
122
|
XMP => [ undef, 'WriteXMP' ],
|
123
123
|
);
|
124
124
|
|
125
|
-
# RAW file types
|
125
|
+
# RAW file types (2 = raw file where we can delete maker notes from ExifIFD)
|
126
126
|
my %rawType = (
|
127
|
-
'3FR'=> 1, CR3 =>
|
127
|
+
'3FR'=> 1, CR3 => 2, IIQ => 1, NEF => 1, RW2 => 1,
|
128
128
|
ARQ => 1, CRW => 1, K25 => 1, NRW => 1, RWL => 1,
|
129
129
|
ARW => 1, DCR => 1, KDC => 1, ORF => 1, SR2 => 1,
|
130
130
|
ARW => 1, ERF => 1, MEF => 1, PEF => 1, SRF => 1,
|
@@ -278,6 +278,7 @@ my %ignorePrintConv = map { $_ => 1 } qw(OTHER BITMASK Notes);
|
|
278
278
|
# ListOnly => [internal use] set only list or non-list tags
|
279
279
|
# SetTags => [internal use] hash ref to return tagInfo refs of set tags
|
280
280
|
# Sanitized => [internal use] set to avoid double-sanitizing the value
|
281
|
+
# Fixup => [internal use] fixup information when writing maker notes
|
281
282
|
# Returns: number of tags set (plus error string in list context)
|
282
283
|
# Notes: For tag lists (like Keywords), call repeatedly with the same tag name for
|
283
284
|
# each value in the list. Internally, the new information is stored in
|
@@ -1002,10 +1003,8 @@ TAG: foreach $tagInfo (@matchingTags) {
|
|
1002
1003
|
$$nvHash{NoReplace} = 1 if $$tagInfo{List} and not $options{Replace};
|
1003
1004
|
$$nvHash{WantGroup} = $wantGroup;
|
1004
1005
|
$$nvHash{EditOnly} = 1 if $editOnly;
|
1005
|
-
# save maker note information if writing maker notes
|
1006
|
-
if
|
1007
|
-
$$nvHash{MAKER_NOTE_FIXUP} = $$self{MAKER_NOTE_FIXUP};
|
1008
|
-
}
|
1006
|
+
# save maker note fixup information if writing maker notes
|
1007
|
+
$$nvHash{MAKER_NOTE_FIXUP} = $options{Fixup} if $$tagInfo{MakerNotes};
|
1009
1008
|
if ($createOnly) { # create only (never edit)
|
1010
1009
|
# empty item in DelValue list to never edit existing value
|
1011
1010
|
$$nvHash{DelValue} = [ '' ];
|
@@ -1272,6 +1271,7 @@ sub SetNewValuesFromFile($$;@)
|
|
1272
1271
|
# +------------------------------------------+
|
1273
1272
|
$srcExifTool->Options(
|
1274
1273
|
Binary => 1,
|
1274
|
+
ByteUnit => $$options{ByteUnit},
|
1275
1275
|
Charset => $$options{Charset},
|
1276
1276
|
CharsetEXIF => $$options{CharsetEXIF},
|
1277
1277
|
CharsetFileName => $$options{CharsetFileName},
|
@@ -1372,8 +1372,8 @@ sub SetNewValuesFromFile($$;@)
|
|
1372
1372
|
#
|
1373
1373
|
unless (@setTags) {
|
1374
1374
|
# transfer maker note information to this object
|
1375
|
-
$$self{MAKER_NOTE_FIXUP} = $$srcExifTool{MAKER_NOTE_FIXUP};
|
1376
1375
|
$$self{MAKER_NOTE_BYTE_ORDER} = $$srcExifTool{MAKER_NOTE_BYTE_ORDER};
|
1376
|
+
my $tagExtra = $$srcExifTool{TAG_EXTRA};
|
1377
1377
|
foreach $tag (@tags) {
|
1378
1378
|
# don't try to set errors or warnings
|
1379
1379
|
next if $tag =~ /^(Error|Warning)\b/;
|
@@ -1381,10 +1381,13 @@ sub SetNewValuesFromFile($$;@)
|
|
1381
1381
|
if ($opts{SrcType} and $opts{SrcType} ne $srcType) {
|
1382
1382
|
$$info{$tag} = $srcExifTool->GetValue($tag, $opts{SrcType});
|
1383
1383
|
}
|
1384
|
+
my $fixup = $$tagExtra{$tag}{Fixup};
|
1385
|
+
$opts{Fixup} = $fixup if $fixup;
|
1384
1386
|
# set value for this tag
|
1385
1387
|
my ($n, $e) = $self->SetNewValue($tag, $$info{$tag}, %opts);
|
1386
1388
|
# delete this tag if we couldn't set it
|
1387
1389
|
$n or delete $$info{$tag};
|
1390
|
+
delete $opts{Fixup} if $fixup;
|
1388
1391
|
}
|
1389
1392
|
return $info;
|
1390
1393
|
}
|
@@ -1617,7 +1620,7 @@ SET: foreach $set (@setList) {
|
|
1617
1620
|
}
|
1618
1621
|
# transfer maker note information if setting this tag
|
1619
1622
|
if ($$srcExifTool{TAG_INFO}{$tag}{MakerNotes}) {
|
1620
|
-
$$
|
1623
|
+
$$opts{Fixup} = $$srcExifTool{TAG_EXTRA}{$tag}{Fixup};
|
1621
1624
|
$$self{MAKER_NOTE_BYTE_ORDER} = $$srcExifTool{MAKER_NOTE_BYTE_ORDER};
|
1622
1625
|
}
|
1623
1626
|
if ($dstTag eq '*') {
|
@@ -1649,6 +1652,7 @@ SET: foreach $set (@setList) {
|
|
1649
1652
|
$rtnInfo{NextFreeTagKey(\%rtnInfo, 'Warning')} = $wrn;
|
1650
1653
|
$noWarn = 1;
|
1651
1654
|
}
|
1655
|
+
delete $$opts{Fixup};
|
1652
1656
|
$rtnInfo{$tag} = $val if $rtn; # tag was set successfully
|
1653
1657
|
}
|
1654
1658
|
}
|
@@ -4176,6 +4180,7 @@ sub WriteDirectory($$$;$)
|
|
4176
4180
|
$out = $$self{OPTIONS}{TextOut} if $$self{OPTIONS}{Verbose};
|
4177
4181
|
# set directory name from default group0 name if not done already
|
4178
4182
|
my $dirName = $$dirInfo{DirName};
|
4183
|
+
my $parent = $$dirInfo{Parent} || '';
|
4179
4184
|
my $dataPt = $$dirInfo{DataPt};
|
4180
4185
|
my $grp0 = $$tagTablePtr{GROUPS}{0};
|
4181
4186
|
$dirName or $dirName = $$dirInfo{DirName} = $grp0;
|
@@ -4183,14 +4188,19 @@ sub WriteDirectory($$$;$)
|
|
4183
4188
|
my $delGroup = $$self{DEL_GROUP};
|
4184
4189
|
# delete entire directory if specified
|
4185
4190
|
my $grp1 = $dirName;
|
4186
|
-
$delFlag = ($$delGroup{$grp0} or $$delGroup{$grp1})
|
4191
|
+
$delFlag = ($$delGroup{$grp0} or $$delGroup{$grp1});
|
4192
|
+
if ($permanentDir{$grp0} and not ($$dirInfo{TagInfo} and $$dirInfo{TagInfo}{Deletable})) {
|
4193
|
+
undef $delFlag;
|
4194
|
+
}
|
4187
4195
|
# (never delete an entire QuickTime group)
|
4188
4196
|
if ($delFlag) {
|
4189
4197
|
if (($grp0 =~ /^(MakerNotes)$/ or $grp1 =~ /^(IFD0|ExifIFD|MakerNotes)$/) and
|
4190
4198
|
$self->IsRawType() and
|
4191
4199
|
# allow non-permanent MakerNote directories to be deleted (ie. NikonCapture)
|
4192
4200
|
(not $$dirInfo{TagInfo} or not defined $$dirInfo{TagInfo}{Permanent} or
|
4193
|
-
$$dirInfo{TagInfo}{Permanent})
|
4201
|
+
$$dirInfo{TagInfo}{Permanent}) and
|
4202
|
+
# allow MakerNotes to be deleted from ExifIFD of CR3 file
|
4203
|
+
not ($self->IsRawType() == 2 and $parent eq 'ExifIFD'))
|
4194
4204
|
{
|
4195
4205
|
$self->WarnOnce("Can't delete $1 from $$self{FileType}",1);
|
4196
4206
|
undef $grp1;
|
@@ -4226,7 +4236,6 @@ sub WriteDirectory($$$;$)
|
|
4226
4236
|
if ($delFlag == 2 and $right) {
|
4227
4237
|
# also check grandparent because some routines create 2 levels in 1
|
4228
4238
|
my $right2 = $$self{ADD_DIRS}{$right} || '';
|
4229
|
-
my $parent = $$dirInfo{Parent};
|
4230
4239
|
if (not $parent or $parent eq $right or $parent eq $right2) {
|
4231
4240
|
# prevent duplicate directories from being recreated at the same path
|
4232
4241
|
my $path = join '-', @{$$self{PATH}}, $dirName;
|
@@ -4284,10 +4293,27 @@ sub WriteDirectory($$$;$)
|
|
4284
4293
|
last unless $self->IsOverwriting($nvHash, $dataPt ? $$dataPt : '');
|
4285
4294
|
my $verb = 'Writing';
|
4286
4295
|
my $newVal = $self->GetNewValue($nvHash);
|
4287
|
-
|
4296
|
+
if (defined $newVal and length $newVal) {
|
4297
|
+
# hack to add back TIFF header when writing MakerNoteCanon to CMT3 in CR3 images
|
4298
|
+
if ($$tagInfo{Name} eq 'MakerNoteCanon') {
|
4299
|
+
require Image::ExifTool::Canon;
|
4300
|
+
if ($tagInfo eq $Image::ExifTool::Canon::uuid{CMT3}) {
|
4301
|
+
my $hdr;
|
4302
|
+
if (substr($newVal, 0, 1) eq "\0") {
|
4303
|
+
$hdr = "MM\0\x2a" . pack('N', 8);
|
4304
|
+
} else {
|
4305
|
+
$hdr = "II\x2a\0" . pack('V', 8);
|
4306
|
+
}
|
4307
|
+
$newVal = $hdr . $newVal;
|
4308
|
+
}
|
4309
|
+
}
|
4310
|
+
} else {
|
4288
4311
|
return '' unless $dataPt or $$dirInfo{RAF}; # nothing to do if block never existed
|
4289
4312
|
# don't allow MakerNotes to be removed from RAW files
|
4290
|
-
if ($blockName eq 'MakerNotes' and $
|
4313
|
+
if ($blockName eq 'MakerNotes' and $self->IsRawType() and
|
4314
|
+
# but allow MakerNotes to be deleted from ExifIFD of CR3 image (shouldn't be there)
|
4315
|
+
not ($self->IsRawType() == 2 and $parent eq 'ExifIFD'))
|
4316
|
+
{
|
4291
4317
|
$self->Warn("Can't delete MakerNotes from $$self{FileType}",1);
|
4292
4318
|
return undef;
|
4293
4319
|
}
|
@@ -7067,7 +7093,7 @@ sub WriteBinaryData($$$)
|
|
7067
7093
|
$newVal = length($data) if defined $data;
|
7068
7094
|
my $format = $$tagInfo{Format} || $$tagTablePtr{FORMAT} || 'int32u';
|
7069
7095
|
if ($format =~ /^int16/ and $newVal > 0xffff) {
|
7070
|
-
$self->Error("$$tagInfo{DataTag} is too large (64
|
7096
|
+
$self->Error("$$tagInfo{DataTag} is too large (64 KiB max. for this file)");
|
7071
7097
|
}
|
7072
7098
|
}
|
7073
7099
|
my $rtnVal = WriteValue($newVal, $format, $count, $dataPt, $entry);
|
@@ -50,7 +50,7 @@ use Image::ExifTool::Exif;
|
|
50
50
|
use Image::ExifTool::GPS;
|
51
51
|
require Exporter;
|
52
52
|
|
53
|
-
$VERSION = '3.
|
53
|
+
$VERSION = '3.61';
|
54
54
|
@ISA = qw(Exporter);
|
55
55
|
@EXPORT_OK = qw(EscapeXML UnescapeXML);
|
56
56
|
|
@@ -201,6 +201,8 @@ my %xmpNS = (
|
|
201
201
|
nine => 'http://ns.nikon.com/nine/1.0/',
|
202
202
|
hdr_metadata => 'http://ns.adobe.com/hdr-metadata/1.0/',
|
203
203
|
hdrgm => 'http://ns.adobe.com/hdr-gain-map/1.0/',
|
204
|
+
# Note: Not included due to namespace prefix conflict with Device:Container
|
205
|
+
# Container => 'http://ns.google.com/photos/1.0/container/',
|
204
206
|
);
|
205
207
|
|
206
208
|
# build reverse namespace lookup
|
@@ -479,7 +481,7 @@ my %sCorrRangeMask = (
|
|
479
481
|
LuminanceDepthSampleInfo => { },
|
480
482
|
);
|
481
483
|
# new LR2 crs structures (PH)
|
482
|
-
my %sCorrectionMask;
|
484
|
+
my %sCorrectionMask; # (must define this before assigning because it is self-referential)
|
483
485
|
%sCorrectionMask = (
|
484
486
|
STRUCT_NAME => 'CorrectionMask',
|
485
487
|
NAMESPACE => 'crs',
|
@@ -919,6 +921,11 @@ my %sRangeMask = (
|
|
919
921
|
Name => 'hdrgm',
|
920
922
|
SubDirectory => { TagTable => 'Image::ExifTool::XMP::hdrgm' },
|
921
923
|
},
|
924
|
+
# Note: Note included due to namespace prefix conflict with Device:Container
|
925
|
+
# Container => {
|
926
|
+
# Name => 'Container',
|
927
|
+
# SubDirectory => { TagTable => 'Image::ExifTool::XMP::Container' },
|
928
|
+
# },
|
922
929
|
);
|
923
930
|
|
924
931
|
# hack to allow XML containing Dublin Core metadata to be handled like XMP (eg. EPUB - see ZIP.pm)
|
@@ -1699,6 +1706,8 @@ my %sPantryItem = (
|
|
1699
1706
|
ToneCurvePV2012Red => { List => 'Seq' },
|
1700
1707
|
ToneCurvePV2012Green => { List => 'Seq' },
|
1701
1708
|
ToneCurvePV2012Blue => { List => 'Seq' },
|
1709
|
+
Highlights2012 => { },
|
1710
|
+
Shadows2012 => { },
|
1702
1711
|
},
|
1703
1712
|
},
|
1704
1713
|
}
|
@@ -1760,6 +1769,62 @@ my %sPantryItem = (
|
|
1760
1769
|
SDRShadows => { Writable => 'real' },
|
1761
1770
|
SDRWhites => { Writable => 'real' },
|
1762
1771
|
SDRBlend => { Writable => 'real' },
|
1772
|
+
# new for ACR 16 (ref forum15305)
|
1773
|
+
LensBlur => {
|
1774
|
+
Struct => {
|
1775
|
+
STRUCT_NAME => 'LensBlur',
|
1776
|
+
NAMESPACE => 'crs',
|
1777
|
+
# (Note: all the following 'real' values could be limited to 'integer')
|
1778
|
+
Active => { Writable => 'boolean' },
|
1779
|
+
BlurAmount => { FlatName => 'Amount', Writable => 'real' },
|
1780
|
+
BokehAspect => { Writable => 'real' },
|
1781
|
+
BokehRotation => { Writable => 'real' },
|
1782
|
+
BokehShape => { Writable => 'real' },
|
1783
|
+
BokehShapeDetail => { Writable => 'real' },
|
1784
|
+
CatEyeAmount => { Writable => 'real' },
|
1785
|
+
CatEyeScale => { Writable => 'real' },
|
1786
|
+
FocalRange => { }, # (eg. "-48 32 64 144")
|
1787
|
+
FocalRangeSource => { Writable => 'real' },
|
1788
|
+
HighlightsBoost => { Writable => 'real' },
|
1789
|
+
HighlightsThreshold => { Writable => 'real' },
|
1790
|
+
SampledArea => { }, # (eg. "0.500000 0.500000 0.500000 0.500000")
|
1791
|
+
SampledRange => { }, # (eg. "0 0")
|
1792
|
+
SphericalAberration => { Writable => 'real' },
|
1793
|
+
SubjectRange => { }, # (eg. "0 57");
|
1794
|
+
Version => { },
|
1795
|
+
},
|
1796
|
+
},
|
1797
|
+
DepthMapInfo => {
|
1798
|
+
Struct => {
|
1799
|
+
STRUCT_NAME => 'DepthMapInfo',
|
1800
|
+
NAMESPACE => 'crs',
|
1801
|
+
BaseHighlightGuideInputDigest => { },
|
1802
|
+
BaseHighlightGuideTable => { },
|
1803
|
+
BaseHighlightGuideVersion => { },
|
1804
|
+
BaseLayeredDepthInputDigest => { },
|
1805
|
+
BaseLayeredDepthTable => { },
|
1806
|
+
BaseLayeredDepthVersion => { },
|
1807
|
+
BaseRawDepthInputDigest => { },
|
1808
|
+
BaseRawDepthTable => { },
|
1809
|
+
BaseRawDepthVersion => { },
|
1810
|
+
DepthSource => { },
|
1811
|
+
},
|
1812
|
+
},
|
1813
|
+
DepthBasedCorrections => {
|
1814
|
+
List => 'Seq',
|
1815
|
+
FlatName => 'DepthBasedCorr',
|
1816
|
+
Struct => {
|
1817
|
+
STRUCT_NAME => 'DepthBasedCorr',
|
1818
|
+
NAMESPACE => 'crs',
|
1819
|
+
CorrectionActive => { Writable => 'boolean' },
|
1820
|
+
CorrectionAmount => { Writable => 'real' },
|
1821
|
+
CorrectionMasks => { FlatName => 'Mask', List => 'Seq', Struct => \%sCorrectionMask },
|
1822
|
+
CorrectionSyncID => { },
|
1823
|
+
LocalCorrectedDepth => { Writable => 'real' },
|
1824
|
+
LocalCurveRefineSaturation => { Writable => 'real' },
|
1825
|
+
What => { },
|
1826
|
+
},
|
1827
|
+
},
|
1763
1828
|
);
|
1764
1829
|
|
1765
1830
|
# Tiff namespace properties (tiff)
|
@@ -1873,6 +1873,10 @@ my %sSubVersion = (
|
|
1873
1873
|
ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)',
|
1874
1874
|
ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)',
|
1875
1875
|
},
|
1876
|
+
HdrPlusMakernote => {
|
1877
|
+
ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)',
|
1878
|
+
ValueConvInv => 'Image::ExifTool::XMP::EncodeBase64($val)',
|
1879
|
+
},
|
1876
1880
|
);
|
1877
1881
|
|
1878
1882
|
# Google creations namespace (ref PH)
|
@@ -2037,6 +2041,37 @@ my %sSubVersion = (
|
|
2037
2041
|
},
|
2038
2042
|
);
|
2039
2043
|
|
2044
|
+
# Google container tags (ref https://developer.android.com/guide/topics/media/platform/hdr-image-format)
|
2045
|
+
# NOTE: Not included because these namespace prefixes conflict with Google's depth-map Device tags!
|
2046
|
+
# (see ../pics/GooglePixel8Pro.jpg sample image)
|
2047
|
+
# %Image::ExifTool::XMP::Container = (
|
2048
|
+
# %xmpTableDefaults,
|
2049
|
+
# GROUPS => { 1 => 'XMP-Container', 2 => 'Image' },
|
2050
|
+
# NAMESPACE => 'Container',
|
2051
|
+
# NOTES => 'Google Container namespace.',
|
2052
|
+
# Directory => {
|
2053
|
+
# Name => 'ContainerDirectory',
|
2054
|
+
# FlatName => 'Directory',
|
2055
|
+
# List => 'Seq',
|
2056
|
+
# Struct => {
|
2057
|
+
# STRUCT_NAME => 'Directory',
|
2058
|
+
# Item => {
|
2059
|
+
# Namespace => 'Container',
|
2060
|
+
# Struct => {
|
2061
|
+
# STRUCT_NAME => 'Item',
|
2062
|
+
# NAMESPACE => { Item => 'http://ns.google.com/photos/1.0/container/item/'},
|
2063
|
+
# Mime => { },
|
2064
|
+
# Semantic => { },
|
2065
|
+
# Length => { Writable => 'integer' },
|
2066
|
+
# Label => { },
|
2067
|
+
# Padding => { Writable => 'integer' },
|
2068
|
+
# URI => { },
|
2069
|
+
# },
|
2070
|
+
# },
|
2071
|
+
# },
|
2072
|
+
# },
|
2073
|
+
# );
|
2074
|
+
|
2040
2075
|
# Getty Images namespace (ref PH)
|
2041
2076
|
%Image::ExifTool::XMP::GettyImages = (
|
2042
2077
|
%xmpTableDefaults,
|