exiftool-vendored.pl 12.69.0 → 12.72.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 +78 -12
- package/bin/MANIFEST +5 -0
- package/bin/META.json +1 -1
- package/bin/META.yml +1 -1
- package/bin/README +10 -10
- package/bin/exiftool +32 -25
- package/bin/lib/Image/ExifTool/AAC.pm +175 -0
- package/bin/lib/Image/ExifTool/BuildTagLookup.pm +2 -1
- package/bin/lib/Image/ExifTool/CBOR.pm +18 -2
- package/bin/lib/Image/ExifTool/Canon.pm +82 -20
- package/bin/lib/Image/ExifTool/DJI.pm +3 -2
- package/bin/lib/Image/ExifTool/EXE.pm +54 -6
- package/bin/lib/Image/ExifTool/Exif.pm +111 -11
- package/bin/lib/Image/ExifTool/FujiFilm.pm +145 -20
- package/bin/lib/Image/ExifTool/GIF.pm +5 -1
- package/bin/lib/Image/ExifTool/GoPro.pm +16 -1
- package/bin/lib/Image/ExifTool/ID3.pm +76 -10
- package/bin/lib/Image/ExifTool/InDesign.pm +1 -1
- package/bin/lib/Image/ExifTool/JPEG.pm +1 -1
- package/bin/lib/Image/ExifTool/JSON.pm +4 -1
- package/bin/lib/Image/ExifTool/Jpeg2000.pm +30 -15
- package/bin/lib/Image/ExifTool/M2TS.pm +21 -16
- package/bin/lib/Image/ExifTool/MakerNotes.pm +2 -2
- package/bin/lib/Image/ExifTool/Nikon.pm +203 -102
- package/bin/lib/Image/ExifTool/Olympus.pm +7 -1
- package/bin/lib/Image/ExifTool/PNG.pm +8 -13
- package/bin/lib/Image/ExifTool/Panasonic.pm +10 -1
- package/bin/lib/Image/ExifTool/Pentax.pm +15 -6
- package/bin/lib/Image/ExifTool/QuickTime.pm +59 -13
- package/bin/lib/Image/ExifTool/QuickTimeStream.pl +59 -11
- package/bin/lib/Image/ExifTool/README +7 -2
- package/bin/lib/Image/ExifTool/RIFF.pm +53 -9
- package/bin/lib/Image/ExifTool/Ricoh.pm +109 -1
- package/bin/lib/Image/ExifTool/Samsung.pm +3 -2
- package/bin/lib/Image/ExifTool/Sony.pm +177 -37
- package/bin/lib/Image/ExifTool/TagLookup.pm +6961 -6856
- package/bin/lib/Image/ExifTool/TagNames.pod +580 -344
- package/bin/lib/Image/ExifTool/Text.pm +4 -5
- package/bin/lib/Image/ExifTool/Validate.pm +6 -5
- package/bin/lib/Image/ExifTool/WriteExif.pl +19 -4
- package/bin/lib/Image/ExifTool/WriteQuickTime.pl +1 -0
- package/bin/lib/Image/ExifTool/WriteRIFF.pl +9 -3
- package/bin/lib/Image/ExifTool/Writer.pl +102 -50
- package/bin/lib/Image/ExifTool.pm +74 -36
- package/bin/lib/Image/ExifTool.pod +28 -17
- package/bin/perl-Image-ExifTool.spec +9 -9
- package/bin/pp_build_exe.args +5 -4
- package/package.json +4 -5
|
@@ -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)
|
|
@@ -458,8 +459,8 @@ sub ValidateExif($$$$$$$$)
|
|
|
458
459
|
} elsif (not $otherSpec{$$et{FileType}} or
|
|
459
460
|
(not $otherSpec{$$et{FileType}}{$tag} and not $otherSpec{$$et{FileType}}{All}))
|
|
460
461
|
{
|
|
461
|
-
if ($tagTablePtr eq \%Image::ExifTool::Exif::Main or $$
|
|
462
|
-
$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};
|
|
463
464
|
}
|
|
464
465
|
}
|
|
465
466
|
# change expected count from read Format to Writable size
|
|
@@ -480,7 +481,7 @@ sub ValidateExif($$$$$$$$)
|
|
|
480
481
|
} elsif (not $otherSpec{$$et{FileType}} or
|
|
481
482
|
(not $otherSpec{$$et{FileType}}{$tag} and not $otherSpec{$$et{FileType}}{All}))
|
|
482
483
|
{
|
|
483
|
-
$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};
|
|
484
485
|
}
|
|
485
486
|
}
|
|
486
487
|
|
|
@@ -569,6 +569,7 @@ sub WriteExif($$$)
|
|
|
569
569
|
my $imageDataFlag = $$dirInfo{ImageData} || '';
|
|
570
570
|
my $verbose = $et->Options('Verbose');
|
|
571
571
|
my $out = $et->Options('TextOut');
|
|
572
|
+
my $noMandatory = $et->Options('NoMandatory');
|
|
572
573
|
my ($nextIfdPos, %offsetData, $inMakerNotes);
|
|
573
574
|
my (@offsetInfo, %validateInfo, %xDelete, $strEnc);
|
|
574
575
|
my $deleteAll = 0;
|
|
@@ -698,8 +699,8 @@ sub WriteExif($$$)
|
|
|
698
699
|
}
|
|
699
700
|
|
|
700
701
|
# initialize variables to handle mandatory tags
|
|
701
|
-
my $mandatory
|
|
702
|
-
|
|
702
|
+
my ($mandatory, $allMandatory, $addMandatory);
|
|
703
|
+
$mandatory = $mandatory{$dirName} unless $noMandatory;
|
|
703
704
|
if ($mandatory) {
|
|
704
705
|
# use X/Y resolution values from JFIF if available
|
|
705
706
|
if ($dirName eq 'IFD0' and defined $$et{JFIFYResolution}) {
|
|
@@ -1152,7 +1153,7 @@ Entry: for (;;) {
|
|
|
1152
1153
|
}
|
|
1153
1154
|
my $nvHash;
|
|
1154
1155
|
$nvHash = $et->GetNewValueHash($curInfo, $dirName) if $isNew >= 0;
|
|
1155
|
-
unless ($nvHash or defined $$mandatory{$newID}) {
|
|
1156
|
+
unless ($nvHash or (defined $$mandatory{$newID} and not $noMandatory)) {
|
|
1156
1157
|
goto NoWrite unless $wrongDir; # GOTO !
|
|
1157
1158
|
# delete stuff from the wrong directory if setting somewhere else
|
|
1158
1159
|
$nvHash = $et->GetNewValueHash($curInfo, $wrongDir);
|
|
@@ -2235,6 +2236,19 @@ NoOverwrite: next if $isNew > 0;
|
|
|
2235
2236
|
|
|
2236
2237
|
# do our fixups now so we can more easily calculate offsets below
|
|
2237
2238
|
$fixup->ApplyFixup(\$newData);
|
|
2239
|
+
# write Sony HiddenData now if this is an ARW file
|
|
2240
|
+
if ($$et{HiddenData} and not $$dirInfo{Fixup} and $$et{FILE_TYPE} eq 'TIFF') {
|
|
2241
|
+
$fixup->SetMarkerPointers(\$newData, 'HiddenData', length($newData));
|
|
2242
|
+
my $hbuf;
|
|
2243
|
+
my $hd = $$et{HiddenData};
|
|
2244
|
+
if ($raf->Seek($$hd{Offset}, 0) and $raf->Read($hbuf, $$hd{Size}) == $$hd{Size} and
|
|
2245
|
+
$hbuf =~ /^\x55\x26\x11\x05\0/)
|
|
2246
|
+
{
|
|
2247
|
+
$newData .= $hbuf;
|
|
2248
|
+
} else {
|
|
2249
|
+
$et->Error('Error copying hidden data', 1);
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2238
2252
|
#
|
|
2239
2253
|
# determine total block size for deferred data
|
|
2240
2254
|
#
|
|
@@ -2625,8 +2639,9 @@ NoOverwrite: next if $isNew > 0;
|
|
|
2625
2639
|
$$fixup{Shift} += $newDataPos;
|
|
2626
2640
|
$fixup->ApplyFixup(\$newData);
|
|
2627
2641
|
}
|
|
2628
|
-
# save fixup for adjusting Leica trailer
|
|
2642
|
+
# save fixup for adjusting Leica trailer and Sony HiddenData offsets if necessary
|
|
2629
2643
|
$$et{LeicaTrailer}{Fixup}->AddFixup($fixup) if $$et{LeicaTrailer};
|
|
2644
|
+
$$et{HiddenData}{Fixup}->AddFixup($fixup) if $$et{HiddenData};
|
|
2630
2645
|
# save fixup for PreviewImage in JPEG file if necessary
|
|
2631
2646
|
my $previewInfo = $$et{PREVIEW_INFO};
|
|
2632
2647
|
if ($previewInfo) {
|
|
@@ -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',
|
|
@@ -168,10 +170,10 @@ sub WriteRIFF($$)
|
|
|
168
170
|
#
|
|
169
171
|
# add/edit/delete EXIF/XMP/ICCP (note: EXIF must come before XMP, and ICCP is written elsewhere)
|
|
170
172
|
#
|
|
171
|
-
my %dirName = ( EXIF => 'IFD0', 'XMP ' => 'XMP', ICCP => 'ICC_Profile' );
|
|
172
|
-
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' );
|
|
173
175
|
my $dir;
|
|
174
|
-
foreach $dir ('EXIF', 'XMP ', 'ICCP' ) {
|
|
176
|
+
foreach $dir ('EXIF', 'XMP ', 'ICCP', 'C2PA' ) {
|
|
175
177
|
next unless $tag eq $dir or ($$addDirs{$dir} and
|
|
176
178
|
($tag eq '' or ($tag eq 'XMP ' and $dir eq 'EXIF')));
|
|
177
179
|
my $start;
|
|
@@ -207,6 +209,10 @@ sub WriteRIFF($$)
|
|
|
207
209
|
Parent => $dir,
|
|
208
210
|
DirName => $dirName{$dir},
|
|
209
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
|
+
}
|
|
210
216
|
my $tagTablePtr = GetTagTable("Image::ExifTool::$tblName{$dir}::Main");
|
|
211
217
|
# (override writeProc for EXIF because it has the TIFF header)
|
|
212
218
|
my $writeProc = $dir eq 'EXIF' ? \&Image::ExifTool::WriteTIFF : undef;
|
|
@@ -690,6 +690,12 @@ TAG: foreach $tagInfo (@matchingTags) {
|
|
|
690
690
|
$writeProc = $$src{WRITE_PROC} unless $writeProc;
|
|
691
691
|
}
|
|
692
692
|
{
|
|
693
|
+
# make sure module is loaded if the writeProc is a string
|
|
694
|
+
unless (ref $writeProc) {
|
|
695
|
+
my $module = $writeProc;
|
|
696
|
+
$module =~ s/::\w+$//;
|
|
697
|
+
eval "require $module";
|
|
698
|
+
}
|
|
693
699
|
no strict 'refs';
|
|
694
700
|
next unless $writeProc and &$writeProc();
|
|
695
701
|
}
|
|
@@ -1271,6 +1277,7 @@ sub SetNewValuesFromFile($$;@)
|
|
|
1271
1277
|
# +------------------------------------------+
|
|
1272
1278
|
$srcExifTool->Options(
|
|
1273
1279
|
Binary => 1,
|
|
1280
|
+
ByteUnit => $$options{ByteUnit},
|
|
1274
1281
|
Charset => $$options{Charset},
|
|
1275
1282
|
CharsetEXIF => $$options{CharsetEXIF},
|
|
1276
1283
|
CharsetFileName => $$options{CharsetFileName},
|
|
@@ -3238,9 +3245,15 @@ sub InsertTagValues($$$;$$$)
|
|
|
3238
3245
|
$tag = $docGrp . ':' . $tag;
|
|
3239
3246
|
$lcTag = lc $tag;
|
|
3240
3247
|
}
|
|
3241
|
-
my $et = $self;
|
|
3248
|
+
my ($et, $fileTags) = ($self, $foundTags);
|
|
3242
3249
|
if ($tag =~ s/(\bfile\d+)://i) {
|
|
3243
|
-
$et = $$self{ALT_EXIFTOOL}{ucfirst lc $1}
|
|
3250
|
+
$et = $$self{ALT_EXIFTOOL}{ucfirst lc $1};
|
|
3251
|
+
if ($et) {
|
|
3252
|
+
$fileTags = $$et{FoundTags};
|
|
3253
|
+
} else {
|
|
3254
|
+
$et = $self;
|
|
3255
|
+
$tag = 'no_alt_file';
|
|
3256
|
+
}
|
|
3244
3257
|
}
|
|
3245
3258
|
if ($lcTag eq 'all') {
|
|
3246
3259
|
$val = 1; # always some tag available
|
|
@@ -3251,11 +3264,11 @@ sub InsertTagValues($$$;$$$)
|
|
|
3251
3264
|
($group, $tag) = ($1, $2);
|
|
3252
3265
|
if (lc $tag eq 'all') {
|
|
3253
3266
|
# see if any tag from the specified group exists
|
|
3254
|
-
my $match = $et->GroupMatches($group, $
|
|
3267
|
+
my $match = $et->GroupMatches($group, $fileTags);
|
|
3255
3268
|
$val = $match ? 1 : 0;
|
|
3256
3269
|
} else {
|
|
3257
3270
|
# find the specified tag
|
|
3258
|
-
my @matches = grep /^$tag(\s|$)/i, @$
|
|
3271
|
+
my @matches = grep /^$tag(\s|$)/i, @$fileTags;
|
|
3259
3272
|
@matches = $et->GroupMatches($group, \@matches);
|
|
3260
3273
|
foreach $tg (@matches) {
|
|
3261
3274
|
if (defined $val and $tg =~ / \((\d+)\)$/) {
|
|
@@ -3275,7 +3288,7 @@ sub InsertTagValues($$$;$$$)
|
|
|
3275
3288
|
$val = $et->GetValue($tag, $type);
|
|
3276
3289
|
unless (defined $val) {
|
|
3277
3290
|
# check for tag name with different case
|
|
3278
|
-
($tg) = grep /^$tag$/i, @$
|
|
3291
|
+
($tg) = grep /^$tag$/i, @$fileTags;
|
|
3279
3292
|
if (defined $tg) {
|
|
3280
3293
|
$val = $et->GetValue($tg, $type);
|
|
3281
3294
|
$tag = $tg;
|
|
@@ -3926,7 +3939,7 @@ sub RemoveNewValuesForGroup($$)
|
|
|
3926
3939
|
my $wgrp = $$nvHash{WriteGroup};
|
|
3927
3940
|
# use group1 if write group is not specific
|
|
3928
3941
|
$wgrp = $grp1 if $wgrp eq $grp0;
|
|
3929
|
-
if (grep /^($grp0|$wgrp)$/i, @groups) {
|
|
3942
|
+
if ($grp0 eq '*' or $wgrp eq '*' or grep /^($grp0|$wgrp)$/i, @groups) {
|
|
3930
3943
|
$out and print $out "Removed new value for $wgrp:$$tagInfo{Name}\n";
|
|
3931
3944
|
# remove from linked list
|
|
3932
3945
|
$self->RemoveNewValueHash($nvHash, $tagInfo);
|
|
@@ -4187,7 +4200,10 @@ sub WriteDirectory($$$;$)
|
|
|
4187
4200
|
my $delGroup = $$self{DEL_GROUP};
|
|
4188
4201
|
# delete entire directory if specified
|
|
4189
4202
|
my $grp1 = $dirName;
|
|
4190
|
-
$delFlag = ($$delGroup{$grp0} or $$delGroup{$grp1})
|
|
4203
|
+
$delFlag = ($$delGroup{$grp0} or $$delGroup{$grp1});
|
|
4204
|
+
if ($permanentDir{$grp0} and not ($$dirInfo{TagInfo} and $$dirInfo{TagInfo}{Deletable})) {
|
|
4205
|
+
undef $delFlag;
|
|
4206
|
+
}
|
|
4191
4207
|
# (never delete an entire QuickTime group)
|
|
4192
4208
|
if ($delFlag) {
|
|
4193
4209
|
if (($grp0 =~ /^(MakerNotes)$/ or $grp1 =~ /^(IFD0|ExifIFD|MakerNotes)$/) and
|
|
@@ -4289,7 +4305,21 @@ sub WriteDirectory($$$;$)
|
|
|
4289
4305
|
last unless $self->IsOverwriting($nvHash, $dataPt ? $$dataPt : '');
|
|
4290
4306
|
my $verb = 'Writing';
|
|
4291
4307
|
my $newVal = $self->GetNewValue($nvHash);
|
|
4292
|
-
|
|
4308
|
+
if (defined $newVal and length $newVal) {
|
|
4309
|
+
# hack to add back TIFF header when writing MakerNoteCanon to CMT3 in CR3 images
|
|
4310
|
+
if ($$tagInfo{Name} eq 'MakerNoteCanon') {
|
|
4311
|
+
require Image::ExifTool::Canon;
|
|
4312
|
+
if ($tagInfo eq $Image::ExifTool::Canon::uuid{CMT3}) {
|
|
4313
|
+
my $hdr;
|
|
4314
|
+
if (substr($newVal, 0, 1) eq "\0") {
|
|
4315
|
+
$hdr = "MM\0\x2a" . pack('N', 8);
|
|
4316
|
+
} else {
|
|
4317
|
+
$hdr = "II\x2a\0" . pack('V', 8);
|
|
4318
|
+
}
|
|
4319
|
+
$newVal = $hdr . $newVal;
|
|
4320
|
+
}
|
|
4321
|
+
}
|
|
4322
|
+
} else {
|
|
4293
4323
|
return '' unless $dataPt or $$dirInfo{RAF}; # nothing to do if block never existed
|
|
4294
4324
|
# don't allow MakerNotes to be removed from RAW files
|
|
4295
4325
|
if ($blockName eq 'MakerNotes' and $self->IsRawType() and
|
|
@@ -4645,9 +4675,18 @@ sub DumpUnknownTrailer($$)
|
|
|
4645
4675
|
# account for preview/MPF image trailer
|
|
4646
4676
|
my $prePos = $$self{VALUE}{PreviewImageStart} || $$self{PreviewImageStart};
|
|
4647
4677
|
my $preLen = $$self{VALUE}{PreviewImageLength} || $$self{PreviewImageLength};
|
|
4678
|
+
my $hidPos = $$self{VALUE}{HiddenDataOffset};
|
|
4679
|
+
my $hidLen = $$self{VALUE}{HiddenDataLength};
|
|
4648
4680
|
my $tag = 'PreviewImage';
|
|
4649
4681
|
my $mpImageNum = 0;
|
|
4650
4682
|
my (%image, $lastOne);
|
|
4683
|
+
# add HiddenData to list of known trailer blocks
|
|
4684
|
+
if ($hidPos and $hidLen) {
|
|
4685
|
+
# call ReadHiddenData to validate hidden data and fix offset if necessary
|
|
4686
|
+
require Image::ExifTool::Sony;
|
|
4687
|
+
my $datPt = Image::ExifTool::Sony::ReadHiddenData($self, $hidPos, $hidLen);
|
|
4688
|
+
$image{$hidPos} = ['HiddenData', $hidLen] if $datPt;
|
|
4689
|
+
}
|
|
4651
4690
|
for (;;) {
|
|
4652
4691
|
# add to Preview block list if valid and in the trailer
|
|
4653
4692
|
$image{$prePos} = [$tag, $preLen] if $prePos and $preLen and $prePos+$preLen > $pos;
|
|
@@ -5762,13 +5801,16 @@ sub WriteJPEG($$)
|
|
|
5762
5801
|
}
|
|
5763
5802
|
}
|
|
5764
5803
|
# switch to buffered output if required
|
|
5765
|
-
if (($$self{PREVIEW_INFO} or $$self{LeicaTrailer}
|
|
5804
|
+
if (($$self{PREVIEW_INFO} or $$self{LeicaTrailer} or $$self{HiddenData}) and
|
|
5805
|
+
not $oldOutfile)
|
|
5806
|
+
{
|
|
5766
5807
|
$writeBuffer = '';
|
|
5767
5808
|
$oldOutfile = $outfile;
|
|
5768
5809
|
$outfile = \$writeBuffer;
|
|
5769
5810
|
# account for segment, EXIF and TIFF headers
|
|
5770
5811
|
$$self{PREVIEW_INFO}{Fixup}{Start} += 18 if $$self{PREVIEW_INFO};
|
|
5771
5812
|
$$self{LeicaTrailer}{Fixup}{Start} += 18 if $$self{LeicaTrailer};
|
|
5813
|
+
$$self{HiddenData}{Fixup}{Start} += 18 if $$self{HiddenData};
|
|
5772
5814
|
}
|
|
5773
5815
|
# write as multi-segment
|
|
5774
5816
|
my $n = WriteMultiSegment($outfile, 0xe1, $exifAPP1hdr, \$buff, 'EXIF');
|
|
@@ -5914,7 +5956,9 @@ sub WriteJPEG($$)
|
|
|
5914
5956
|
my $delPreview = $$self{DEL_PREVIEW};
|
|
5915
5957
|
$trailInfo = IdentifyTrailer($raf) unless $$delGroup{Trailer};
|
|
5916
5958
|
my $nvTrail = $self->GetNewValueHash($Image::ExifTool::Extra{Trailer});
|
|
5917
|
-
unless ($oldOutfile or $delPreview or $trailInfo or $$delGroup{Trailer} or $nvTrail
|
|
5959
|
+
unless ($oldOutfile or $delPreview or $trailInfo or $$delGroup{Trailer} or $nvTrail or
|
|
5960
|
+
$$self{HiddenData})
|
|
5961
|
+
{
|
|
5918
5962
|
# blindly copy the rest of the file
|
|
5919
5963
|
while ($raf->Read($buff, 65536)) {
|
|
5920
5964
|
Write($outfile, $buff) or $err = 1, last;
|
|
@@ -5944,7 +5988,7 @@ sub WriteJPEG($$)
|
|
|
5944
5988
|
$endedWithFF = substr($buff, 65535, 1) eq "\xff" ? 1 : 0;
|
|
5945
5989
|
}
|
|
5946
5990
|
# remember position of last data copied
|
|
5947
|
-
$endPos = $raf->Tell() - length($buff);
|
|
5991
|
+
$endPos = $$self{TrailerStart} = $raf->Tell() - length($buff);
|
|
5948
5992
|
# write new trailer if specified
|
|
5949
5993
|
if ($nvTrail) {
|
|
5950
5994
|
# access new value directly to avoid copying a potentially very large data block
|
|
@@ -5958,6 +6002,34 @@ sub WriteJPEG($$)
|
|
|
5958
6002
|
}
|
|
5959
6003
|
last; # all done
|
|
5960
6004
|
}
|
|
6005
|
+
# copy HiddenData if necessary
|
|
6006
|
+
if ($$self{HiddenData}) {
|
|
6007
|
+
my $pad;
|
|
6008
|
+
my $hd = $$self{HiddenData};
|
|
6009
|
+
my $hdOff = $$hd{Offset} + $$hd{Base};
|
|
6010
|
+
require Image::ExifTool::Sony;
|
|
6011
|
+
# read HiddenData, updating $hdOff with actual offset if necessary
|
|
6012
|
+
my $dataPt = Image::ExifTool::Sony::ReadHiddenData($self, $hdOff, $$hd{Size});
|
|
6013
|
+
if ($dataPt) {
|
|
6014
|
+
# preserve padding to avoid invalidating MPF pointers (yuk!)
|
|
6015
|
+
my $padLen = $hdOff - $endPos;
|
|
6016
|
+
unless ($padLen >= 0 and $raf->Seek($endPos,0) and $raf->Read($pad,$padLen)==$padLen) {
|
|
6017
|
+
$self->Error('Error reading HiddenData padding',1);
|
|
6018
|
+
$pad = '';
|
|
6019
|
+
}
|
|
6020
|
+
$endPos += length($pad) + length($$dataPt); # update end position
|
|
6021
|
+
} else {
|
|
6022
|
+
$$dataPt = $pad = '';
|
|
6023
|
+
}
|
|
6024
|
+
my $fixup = $$self{HiddenData}{Fixup};
|
|
6025
|
+
# set MakerNote pointer and size (subtract 10 for segment and EXIF headers)
|
|
6026
|
+
$fixup->SetMarkerPointers($outfile, 'HiddenData', length($$outfile) + length($pad) - 10);
|
|
6027
|
+
# clean up and write the buffered data
|
|
6028
|
+
$outfile = $oldOutfile;
|
|
6029
|
+
undef $oldOutfile;
|
|
6030
|
+
Write($outfile, $writeBuffer, $pad, $$dataPt) or $err = 1;
|
|
6031
|
+
undef $writeBuffer;
|
|
6032
|
+
}
|
|
5961
6033
|
# rewrite existing trailers
|
|
5962
6034
|
if ($trailInfo) {
|
|
5963
6035
|
my $tbuf = '';
|
|
@@ -6067,7 +6139,7 @@ sub WriteJPEG($$)
|
|
|
6067
6139
|
$delPreview = 1; # remove old preview
|
|
6068
6140
|
}
|
|
6069
6141
|
}
|
|
6070
|
-
# copy over preview image if necessary
|
|
6142
|
+
# copy over preview image (or other data) if necessary
|
|
6071
6143
|
unless ($delPreview) {
|
|
6072
6144
|
my $extra;
|
|
6073
6145
|
if ($trailInfo) {
|
|
@@ -6234,13 +6306,16 @@ sub WriteJPEG($$)
|
|
|
6234
6306
|
}
|
|
6235
6307
|
}
|
|
6236
6308
|
# switch to buffered output if required
|
|
6237
|
-
if (($$self{PREVIEW_INFO} or $$self{LeicaTrailer}
|
|
6309
|
+
if (($$self{PREVIEW_INFO} or $$self{LeicaTrailer} or $$self{HiddenData}) and
|
|
6310
|
+
not $oldOutfile)
|
|
6311
|
+
{
|
|
6238
6312
|
$writeBuffer = '';
|
|
6239
6313
|
$oldOutfile = $outfile;
|
|
6240
6314
|
$outfile = \$writeBuffer;
|
|
6241
6315
|
# must account for segment, EXIF and TIFF headers
|
|
6242
6316
|
$$self{PREVIEW_INFO}{Fixup}{Start} += 18 if $$self{PREVIEW_INFO};
|
|
6243
6317
|
$$self{LeicaTrailer}{Fixup}{Start} += 18 if $$self{LeicaTrailer};
|
|
6318
|
+
$$self{HiddenData}{Fixup}{Start} += 18 if $$self{HiddenData};
|
|
6244
6319
|
}
|
|
6245
6320
|
# write as multi-segment
|
|
6246
6321
|
my $n = WriteMultiSegment($outfile, $marker, $exifAPP1hdr, $segDataPt, 'EXIF');
|
|
@@ -7075,7 +7150,7 @@ sub WriteBinaryData($$$)
|
|
|
7075
7150
|
$newVal = length($data) if defined $data;
|
|
7076
7151
|
my $format = $$tagInfo{Format} || $$tagTablePtr{FORMAT} || 'int32u';
|
|
7077
7152
|
if ($format =~ /^int16/ and $newVal > 0xffff) {
|
|
7078
|
-
$self->Error("$$tagInfo{DataTag} is too large (64
|
|
7153
|
+
$self->Error("$$tagInfo{DataTag} is too large (64 KiB max. for this file)");
|
|
7079
7154
|
}
|
|
7080
7155
|
}
|
|
7081
7156
|
my $rtnVal = WriteValue($newVal, $format, $count, $dataPt, $entry);
|
|
@@ -7105,14 +7180,24 @@ sub WriteBinaryData($$$)
|
|
|
7105
7180
|
# ignore if offset is zero (eg. Ricoh DNG uses this to indicate no preview)
|
|
7106
7181
|
next unless $offset;
|
|
7107
7182
|
$fixup->AddFixup($entry, $$tagInfo{DataTag}, $format);
|
|
7108
|
-
|
|
7109
|
-
next unless $$self{FILE_TYPE} eq 'JPEG' and $$tagInfo{DataTag} and
|
|
7110
|
-
$$tagInfo{DataTag} eq 'PreviewImage' and defined $$tagInfo{OffsetPair};
|
|
7183
|
+
next unless $$tagInfo{DataTag} and defined $$tagInfo{OffsetPair};
|
|
7111
7184
|
# NOTE: here we assume there are no var-sized tags between the
|
|
7112
7185
|
# OffsetPair tags. If this ever becomes possible we must recalculate
|
|
7113
7186
|
# $varSize for the OffsetPair tag here!
|
|
7114
7187
|
$entry = $$tagInfo{OffsetPair} * $increment + $varSize;
|
|
7115
7188
|
my $size = ReadValue($dataPt, $entry, $format, 1, $dirLen-$entry);
|
|
7189
|
+
next unless defined $size;
|
|
7190
|
+
if ($$tagInfo{DataTag} eq 'HiddenData') {
|
|
7191
|
+
$$self{HiddenData} = {
|
|
7192
|
+
Offset => $offset,
|
|
7193
|
+
Size => $size,
|
|
7194
|
+
Fixup => new Image::ExifTool::Fixup,
|
|
7195
|
+
Base => $$dirInfo{Base},
|
|
7196
|
+
};
|
|
7197
|
+
next;
|
|
7198
|
+
}
|
|
7199
|
+
# handle the preview image now if this is a JPEG file
|
|
7200
|
+
next unless $$tagInfo{DataTag} eq 'PreviewImage' and $$self{FILE_TYPE} eq 'JPEG';
|
|
7116
7201
|
my $previewInfo = $$self{PREVIEW_INFO};
|
|
7117
7202
|
$previewInfo or $previewInfo = $$self{PREVIEW_INFO} = {
|
|
7118
7203
|
Fixup => new Image::ExifTool::Fixup,
|
|
@@ -7194,39 +7279,6 @@ sub WriteTIFF($$$)
|
|
|
7194
7279
|
{
|
|
7195
7280
|
my ($self, $dirInfo, $tagTablePtr) = @_;
|
|
7196
7281
|
$self or return 1; # allow dummy access
|
|
7197
|
-
# hack to allow MakeNoteCanon to be written as a block in CMT3 chunk of CR3 image
|
|
7198
|
-
if ($$dirInfo{DirName} and $$dirInfo{DirName} eq 'MakerNoteCanon') {
|
|
7199
|
-
require Image::ExifTool::Canon;
|
|
7200
|
-
my $tagInfo = $Image::ExifTool::Canon::uuid{CMT3};
|
|
7201
|
-
my $nvHash;
|
|
7202
|
-
if ($tagInfo and ($nvHash = $$self{NEW_VALUE}{$tagInfo}) and
|
|
7203
|
-
$self->IsOverwriting($nvHash) and not $$nvHash{CreateOnly})
|
|
7204
|
-
{
|
|
7205
|
-
my $newVal = $self->GetNewValue($nvHash);
|
|
7206
|
-
if (defined $newVal and length $newVal) {
|
|
7207
|
-
# fix up offsets
|
|
7208
|
-
if ($$nvHash{MAKER_NOTE_FIXUP}) {
|
|
7209
|
-
# must clone fixup because we will be shifting it
|
|
7210
|
-
my $makerFixup = $$nvHash{MAKER_NOTE_FIXUP}->Clone();
|
|
7211
|
-
$$makerFixup{Shift} += 8; # shift for TIFF header
|
|
7212
|
-
$makerFixup->ApplyFixup(\$newVal);
|
|
7213
|
-
}
|
|
7214
|
-
# add TIFF header
|
|
7215
|
-
my $hdr;
|
|
7216
|
-
if (substr($newVal, 0, 1) eq "\0") {
|
|
7217
|
-
$hdr = "MM\0\x2a" . pack('N', 8);
|
|
7218
|
-
} else {
|
|
7219
|
-
$hdr = "II\x2a\0" . pack('V', 8);
|
|
7220
|
-
}
|
|
7221
|
-
$self->VPrint(0, " Writing MakerNoteCanon as a block\n");
|
|
7222
|
-
++$$self{CHANGED};
|
|
7223
|
-
return $hdr . $newVal;
|
|
7224
|
-
} elsif ($$dirInfo{Parent} and $$dirInfo{Parent} eq 'UUID-Canon') {
|
|
7225
|
-
$self->Warn("Can't delete CanonMakerNotes from $$dirInfo{Parent}");
|
|
7226
|
-
return undef;
|
|
7227
|
-
}
|
|
7228
|
-
}
|
|
7229
|
-
}
|
|
7230
7282
|
my $buff = '';
|
|
7231
7283
|
$$dirInfo{OutFile} = \$buff;
|
|
7232
7284
|
return $buff if $self->ProcessTIFF($dirInfo, $tagTablePtr) > 0;
|