exiftool-vendored.exe 12.67.0 → 12.69.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 (31) hide show
  1. package/bin/exiftool_files/Changes +40 -2
  2. package/bin/exiftool_files/README +7 -7
  3. package/bin/exiftool_files/exiftool.pl +26 -20
  4. package/bin/exiftool_files/lib/Image/ExifTool/Canon.pm +25 -1
  5. package/bin/exiftool_files/lib/Image/ExifTool/DNG.pm +25 -2
  6. package/bin/exiftool_files/lib/Image/ExifTool/Exif.pm +95 -13
  7. package/bin/exiftool_files/lib/Image/ExifTool/FujiFilm.pm +17 -1
  8. package/bin/exiftool_files/lib/Image/ExifTool/Geotag.pm +16 -11
  9. package/bin/exiftool_files/lib/Image/ExifTool/Nikon.pm +38 -11
  10. package/bin/exiftool_files/lib/Image/ExifTool/PNG.pm +14 -7
  11. package/bin/exiftool_files/lib/Image/ExifTool/Panasonic.pm +13 -9
  12. package/bin/exiftool_files/lib/Image/ExifTool/Pentax.pm +6 -1
  13. package/bin/exiftool_files/lib/Image/ExifTool/PhotoMechanic.pm +2 -1
  14. package/bin/exiftool_files/lib/Image/ExifTool/QuickTime.pm +62 -52
  15. package/bin/exiftool_files/lib/Image/ExifTool/README +7 -3
  16. package/bin/exiftool_files/lib/Image/ExifTool/RIFF.pm +8 -2
  17. package/bin/exiftool_files/lib/Image/ExifTool/Sony.pm +66 -21
  18. package/bin/exiftool_files/lib/Image/ExifTool/TagLookup.pm +6881 -6710
  19. package/bin/exiftool_files/lib/Image/ExifTool/TagNames.pod +445 -32
  20. package/bin/exiftool_files/lib/Image/ExifTool/Validate.pm +18 -16
  21. package/bin/exiftool_files/lib/Image/ExifTool/WriteCanonRaw.pl +2 -2
  22. package/bin/exiftool_files/lib/Image/ExifTool/WriteExif.pl +14 -4
  23. package/bin/exiftool_files/lib/Image/ExifTool/WriteQuickTime.pl +2 -0
  24. package/bin/exiftool_files/lib/Image/ExifTool/WriteRIFF.pl +22 -3
  25. package/bin/exiftool_files/lib/Image/ExifTool/Writer.pl +52 -11
  26. package/bin/exiftool_files/lib/Image/ExifTool/XISF.pm +185 -0
  27. package/bin/exiftool_files/lib/Image/ExifTool/XMP.pm +67 -2
  28. package/bin/exiftool_files/lib/Image/ExifTool/XMP2.pl +35 -0
  29. package/bin/exiftool_files/lib/Image/ExifTool.pm +36 -15
  30. package/bin/exiftool_files/lib/Image/ExifTool.pod +5 -5
  31. package/package.json +1 -1
@@ -17,7 +17,7 @@ package Image::ExifTool::Validate;
17
17
  use strict;
18
18
  use vars qw($VERSION %exifSpec);
19
19
 
20
- $VERSION = '1.21';
20
+ $VERSION = '1.22';
21
21
 
22
22
  use Image::ExifTool qw(:Utils);
23
23
  use Image::ExifTool::Exif;
