exiftool-vendored.pl 13.30.0 → 13.32.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 (34) hide show
  1. package/bin/Changes +35 -0
  2. package/bin/META.json +2 -2
  3. package/bin/META.yml +2 -2
  4. package/bin/README +2 -2
  5. package/bin/exiftool +23 -12
  6. package/bin/lib/Image/ExifTool/BuildTagLookup.pm +3 -3
  7. package/bin/lib/Image/ExifTool/Canon.pm +11 -4
  8. package/bin/lib/Image/ExifTool/Exif.pm +6 -3
  9. package/bin/lib/Image/ExifTool/FujiFilm.pm +3 -0
  10. package/bin/lib/Image/ExifTool/GoPro.pm +10 -3
  11. package/bin/lib/Image/ExifTool/LNK.pm +21 -3
  12. package/bin/lib/Image/ExifTool/Lang/de.pm +2 -1
  13. package/bin/lib/Image/ExifTool/Lang/fr.pm +2 -1
  14. package/bin/lib/Image/ExifTool/LigoGPS.pm +14 -6
  15. package/bin/lib/Image/ExifTool/Nikon.pm +13 -5
  16. package/bin/lib/Image/ExifTool/Olympus.pm +2 -1
  17. package/bin/lib/Image/ExifTool/PDF.pm +1 -0
  18. package/bin/lib/Image/ExifTool/Panasonic.pm +1 -1
  19. package/bin/lib/Image/ExifTool/Parrot.pm +1 -1
  20. package/bin/lib/Image/ExifTool/Pentax.pm +179 -52
  21. package/bin/lib/Image/ExifTool/Plot.pm +2 -3
  22. package/bin/lib/Image/ExifTool/QuickTime.pm +3 -2
  23. package/bin/lib/Image/ExifTool/QuickTimeStream.pl +41 -17
  24. package/bin/lib/Image/ExifTool/Sigma.pm +19 -1
  25. package/bin/lib/Image/ExifTool/Sony.pm +2 -1
  26. package/bin/lib/Image/ExifTool/TagLookup.pm +3760 -3750
  27. package/bin/lib/Image/ExifTool/TagNames.pod +32 -9
  28. package/bin/lib/Image/ExifTool/WritePDF.pl +1 -0
  29. package/bin/lib/Image/ExifTool/Writer.pl +134 -131
  30. package/bin/lib/Image/ExifTool/XMPStruct.pl +1 -1
  31. package/bin/lib/Image/ExifTool.pm +6 -4
  32. package/bin/perl-Image-ExifTool.spec +1 -1
  33. package/bin/windows_exiftool.txt +14 -11
  34. package/package.json +12 -5
@@ -12,7 +12,7 @@ meta information extracted from or written to a file.
12
12
  =head1 TAG TABLES
13
13
 
14
14
  The tables listed below give the names of all tags recognized by ExifTool.
15
- They contain a total of 28450 tags, with 17673 unique tag names.
15
+ They contain a total of 28465 tags, with 17681 unique tag names.
16
16
 
17
17
  B<Tag ID>, B<Index#> or B<Sequence> is given in the first column of each
18
18
  table. A B<Tag ID> is the computer-readable equivalent of a tag name, and
@@ -364,11 +364,11 @@ tags remain.
364
364
 
365
365
  The table below lists all EXIF tags. Also listed are TIFF, DNG, HDP and
366
366
  other tags which are not part of the EXIF specification, but may co-exist
367
- with EXIF tags in some images. Tags which are part of the EXIF 2.32
367
+ with EXIF tags in some images. Tags which are part of the EXIF 3.0
368
368
  specification have an underlined B<Tag Name> in the HTML version of this
369
369
  documentation. See
370
- L<https://web.archive.org/web/20190624045241if_/http://www.cipa.jp:80/std/documents/e/DC-008-Translation-2019-E.pdf>
371
- for the official EXIF 2.32 specification.
370
+ L<https://www.cipa.jp/std/documents/download_e.html?CIPA_DC-008-2024-E>
371
+ for the official EXIF 3.0 specification.
372
372
 
373
373
  Tag ID Tag Name Group Writable
374
374
  ------ -------- ----- --------
@@ -1039,6 +1039,8 @@ for the official EXIF 2.32 specification.
1039
1039
  0xc7aa CacheVersion SubIFD2 int32u!
1040
1040
  0xc7b5 DefaultUserCrop SubIFD rational64u[4]!
1041
1041
  0xc7d5 NikonNEFInfo - Nikon NEFInfo
1042
+ 0xc7d7 ZIFMetadata - no
1043
+ 0xc7d8 ZIFAnnotations - no
1042
1044
  0xc7e9 DepthFormat IFD0 int16u!
1043
1045
  0xc7ea DepthNear IFD0 rational64u!
1044
1046
  0xc7eb DepthFar IFD0 rational64u!
@@ -8049,6 +8051,7 @@ boot, not including standby time.
8049
8051
  42 ColorTone int16s
8050
8052
  46 SRAWQuality int16s
8051
8053
  51 Clarity int16s
8054
+ 52 HDR-PQ int16s
8052
8055
 
8053
8056
  =head3 Canon FocalLength Tags
8054
8057
 
