exiftool_vendored 12.41.0 → 12.50.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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +209 -6
  3. data/bin/MANIFEST +12 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +45 -44
  7. data/bin/config_files/acdsee.config +2 -1
  8. data/bin/config_files/frameCount.config +56 -0
  9. data/bin/config_files/tiff_version.config +1 -1
  10. data/bin/exiftool +115 -96
  11. data/bin/fmt_files/gpx.fmt +3 -0
  12. data/bin/fmt_files/gpx_wpt.fmt +3 -0
  13. data/bin/lib/Image/ExifTool/Apple.pm +16 -3
  14. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +23 -12
  15. data/bin/lib/Image/ExifTool/Canon.pm +71 -33
  16. data/bin/lib/Image/ExifTool/CanonRaw.pm +8 -1
  17. data/bin/lib/Image/ExifTool/CanonVRD.pm +7 -8
  18. data/bin/lib/Image/ExifTool/DJI.pm +60 -1
  19. data/bin/lib/Image/ExifTool/DNG.pm +8 -2
  20. data/bin/lib/Image/ExifTool/DarwinCore.pm +13 -1
  21. data/bin/lib/Image/ExifTool/EXE.pm +9 -1
  22. data/bin/lib/Image/ExifTool/Exif.pm +26 -12
  23. data/bin/lib/Image/ExifTool/FLAC.pm +17 -3
  24. data/bin/lib/Image/ExifTool/FLIR.pm +4 -3
  25. data/bin/lib/Image/ExifTool/FlashPix.pm +26 -3
  26. data/bin/lib/Image/ExifTool/FujiFilm.pm +51 -4
  27. data/bin/lib/Image/ExifTool/GPS.pm +21 -1
  28. data/bin/lib/Image/ExifTool/Geotag.pm +25 -5
  29. data/bin/lib/Image/ExifTool/ICC_Profile.pm +12 -9
  30. data/bin/lib/Image/ExifTool/ICO.pm +143 -0
  31. data/bin/lib/Image/ExifTool/ID3.pm +11 -11
  32. data/bin/lib/Image/ExifTool/IPTC.pm +5 -1
  33. data/bin/lib/Image/ExifTool/LNK.pm +5 -2
  34. data/bin/lib/Image/ExifTool/M2TS.pm +98 -8
  35. data/bin/lib/Image/ExifTool/MIE.pm +9 -3
  36. data/bin/lib/Image/ExifTool/MISB.pm +494 -0
  37. data/bin/lib/Image/ExifTool/MakerNotes.pm +8 -1
  38. data/bin/lib/Image/ExifTool/Matroska.pm +24 -16
  39. data/bin/lib/Image/ExifTool/Motorola.pm +8 -2
  40. data/bin/lib/Image/ExifTool/Nikon.pm +293 -122
  41. data/bin/lib/Image/ExifTool/NikonCustom.pm +4 -1
  42. data/bin/lib/Image/ExifTool/NikonSettings.pm +5 -3
  43. data/bin/lib/Image/ExifTool/Olympus.pm +22 -2
  44. data/bin/lib/Image/ExifTool/PDF.pm +2 -1
  45. data/bin/lib/Image/ExifTool/Panasonic.pm +30 -4
  46. data/bin/lib/Image/ExifTool/PanasonicRaw.pm +25 -5
  47. data/bin/lib/Image/ExifTool/Parrot.pm +96 -2
  48. data/bin/lib/Image/ExifTool/Pentax.pm +8 -3
  49. data/bin/lib/Image/ExifTool/Photoshop.pm +35 -8
  50. data/bin/lib/Image/ExifTool/QuickTime.pm +163 -13
  51. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +119 -13
  52. data/bin/lib/Image/ExifTool/README +13 -3
  53. data/bin/lib/Image/ExifTool/RIFF.pm +106 -9
  54. data/bin/lib/Image/ExifTool/Samsung.pm +234 -3
  55. data/bin/lib/Image/ExifTool/Shortcuts.pm +2 -1
  56. data/bin/lib/Image/ExifTool/Sigma.pm +27 -1
  57. data/bin/lib/Image/ExifTool/SigmaRaw.pm +37 -13
  58. data/bin/lib/Image/ExifTool/Sony.pm +71 -43
  59. data/bin/lib/Image/ExifTool/TagInfoXML.pm +3 -1
  60. data/bin/lib/Image/ExifTool/TagLookup.pm +4752 -4516
  61. data/bin/lib/Image/ExifTool/TagNames.pod +1885 -1434
  62. data/bin/lib/Image/ExifTool/Text.pm +3 -4
  63. data/bin/lib/Image/ExifTool/Torrent.pm +2 -3
  64. data/bin/lib/Image/ExifTool/Validate.pm +3 -3
  65. data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +7 -0
  66. data/bin/lib/Image/ExifTool/WriteExif.pl +100 -23
  67. data/bin/lib/Image/ExifTool/WriteIPTC.pl +2 -6
  68. data/bin/lib/Image/ExifTool/WritePhotoshop.pl +5 -5
  69. data/bin/lib/Image/ExifTool/WriteRIFF.pl +359 -0
  70. data/bin/lib/Image/ExifTool/Writer.pl +14 -6
  71. data/bin/lib/Image/ExifTool/XMP.pm +78 -59
  72. data/bin/lib/Image/ExifTool/XMP2.pl +19 -4
  73. data/bin/lib/Image/ExifTool.pm +120 -33
  74. data/bin/lib/Image/ExifTool.pod +83 -69
  75. data/bin/perl-Image-ExifTool.spec +43 -43
  76. data/lib/exiftool_vendored/version.rb +1 -1
  77. metadata +9 -4