@@ -142,20 +142,22 @@ my %stdFormat = (
142
142
  # GeoTiff tags:
143
143
  0x830e => 'double', 0x8482 => 'double', 0x87af => 'int16u', 0x87b1 => 'string',
144
144
  0x8480 => 'double', 0x85d8 => 'double', 0x87b0 => 'double',
145
- # DNG tags:
146
- 0xc615 => '(string|int8u)', 0xc6d3 => '',
147
- 0xc61a => '(int16u|int32u|rational64u)', 0xc6f4 => '(string|int8u)',
148
- 0xc61d => 'int(16|32)u', 0xc6f6 => '(string|int8u)',
149
- 0xc61f => '(int16u|int32u|rational64u)', 0xc6f8 => '(string|int8u)',
150
- 0xc620 => '(int16u|int32u|rational64u)', 0xc6fe => '(string|int8u)',
151
- 0xc628 => '(int16u|rational64u)', 0xc716 => '(string|int8u)',
152
- 0xc634 => 'int8u', 0xc717 => '(string|int8u)',
153
- 0xc640 => '', 0xc718 => '(string|int8u)',
154
- 0xc660 => '', 0xc71e => 'int(16|32)u',
155
- 0xc68b => '(string|int8u)', 0xc71f => 'int(16|32)u',
156
- 0xc68d => 'int(16|32)u', 0xc791 => 'int(16|32)u',
157
- 0xc68e => 'int(16|32)u', 0xc792 => 'int(16|32)u',
158
- 0xc6d2 => '', 0xc793 => '(int16u|int32u|rational64u)',
145
+ # DNG tags: (use '' for non-DNG tags in the range 0xc612-0xcd48)
146
+ 0xc615 => '(string|int8u)', 0xc6f4 => '(string|int8u)',
147
+ 0xc61a => '(int16u|int32u|rational64u)', 0xc6f6 => '(string|int8u)',
148
+ 0xc61d => 'int(16|32)u', 0xc6f8 => '(string|int8u)',
149
+ 0xc61f => '(int16u|int32u|rational64u)', 0xc6fe => '(string|int8u)',
150
+ 0xc620 => '(int16u|int32u|rational64u)', 0xc716 => '(string|int8u)',
151
+ 0xc628 => '(int16u|rational64u)', 0xc717 => '(string|int8u)',
152
+ 0xc634 => 'int8u', 0xc718 => '(string|int8u)',
153
+ 0xc640 => '', 0xc71e => 'int(16|32)u',
154
+ 0xc660 => '', 0xc71f => 'int(16|32)u',
155
+ 0xc68b => '(string|int8u)', 0xc791 => 'int(16|32)u',
156
+ 0xc68d => 'int(16|32)u', 0xc792 => 'int(16|32)u',
157
+ 0xc68e => 'int(16|32)u', 0xc793 => '(int16u|int32u|rational64u)',
158
+ 0xc6d2 => '', 0xcd43 => 'int(16|32)u',
159
+ 0xc6d3 => '', 0xcd48 => '(string|int8u)',
160
+
159
161
  # Exif 3.0 spec
160
162
  0x10e => 'string|utf8', 0xa430 => 'string|utf8', 0xa439 => 'string|utf8',
161
163
  0x10f => 'string|utf8', 0xa433 => 'string|utf8', 0xa43a => 'string|utf8',
@@ -430,7 +432,7 @@ sub ValidateExif($$$$$$$$)
430
432
  my $stdFmt = $stdFormat{$ifd} || $stdFormat{IFD};
431
433
  if (defined $$stdFmt{All} or ($tagTablePtr eq \%Image::ExifTool::Exif::Main and
432
434
  ($exifSpec{$tag} or $$stdFmt{$tag} or
433
- ($tag >= 0xc612 and $tag <= 0xc7b5 and not defined $$stdFmt{$tag}))) or # (DNG tags)
435
+ ($tag >= 0xc612 and $tag <= 0xcd48 and not defined $$stdFmt{$tag}))) or # (DNG tags)
434
436
  $$tagTablePtr{SHORT_NAME} eq 'GPS::Main')
435
437
  {
436
438
  my $wgp = $$ti{WriteGroup} || $$tagTablePtr{WRITE_GROUP};
@@ -142,7 +142,6 @@ sub SaveMakerNotes($)
142
142
  }
143
143
  # save position of maker notes for pointer fixups
144
144
  $fixup->{Shift} += length($makerNotes);
145
- $$et{MAKER_NOTE_FIXUP} = $fixup;
146
145
  $$et{MAKER_NOTE_BYTE_ORDER} = GetByteOrder();
147
146
  # add value data
148
147
  $makerNotes .= $makerInfo->{ValBuff};
@@ -150,7 +149,8 @@ sub SaveMakerNotes($)
150
149
  my $tagTablePtr = Image::ExifTool::GetTagTable('Image::ExifTool::Exif::Main');
151
150
  my $tagInfo = $et->GetTagInfo($tagTablePtr, 0x927c, \$makerNotes);
152
151
  # save the MakerNotes
153
- $et->FoundTag($tagInfo, $makerNotes);
152
+ my $key = $et->FoundTag($tagInfo, $makerNotes);
153
+ $$et{TAG_EXTRA}{$key}{Fixup} = $fixup;
154
154
  # save the garbage collection some work later
155
155
  delete $makerInfo->{Entries};
156
156
  delete $makerInfo->{ValBuff};
@@ -930,8 +930,16 @@ Entry: for (;;) {
930
930
  }
931
931
  }
932
932
  unless ($success) {
933
- return undef if $et->Error("Error reading value for $name entry $index", $inMakerNotes);
934
- ++$index; $oldID = $newID; next; # drop this tag
933
+ my $wrn = sprintf("Error reading value for $name entry $index, ID 0x%.4x", $oldID);
934
+ my $truncOK;
935
+ if ($oldInfo and not $$oldInfo{Unknown}) {
936
+ $wrn .= " $$oldInfo{Name}";
937
+ $truncOK = $$oldInfo{TruncateOK};
938
+ }
939
+ return undef if $et->Error($wrn, $inMakerNotes || $truncOK);
940
+ unless ($truncOK) {
941
+ ++$index; $oldID = $newID; next; # drop this tag
942
+ }
935
943
  }