@@ -20360,6 +20363,7 @@ These tags are used in Pentax/Asahi cameras.
20360
20363
  0x0402 ToneCurve yes~
20361
20364
  0x0403 ToneCurves yes~
20362
20365
  0x0405 UnknownBlock? undef
20366
+ 0x040c AFInfoK3III Pentax AFInfoK3III
20363
20367
  0x0e00 PrintIM PrintIM
20364
20368
 
20365
20369
  =head3 Pentax LensRec Tags
@@ -20934,6 +20938,20 @@ sensors are located in the camera.
20934
20938
  ------ -------- --------
20935
20939
  [no tags known]
20936
20940
 
20941
+ =head3 Pentax AFInfoK3III Tags
20942
+
20943
+ AF tags written by the K-3 Mark III, GR III and GR IIIx.
20944
+
20945
+ Index2 Tag Name Writable
20946
+ ------ -------- --------
20947
+ 0 AFInfo? int16u[$size/2]
20948
+ 0.1 AFMode int16u
20949
+ 1 AFSelectionMode int16u
20950
+ 3 NumAFPoints int16u
20951
+ 7 AFFrameSize no
20952
+ 7.1 AFAreas no+
20953
+ 11 AFAreaSize no
20954
+
20937
20955
  =head3 Pentax Type2 Tags
20938
20956
 
20939
20957
  These tags are used by the Pentax Optio 330 and 430, and are similar to the
@@ -21811,6 +21829,7 @@ are less than consistent about their metadata formats.
21811
21829
  0x003b Firmware string
21812
21830
  0x003c WhiteBalance string
21813
21831
  0x003d PictureMode string
21832
+ 0x0047 ExposureCompensation rational64s
21814
21833
  0x0048 LensApertureRange string
21815
21834
  0x0049 FNumber rational64u
21816
21835
  0x004a ExposureTime rational64u
@@ -21826,9 +21845,12 @@ are less than consistent about their metadata formats.
21826
21845
  0x0087 ResolutionMode string
21827
21846
  0x0088 WhiteBalance string
21828
21847
  0x008c Firmware string
21848
+ 0x0113 PictureModeStrength int32s
21829
21849
  0x011f CameraCalibration float[9]
21830
21850
  0x0120 WBSettings Sigma WBSettings
21831
21851
  0x0121 WBSettings2 Sigma WBSettings2
21852
+ 0x0138 Fade rational64u
21853
+ 0x0139 Vignette rational64u
21832
21854
 
21833
21855
  =head3 Sigma WBSettings Tags
21834
21856
 
@@ -29664,10 +29686,11 @@ C2PA JUMBF metadata extracted from "/C2PA_Manifest" file.
29664
29686
 
29665
29687
  =head3 PDF Pages Tags
29666
29688
 
29667
- Tag ID Tag Name Writable
29668
- ------ -------- --------
29669
- 'Count' PageCount no
29670
- 'Kids' Kids PDF Kids
29689
+ Tag ID Tag Name Writable
29690
+ ------ -------- --------
29691
+ 'Count' PageCount no
29692
+ 'Kids' Kids PDF Kids
29693
+ 'MediaBox' MediaBox no+
29671
29694
 
29672
29695
  =head3 PDF Kids Tags
29673
29696
 
@@ -30380,7 +30403,7 @@ for the official QuickTime specification.
30380
30403
  The tags below are extracted from timed metadata in QuickTime and other
30381
30404
  formats of video files when the ExtractEmbedded option is used. Although
30382
30405
  most of these tags are combined into the single table below, ExifTool
30383
- currently reads 107 different types of timed GPS metadata from video files.
30406
+ currently reads 110 different types of timed GPS metadata from video files.
30384
30407
 
30385
30408
  Tag ID Tag Name Writable
30386
30409
  ------ -------- --------
@@ -81,6 +81,7 @@ sub WritePDFValue($$$)
81
81
  EncodeString(\$val);