@@ -14,9 +14,8 @@ package Image::ExifTool::Text;
14
14
  use strict;
15
15
  use vars qw($VERSION);
16
16
  use Image::ExifTool qw(:DataAccess :Utils);
17
- use Image::ExifTool::XMP;
18
17
 
19
- $VERSION = '1.03';
18
+ $VERSION = '1.04';
20
19
 
21
20
  # Text tags
22
21
  %Image::ExifTool::Text::Main = (
@@ -97,7 +96,7 @@ sub ProcessTXT($$)
97
96
  $nl =~ tr/\0//d; # remove nulls from newline sequence
98
97
  $isBOM = 1; # (we don't recognize UTF-16/UTF-32 without one)
99
98
  } else {
100
- $isUTF8 = Image::ExifTool::XMP::IsUTF8($dataPt, 1);
99
+ $isUTF8 = Image::ExifTool::IsUTF8($dataPt, 1);
101
100
  if ($isUTF8 == 0) {
102
101
  $enc = 'us-ascii';
103
102
  } elsif ($isUTF8 > 0) {
@@ -183,7 +182,7 @@ sub ProcessTXT($$)
183
182
  next if $raf->Tell() < 65536;
184
183
  # continue to check encoding after the first 64 kB
185
184
  if ($isUTF8 >= 0) { # (if ascii or utf8)
186
- $isUTF8 = Image::ExifTool::XMP::IsUTF8(\$buff);
185
+ $isUTF8 = Image::ExifTool::IsUTF8(\$buff);
187
186
  if ($isUTF8 > 0) {
188
187
  $enc = 'utf-8';
189
188
  } elsif ($isUTF8 < 0) {
@@ -13,9 +13,8 @@ package Image::ExifTool::Torrent;
13
13
  use strict;
14
14
  use vars qw($VERSION);
15
15
  use Image::ExifTool qw(:DataAccess :Utils);
16
- use Image::ExifTool::XMP;
17
16
 
18
- $VERSION = '1.05';
17
+ $VERSION = '1.06';
19
18
 
20
19
  sub ReadBencode($$$);
21
20
  sub ExtractTags($$$;$$@);
@@ -169,7 +168,7 @@ sub ReadBencode($$$)
169
168
  if (length($value) > 256) {
170
169
  $val = \$value;
171
170
  } elsif ($value =~ /[^\t\x20-\x7e]/) {
172
- if (Image::ExifTool::XMP::IsUTF8(\$value) >= 0) {
171
+ if (Image::ExifTool::IsUTF8(\$value) >= 0) {
173
172
  $val = $et->Decode($value, 'UTF8');
174
173
  } else {
175
174
  $val = \$value;
@@ -17,7 +17,7 @@ package Image::ExifTool::Validate;
17
17
  use strict;
18
18
  use vars qw($VERSION %exifSpec);
19
19
 
20
- $VERSION = '1.18';
20
+ $VERSION = '1.19';
21
21
 
22
22
  use Image::ExifTool qw(:Utils);
23
23
  use Image::ExifTool::Exif;
@@ -82,8 +82,8 @@ my %otherSpec = (
82
82
  CR2 => { 0xc5d8 => 1, 0xc5d9 => 1, 0xc5e0 => 1, 0xc640 => 1, 0xc6dc => 1, 0xc6dd => 1 },
83
83
  NEF => { 0x9216 => 1, 0x9217 => 1 },
84
84
  DNG => { 0x882a => 1, 0x9211 => 1, 0x9216 => 1 },
85
- ARW => { 0x7000 => 1, 0x7001 => 1, 0x7010 => 1, 0x7011 => 1, 0x7020 => 1,
86
- 0x7031 => 1, 0x7032 => 1, 0x7034 => 1, 0x7035 => 1, 0x7036 => 1, 0x7037 => 1,
85
+ ARW => { 0x7000 => 1, 0x7001 => 1, 0x7010 => 1, 0x7011 => 1, 0x7020 => 1, 0x7031 => 1,
86
+ 0x7032 => 1, 0x7034 => 1, 0x7035 => 1, 0x7036 => 1, 0x7037 => 1, 0x7038 => 1,
87
87
  0x7310 => 1, 0x7313 => 1, 0x7316 => 1, 0x74c7 => 1, 0x74c8 => 1, 0xa500 => 1 },
88
88
  RW2 => { All => 1 }, # ignore all unknown tags in RW2
89
89
  RWL => { All => 1 },
@@ -271,6 +271,13 @@ sub WriteCanonRaw($$$)
271
271
  $raf->Seek($blockStart+$blockSize-4, 0) or return 0;
272
272
  $raf->Read($buff, 4) == 4 or return 0;
273
273
  my $dirOffset = Get32u(\$buff,0) + $blockStart;
274
+ # avoid infinite recursion
275
+ $$et{ProcessedCanonRaw} or $$et{ProcessedCanonRaw} = { };
276
+ if ($$et{ProcessedCanonRaw}{$dirOffset}) {
277
+ $et->Error("Double-referenced $$dirInfo{DirName} directory");
278
+ return 0;
279
+ }
280
+ $$et{ProcessedCanonRaw}{$dirOffset} = 1;
274
281
  $raf->Seek($dirOffset, 0) or return 0;
275
282
  $raf->Read($buff, 2) == 2 or return 0;
276
283
  my $entries = Get16u(\$buff,0); # get number of entries in directory
@@ -586,7 +586,7 @@ sub WriteExif($$$)
586
586
  $et->Error("$str $name directory", 1);
587
587
  }
588
588
  }
589
- my ($index, $dirEnd, $numEntries);
589
+ my ($index, $dirEnd, $numEntries, %hasOldID, $unsorted);
590
590
  if ($dirStart + 4 < $dataLen) {
591
591
  $numEntries = Get16u($dataPt, $dirStart);
592
592
  $dirEnd = $dirStart + 2 + 12 * $numEntries;
@@ -596,19 +596,20 @@ sub WriteExif($$$)
596
596
  return undef unless $n and defined $rtn;
597
597
  $numEntries = $n; # continue processing the entries we have
598
598
  }
599
- # sort entries if necessary (but not in maker notes IFDs)
600
- unless ($inMakerNotes) {
601
- my $lastID = -1;
602
- for ($index=0; $index<$numEntries; ++$index) {
603
- my $tagID = Get16u($dataPt, $dirStart + 2 + 12 * $index);
604
- # check for proper sequence (but ignore null entries at end)
605
- if ($tagID < $lastID and ($tagID or $$tagTablePtr{0})) {
606
- SortIFD($dataPt, $dirStart, $numEntries, $$tagTablePtr{0});
607
- $et->Warn("Entries in $name were out of sequence. Fixed.",1);
608
- last;
609
- }
610
- $lastID = $tagID;
611
- }
599
+ # create lookup for existing tag ID's and determine if directory is sorted
600
+ my $lastID = -1;
601
+ for ($index=0; $index<$numEntries; ++$index) {
602
+ my $tagID = Get16u($dataPt, $dirStart + 2 + 12 * $index);
603
+ $hasOldID{$tagID} = 1;
604
+ # check for proper sequence (but ignore null entries at end)
605
+ $unsorted = 1 if $tagID < $lastID and ($tagID or $$tagTablePtr{0});
606
+ $lastID = $tagID;
607
+ }
608
+ # sort entries if out-of-order (but not in maker notes IFDs or RAW files)
609
+ if ($unsorted and not ($inMakerNotes or $et->IsRawType())) {
610
+ SortIFD($dataPt, $dirStart, $numEntries, $$tagTablePtr{0});
611
+ $et->Warn("Entries in $name were out of sequence. Fixed.",1);
612
+ $unsorted = 0;
612
613
  }
613
614
  } else {
614
615
  $numEntries = 0;
@@ -616,11 +617,12 @@ sub WriteExif($$$)
616
617
  }
617
618
 
618
619
  # loop through new values and accumulate all information for this IFD
619
- my (%set, %mayDelete, $tagInfo);
620
+ my (%set, %mayDelete, $tagInfo, %hasNewID);
620
621
  my $wrongDir = $crossDelete{$dirName};
621
622
  my @newTagInfo = $et->GetNewTagInfoList($tagTablePtr);
622
623
  foreach $tagInfo (@newTagInfo) {
623
624
  my $tagID = $$tagInfo{TagID};
625
+ $hasNewID{$tagID} = 1;
624
626
  # must evaluate Condition later when we have all DataMember's available
625
627
  $set{$tagID} = (ref $$tagTablePtr{$tagID} eq 'ARRAY' or $$tagInfo{Condition}) ? '' : $tagInfo;
626
628
  }
@@ -723,7 +725,7 @@ Entry: for (;;) {
723
725
  $readFormat = $oldFormat = Get16u($dataPt, $entry+2);
724
726
  $readCount = $oldCount = Get32u($dataPt, $entry+4);
725
727
  undef $oldImageData;
726
- if ($oldFormat < 1 or $oldFormat > 13) {
728
+ if ($oldFormat < 1 or $oldFormat > 13 and not ($oldFormat == 16 and $$et{Make} eq 'Apple' and $inMakerNotes)) {
727
729
  my $msg = "Bad format ($oldFormat) for $name entry $index";
728
730
  # patch to preserve invalid directory entries in SubIFD3 of
729
731
  # various Kodak Z-series cameras (Z812, Z1085IS, Z1275)
@@ -972,7 +974,7 @@ Entry: for (;;) {
972
974
  $readCount = $oldSize / $formatSize[$readFormat];
973
975
  }
974
976
  }
975
- if ($oldID <= $lastTagID and not $inMakerNotes) {
977
+ if ($oldID <= $lastTagID and not ($inMakerNotes or $et->IsRawType())) {
976
978
  my $str = $oldInfo ? "$$oldInfo{Name} tag" : sprintf('tag 0x%x',$oldID);
977
979
  if ($oldID == $lastTagID) {
978
980
  $et->Warn("Duplicate $str in $name");
@@ -1006,6 +1008,23 @@ Entry: for (;;) {
1006
1008
  }
1007
1009
  } else {
1008
1010
  $isNew = $oldID <=> $newID;
1011
+ # special logic needed if directory has out-of-order entries
1012
+ if ($unsorted and $isNew) {
1013
+ if ($isNew > 0 and $hasOldID{$newID}) {
1014
+ # we wanted to create the new tag, but an old tag
1015
+ # does exist with this ID, so defer writing the new tag
1016
+ $isNew = -1;
1017
+ }
1018
+ if ($isNew < 0 and $hasNewID{$oldID}) {
1019
+ # we wanted to write the old tag, but we have
1020
+ # a new tag with this ID, so move it up in the order
1021
+ my @tmpTags = ( $oldID );
1022
+ $_ == $oldID or push @tmpTags, $_ foreach @newTags;
1023
+ @newTags = @tmpTags;
1024
+ $newID = $oldID;
1025
+ $isNew = 0;
1026
+ }
1027
+ }
1009
1028
  }
1010
1029
  my $newInfo = $oldInfo;
1011
1030
  my $newFormat = $oldFormat;
@@ -2170,17 +2189,39 @@ NoOverwrite: next if $isNew > 0;
2170
2189
  my @offsetList;
2171
2190
  if ($ifd >= 0) {
2172
2191
  my $offsetInfo = $offsetInfo[$ifd] or next;
2192
+ if ($$offsetInfo{0x111} and $$offsetInfo{0x144}) {
2193
+ # SubIFD may contain double-referenced data as both strips and tiles
2194
+ # for Sony ARW files when SonyRawFileType is "Lossless Compressed RAW 2"
2195
+ if ($dirName eq 'SubIFD' and $$et{TIFF_TYPE} eq 'ARW' and
2196
+ $$offsetInfo{0x117} and $$offsetInfo{0x145} and
2197
+ $$offsetInfo{0x111}[2]==1) # (must be a single strip or the tile offsets could get out of sync)
2198
+ {
2199
+ # some Sony ARW images contain double-referenced raw data stored as both strips
2200
+ # and tiles. Copy the data using only the strip tags, but store the TileOffets
2201
+ # information for updating later (see PanasonicRaw:PatchRawDataOffset for a
2202
+ # description of offsetInfo elements)
2203
+ $$offsetInfo{0x111}[5] = $$offsetInfo{0x144}; # hack to save TileOffsets
2204
+ # delete tile information from offsetInfo because we will copy as strips
2205
+ delete $$offsetInfo{0x144};
2206
+ delete $$offsetInfo{0x145};
2207
+ } else {
2208
+ $et->Error("TIFF $dirName contains both strip and tile data");
2209
+ }
2210
+ }
2173
2211
  # patch Panasonic RAW/RW2 StripOffsets/StripByteCounts if necessary
2174
2212
  my $stripOffsets = $$offsetInfo{0x111};
2175
- if ($stripOffsets and $$stripOffsets[0]{PanasonicHack}) {
2213
+ my $rawDataOffset = $$offsetInfo{0x118};
2214
+ if ($stripOffsets and $$stripOffsets[0]{PanasonicHack} or
2215
+ $rawDataOffset and $$rawDataOffset[0]{PanasonicHack})
2216
+ {
2176
2217
  require Image::ExifTool::PanasonicRaw;
2177
2218
  my $err = Image::ExifTool::PanasonicRaw::PatchRawDataOffset($offsetInfo, $raf, $ifd);
2178
2219
  $err and $et->Error($err);
2179
2220
  }
2180
2221
  my $tagID;
2181
- # loop through all tags in reverse order so we save thumbnail
2222
+ # loop through all tags in reverse numerical order so we save thumbnail
2182
2223
  # data before main image data if both exist in the same IFD
2183
- foreach $tagID (reverse sort keys %$offsetInfo) {
2224
+ foreach $tagID (reverse sort { $a <=> $b } keys %$offsetInfo) {
2184
2225
  my $tagInfo = $$offsetInfo{$tagID}[0];
2185
2226
  next unless $$tagInfo{IsOffset}; # handle byte counts with offsets
2186
2227
  my $sizeInfo = $$offsetInfo{$$tagInfo{OffsetPair}};
@@ -2203,6 +2244,7 @@ NoOverwrite: next if $isNew > 0;
2203
2244
  }
2204
2245
  } else {
2205
2246
  last unless @writeLater;
2247
+ # finally, copy all deferred data
2206
2248
  @offsetList = @writeLater;
2207
2249
  }
2208
2250
  my $offsetPair;
@@ -2296,6 +2338,23 @@ NoOverwrite: next if $isNew > 0;
2296
2338
  $size = length($buff);
2297
2339
  Set32u($size, \$newData, $byteCountPos);
2298
2340
  } elsif ($ifd < 0) {
2341
+ # hack for fixed-offset data (Panasonic GH6)
2342
+ if ($$offsetPair[0][6]) {
2343
+ if ($count > 1) {
2344
+ $et->Error("Can't handle fixed offsets with count > 1");
2345
+ } else {
2346
+ my $fixedOffset = Get32u(\$newData, $offsets);
2347
+ my $padToFixedOffset = $fixedOffset - ($newOffset + $dpos);
2348
+ if ($padToFixedOffset < 0) {
2349
+ $et->Error('Metadata too large to fit before fixed-offset image data');
2350
+ } else {
2351
+ # add necessary padding before raw data
2352
+ push @imageData, [$offset+$dbase+$dpos, 0, $padToFixedOffset];
2353
+ $newOffset += $padToFixedOffset;
2354
+ $et->Warn("Adding $padToFixedOffset bytes of padding before fixed-offset image data", 1);
2355
+ }
2356
+ }
2357
+ }
2299
2358
  # pad if necessary (but don't pad contiguous image blocks)
2300
2359
  my $pad = 0;
2301
2360
  ++$pad if ($blockSize + $size) & 0x01 and ($n+1 >= $count or
@@ -2406,10 +2465,28 @@ NoOverwrite: next if $isNew > 0;
2406
2465
  # also add to subIfdDataFixup if necessary
2407
2466
  $subIfdDataFixup->AddFixup($offsetPos, $dataTag) if $subIfdDataFixup;
2408
2467
  # must also (sometimes) update StripOffsets in Panasonic RW2 images
2468
+ # and TileOffsets in Sony ARW images
2409
2469
  my $otherPos = $$offsetPair[0][5];
2410
- if ($otherPos and $$tagInfo{PanasonicHack}) {
2411
- Set32u($newOffset, \$newData, $otherPos);
2412
- $fixup->AddFixup($otherPos, $dataTag);
2470
+ if ($otherPos) {
2471
+ if ($$tagInfo{PanasonicHack}) {
2472
+ Set32u($newOffset, \$newData, $otherPos);
2473
+ $fixup->AddFixup($otherPos, $dataTag);
2474
+ } elsif (ref $otherPos eq 'ARRAY') {
2475
+ # the image data was copied as one large strip, and is double-referenced
2476
+ # as tile data, so all we need to do now is properly update the tile offsets
2477
+ my $oldRawDataOffset = $$offsetPair[0][3][0];
2478
+ my $count = $$otherPos[2];
2479
+ my $i;
2480
+ # point to offsets in value data if more than one pointer
2481
+ $$otherPos[1] = Get32u(\$newData, $$otherPos[1]) if $count > 1;
2482
+ for ($i=0; $i<$count; ++$i) {
2483
+ my $oldTileOffset = $$otherPos[3][$i];
2484
+ my $ptrPos = $$otherPos[1] + 4 * $i;
2485
+ Set32u($newOffset + $oldTileOffset - $oldRawDataOffset, \$newData, $ptrPos);
2486
+ $fixup->AddFixup($ptrPos, $dataTag);
2487
+ $subIfdDataFixup->AddFixup($ptrPos, $dataTag) if $subIfdDataFixup;
2488
+ }
2489
+ }
2413
2490
  }
2414
2491
  if ($ifd >= 0) {
2415
2492
  # buff length must be even (Note: may have changed since $size was set)
@@ -334,13 +334,9 @@ sub DoWriteIPTC($$$)
334
334
  # - improves speed
335
335
  # - avoids changing current MD5 digest unnecessarily
336
336
  # - avoids adding mandatory tags unless some other IPTC is changed
337
- unless (exists $$et{EDIT_DIRS}{$$dirInfo{DirName}} or
337
+ return undef unless exists $$et{EDIT_DIRS}{$$dirInfo{DirName}} or
338
338
  # standard IPTC tags in other locations should be edited too (eg. AFCP_IPTC)
339
- ($tagTablePtr eq \%Image::ExifTool::IPTC::Main and exists $$et{EDIT_DIRS}{IPTC}))
340
- {
341
- print $out "$$et{INDENT} [nothing changed]\n" if $verbose;
342
- return undef;
343
- }
339
+ ($tagTablePtr eq \%Image::ExifTool::IPTC::Main and exists $$et{EDIT_DIRS}{IPTC});
344
340
  my $dataPt = $$dirInfo{DataPt};
345
341
  unless ($dataPt) {
346
342
  my $emptyData = '';
@@ -138,13 +138,13 @@ sub WritePhotoshop($$$)
138
138
  unless ($tagInfo) {
139
139
  # process subdirectory anyway if writable (except EXIF to avoid recursion)
140
140
  # --> this allows IPTC to be processed if found here in TIFF images
141
- # (note that I have seen a case of XMP in PSD-EXIFInfo-IFD0, and the EXIF
142
- # exclusion means that this won't be written unless an EXIF tag is
143
- # specifically edited, see forum10768 -- maybe this should be changed
144
- # if it happens again)
141
+ # (but allow EXIF to be written in PSD files if XMP or IPTC tags are
142
+ # being written because I have seen cases of XMP in PSD-EXIFInfo-IFD0
143
+ # and IPTC in PSD-EXIFInfo-IFD0-IPTC, see forum10768 and forum13198)
145
144
  my $tmpInfo = $et->GetTagInfo($tagTablePtr, $tagID);
146
145
  if ($tmpInfo and $$tmpInfo{SubDirectory} and
147
- $tmpInfo->{SubDirectory}->{TagTable} ne 'Image::ExifTool::Exif::Main')
146
+ ($tmpInfo->{SubDirectory}->{TagTable} ne 'Image::ExifTool::Exif::Main' or
147
+ ($$et{FILE_TYPE} eq 'PSD' and ($$editDirs{0x0404} or $$editDirs{0x0424}))))
148
148
  {
149
149
  my $table = Image::ExifTool::GetTagTable($tmpInfo->{SubDirectory}->{TagTable});
150
150
  $tagInfo = $tmpInfo if $$table{WRITE_PROC};