exiftool-vendored.exe 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.
Files changed (43) hide show
  1. package/bin/exiftool_files/Changes +78 -12
  2. package/bin/exiftool_files/README +10 -10
  3. package/bin/exiftool_files/exiftool.pl +32 -27
  4. package/bin/exiftool_files/lib/Image/ExifTool/AAC.pm +175 -0
  5. package/bin/exiftool_files/lib/Image/ExifTool/BuildTagLookup.pm +2 -1
  6. package/bin/exiftool_files/lib/Image/ExifTool/CBOR.pm +18 -2
  7. package/bin/exiftool_files/lib/Image/ExifTool/Canon.pm +82 -20
  8. package/bin/exiftool_files/lib/Image/ExifTool/DJI.pm +3 -2
  9. package/bin/exiftool_files/lib/Image/ExifTool/EXE.pm +54 -6
  10. package/bin/exiftool_files/lib/Image/ExifTool/Exif.pm +111 -11
  11. package/bin/exiftool_files/lib/Image/ExifTool/FujiFilm.pm +145 -20
  12. package/bin/exiftool_files/lib/Image/ExifTool/GIF.pm +5 -1
  13. package/bin/exiftool_files/lib/Image/ExifTool/GoPro.pm +16 -1
  14. package/bin/exiftool_files/lib/Image/ExifTool/ID3.pm +76 -10
  15. package/bin/exiftool_files/lib/Image/ExifTool/InDesign.pm +1 -1
  16. package/bin/exiftool_files/lib/Image/ExifTool/JPEG.pm +1 -1
  17. package/bin/exiftool_files/lib/Image/ExifTool/JSON.pm +4 -1
  18. package/bin/exiftool_files/lib/Image/ExifTool/Jpeg2000.pm +30 -15
  19. package/bin/exiftool_files/lib/Image/ExifTool/M2TS.pm +21 -16
  20. package/bin/exiftool_files/lib/Image/ExifTool/MakerNotes.pm +2 -2
  21. package/bin/exiftool_files/lib/Image/ExifTool/Nikon.pm +203 -102
  22. package/bin/exiftool_files/lib/Image/ExifTool/Olympus.pm +7 -1
  23. package/bin/exiftool_files/lib/Image/ExifTool/PNG.pm +8 -13
  24. package/bin/exiftool_files/lib/Image/ExifTool/Panasonic.pm +10 -1
  25. package/bin/exiftool_files/lib/Image/ExifTool/Pentax.pm +15 -6
  26. package/bin/exiftool_files/lib/Image/ExifTool/QuickTime.pm +59 -13
  27. package/bin/exiftool_files/lib/Image/ExifTool/QuickTimeStream.pl +59 -11
  28. package/bin/exiftool_files/lib/Image/ExifTool/README +7 -2
  29. package/bin/exiftool_files/lib/Image/ExifTool/RIFF.pm +53 -9
  30. package/bin/exiftool_files/lib/Image/ExifTool/Ricoh.pm +109 -1
  31. package/bin/exiftool_files/lib/Image/ExifTool/Samsung.pm +3 -2
  32. package/bin/exiftool_files/lib/Image/ExifTool/Sony.pm +177 -37
  33. package/bin/exiftool_files/lib/Image/ExifTool/TagLookup.pm +6961 -6856
  34. package/bin/exiftool_files/lib/Image/ExifTool/TagNames.pod +580 -344
  35. package/bin/exiftool_files/lib/Image/ExifTool/Text.pm +4 -5
  36. package/bin/exiftool_files/lib/Image/ExifTool/Validate.pm +6 -5
  37. package/bin/exiftool_files/lib/Image/ExifTool/WriteExif.pl +19 -4
  38. package/bin/exiftool_files/lib/Image/ExifTool/WriteQuickTime.pl +1 -0
  39. package/bin/exiftool_files/lib/Image/ExifTool/WriteRIFF.pl +9 -3
  40. package/bin/exiftool_files/lib/Image/ExifTool/Writer.pl +102 -50
  41. package/bin/exiftool_files/lib/Image/ExifTool.pm +74 -36
  42. package/bin/exiftool_files/lib/Image/ExifTool.pod +28 -17
  43. package/package.json +5 -4
@@ -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 kB in which case some
29
- tags are not produced. To avoid long processing delays, ExifTool will issue
30
- a minor warning and process only the first 64 kB of any file larger than 20
31
- MB unless the L<IgnoreMinorErrors|../ExifTool.html#IgnoreMinorErrors> (-m)
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.22';
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 $$tagInfo{Unknown}) {
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 = $mandatory{$dirName};
702
- my ($allMandatory, $addMandatory);
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 offset if necessary
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) {
@@ -1056,6 +1056,7 @@ sub WriteQuickTime($$$)
1056
1056
  Parent => $dirName,
1057
1057
  DirName => $subName,
1058
1058
  Name => $$tagInfo{Name},
1059
+ TagInfo => $tagInfo,
1059
1060
  DirID => $tag,
1060
1061
  DataPt => \$buff,
1061
1062
  DataLen => $size,
@@ -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} or $et=$self, $tag = 'no_alt_file';
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, $foundTags);
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, @$foundTags;
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, @$foundTags;
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}) unless $permanentDir{$grp0};
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
- unless (defined $newVal and length $newVal) {
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}) and not $oldOutfile) {
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}) and not $oldOutfile) {
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 kB max. for this file)");
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
- # handle the preview image now if this is a JPEG file
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;