82
82
  } elsif ($format eq 'date') {
83
83
  # convert date to "D:YYYYmmddHHMMSS+-HH'MM'" format
84
+ $val =~ s/(:\d{2})\.\d*/$1/; # remove sub-seconds
84
85
  $val =~ s/([-+]\d{2}):(\d{2})/${1}'${2}'/; # change timezone delimiters if necessary
85
86
  $val =~ tr/ ://d; # remove spaces and colons
86
87
  $val = "D:$val"; # add leading "D:"
@@ -1907,7 +1907,7 @@ sub RestoreNewValues($)
1907
1907
  #------------------------------------------------------------------------------
1908
1908
  # Set alternate file for extracting information
1909
1909
  # Inputs: 0) ExifTool ref, 1) family 8 group name (of the form "File#" where # is any number)
1910
- # 2) alternate file name, or undef to reset
1910
+ # 2) alternate file name (may contain tag names with leading "$"), or undef to reset
1911
1911
  # Returns: 1 on success, or 0 on invalid group name
1912
1912
  sub SetAlternateFile($$$)
1913
1913
  {
@@ -1917,7 +1917,9 @@ sub SetAlternateFile($$$)
1917
1917
  # keep the same file if already initialized (possibly has metadata extracted)
1918
1918
  if (not defined $file) {
1919
1919
  delete $$self{ALT_EXIFTOOL}{$g8};
1920
- } elsif (not ($$self{ALT_EXIFTOOL}{$g8} and $$self{ALT_EXIFTOOL}{$g8}{ALT_FILE} eq $file)) {
1920
+ } elsif (not ($$self{ALT_EXIFTOOL}{$g8} and $file !~ /\$/ and
1921
+ $$self{ALT_EXIFTOOL}{$g8}{ALT_FILE} eq $file))
1922
+ {
1921
1923
  my $altExifTool = Image::ExifTool->new;
1922
1924
  $$altExifTool{ALT_FILE} = $file;
1923
1925
  $$self{ALT_EXIFTOOL}{$g8} = $altExifTool;
@@ -4741,10 +4743,11 @@ sub DumpUnknownTrailer($$)
4741
4743
  my $pos = $$dirInfo{DataPos};
4742
4744
  my $endPos = $pos + $$dirInfo{DirLen};
4743
4745
  # account for preview/MPF image trailer
4744
- my $prePos = $$self{VALUE}{PreviewImageStart} || $$self{PreviewImageStart};
4745
- my $preLen = $$self{VALUE}{PreviewImageLength} || $$self{PreviewImageLength};
4746
- my $hidPos = $$self{VALUE}{HiddenDataOffset};
4747
- my $hidLen = $$self{VALUE}{HiddenDataLength};
4746
+ my $value = $$self{VALUE};
4747
+ my $prePos = $$value{PreviewImageStart} || $$self{PreviewImageStart};
4748
+ my $preLen = $$value{PreviewImageLength} || $$self{PreviewImageLength};
4749
+ my $hidPos = $$value{HiddenDataOffset};
4750
+ my $hidLen = $$value{HiddenDataLength};
4748
4751
  my $tag = 'PreviewImage';
4749
4752
  my $mpImageNum = 0;
4750
4753
  my (%image, $lastOne);
@@ -4761,12 +4764,12 @@ sub DumpUnknownTrailer($$)
4761
4764
  last if $lastOne; # checked all images
4762
4765
  # look for MPF images (in the proper order)
4763
4766
  ++$mpImageNum;
4764
- $prePos = $$self{VALUE}{"MPImageStart ($mpImageNum)"};
4767
+ $prePos = $$value{"MPImageStart ($mpImageNum)"};
4765
4768
  if (defined $prePos) {
4766
- $preLen = $$self{VALUE}{"MPImageLength ($mpImageNum)"};
4769
+ $preLen = $$value{"MPImageLength ($mpImageNum)"};
4767
4770
  } else {
4768
- $prePos = $$self{VALUE}{'MPImageStart'};
4769
- $preLen = $$self{VALUE}{'MPImageLength'};
4771
+ $prePos = $$value{MPImageStart};
4772
+ $preLen = $$value{MPImageLength};
4770
4773
  $lastOne = 1;
4771
4774
  }
4772
4775
  $tag = "MPImage$mpImageNum";
@@ -5887,10 +5890,10 @@ sub WriteJPEG($$)
5887
5890
  $writeBuffer = '';
5888
5891
  $oldOutfile = $outfile;
5889
5892
  $outfile = \$writeBuffer;
5890
- # account for segment, EXIF and TIFF headers
5891
- $$self{PREVIEW_INFO}{Fixup}{Start} += 18 if $$self{PREVIEW_INFO};
5892
- $$self{LeicaTrailer}{Fixup}{Start} += 18 if $$self{LeicaTrailer};
5893
- $$self{HiddenData}{Fixup}{Start} += 18 if $$self{HiddenData};
5893
+ # must account for segment, EXIF and TIFF headers
5894
+ foreach (qw(PREVIEW_INFO LeicaTrailer HiddenData)) {
5895
+ $$self{$_}{Fixup}{Start} += 18 if $$self{$_};
5896
+ }
5894
5897
  }
5895
5898
  # write as multi-segment
5896
5899
  my $n = WriteMultiSegment($outfile, 0xe1, $exifAPP1hdr, \$buff, 'EXIF');
@@ -6036,8 +6039,8 @@ sub WriteJPEG($$)
6036
6039
  my $delPreview = $$self{DEL_PREVIEW};
6037
6040
  $trailInfo = $self->IdentifyTrailer($raf) unless $$delGroup{Trailer};
6038
6041
  my $nvTrail = $self->GetNewValueHash($Image::ExifTool::Extra{Trailer});
6039
- unless ($oldOutfile or $delPreview or $trailInfo or $$delGroup{Trailer} or $nvTrail or
6040
- $$self{HiddenData})
6042
+ unless ($oldOutfile or $delPreview or $trailInfo or $$delGroup{Trailer} or
6043
+ $nvTrail or $$self{HiddenData})
6041
6044
  {
6042
6045
  # blindly copy the rest of the file
6043
6046
  while ($raf->Read($buff, 65536)) {
@@ -6082,35 +6085,7 @@ sub WriteJPEG($$)
6082
6085
  }
6083
6086
  last; # all done
6084
6087
  }
6085
- # copy HiddenData if necessary
6086
- if ($$self{HiddenData}) {
6087
- my $pad;
6088
- my $hd = $$self{HiddenData};
6089
- my $hdOff = $$hd{Offset} + $$hd{Base};
6090
- require Image::ExifTool::Sony;
6091
- # read HiddenData, updating $hdOff with actual offset if necessary
6092
- my $dataPt = Image::ExifTool::Sony::ReadHiddenData($self, $hdOff, $$hd{Size});
6093
- if ($dataPt) {
6094
- # preserve padding to avoid invalidating MPF pointers (yuk!)
6095
- my $padLen = $hdOff - $endPos;
6096
- unless ($padLen >= 0 and $raf->Seek($endPos,0) and $raf->Read($pad,$padLen)==$padLen) {
6097
- $self->Error('Error reading HiddenData padding',1);
6098
- $pad = '';
6099
- }
6100
- $endPos += length($pad) + length($$dataPt); # update end position
6101
- } else {
6102
- $$dataPt = $pad = '';
6103
- }
6104
- my $fixup = $$self{HiddenData}{Fixup};
6105
- # set MakerNote pointer and size (subtract 10 for segment and EXIF headers)
6106
- $fixup->SetMarkerPointers($outfile, 'HiddenData', length($$outfile) + length($pad) - 10);
6107
- # clean up and write the buffered data
6108
- $outfile = $oldOutfile;
6109
- undef $oldOutfile;
6110
- Write($outfile, $writeBuffer, $pad, $$dataPt) or $err = 1;
6111
- undef $writeBuffer;
6112
- }
6113
- # rewrite existing trailers
6088
+ # rewrite existing trailers into buffer
6114
6089
  if ($trailInfo) {
6115
6090
  my $tbuf = '';
6116
6091
  $raf->Seek(-length($buff), 1); # seek back to just after EOI
@@ -6118,100 +6093,126 @@ sub WriteJPEG($$)
6118
6093
  $$trailInfo{ScanForTrailer} = 1;# scan if necessary
6119
6094
  $self->ProcessTrailers($trailInfo) or undef $trailInfo;
6120
6095
  }
6121
- if (not $oldOutfile) {
6122
- # do nothing special
6123
- } elsif ($$self{LeicaTrailer}) {
6124
- my $trailLen;
6125
- if ($trailInfo) {
6126
- $trailLen = $$trailInfo{DataPos} - $endPos;
6127
- } else {
6128
- $raf->Seek(0, 2) or $err = 1;
6129
- $trailLen = $raf->Tell() - $endPos;
6130
- }
6131
- my $fixup = $$self{LeicaTrailer}{Fixup};
6132
- $$self{LeicaTrailer}{TrailPos} = $endPos;
6133
- $$self{LeicaTrailer}{TrailLen} = $trailLen;
6134
- # get _absolute_ position of new Leica trailer
6135
- my $absPos = Tell($oldOutfile) + length($$outfile);
6136
- require Image::ExifTool::Panasonic;
6137
- my $dat = Image::ExifTool::Panasonic::ProcessLeicaTrailer($self, $absPos);
6138
- # allow some junk before Leica trailer (just in case)
6139
- my $junk = $$self{LeicaTrailerPos} - $endPos;
6140
- # set MakerNote pointer and size (subtract 10 for segment and EXIF headers)
6141
- $fixup->SetMarkerPointers($outfile, 'LeicaTrailer', length($$outfile) - 10 + $junk);
6142
- # use this fixup to set the size too (sneaky)
6143
- my $trailSize = defined($dat) ? length($dat) - $junk : $$self{LeicaTrailer}{Size};
6144
- $$fixup{Start} -= 4; $$fixup{Shift} += 4;
6145
- $fixup->SetMarkerPointers($outfile, 'LeicaTrailer', $trailSize) if defined $trailSize;
6146
- $$fixup{Start} += 4; $$fixup{Shift} -= 4;
6147
- # clean up and write the buffered data
6148
- $outfile = $oldOutfile;
6149
- undef $oldOutfile;
6150
- Write($outfile, $writeBuffer) or $err = 1;
6151
- undef $writeBuffer;
6152
- if (defined $dat) {
6153
- Write($outfile, $dat) or $err = 1; # write new Leica trailer
6154
- $delPreview = 1; # delete existing Leica trailer
6096
+ if ($oldOutfile) {
6097
+ my $previewInfo;
6098
+ # copy HiddenData if necessary
6099
+ if ($$self{HiddenData}) {
6100
+ my $pad;
6101
+ my $hd = $$self{HiddenData};
6102
+ my $hdOff = $$hd{Offset} + $$hd{Base};
6103
+ require Image::ExifTool::Sony;
6104
+ # read HiddenData, updating $hdOff with actual offset if necessary
6105
+ my $dataPt = Image::ExifTool::Sony::ReadHiddenData($self, $hdOff, $$hd{Size});
6106
+ if ($dataPt) {
6107
+ # preserve padding to avoid invalidating MPF pointers (yuk!)
6108
+ my $padLen = $hdOff - $endPos;
6109
+ unless ($padLen >= 0 and $raf->Seek($endPos,0) and $raf->Read($pad,$padLen)==$padLen) {
6110
+ $self->Error('Error reading HiddenData padding',1);
6111
+ $pad = '';
6112
+ }
6113
+ $endPos += length($pad) + length($$dataPt); # update end position
6114
+ } else {
6115
+ $$dataPt = $pad = '';
6116
+ }
6117
+ my $fixup = $$self{HiddenData}{Fixup};
6118
+ # set MakerNote pointer and size (subtract 10 for segment and EXIF headers)
6119
+ $fixup->SetMarkerPointers($outfile, 'HiddenData', length($$outfile) + length($pad) - 10);
6120
+ $writeBuffer .= $pad . $$dataPt; # keep padding for now
6155
6121
  }
6156
- } else {
6157
- # locate preview image and fix up preview offsets
6158
- my $scanLen = $$self{Make} =~ /^SONY/i ? 65536 : 1024;
6159
- if (length($buff) < $scanLen) { # make sure we have enough trailer to scan
6160
- my $buf2;
6161
- $buff .= $buf2 if $raf->Read($buf2, $scanLen - length($buff));
6122
+ if ($$self{LeicaTrailer}) {
6123
+ my $trailLen;
6124
+ if ($trailInfo) {
6125
+ $trailLen = $$trailInfo{DataPos} - $endPos;
6126
+ } else {
6127
+ $raf->Seek(0, 2) or $err = 1;
6128
+ $trailLen = $raf->Tell() - $endPos;
6129
+ }
6130
+ my $fixup = $$self{LeicaTrailer}{Fixup};
6131
+ $$self{LeicaTrailer}{TrailPos} = $endPos;
6132
+ $$self{LeicaTrailer}{TrailLen} = $trailLen;
6133
+ # get _absolute_ position of new Leica trailer
6134
+ my $absPos = Tell($oldOutfile) + length($$outfile);
6135
+ require Image::ExifTool::Panasonic;
6136
+ my $dat = Image::ExifTool::Panasonic::ProcessLeicaTrailer($self, $absPos);
6137
+ # allow some junk before Leica trailer (just in case)
6138
+ my $junk = $$self{LeicaTrailerPos} - $endPos;
6139
+ # set MakerNote pointer and size (subtract 10 for segment and EXIF headers)
6140
+ $fixup->SetMarkerPointers($outfile, 'LeicaTrailer', length($$outfile) - 10 + $junk);
6141
+ # use this fixup to set the size too (sneaky)
6142
+ my $trailSize = defined($dat) ? length($dat) - $junk : $$self{LeicaTrailer}{Size};
6143
+ $$fixup{Start} -= 4; $$fixup{Shift} += 4;
6144
+ $fixup->SetMarkerPointers($outfile, 'LeicaTrailer', $trailSize) if defined $trailSize;
6145
+ $$fixup{Start} += 4; $$fixup{Shift} -= 4;
6146
+ if (defined $dat) {
6147
+ Write($outfile, $dat) or $err = 1; # write new Leica trailer
6148
+ $delPreview = 1; # delete existing Leica trailer
6149
+ }
6162
6150
  }
6163
- # get new preview image position, relative to EXIF base
6164
- my $newPos = length($$outfile) - 10; # (subtract 10 for segment and EXIF headers)
6165
- my $junkLen;
6166
- # adjust position if image isn't at the start (eg. Olympus E-1/E-300)
6167
- if ($buff =~ /(\xff\xd8\xff.|.\xd8\xff\xdb)(..)/sg) {
6168
- my ($jpegHdr, $segLen) = ($1, $2);
6169
- $junkLen = pos($buff) - 6;
6170
- # Sony previewimage trailer has a 32 byte header
6171
- if ($$self{Make} =~ /^SONY/i and $junkLen > 32) {
6172
- # with some newer Sony models, the makernotes preview pointer
6173
- # points to JPEG at end of EXIF inside MPImage preview (what a pain!)
6174
- if ($jpegHdr eq "\xff\xd8\xff\xe1") { # is the first segment EXIF?
6175
- $segLen = unpack('n', $segLen); # the EXIF segment length
6176
- # Sony PreviewImage starts with last 2 bytes of EXIF segment
6177
- # (and first byte is usually "\0", not "\xff", so don't check this)
6178
- if (length($buff) > $junkLen + $segLen + 6 and
6179
- substr($buff, $junkLen + $segLen + 3, 3) eq "\xd8\xff\xdb")
6180
- {
6181
- $junkLen += $segLen + 2;
6182
- # (note: this will not copy the trailer after PreviewImage,
6183
- # which is a 14kB block full of zeros for the A77)
6151
+ # handle preview image last
6152
+ if ($$self{PREVIEW_INFO}) {
6153
+ # locate preview image and fix up preview offsets
6154
+ my $scanLen = $$self{Make} =~ /^SONY/i ? 65536 : 1024;
6155
+ if (length($buff) < $scanLen) { # make sure we have enough trailer to scan
6156
+ my $buf2;
6157
+ $buff .= $buf2 if $raf->Read($buf2, $scanLen - length($buff));
6158
+ }
6159
+ # get new preview image position, relative to EXIF base
6160
+ my $newPos = length($$outfile) - 10; # (subtract 10 for segment and EXIF headers)
6161
+ my $junkLen;
6162
+ # adjust position if image isn't at the start (eg. Olympus E-1/E-300)
6163
+ if ($buff =~ /(\xff\xd8\xff.|.\xd8\xff\xdb)(..)/sg) {
6164
+ my ($jpegHdr, $segLen) = ($1, $2);
6165
+ $junkLen = pos($buff) - 6;
6166
+ # Sony previewimage trailer has a 32 byte header
6167
+ if ($$self{Make} =~ /^SONY/i and $junkLen > 32) {
6168
+ # with some newer Sony models, the makernotes preview pointer
6169
+ # points to JPEG at end of EXIF inside MPImage preview (what a pain!)
6170
+ if ($jpegHdr eq "\xff\xd8\xff\xe1") { # is the first segment EXIF?
6171
+ $segLen = unpack('n', $segLen); # the EXIF segment length
6172
+ # Sony PreviewImage starts with last 2 bytes of EXIF segment
6173
+ # (and first byte is usually "\0", not "\xff", so don't check this)
6174
+ if (length($buff) > $junkLen + $segLen + 6 and
6175
+ substr($buff, $junkLen + $segLen + 3, 3) eq "\xd8\xff\xdb")
6176
+ {
6177
+ $junkLen += $segLen + 2;
6178
+ # (note: this will not copy the trailer after PreviewImage,
6179
+ # which is a 14kB block full of zeros for the A77)
6180
+ }
6184
6181
  }
6182
+ $junkLen -= 32;
6185
6183
  }
6186
- $junkLen -= 32;
6184
+ $newPos += $junkLen;
6185
+ }
6186
+ # fix up the preview offsets to point to the start of the new image
6187
+ $previewInfo = $$self{PREVIEW_INFO};
6188
+ delete $$self{PREVIEW_INFO};
6189
+ my $fixup = $$previewInfo{Fixup};
6190
+ $newPos += ($$previewInfo{BaseShift} || 0);
6191
+ # adjust to absolute file offset if necessary (Samsung STMN)
6192
+ $newPos += Tell($oldOutfile) + 10 if $$previewInfo{Absolute};
6193
+ if ($$previewInfo{Relative}) {
6194
+ # adjust for our base by looking at how far the pointer got shifted
6195
+ $newPos -= ($fixup->GetMarkerPointers($outfile, 'PreviewImage') || 0);
6196
+ } elsif ($$previewInfo{ChangeBase}) {
6197
+ # Leica S2 uses relative offsets for the preview only (leica sucks)
6198
+ my $makerOffset = $fixup->GetMarkerPointers($outfile, 'LeicaTrailer');
6199
+ $newPos -= $makerOffset if $makerOffset;
6200
+ }
6201
+ $fixup->SetMarkerPointers($outfile, 'PreviewImage', $newPos);
6202
+ if ($$previewInfo{Data} ne 'LOAD_PREVIEW') {
6203
+ # write any junk that existed before the preview image
6204
+ $$previewInfo{Junk} = substr($buff,0,$junkLen) if $junkLen;
6187
6205
  }
6188
- $newPos += $junkLen;
6189
- }
6190
- # fix up the preview offsets to point to the start of the new image
6191
- my $previewInfo = $$self{PREVIEW_INFO};
6192
- delete $$self{PREVIEW_INFO};
6193
- my $fixup = $$previewInfo{Fixup};
6194
- $newPos += ($$previewInfo{BaseShift} || 0);
6195
- # adjust to absolute file offset if necessary (Samsung STMN)
6196
- $newPos += Tell($oldOutfile) + 10 if $$previewInfo{Absolute};
6197
- if ($$previewInfo{Relative}) {
6198
- # adjust for our base by looking at how far the pointer got shifted
6199
- $newPos -= ($fixup->GetMarkerPointers($outfile, 'PreviewImage') || 0);
6200
- } elsif ($$previewInfo{ChangeBase}) {
6201
- # Leica S2 uses relative offsets for the preview only (leica sucks)
6202
- my $makerOffset = $fixup->GetMarkerPointers($outfile, 'LeicaTrailer');
6203
- $newPos -= $makerOffset if $makerOffset;
6204
6206
  }
6205
- $fixup->SetMarkerPointers($outfile, 'PreviewImage', $newPos);
6206
6207
  # clean up and write the buffered data
6207
6208
  $outfile = $oldOutfile;
6208
6209
  undef $oldOutfile;
6209
6210
  Write($outfile, $writeBuffer) or $err = 1;
6210
6211
  undef $writeBuffer;
6211
6212
  # write preview image
6212
- if ($$previewInfo{Data} ne 'LOAD_PREVIEW') {
6213
+ if ($previewInfo and $$previewInfo{Data} ne 'LOAD_PREVIEW') {
6213
6214
  # write any junk that existed before the preview image
6214
- Write($outfile, substr($buff,0,$junkLen)) or $err = 1 if $junkLen;
6215
+ Write($outfile, $$previewInfo{Junk}) or $err = 1 if defined $$previewInfo{Junk};
6215
6216
  # write the saved preview image
6216
6217
  Write($outfile, $$previewInfo{Data}) or $err = 1;
6217
6218
  delete $$previewInfo{Data};
@@ -6224,7 +6225,7 @@ sub WriteJPEG($$)
6224
6225
  my $extra;
6225
6226
  if ($trailInfo) {
6226
6227
  # copy everything up to start of first processed trailer
6227
- $extra = $$trailInfo{DataPos} - $endPos;
6228
+ $extra = defined $$trailInfo{DataPos} ? ($$trailInfo{DataPos} - $endPos) : 0;
6228
6229
  } else {
6229
6230
  # copy everything up to end of file
6230
6231
  $raf->Seek(0, 2) or $err = 1;
@@ -6393,9 +6394,9 @@ sub WriteJPEG($$)
6393
6394
  $oldOutfile = $outfile;
6394
6395
  $outfile = \$writeBuffer;
6395
6396
  # must account for segment, EXIF and TIFF headers
6396
- $$self{PREVIEW_INFO}{Fixup}{Start} += 18 if $$self{PREVIEW_INFO};
6397
- $$self{LeicaTrailer}{Fixup}{Start} += 18 if $$self{LeicaTrailer};
6398
- $$self{HiddenData}{Fixup}{Start} += 18 if $$self{HiddenData};
6397
+ foreach (qw(PREVIEW_INFO LeicaTrailer HiddenData)) {
6398
+ $$self{$_}{Fixup}{Start} += 18 if $$self{$_};
6399
+ }
6399
6400
  }
6400
6401
  # write as multi-segment
6401
6402
  my $n = WriteMultiSegment($outfile, $marker, $exifAPP1hdr, $segDataPt, 'EXIF');
@@ -6922,7 +6923,7 @@ sub CheckBinaryData($$$)
6922
6923
  $format = $1;
6923
6924
  $count = $2;
6924
6925
  # can't evaluate $count now because we don't know $size yet
6925
- undef $count if $count =~ /\$size/;
6926
+ $count = -1 if $count =~ /\$size/; # (-1 = any count allowed)
6926
6927
  }
6927
6928
  return CheckValue($valPtr, $format, $count);
6928
6929
  }
@@ -7248,6 +7249,8 @@ sub WriteBinaryData($$$)
7248
7249
  $self->VerboseValue("- $dirName:$$tagInfo{Name}", $val);
7249
7250
  $self->VerboseValue("+ $dirName:$$tagInfo{Name}", $newVal);
7250
7251
  ++$$self{CHANGED};
7252
+ } else {
7253
+ $self->Warn("Error packing $$tagInfo{Name} value");
7251
7254
  }
7252
7255
  }
7253
7256
  # add necessary fixups for any offsets
@@ -86,7 +86,7 @@ sub InflateStruct($$;$)
86
86
  my %struct;
87
87
  for (;;) {
88
88
  last unless $sfmt ? $$obj =~ s/^\s*"(.*?)"\s*://s :
89
- $$obj =~ s/^\s*([-\w:]+#?)\s*=//s;
89
+ $$obj =~ s/^\s*([-\w:.]+#?)\s*=//s;
90
90
  my $tag = $1;
91
91
  my ($v, $w) = InflateStruct($et, $obj, '}');
92
92
  $warn = $w if $w and not $warn;
@@ -29,7 +29,7 @@ use vars qw($VERSION $RELEASE @ISA @EXPORT_OK %EXPORT_TAGS $AUTOLOAD @fileTypes
29
29
  %jpegMarker %specialTags %fileTypeLookup $testLen $exeDir
30
30
  %static_vars $advFmtSelf $configFile @configFiles $noConfig);
31
31
 
32
- $VERSION = '13.30';
32
+ $VERSION = '13.32';
33
33
  $RELEASE = '';
34
34
  @ISA = qw(Exporter);
35
35
  %EXPORT_TAGS = (
@@ -42,7 +42,7 @@ $RELEASE = '';
42
42
  # exports not part of the public API, but used by ExifTool modules:
43
43
  DataAccess => [qw(
44
44
  ReadValue GetByteOrder SetByteOrder ToggleByteOrder Get8u Get8s Get16u
45
- Get16s Get32u Get32s Get64u GetFloat GetDouble GetFixed32s Write
45
+ Get16s Get32u Get32s Get64u Get64s GetFloat GetDouble GetFixed32s Write
46
46
  WriteValue Tell Set8u Set8s Set16u Set32u Set64u Set64s
47
47
  )],
48
48
  Utils => [qw(GetTagTable TagTableKeys GetTagInfoList AddTagToTable HexDump)],
@@ -9719,8 +9719,10 @@ sub ExtractBinary($$$;$)
9719
9719
  $isPreview = 1;
9720
9720
  }
9721
9721
  my $lcTag = lc $tag;
9722
- if ((not $$self{OPTIONS}{Binary} or $$self{EXCL_TAG_LOOKUP}{$lcTag}) and
9723
- not $$self{OPTIONS}{Verbose} and not $$self{REQ_TAG_LOOKUP}{$lcTag})
9722
+ my $options = $$self{OPTIONS};
9723
+ if ((not $$options{Binary} or $$self{EXCL_TAG_LOOKUP}{$lcTag}) and
9724
+ not $$options{Verbose} and not $$options{Validate} and
9725
+ not $$self{REQ_TAG_LOOKUP}{$lcTag})
9724
9726
  {
9725
9727
  return "Binary data $length bytes";
9726
9728
  }
@@ -1,6 +1,6 @@
1
1
  Summary: perl module for image data extraction
2
2
  Name: perl-Image-ExifTool
3
- Version: 13.30
3
+ Version: 13.32
4
4
  Release: 1
5
5
  License: Artistic/GPL
6
6
  Group: Development/Libraries/Perl
@@ -611,11 +611,13 @@ OPTIONS
611
611
  useful for some text strings since control characters (such as
612
612
  newlines) are not replaced by '.' as they are in the default
613
613
  output. By default, list items are separated by a newline when
614
- extracted with the -b option, but this may be changed (see the -sep
615
- option for details). May be combined with -j, -php or -X to extract
616
- binary data in JSON, PHP or XML format, but note that "Unsafe" tags
617
- are not extracted as binary unless they are specified explicitly or
618
- the API RequestAll option is set to 3 or higher.
614
+ extracted with the -b option and no terminator is added after each
615
+ tag value, but the list separator may be changed with a -sep option
616
+ and a terminator may be set by adding a second -sep option (see the
617
+ -sep option for details). May be combined with -j, -php or -X to
618
+ extract binary data in JSON, PHP or XML format, but note that
619
+ "Unsafe" tags are not extracted as binary unless they are specified
620
+ explicitly or the API RequestAll option is set to 3 or higher.
619
621
 
620
622
  With a leading double dash (--b or --binary), tags which contain
621
623
  binary data are suppressed in the output when reading.
@@ -1079,7 +1081,7 @@ OPTIONS
1079
1081
 
1080
1082
  produces output like this:
1081
1083
 
1082
- -- Generated by ExifTool 13.30 --
1084
+ -- Generated by ExifTool 13.32 --
1083
1085
  File: a.jpg - 2003:10:31 15:44:19
1084
1086
  (f/5.6, 1/60s, ISO 100)
1085
1087
  File: b.jpg - 2006:05:23 11:57:38
@@ -1895,9 +1897,10 @@ OPTIONS
1895
1897
  with -listf, -listr or -listwf to add file descriptions to the
1896
1898
  list. The -lang option may be combined with -listx to output
1897
1899
  descriptions in a single language, and the -sort and/or -lang
1898
- options may be combined with -listgeo. Also, the API GeolocMinPop,
1899
- GeolocFeature and GeolocAltNames options apply to the -listgeo
1900
- output. Here are some examples:
1900
+ options may be combined with -listgeo (installation of the
1901
+ alternate database is required for the additional languages). Also,
1902
+ the API GeolocMinPop, GeolocFeature and GeolocAltNames options
1903
+ apply to the -listgeo output. Here are some examples:
1901
1904
 
1902
1905
  -list # list all tag names
1903
1906
  -list -EXIF:All # list all EXIF tags
@@ -2307,6 +2310,8 @@ OPTIONS
2307
2310
  in file names.)
2308
2311
 
2309
2312
  Helper functions
2313
+ Note that function names are case sensitive.
2314
+
2310
2315
  "DateFmt"
2311
2316
 
2312
2317
  Simplifies reformatting of individual date/time values. This function
@@ -2345,8 +2350,6 @@ OPTIONS
2345
2350
 
2346
2351
  exiftool -sep "##" "-keywords<${keywords;NoDups(1)}" a.jpg
2347
2352
 
2348
- Note that function names are case sensitive.
2349
-
2350
2353
  ExifTool 12.64 adds an API NoDups option which makes the NoDups helper
2351
2354
  function largely redundant, with all the functionality except the
2352
2355
  ability to avoid rewriting the file if there are no duplicates, but with
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "exiftool-vendored.pl",
3
- "version": "13.30.0",
3
+ "version": "13.32.0",
4
4
  "description": "Vendored perl ExifTool for Node.js",
5
5
  "main": "./index.js",
6
6
  "homepage": "https://github.com/photostructure/exiftool-vendored.pl#readme",
@@ -30,7 +30,12 @@
30
30
  "scripts": {
31
31
  "prettier": "prettier --write test/*.js",
32
32
  "test": "mocha",
33
- "update-exiftool": "bash -c ./update-exiftool.sh",
33
+ "update": "run-p update:*",
34
+ "update:deps": "ncu -u",
35
+ "update:exiftool": "bash -c ./update-exiftool.sh",
36
+ "check-version": "node check-version.js",
37
+ "install:pinact": "go install github.com/suzuki-shunsuke/pinact/cmd/pinact@latest",
38
+ "update:actions": "pinact run -u",
34
39
  "release": "release-it"
35
40
  },
36
41
  "release-it": {
@@ -47,8 +52,10 @@
47
52
  }
48
53
  },
49
54
  "devDependencies": {
50
- "mocha": "^11.1.0",
51
- "prettier": "^3.5.3",
52
- "release-it": "^19.0.2"
55
+ "mocha": "^11.7.1",
56
+ "npm-run-all": "4.1.5",
57
+ "prettier": "^3.6.2",
58
+ "release-it": "^19.0.3",
59
+ "xml2js": "^0.6.2"
53
60
  }
54
61
  }