936
944
  } elsif (not $invalidPreview) {
937
945
  return undef if $et->Error("Bad $name offset for $tagStr", $inMakerNotes);
@@ -1094,6 +1102,8 @@ Entry: for (;;) {
1094
1102
  # add, edit or delete this tag
1095
1103
  shift @newTags; # remove from list
1096
1104
  my $curInfo = $set{$newID};
1105
+ # don't allow MakerNotes to be added to ExifIFD of CR3 file
1106
+ next if $newID == 0x927c and $isNew > 0 and $$et{FileType} eq 'CR3';
1097
1107
  unless ($curInfo or $$addDirs{$newID}) {
1098
1108
  # we can finally get the specific tagInfo reference for this tag
1099
1109
  # (because we can now evaluate the Condition statement since all
@@ -1429,8 +1439,8 @@ NoOverwrite: next if $isNew > 0;
1429
1439
  if ($$et{DEL_GROUP}{MakerNotes} and
1430
1440
  ($$et{DEL_GROUP}{MakerNotes} != 2 or $isNew <= 0))
1431
1441
  {
1432
- if ($et->IsRawType()) {
1433
- $et->WarnOnce("Can't delete MakerNotes from $$et{FileType}",1);
1442
+ if ($et->IsRawType() and not ($et->IsRawType() == 2 and $dirName eq 'ExifIFD')) {
1443
+ $et->Warn("Can't delete MakerNotes from $$et{FileType}",1);
1434
1444
  } else {
1435
1445
  if ($isNew <= 0) {
1436
1446
  ++$$et{CHANGED};
@@ -96,6 +96,8 @@ my %ctboID = (
96
96
  "\xbe\x7a\xcf\xcb\x97\xa9\x42\xe8\x9c\x71\x99\x94\x91\xe3\xaf\xac" => 1, # XMP
97
97
  "\xea\xf4\x2b\x5e\x1c\x98\x4b\x88\xb9\xfb\xb7\xdc\x40\x6e\x4d\x16" => 2, # PreviewImage
98
98
  # ID 3 is used for 'mdat' atom (not a uuid)
99
+ # (haven't seen ID 4 yet)
100
+ "\x57\x66\xb8\x29\xbb\x6a\x47\xc5\xbc\xfb\x8b\x9f\x22\x60\xd0\x6d" => 5, # something to do with burst-roll image
99
101
  );
100
102
 
101
103
  # mark UserData tags that don't have ItemList counterparts as Preferred
@@ -66,6 +66,7 @@ sub WriteRIFF($$)
66
66
  $et->InitWriteDirs(\%webpMap);
67
67
  my $addDirs = $$et{ADD_DIRS};
68
68
  my $editDirs = $$et{EDIT_DIRS};
69
+ $$addDirs{IFD0} = 'EXIF' if $$addDirs{EXIF}; # set flag to add IFD0 if adding EXIF (don't ask)
69
70
  my ($createVP8X, $deleteVP8X);
70
71
 
71
72
  # write header
@@ -142,6 +143,17 @@ sub WriteRIFF($$)
142
143
  }
143
144
  # RIFF chunks are padded to an even number of bytes
144
145
  my $len2 = $len + ($len & 0x01);
146
+ # handle incorrect "XMP\0" chunk ID written by Google software
147
+ if ($tag eq "XMP\0") {
148
+ if ($$et{DEL_GROUP}{XMP}) {
149
+ # just ignore this chunk if deleting XMP
150
+ $raf->Seek($len2, 1) or $et->Error('Seek error'), last;
151
+ ++$$et{CHANGED};
152
+ next;
153
+ } else {
154
+ $et->Warn('Incorrect XMP tag ID',1) if $pass;
155
+ }
156
+ }
145
157
  # edit/add/delete necessary metadata chunks (EXIF must come before XMP)
146
158
  if ($$editDirs{$tag} or $tag eq '' or ($tag eq 'XMP ' and $$addDirs{EXIF})) {
147
159
  my $handledTag;
@@ -162,7 +174,6 @@ sub WriteRIFF($$)
162
174
  foreach $dir ('EXIF', 'XMP ', 'ICCP' ) {
163
175
  next unless $tag eq $dir or ($$addDirs{$dir} and
164
176
  ($tag eq '' or ($tag eq 'XMP ' and $dir eq 'EXIF')));
165
- delete $$addDirs{$dir}; # (don't try to add again)
166
177
  my $start;
167
178
  unless ($pass) {
168
179
  # write the EXIF and save the result for the next pass
@@ -170,8 +181,15 @@ sub WriteRIFF($$)
170
181
  if ($tag eq 'EXIF') {
171
182
  # (only need to set directory $start for EXIF)
172
183
  if ($buff =~ /^Exif\0\0/) {
173
- $et->Warn('Improper EXIF header') unless $pass;
174
- $start = 6;
184
+ if ($$et{DEL_GROUP}{EXIF}) {
185
+ # remove incorrect header if rewriting anyway
186
+ $buff = substr($buff, 6);
187
+ $len -= 6;
188
+ $len2 -= 6;
189
+ } else {
190
+ $et->Warn('Improper EXIF header',1) unless $pass;
191
+ $start = 6;
192
+ }
175
193
  } else {
176
194
  $start = 0;
177
195
  }
@@ -194,6 +212,7 @@ sub WriteRIFF($$)
194
212
  my $writeProc = $dir eq 'EXIF' ? \&Image::ExifTool::WriteTIFF : undef;
195
213
  $dirDat{$dir} = $et->WriteDirectory(\%dirInfo, $tagTablePtr, $writeProc);
196
214
  }
215
+ delete $$addDirs{$dir}; # (don't try to add again)
197
216
  if (defined $dirDat{$dir}) {
198
217
  if ($dir eq $tag) {
199
218
  $handledTag = 1; # set flag indicating we edited this tag
@@ -122,9 +122,9 @@ my %writableType = (
122
122
  XMP => [ undef, 'WriteXMP' ],
123
123
  );
124
124
 
125
- # RAW file types
125
+ # RAW file types (2 = raw file where we can delete maker notes from ExifIFD)
126
126
  my %rawType = (
127
- '3FR'=> 1, CR3 => 1, IIQ => 1, NEF => 1, RW2 => 1,
127
+ '3FR'=> 1, CR3 => 2, IIQ => 1, NEF => 1, RW2 => 1,
128
128
  ARQ => 1, CRW => 1, K25 => 1, NRW => 1, RWL => 1,
129
129
  ARW => 1, DCR => 1, KDC => 1, ORF => 1, SR2 => 1,
130
130
  ARW => 1, ERF => 1, MEF => 1, PEF => 1, SRF => 1,
@@ -278,6 +278,7 @@ my %ignorePrintConv = map { $_ => 1 } qw(OTHER BITMASK Notes);
278
278
  # ListOnly => [internal use] set only list or non-list tags
279
279
  # SetTags => [internal use] hash ref to return tagInfo refs of set tags
280
280
  # Sanitized => [internal use] set to avoid double-sanitizing the value
281
+ # Fixup => [internal use] fixup information when writing maker notes
281
282
  # Returns: number of tags set (plus error string in list context)
282
283
  # Notes: For tag lists (like Keywords), call repeatedly with the same tag name for
283
284
  # each value in the list. Internally, the new information is stored in
@@ -1002,10 +1003,8 @@ TAG: foreach $tagInfo (@matchingTags) {
1002
1003
  $$nvHash{NoReplace} = 1 if $$tagInfo{List} and not $options{Replace};
1003
1004
  $$nvHash{WantGroup} = $wantGroup;
1004
1005
  $$nvHash{EditOnly} = 1 if $editOnly;
1005
- # save maker note information if writing maker notes
1006
- if ($$tagInfo{MakerNotes}) {
1007
- $$nvHash{MAKER_NOTE_FIXUP} = $$self{MAKER_NOTE_FIXUP};
1008
- }
1006
+ # save maker note fixup information if writing maker notes
1007
+ $$nvHash{MAKER_NOTE_FIXUP} = $options{Fixup} if $$tagInfo{MakerNotes};
1009
1008
  if ($createOnly) { # create only (never edit)
1010
1009
  # empty item in DelValue list to never edit existing value
1011
1010
  $$nvHash{DelValue} = [ '' ];
@@ -1372,8 +1371,8 @@ sub SetNewValuesFromFile($$;@)
1372
1371
  #
1373
1372
  unless (@setTags) {
1374
1373
  # transfer maker note information to this object
1375
- $$self{MAKER_NOTE_FIXUP} = $$srcExifTool{MAKER_NOTE_FIXUP};
1376
1374
  $$self{MAKER_NOTE_BYTE_ORDER} = $$srcExifTool{MAKER_NOTE_BYTE_ORDER};
1375
+ my $tagExtra = $$srcExifTool{TAG_EXTRA};
1377
1376
  foreach $tag (@tags) {
1378
1377
  # don't try to set errors or warnings
1379
1378
  next if $tag =~ /^(Error|Warning)\b/;
@@ -1381,10 +1380,13 @@ sub SetNewValuesFromFile($$;@)
1381
1380
  if ($opts{SrcType} and $opts{SrcType} ne $srcType) {
1382
1381
  $$info{$tag} = $srcExifTool->GetValue($tag, $opts{SrcType});
1383
1382
  }
1383
+ my $fixup = $$tagExtra{$tag}{Fixup};
1384
+ $opts{Fixup} = $fixup if $fixup;
1384
1385
  # set value for this tag
1385
1386
  my ($n, $e) = $self->SetNewValue($tag, $$info{$tag}, %opts);
1386
1387
  # delete this tag if we couldn't set it
1387
1388
  $n or delete $$info{$tag};
1389
+ delete $opts{Fixup} if $fixup;
1388
1390
  }
1389
1391
  return $info;
1390
1392
  }
@@ -1617,7 +1619,7 @@ SET: foreach $set (@setList) {
1617
1619
  }
1618
1620
  # transfer maker note information if setting this tag
1619
1621
  if ($$srcExifTool{TAG_INFO}{$tag}{MakerNotes}) {
1620
- $$self{MAKER_NOTE_FIXUP} = $$srcExifTool{MAKER_NOTE_FIXUP};
1622
+ $$opts{Fixup} = $$srcExifTool{TAG_EXTRA}{$tag}{Fixup};
1621
1623
  $$self{MAKER_NOTE_BYTE_ORDER} = $$srcExifTool{MAKER_NOTE_BYTE_ORDER};
1622
1624
  }
1623
1625
  if ($dstTag eq '*') {
@@ -1649,6 +1651,7 @@ SET: foreach $set (@setList) {
1649
1651
  $rtnInfo{NextFreeTagKey(\%rtnInfo, 'Warning')} = $wrn;
1650
1652
  $noWarn = 1;
1651
1653
  }
1654
+ delete $$opts{Fixup};
1652
1655
  $rtnInfo{$tag} = $val if $rtn; # tag was set successfully
1653
1656
  }
1654
1657
  }
@@ -4176,6 +4179,7 @@ sub WriteDirectory($$$;$)
4176
4179
  $out = $$self{OPTIONS}{TextOut} if $$self{OPTIONS}{Verbose};
4177
4180
  # set directory name from default group0 name if not done already
4178
4181
  my $dirName = $$dirInfo{DirName};
4182
+ my $parent = $$dirInfo{Parent} || '';
4179
4183
  my $dataPt = $$dirInfo{DataPt};
4180
4184
  my $grp0 = $$tagTablePtr{GROUPS}{0};
4181
4185
  $dirName or $dirName = $$dirInfo{DirName} = $grp0;
@@ -4190,7 +4194,9 @@ sub WriteDirectory($$$;$)
4190
4194
  $self->IsRawType() and
4191
4195
  # allow non-permanent MakerNote directories to be deleted (ie. NikonCapture)
4192
4196
  (not $$dirInfo{TagInfo} or not defined $$dirInfo{TagInfo}{Permanent} or
4193
- $$dirInfo{TagInfo}{Permanent}))
4197
+ $$dirInfo{TagInfo}{Permanent}) and
4198
+ # allow MakerNotes to be deleted from ExifIFD of CR3 file
4199
+ not ($self->IsRawType() == 2 and $parent eq 'ExifIFD'))
4194
4200
  {
4195
4201
  $self->WarnOnce("Can't delete $1 from $$self{FileType}",1);
4196
4202
  undef $grp1;
@@ -4226,7 +4232,6 @@ sub WriteDirectory($$$;$)
4226
4232
  if ($delFlag == 2 and $right) {
4227
4233
  # also check grandparent because some routines create 2 levels in 1
4228
4234
  my $right2 = $$self{ADD_DIRS}{$right} || '';
4229
- my $parent = $$dirInfo{Parent};
4230
4235
  if (not $parent or $parent eq $right or $parent eq $right2) {
4231
4236
  # prevent duplicate directories from being recreated at the same path
4232
4237
  my $path = join '-', @{$$self{PATH}}, $dirName;
@@ -4287,7 +4292,10 @@ sub WriteDirectory($$$;$)
4287
4292
  unless (defined $newVal and length $newVal) {
4288
4293
  return '' unless $dataPt or $$dirInfo{RAF}; # nothing to do if block never existed
4289
4294
  # don't allow MakerNotes to be removed from RAW files
4290
- if ($blockName eq 'MakerNotes' and $rawType{$$self{FileType}}) {
4295
+ if ($blockName eq 'MakerNotes' and $self->IsRawType() and
4296
+ # but allow MakerNotes to be deleted from ExifIFD of CR3 image (shouldn't be there)
4297
+ not ($self->IsRawType() == 2 and $parent eq 'ExifIFD'))
4298
+ {
4291
4299
  $self->Warn("Can't delete MakerNotes from $$self{FileType}",1);
4292
4300
  return undef;
4293
4301
  }
@@ -7186,6 +7194,39 @@ sub WriteTIFF($$$)
7186
7194
  {
7187
7195
  my ($self, $dirInfo, $tagTablePtr) = @_;
7188
7196
  $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
+ }
7189
7230
  my $buff = '';
7190
7231
  $$dirInfo{OutFile} = \$buff;
7191
7232
  return $buff if $self->ProcessTIFF($dirInfo, $tagTablePtr) > 0;
@@ -0,0 +1,185 @@
1
+ #------------------------------------------------------------------------------
2
+ # File: XISF.pm
3
+ #
4
+ # Description: Read Extensible Image Serialization Format metadata
5
+ #
6
+ # Revisions: 2023-10-10 - P. Harvey Created
7
+ #
8
+ # References: 1) https://pixinsight.com/doc/docs/XISF-1.0-spec/XISF-1.0-spec.html
9
+ #------------------------------------------------------------------------------
10
+
11
+ package Image::ExifTool::XISF;
12
+
13
+ use strict;
14
+ use vars qw($VERSION);
15
+ use Image::ExifTool qw(:DataAccess :Utils);
16
+ use Image::ExifTool::XMP;
17
+
18
+ $VERSION = '1.00';
19
+
20
+ # XISF tags (ref 1)
21
+ %Image::ExifTool::XISF::Main = (
22
+ GROUPS => { 0 => 'XML', 1 => 'XML', 2 => 'Image' },
23
+ VARS => { LONG_TAGS => 1 },
24
+ NOTES => q{
25
+ This table lists some standard Extensible Image Serialization Format (XISF)
26
+ tags, but ExifTool will extract any other tags found. See
27
+ L<https://pixinsight.com/xisf/> for the specification.
28
+ },
29
+ ImageGeometry => { },
30
+ ImageSampleFormat => { },
31
+ ImageBounds => { },
32
+ ImageImageType => { Name => 'ImageType' },
33
+ ImageColorSpace => { Name => 'ColorSpace' },
34
+ ImageLocation => { },
35
+ ImageResolutionHorizontal => 'XResolution',
36
+ ImageResolutionVertical => 'YResolution',
37
+ ImageResolutionUnit => 'ResolutionUnit',
38
+ ImageICCProfile => {
39
+ Name => 'ICC_Profile',
40
+ ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)',
41
+ Binary => 1,
42
+ },
43
+ ImageICCProfileLocation => { Name => 'ICCProfileLocation' },
44
+ ImagePixelStorage => { },
45
+ ImageOffset => { Name => 'ImagePixelOffset' },
46
+ ImageOrientation => { Name => 'Orientation' },
47
+ ImageId => { Name => 'ImageID' },
48
+ ImageUuid => { Name => 'UUID' },
49
+ ImageData => { Binary => 1 },
50
+ 'CreationTime' => {
51
+ Name => 'CreateDate',
52
+ Shift => 'Time',
53
+ Groups => { 2 => 'Time' },
54
+ ValueConv => 'Image::ExifTool::XMP::ConvertXMPDate($val)',
55
+ PrintConv => '$self->ConvertDateTime($val)',
56
+ },
57
+ CreatorApplication => { },
58
+ Abstract => { },
59
+ AccessRights => { },
60
+ Authors => { Groups => { 2 => 'Author' } },
61
+ BibliographicReferences => { },
62
+ BriefDescription => { },
63
+ CompressionLevel => { },
64
+ CompressionCodecs => { },
65
+ Contributors => { Groups => { 2 => 'Author' } },
66
+ Copyright => { Groups => { 2 => 'Author' } },
67
+ CreatorModule => { },
68
+ CreatorOS => { },
69
+ Description => { },
70
+ Keywords => { },
71
+ Languages => { },
72
+ License => { },
73
+ OriginalCreationTime => {
74
+ Name => 'DateTimeOriginal',
75
+ Description => 'Date/Time Original',
76
+ Shift => 'Time',
77
+ Groups => { 2 => 'Time' },
78
+ ValueConv => 'Image::ExifTool::XMP::ConvertXMPDate($val)',
79
+ PrintConv => '$self->ConvertDateTime($val)',
80
+ },
81
+ RelatedResources => { },
82
+ Title => { },
83
+ );
84
+
85
+ #------------------------------------------------------------------------------
86
+ # Handle properties in XISF metadata structures
87
+ # Inputs: 0) attribute list ref, 1) attr hash ref,
88
+ # 2) property name ref, 3) property value ref
89
+ # Returns: true if value was changed
90
+ sub HandleXISFAttrs($$$$)
91
+ {
92
+ my ($attrList, $attrs, $prop, $valPt) = @_;
93
+ return 0 unless defined $$attrs{id};
94
+ my ($changed, $a);
95
+ # use "id" as the tag name, "value" as the value, and ignore "type"
96
+ $$prop = $$attrs{id};
97
+ $$prop =~ s/^XISF://; # remove XISF namespace
98
+ if (defined $$attrs{value}) {
99
+ $$valPt = $$attrs{value};
100
+ $changed = 1;
101
+ }
102
+ my @attrs = @$attrList;
103
+ @$attrList = ( );
104
+ foreach $a (@attrs) {
105
+ if ($a eq 'id' or $a eq 'value' or $a eq 'type') {
106
+ delete $$attrs{$a};
107
+ } else {
108
+ push @$attrList, $a;
109
+ }
110
+ }
111
+ return $changed;
112
+ }
113
+
114
+ #------------------------------------------------------------------------------
115
+ # Read information in a XISF document
116
+ # Inputs: 0) ExifTool ref, 1) dirInfo ref
117
+ # Returns: 1 on success, 0 if this wasn't a valid XISF file
118
+ sub ProcessXISF($$)
119
+ {
120
+ my ($et, $dirInfo) = @_;
121
+ my $raf = $$dirInfo{RAF};
122
+ my $buff;
123
+
124
+ return 0 unless $raf->Read($buff, 16) == 16 and $buff =~ /^XISF0100/;
125
+ $et->SetFileType();
126
+ SetByteOrder('II');
127
+ my $tagTablePtr = GetTagTable('Image::ExifTool::XISF::Main');
128
+ my $hdrLen = Get32u(\$buff, 8);
129
+ $raf->Read($buff, $hdrLen) == $hdrLen or $et->Warn('Error reading XISF header'), return 1;
130
+ $et->FoundTag(XML => $buff);
131
+ my %dirInfo = (
132
+ DataPt => \$buff,
133
+ IgnoreProp => { xisf => 1, Metadata => 1, Property => 1 },
134
+ XMPParseOpts => { AttrProc => \&HandleXISFAttrs },
135
+ );
136
+ Image::ExifTool::XMP::ProcessXMP($et, \%dirInfo, $tagTablePtr);
137
+ my $geo = $$et{VALUE}{ImageGeometry};
138
+ if ($geo) {
139
+ my ($w, $h, $n) = split /:/, $geo;
140
+ $et->FoundTag(ImageWidth => $w);
141
+ $et->FoundTag(ImageHeight => $h);
142
+ $et->FoundTag(NumPlanes => $n);
143
+ }
144
+ return 1;
145
+ }
146
+
147
+ 1; # end
148
+
149
+ __END__
150
+
151
+ =head1 NAME
152
+
153
+ Image::ExifTool::XISF - Read Extensible Image Serialization Format metadata
154
+
155
+ =head1 SYNOPSIS
156
+
157
+ This module is used by Image::ExifTool
158
+
159
+ =head1 DESCRIPTION
160
+
161
+ This module contains definitions required by Image::ExifTool to read meta
162
+ information from XISF (Extensible Image Serialization Format) images.
163
+
164
+ =head1 AUTHOR
165
+
166
+ Copyright 2003-2023, Phil Harvey (philharvey66 at gmail.com)
167
+
168
+ This library is free software; you can redistribute it and/or modify it
169
+ under the same terms as Perl itself.
170
+
171
+ =head1 REFERENCES
172
+
173
+ =over 4
174
+
175
+ =item L<https://pixinsight.com/doc/docs/XISF-1.0-spec/XISF-1.0-spec.html>
176
+
177
+ =back
178
+
179
+ =head1 SEE ALSO
180
+
181
+ L<Image::ExifTool::TagNames/XISF Tags>,
182
+ L<Image::ExifTool(3pm)|Image::ExifTool>
183
+
184
+ =cut
185
+
@@ -50,7 +50,7 @@ use Image::ExifTool::Exif;
50
50
  use Image::ExifTool::GPS;
51
51
  require Exporter;
52
52
 
53
- $VERSION = '3.60';
53
+ $VERSION = '3.61';
54
54
  @ISA = qw(Exporter);
55
55
  @EXPORT_OK = qw(EscapeXML UnescapeXML);
56
56
 
@@ -201,6 +201,8 @@ my %xmpNS = (
201
201
  nine => 'http://ns.nikon.com/nine/1.0/',
202
202
  hdr_metadata => 'http://ns.adobe.com/hdr-metadata/1.0/',
203
203
  hdrgm => 'http://ns.adobe.com/hdr-gain-map/1.0/',
204
+ # Note: Not included due to namespace prefix conflict with Device:Container
205
+ # Container => 'http://ns.google.com/photos/1.0/container/',
204
206
  );
205
207
 
206
208
  # build reverse namespace lookup
@@ -479,7 +481,7 @@ my %sCorrRangeMask = (
479
481
  LuminanceDepthSampleInfo => { },
480
482
  );
481
483
  # new LR2 crs structures (PH)
482
- my %sCorrectionMask;
484
+ my %sCorrectionMask; # (must define this before assigning because it is self-referential)
483
485
  %sCorrectionMask = (
484
486
  STRUCT_NAME => 'CorrectionMask',
485
487
  NAMESPACE => 'crs',
@@ -919,6 +921,11 @@ my %sRangeMask = (
919
921
  Name => 'hdrgm',
920
922
  SubDirectory => { TagTable => 'Image::ExifTool::XMP::hdrgm' },
921
923
  },
924
+ # Note: Note included due to namespace prefix conflict with Device:Container
925
+ # Container => {
926
+ # Name => 'Container',
927
+ # SubDirectory => { TagTable => 'Image::ExifTool::XMP::Container' },
928
+ # },
922
929
  );
923
930
 
924
931
  # hack to allow XML containing Dublin Core metadata to be handled like XMP (eg. EPUB - see ZIP.pm)
@@ -1699,6 +1706,8 @@ my %sPantryItem = (
1699
1706
  ToneCurvePV2012Red => { List => 'Seq' },
1700
1707
  ToneCurvePV2012Green => { List => 'Seq' },
1701
1708
  ToneCurvePV2012Blue => { List => 'Seq' },
1709
+ Highlights2012 => { },
1710
+ Shadows2012 => { },
1702
1711
  },
1703
1712
  },
1704
1713
  }
@@ -1760,6 +1769,62 @@ my %sPantryItem = (
1760
1769
  SDRShadows => { Writable => 'real' },
1761
1770
  SDRWhites => { Writable => 'real' },
1762
1771
  SDRBlend => { Writable => 'real' },
1772
+ # new for ACR 16 (ref forum15305)
1773
+ LensBlur => {
1774
+ Struct => {
1775
+ STRUCT_NAME => 'LensBlur',
1776
+ NAMESPACE => 'crs',
1777
+ # (Note: all the following 'real' values could be limited to 'integer')
1778
+ Active => { Writable => 'boolean' },
1779
+ BlurAmount => { FlatName => 'Amount', Writable => 'real' },
1780
+ BokehAspect => { Writable => 'real' },
1781
+ BokehRotation => { Writable => 'real' },
1782
+ BokehShape => { Writable => 'real' },
1783
+ BokehShapeDetail => { Writable => 'real' },
1784
+ CatEyeAmount => { Writable => 'real' },
1785
+ CatEyeScale => { Writable => 'real' },
1786
+ FocalRange => { }, # (eg. "-48 32 64 144")
1787
+ FocalRangeSource => { Writable => 'real' },
1788
+ HighlightsBoost => { Writable => 'real' },
1789
+ HighlightsThreshold => { Writable => 'real' },
1790
+ SampledArea => { }, # (eg. "0.500000 0.500000 0.500000 0.500000")
1791
+ SampledRange => { }, # (eg. "0 0")
1792
+ SphericalAberration => { Writable => 'real' },
1793
+ SubjectRange => { }, # (eg. "0 57");
1794
+ Version => { },
1795
+ },
1796
+ },
1797
+ DepthMapInfo => {
1798
+ Struct => {
1799
+ STRUCT_NAME => 'DepthMapInfo',
1800
+ NAMESPACE => 'crs',
1801
+ BaseHighlightGuideInputDigest => { },
1802
+ BaseHighlightGuideTable => { },
1803
+ BaseHighlightGuideVersion => { },
1804
+ BaseLayeredDepthInputDigest => { },
1805
+ BaseLayeredDepthTable => { },
1806
+ BaseLayeredDepthVersion => { },
1807
+ BaseRawDepthInputDigest => { },
1808
+ BaseRawDepthTable => { },
1809
+ BaseRawDepthVersion => { },
1810
+ DepthSource => { },
1811
+ },
1812
+ },
1813
+ DepthBasedCorrections => {
1814
+ List => 'Seq',
1815
+ FlatName => 'DepthBasedCorr',
1816
+ Struct => {
1817
+ STRUCT_NAME => 'DepthBasedCorr',
1818
+ NAMESPACE => 'crs',
1819
+ CorrectionActive => { Writable => 'boolean' },
1820
+ CorrectionAmount => { Writable => 'real' },
1821
+ CorrectionMasks => { FlatName => 'Mask', List => 'Seq', Struct => \%sCorrectionMask },
1822
+ CorrectionSyncID => { },
1823
+ LocalCorrectedDepth => { Writable => 'real' },
1824
+ LocalCurveRefineSaturation => { Writable => 'real' },
1825
+ What => { },
1826
+ },
1827
+ },
1763
1828
  );
1764
1829
 
1765
1830
  # Tiff namespace properties (tiff)