exiftool_vendored 12.59.0 → 12.61.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.
@@ -34,7 +34,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
34
34
  use Image::ExifTool::Exif;
35
35
  use Image::ExifTool::Minolta;
36
36
 
37
- $VERSION = '3.58';
37
+ $VERSION = '3.60';
38
38
 
39
39
  sub ProcessSRF($$$);
40
40
  sub ProcessSR2($$$);
@@ -161,6 +161,7 @@ sub PrintInvLensSpec($;$$);
161
161
  32876 => 'Sony E 11mm F1.8', #JR
162
162
  32877 => 'Sony E 15mm F1.4 G', #JR
163
163
  32878 => 'Sony FE 20-70mm F4 G', #JR
164
+ 32879 => 'Sony FE 50mm F1.4 GM', #JR
164
165
 
165
166
  # (comment this out so LensID will report the LensModel, which is more useful)
166
167
  # 32952 => 'Metabones Canon EF Speed Booster Ultra', #JR (corresponds to 184, but 'Advanced' mode, LensMount reported as E-mount)
@@ -259,7 +260,10 @@ sub PrintInvLensSpec($;$$);
259
260
  50534 => 'Sigma 20mm F1.4 DG DN | A', #JR (022)
260
261
  50535 => 'Sigma 24mm F1.4 DG DN | A', #JR (022)
261
262
  50536 => 'Sigma 60-600mm F4.5-6.3 DG DN OS | S', #JR (023)
263
+ 50537 => 'Sigma 50mm F2 DG DN | C', #JR (023)
264
+ 50538 => 'Sigma 17mm F4 DG DN | C', #JR (023)
262
265
  50539 => 'Sigma 50mm F1.4 DG DN | A', #JR (023)
266
+ 50544 => 'Sigma 23mm F1.4 DC DN | C', #JR (023)
263
267
 
264
268
  50992 => 'Voigtlander SUPER WIDE-HELIAR 15mm F4.5 III', #JR
265
269
  50993 => 'Voigtlander HELIAR-HYPER WIDE 10mm F5.6', #IB
@@ -1165,7 +1169,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
1165
1169
  },
1166
1170
  },{
1167
1171
  Name => 'AFAreaModeSetting',
1168
- Condition => '$$self{Model} =~ /^(NEX-|ILCE-|ILME-|DSC-(RX10M4|RX100M6|RX100M7|RX100M5A|HX99|RX0M2))/',
1172
+ Condition => '$$self{Model} =~ /^(NEX-|ILCE-|ILME-|ZV-E|DSC-(RX10M4|RX100M6|RX100M7|RX100M5A|HX99|RX0M2))/',
1169
1173
  Notes => 'NEX, ILCE and some DSC models',
1170
1174
  RawConv => '$$self{AFAreaILCE} = $val',
1171
1175
  DataMember => 'AFAreaILCE',
@@ -1201,7 +1205,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
1201
1205
  # observed values in range (0 0) to (640 480), with center (320 240) often seen
1202
1206
  # for NEX-5R/6, positions appear to be in an 11x9 grid
1203
1207
  Name => 'FlexibleSpotPosition',
1204
- Condition => '$$self{Model} =~ /^(NEX-|ILCE-|ILME-|DSC-(RX10M4|RX100M6|RX100M7|RX100M5A|HX99|RX0M2))/',
1208
+ Condition => '$$self{Model} =~ /^(NEX-|ILCE-|ILME-|ZV-E|DSC-(RX10M4|RX100M6|RX100M7|RX100M5A|HX99|RX0M2))/',
1205
1209
  Writable => 'int16u',
1206
1210
  Count => 2,
1207
1211
  Notes => q{
@@ -1669,6 +1673,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
1669
1673
  # 0x28 (e) for ILCE-7RM4/9M2, DSC-RX100M7, ZV-1/E10
1670
1674
  # 0x31 (e) for ILCE-1/7M4/7SM3, ILME-FX3
1671
1675
  # 0x32 (e) for ILCE-7RM5, ILME-FX30
1676
+ # 0x33 (e) for ZV-E1
1672
1677
  # first byte decoded: 40, 204, 202, 27, 58, 62, 48, 215, 28, 106, 89 respectively
1673
1678
  {
1674
1679
  Name => 'Tag9400a',
@@ -1683,7 +1688,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
1683
1688
  SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag9400b' },
1684
1689
  },{
1685
1690
  Name => 'Tag9400c',
1686
- Condition => '$$valPt =~ /^[\x23\x24\x26\x28\x31\x32]/',
1691
+ Condition => '$$valPt =~ /^[\x23\x24\x26\x28\x31\x32\x33]/',
1687
1692
  SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag9400c' },
1688
1693
  },{
1689
1694
  Name => 'Sony_0x9400',
@@ -1896,7 +1901,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
1896
1901
  },
1897
1902
  0x940c => [{
1898
1903
  Name => 'Tag940c',
1899
- Condition => '$$self{Model} =~ /^(NEX-|ILCE-|ILME-|Lunar|ZV-E10)\b/',
1904
+ Condition => '$$self{Model} =~ /^(NEX-|ILCE-|ILME-|Lunar|ZV-E10|ZV-E1)\b/',
1900
1905
  SubDirectory => { TagTable => 'Image::ExifTool::Sony::Tag940c' },
1901
1906
  },{
1902
1907
  Name => 'Sony_0x940c',
@@ -1957,6 +1962,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
1957
1962
  '3 3 3 0' => 'ARW 2.3.3', #JR (ILCE-9)
1958
1963
  '3 3 5 0' => 'ARW 2.3.5', #JR (DSC-HX99)
1959
1964
  '4 0 0 0' => 'ARW 4.0', # (ILCE-7SM3)
1965
+ '4 0 1 0' => 'ARW 4.0.1', #github#195 (ZV-E1)
1960
1966
  # what about cRAW images?
1961
1967
  },
1962
1968
  },
@@ -2063,6 +2069,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
2063
2069
  389 => 'ZV-1F', #IB
2064
2070
  390 => 'ILCE-7RM5', #IB
2065
2071
  391 => 'ILME-FX30', #JR
2072
+ 393 => 'ZV-E1', #JR
2066
2073
  },
2067
2074
  },
2068
2075
  0xb020 => { #2
@@ -8237,7 +8244,7 @@ my %isoSetting2010 = (
8237
8244
  },
8238
8245
  0x002a => [{
8239
8246
  Name => 'Quality2',
8240
- Condition => '$$self{Model} !~ /^(ILCE-(1|7M4|7RM5|7SM3)|ILME-FX3)\b/',
8247
+ Condition => '$$self{Model} !~ /^(ILCE-(1|7M4|7RM5|7SM3)|ILME-(FX3|FX30)|ZV-E1)\b/',
8241
8248
  PrintConv => {
8242
8249
  0 => 'JPEG',
8243
8250
  1 => 'RAW',
@@ -8246,7 +8253,6 @@ my %isoSetting2010 = (
8246
8253
  },
8247
8254
  },{
8248
8255
  Name => 'Quality2',
8249
- Condition => '$$self{Model} =~ /^(ILCE-(1|7M4|7RM5|7SM3)|ILME-FX3)\b/',
8250
8256
  PrintConv => {
8251
8257
  1 => 'JPEG',
8252
8258
  2 => 'RAW',
@@ -8257,13 +8263,13 @@ my %isoSetting2010 = (
8257
8263
  }],
8258
8264
  0x0047 => {
8259
8265
  Name => 'SonyImageHeight',
8260
- Condition => '$$self{Model} !~ /^(ILCE-(1|7M4|7RM5|7SM3)|ILME-FX3)\b/',
8266
+ Condition => '$$self{Model} !~ /^(ILCE-(1|7M4|7RM5|7SM3)|ILME-(FX3|FX30)|ZV-E1)\b/',
8261
8267
  Format => 'int16u',
8262
8268
  PrintConv => '$val > 0 ? 8*$val : "n.a."',
8263
8269
  },
8264
8270
  0x0053 => {
8265
8271
  Name => 'ModelReleaseYear',
8266
- Condition => '$$self{Model} !~ /^(ILCE-(1|7M4|7RM5|7SM3)|ILME-FX3)\b/',
8272
+ Condition => '$$self{Model} !~ /^(ILCE-(1|7M4|7RM5|7SM3)|ILME-(FX3|FX30)|ZV-E1)\b/',
8267
8273
  Format => 'int8u',
8268
8274
  PrintConv => 'sprintf("20%.2d", $val)',
8269
8275
  },
@@ -8278,9 +8284,10 @@ my %isoSetting2010 = (
8278
8284
  FIRST_ENTRY => 0,
8279
8285
  GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
8280
8286
  DATAMEMBER => [ 0 ],
8281
- IS_SUBDIR => [ 0x044e, 0x0498, 0x049d, 0x04a1, 0x04a2, 0x059d, 0x0634, 0x0636, 0x064c, 0x0653, 0x0678, 0x06b8, 0x06de, 0x06e7 ],
8287
+ IS_SUBDIR => [ 0x03e2, 0x044e, 0x0498, 0x049d, 0x04a1, 0x04a2, 0x059d, 0x0634, 0x0636, 0x064c, 0x0653, 0x0678, 0x06b8, 0x06de, 0x06e7 ],
8282
8288
  0x0000 => { Name => 'Ver9401', Hidden => 1, RawConv => '$$self{Ver9401} = $val; $$self{OPTIONS}{Unknown}<2 ? undef : $val' },
8283
8289
 
8290
+ 0x03e2 => { Name => 'ISOInfo', Condition => '$$self{Ver9401} == 181', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } },
8284
8291
  0x044e => { Name => 'ISOInfo', Condition => '$$self{Ver9401} == 178', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } },
8285
8292
  0x0498 => { Name => 'ISOInfo', Condition => '$$self{Ver9401} == 148', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } },
8286
8293
  0x049d => { Name => 'ISOInfo', Condition => '$$self{Ver9401} == 167', Format => 'int8u[5]', SubDirectory => { TagTable => 'Image::ExifTool::Sony::ISOInfo' } },
@@ -1149,7 +1149,7 @@ my %tagLookup = (
1149
1149
  'bitspercomponent' => { 133 => 0x87 },
1150
1150
  'bitspersample' => { 119 => 0x102, 340 => 0xa, 517 => 'BitsPerSample' },
1151
1151
  'blackacquirerows' => { 138 => 0x18ba },
1152
- 'blacklevel' => { 119 => 0xc61a, 206 => 0x20, 233 => 0x3d, 317 => [0x401,0x1012], 379 => 0x21d, 442 => [0x7300,0x7310] },
1152
+ 'blacklevel' => { 119 => [0x7310,0xc61a], 206 => 0x20, 233 => 0x3d, 317 => [0x401,0x1012], 379 => 0x21d, 442 => [0x7300,0x7310] },
1153
1153
  'blacklevel2' => { 316 => 0x600, 320 => 0x600 },
1154
1154
  'blacklevelblue' => { 340 => 0x1e },
1155
1155
  'blacklevelbottom' => { 138 => 0x3f0 },
@@ -6271,6 +6271,7 @@ my %tagLookup = (
6271
6271
  'sonyminaperture' => { 454 => 0x1, 455 => 0x1 },
6272
6272
  'sonymodelid' => { 435 => 0xb001 },
6273
6273
  'sonyquality' => { 184 => 0x3c },
6274
+ 'sonyrawimagesize' => { 119 => 0x7038 },
6274
6275
  'sonytimeminsec' => { 455 => 0x61 },
6275
6276
  'sortalbum' => { 387 => 'soal' },
6276
6277
  'sortalbumartist' => { 387 => 'soaa' },
@@ -7052,7 +7053,7 @@ my %tagLookup = (
7052
7053
  'wb_rgbmulfluorescent' => { 138 => 0x854 },
7053
7054
  'wb_rgbmultungsten' => { 138 => 0x853 },
7054
7055
  'wb_rggbblacklevels' => { 35 => 0x25 },
7055
- 'wb_rggblevels' => { 190 => 0x4, 201 => 0x0, 205 => 0x13e8, 206 => 0x38, 442 => 0x7313 },
7056
+ 'wb_rggblevels' => { 119 => 0x7313, 190 => 0x4, 201 => 0x0, 205 => 0x13e8, 206 => 0x38, 442 => 0x7313 },
7056
7057
  'wb_rggblevelsasshot' => { 38 => 0x0, 39 => 0x0, 40 => 0x19, 41 => 0x55, 42 => 0x69, 43 => 0x22, 44 => 0x3f, 47 => 0x3f, 48 => 0x3f, 49 => 0x3f, 50 => 0x47 },
7057
7058
  'wb_rggblevelsauto' => { 35 => 0x1, 38 => 0x5, 39 => 0x8, 40 => 0x1e, 41 => 0x5a, 42 => 0x6e, 43 => 0x18, 44 => 0x44, 47 => 0x44, 48 => 0x44, 49 => 0x44, 50 => 0x4c, 205 => 0x1478, 206 => 0x114, 409 => 0xa022, 442 => 0x7312 },
7058
7059
  'wb_rggblevelsblack' => { 409 => 0xa028 },
@@ -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 26390 tags, with 16859 unique tag names.
15
+ They contain a total of 26393 tags, with 16860 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
@@ -498,6 +498,9 @@ for the official EXIF 2.32 specification.
498
498
  0x7035 ChromaticAberrationCorrParams SubIFD int16s[33]!
499
499
  0x7036 DistortionCorrection SubIFD int16s!
500
500
  0x7037 DistortionCorrParams SubIFD int16s[17]!
501
+ 0x7038 SonyRawImageSize SubIFD int32u[2]!
502
+ 0x7310 BlackLevel SubIFD int16u[4]!
503
+ 0x7313 WB_RGGBLevels SubIFD int16s[4]!
501
504
  0x74c7 SonyCropTopLeft SubIFD int32u[2]!
502
505
  0x74c8 SonyCropSize SubIFD int32u[2]!
503
506
  0x800d ImageID - no
@@ -20824,6 +20827,7 @@ WX350/WX500, ILCE-1/7/7C/7R/7S/7M2/7M3/7RM2/7RM3/7RM4/7SM2/7SM3/9/9M2/5000/
20824
20827
 
20825
20828
  Index1 Tag Name Writable
20826
20829
  ------ -------- --------
20830
+ 994 ISOInfo Sony ISOInfo
20827
20831
  1102 ISOInfo Sony ISOInfo
20828
20832
  1176 ISOInfo Sony ISOInfo
20829
20833
  1181 ISOInfo Sony ISOInfo
@@ -430,7 +430,6 @@ sub AddImageDataMD5($$$)
430
430
  my $verbose = $et->Options('Verbose');
431
431
  my $md5 = $$et{ImageDataMD5};
432
432
  my $raf = $$dirInfo{RAF};
433
- my $base = $$dirInfo{Base} || 0;
434
433
 
435
434
  foreach $tagID (sort keys %$offsetInfo) {
436
435
  next unless ref $$offsetInfo{$tagID} eq 'ARRAY'; # ignore scalar tag values used for Validate
@@ -451,14 +450,8 @@ sub AddImageDataMD5($$$)
451
450
  foreach $offset (@offsets) {
452
451
  my $size = shift @sizes;
453
452
  next unless $offset =~ /^\d+$/ and $size and $size =~ /^\d+$/ and $size;
454
- next unless $raf->Seek($offset+$base, 0);
455
- while ($size) {
456
- my $bytes = $size > 65536 ? 65536 : $size;
457
- $raf->Read($buff, $bytes) or last;
458
- $md5->add($buff);
459
- $total += length($buff);
460
- $size -= $bytes;
461
- }
453
+ next unless $raf->Seek($offset, 0); # (offset is absolute)
454
+ $total += $et->ImageDataMD5($raf, $size);
462
455
  }
463
456
  if ($verbose) {
464
457
  my $name = "$$dirInfo{DirName}:$$tagInfo{Name}";
@@ -23,7 +23,7 @@ my $beginComment = '%BeginExifToolUpdate';
23
23
  my $endComment = '%EndExifToolUpdate ';
24
24
 
25
25
  my $keyExt; # crypt key extension
26
- my $pdfVer; # version of PDF file we are currently writing
26
+ my $pdfVer; # version of PDF file we are writing (highest Version in Root dictionaries)
27
27
 
28
28
  # internal tags used in dictionary objects
29
29
  my %myDictTags = (
@@ -297,15 +297,11 @@ sub WritePDF($$)
297
297
  $$newTool{PDF_CAPTURE} = \%capture;
298
298
  my $info = $newTool->ImageInfo($raf, 'XMP', 'PDF:*', 'Error', 'Warning');
299
299
  # not a valid PDF file unless we got a version number
300
- # (note: can't just check $$info{PDFVersion} due to possibility of XMP-pdf:PDFVersion)
301
- my $vers = $newTool->GetInfo('PDF:PDFVersion');
302
- # take highest version number if multiple versions in an incremental save
303
- ($pdfVer) = sort { $b <=> $a } values %$vers;
300
+ $pdfVer = $$newTool{PDFVersion};
304
301
  $pdfVer or $et->Error('Missing PDF:PDFVersion'), return 0;
305
302
  # check version number
306
- if ($pdfVer > 1.7) {
307
- $et->Warn("The PDF $pdfVer specification is not freely available", 1);
308
- # (so writing by ExifTool is based on trial and error)
303
+ if ($pdfVer > 2.0) {
304
+ $et->Error("Writing PDF $pdfVer is untested", 1) and return 0;
309
305
  }
310
306
  # fail if we had any serious errors while extracting information
311
307
  if ($capture{Error} or $$info{Error}) {
@@ -412,6 +408,9 @@ sub WritePDF($$)
412
408
  my $tagID;
413
409
  foreach $tagID (sort keys %$newTags) {
414
410
  my $tagInfo = $$newTags{$tagID};
411
+ if ($pdfVer >= 2.0 and not $$tagInfo{PDF2}) {
412
+ next if $et->Warn("Writing PDF:$$tagInfo{Name} is deprecated for PDF 2.0 documents",2);
413
+ }
415
414
  my $nvHash = $et->GetNewValueHash($tagInfo);
416
415
  my (@vals, $deleted);
417
416
  my $tag = $$tagInfo{Name};
@@ -3324,15 +3324,19 @@ sub InsertTagValues($$$;$$$)
3324
3324
  undef $advFmtSelf;
3325
3325
  $didExpr = 1; # set flag indicating an expression was evaluated
3326
3326
  }
3327
- unless (defined $val or ref $opt) {
3327
+ unless (defined $val) {
3328
3328
  $val = $$self{OPTIONS}{MissingTagValue};
3329
3329
  unless (defined $val) {
3330
3330
  my $g3 = ($docGrp and $var !~ /\b(main|doc\d+):/i) ? $docGrp . ':' : '';
3331
3331
  my $msg = $didExpr ? "Advanced formatting expression returned undef for '$g3${var}'" :
3332
3332
  "Tag '$g3${var}' not defined";
3333
- no strict 'refs';
3334
- $opt and ($opt eq 'Silent' or &$opt($self, $msg, 2)) and return $$self{FMT_EXPR} = undef;
3335
- $val = '';
3333
+ if (ref $opt) {
3334
+ $self->Warn($msg,2) or $val = '';
3335
+ } elsif ($opt) {
3336
+ no strict 'refs';
3337
+ ($opt eq 'Silent' or &$opt($self, $msg, 2)) and return $$self{FMT_EXPR} = undef;
3338
+ $val = '';
3339
+ }
3336
3340
  }
3337
3341
  }
3338
3342
  if (ref $opt eq 'HASH') {
@@ -5566,7 +5570,7 @@ sub WriteJPEG($$)
5566
5570
  $s =~ /^JFXX\0\x10/ and $dirName = 'JFXX';
5567
5571
  $s =~ /^(II|MM).{4}HEAPJPGM/s and $dirName = 'CIFF';
5568
5572
  } elsif ($marker == 0xe1) {
5569
- if ($s =~ /^(.{0,4})$exifAPP1hdr(.{1,4})/is) {
5573
+ if ($s =~ /^(.{0,4})Exif\0.(.{1,4})/is) {
5570
5574
  $dirName = 'IFD0';
5571
5575
  my ($junk, $bytes) = ($1, $2);
5572
5576
  # support multi-segment EXIF
@@ -6132,7 +6136,7 @@ sub WriteJPEG($$)
6132
6136
  }
6133
6137
  } elsif ($marker == 0xe1) { # APP1 (EXIF, XMP)
6134
6138
  # check for EXIF data
6135
- if ($$segDataPt =~ /^(.{0,4})$exifAPP1hdr/is) {
6139
+ if ($$segDataPt =~ /^(.{0,4})Exif\0./is) {
6136
6140
  my $hdrLen = length $exifAPP1hdr;
6137
6141
  if (length $1) {
6138
6142
  $hdrLen += length $1;
@@ -6867,6 +6871,36 @@ sub SetFileTime($$;$$$$)
6867
6871
  return 1; # (nothing to do)
6868
6872
  }
6869
6873
 
6874
+ #------------------------------------------------------------------------------
6875
+ # Add data to MD5 checksum
6876
+ # Inputs: 0) ExifTool ref, 1) RAF ref, 2) data size (or undef to read to end of file),
6877
+ # 3) data name (or undef for no warnings or messages), 4) flag for no verbose message
6878
+ # Returns: number of bytes read and MD5'd
6879
+ sub ImageDataMD5($$$;$$)
6880
+ {
6881
+ my ($self, $raf, $size, $type, $noMsg) = @_;
6882
+ my $md5 = $$self{ImageDataMD5} or return;
6883
+ my ($bytesRead, $n) = (0, 65536);
6884
+ my $buff;
6885
+ for (;;) {
6886
+ if (defined $size) {
6887
+ last unless $size;
6888
+ $n = $size > 65536 ? 65536 : $size;
6889
+ $size -= $n;
6890
+ }
6891
+ unless ($raf->Read($buff, $n)) {
6892
+ $self->Warn("Error reading $type data") if $type and defined $size;
6893
+ last;
6894
+ }
6895
+ $md5->add($buff);
6896
+ $bytesRead += length $buff;
6897
+ }
6898
+ if ($$self{OPTIONS}{Verbose} and $bytesRead and $type and not $noMsg) {
6899
+ $self->VPrint(0, "$$self{INDENT}(ImageDataMD5: $bytesRead bytes of $type data)\n");
6900
+ }
6901
+ return $bytesRead;
6902
+ }
6903
+
6870
6904
  #------------------------------------------------------------------------------
6871
6905
  # Copy data block from RAF to output file in max 64kB chunks
6872
6906
  # Inputs: 0) RAF ref, 1) outfile ref, 2) block size
@@ -248,7 +248,11 @@ my %boolConv = (
248
248
 
249
249
  # XMP namespaces which we don't want to contribute to generated EXIF tag names
250
250
  # (Note: namespaces with non-standard prefixes aren't currently ignored)
251
- my %ignoreNamespace = ( 'x'=>1, rdf=>1, xmlns=>1, xml=>1, svg=>1, et=>1, office=>1 );
251
+ my %ignoreNamespace = ( 'x'=>1, rdf=>1, xmlns=>1, xml=>1, svg=>1, office=>1 );
252
+
253
+ # ExifTool properties that don't generate tag names (et:tagid is historic)
254
+ my %ignoreEtProp = ( 'et:desc'=>1, 'et:prt'=>1, 'et:val'=>1 , 'et:id'=>1, 'et:tagid'=>1,
255
+ 'et:toolkit'=>1, 'et:table'=>1, 'et:index'=>1 );
252
256
 
253
257
  # XMP properties to ignore (set dynamically via dirInfo IgnoreProp)
254
258
  my %ignoreProp;
@@ -2850,7 +2854,7 @@ sub GetXMPTagID($;$$)
2850
2854
  # split name into namespace and property name
2851
2855
  # (Note: namespace can be '' for property qualifiers)
2852
2856
  my ($ns, $nm) = ($prop =~ /(.*?):(.*)/) ? ($1, $2) : ('', $prop);
2853
- if ($ignoreNamespace{$ns} or $ignoreProp{$prop}) {
2857
+ if ($ignoreNamespace{$ns} or $ignoreProp{$prop} or $ignoreEtProp{$prop}) {
2854
2858
  # special case: don't ignore rdf numbered items
2855
2859
  # (not technically allowed in XMP, but used in RDF/XML)
2856
2860
  unless ($prop =~ /^rdf:(_\d+)$/) {
@@ -3420,7 +3424,10 @@ NoLoop:
3420
3424
  my %grps = ( 0 => $1, 1 => $2 );
3421
3425
  # apply a little magic to recover original group names
3422
3426
  # from this exiftool-written RDF/XML file
3423
- if ($grps{1} =~ /^\d/) {
3427
+ if ($grps{1} eq 'System') {
3428
+ $grps{1} = 'XML-System';
3429
+ $grps{0} = 'XML';
3430
+ } elsif ($grps{1} =~ /^\d/) {
3424
3431
  # URI's with only family 0 are internal tags from the source file,
3425
3432
  # so change the group name to avoid confusion with tags from this file
3426
3433
  $grps{1} = "XML-$grps{0}";
@@ -3888,7 +3895,9 @@ sub ParseXMPElement($$$;$$$$)
3888
3895
  }
3889
3896
  }
3890
3897
  my $shortVal = $attrs{$shortName};
3891
- if ($ignoreNamespace{$ns} or $ignoreProp{$prop}) {
3898
+ # Note: $prop is the containing property in this loop (not the shorthand property)
3899
+ # so $ignoreProp ignores all attributes of the ignored property
3900
+ if ($ignoreNamespace{$ns} or $ignoreProp{$prop} or $ignoreEtProp{$propName}) {
3892
3901
  $ignored = $propName;
3893
3902
  # handle special attributes (extract as tags only once if not empty)
3894
3903
  if (ref $recognizedAttrs{$propName} and $shortVal) {
@@ -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);
31
31
 
32
- $VERSION = '12.59';
32
+ $VERSION = '12.61';
33
33
  $RELEASE = '';
34
34
  @ISA = qw(Exporter);
35
35
  %EXPORT_TAGS = (
@@ -114,6 +114,7 @@ sub WriteTIFF($$$);
114
114
  sub PackUTF8(@);
115
115
  sub UnpackUTF8($);
116
116
  sub SetPreferredByteOrder($;$);
117
+ sub ImageDataMD5($$$;$$);
117
118
  sub CopyBlock($$$);
118
119
  sub CopyFileAttrs($$$);
119
120
  sub TimeNow(;$$);
@@ -1825,11 +1826,12 @@ my %systemTagsNotes = (
1825
1826
  ImageDataMD5 => {
1826
1827
  Notes => q{
1827
1828
  MD5 of image data. Generated only if specifically requested for JPEG and
1828
- TIFF-based images, CR3, MRW and PNG images, MOV/MP4 videos, and RIFF-based
1829
- files. The MD5 includes the main image data, plus JpgFromRaw/OtherImage for
1830
- some formats, but does not include ThumbnailImage or PreviewImage. Includes
1831
- video and audio data for MOV/MP4. The L<XMP-et:OriginalImageMD5
1832
- tag|XMP.html#ExifTool> provides a place to store these values in the file.
1829
+ TIFF-based images, PNG, CRW, CR3, MRW, RAF, X3F, JP2, JXL and AVIF images,
1830
+ MOV/MP4 videos, and some RIFF-based files. The MD5 includes the main image
1831
+ data, plus JpgFromRaw/OtherImage for some formats, but does not include
1832
+ ThumbnailImage or PreviewImage. Includes video and audio data for MOV/MP4.
1833
+ The L<XMP-et:OriginalImageMD5 tag|XMP.html#ExifTool> provides a place to
1834
+ store these values in the file.
1833
1835
  },
1834
1836
  },
1835
1837
  );
@@ -2501,23 +2503,6 @@ sub ExtractInfo($;@)
2501
2503
  }
2502
2504
  }
2503
2505
  ++$$self{FILE_SEQUENCE}; # count files read
2504
- # extract information from alternate files if necessary
2505
- my ($g8, $altExifTool);
2506
- foreach $g8 (keys %{$$self{ALT_EXIFTOOL}}) {
2507
- $altExifTool = $$self{ALT_EXIFTOOL}{$g8};
2508
- next if $$altExifTool{DID_EXTRACT}; # avoid extracting twice
2509
- $$altExifTool{OPTIONS} = $$self{OPTIONS};
2510
- $$altExifTool{GLOBAL_TIME_OFFSET} = $$self{GLOBAL_TIME_OFFSET};
2511
- $$altExifTool{REQ_TAG_LOOKUP} = $$self{REQ_TAG_LOOKUP};
2512
- $altExifTool->ExtractInfo($$altExifTool{ALT_FILE});
2513
- # set family 8 group name for all tags
2514
- foreach (keys %{$$altExifTool{VALUE}}) {
2515
- my $ex = $$altExifTool{TAG_EXTRA}{$_};
2516
- $ex or $ex = $$altExifTool{TAG_EXTRA}{$_} = { };
2517
- $$ex{G8} = $g8;
2518
- }
2519
- $$altExifTool{DID_EXTRACT} = 1;
2520
- }
2521
2506
  }
2522
2507
 
2523
2508
  my $filename = $$self{FILENAME}; # image file name ('' if already open)
@@ -2659,6 +2644,7 @@ sub ExtractInfo($;@)
2659
2644
  if ($isDir or (defined $stat[2] and ($stat[2] & 0170000) == 0040000)) {
2660
2645
  $self->FoundTag('FileType', 'DIR');
2661
2646
  $self->FoundTag('FileTypeExtension', '');
2647
+ $self->ExtractAltInfo();
2662
2648
  $self->BuildCompositeTags() if $$options{Composite};
2663
2649
  $raf->Close() if $raf;
2664
2650
  return 1;
@@ -2677,6 +2663,7 @@ sub ExtractInfo($;@)
2677
2663
  } else {
2678
2664
  $self->Error('Unknown file type');
2679
2665
  }
2666
+ $self->ExtractAltInfo();
2680
2667
  $self->BuildCompositeTags() if $fast == 4 and $$options{Composite};
2681
2668
  last; # don't read the file
2682
2669
  }
@@ -2843,6 +2830,7 @@ sub ExtractInfo($;@)
2843
2830
  }
2844
2831
  unless ($reEntry) {
2845
2832
  $$self{PATH} = [ ]; # reset PATH
2833
+ $self->ExtractAltInfo();
2846
2834
  # calculate Composite tags
2847
2835
  $self->BuildCompositeTags() if $$options{Composite};
2848
2836
  # do our HTML dump if requested
@@ -3731,13 +3719,21 @@ COMPOSITE_TAG:
3731
3719
  next COMPOSITE_TAG;
3732
3720
  }
3733
3721
  }
3722
+ my ($i, $key, @keys, $altFile);
3723
+ my $et = $self;
3724
+ # get tags from alternate file if a family 8 group was specified
3725
+ if ($reqTag =~ /\b(File\d+):/i and $$self{ALT_EXIFTOOL}{$1}) {
3726
+ $et = $$self{ALT_EXIFTOOL}{$1};
3727
+ $altFile = $1;
3728
+ }
3734
3729
  # (CAREFUL! keys may not be sequential if one was deleted)
3735
- my ($i, $key, @keys);
3736
- for ($key=$name, $i=$$self{DUPL_TAG}{$name} || 0; ; --$i) {
3737
- push @keys, $key if defined $$rawValue{$key};
3730
+ for ($key=$name, $i=$$et{DUPL_TAG}{$name} || 0; ; --$i) {
3731
+ push @keys, $key if defined $$et{VALUE}{$key};
3738
3732
  last if $i <= 0;
3739
3733
  $key = "$name ($i)";
3740
3734
  }
3735
+ # make sure the necessary information is available from the alternate file
3736
+ $self->CopyAltInfo($altFile, \@keys) if $altFile;
3741
3737
  # find first matching tag
3742
3738
  $key = $self->GroupMatches($reqGroup, \@keys);
3743
3739
  $reqTag = $key || "$name (0)";
@@ -4057,6 +4053,42 @@ sub CombineInfo($;@)
4057
4053
  return \%combinedInfo;
4058
4054
  }
4059
4055
 
4056
+ #------------------------------------------------------------------------------
4057
+ # Read metadata from alternate files
4058
+ # Inputs: 0) ExifTool ref
4059
+ # Notes: This is called after reading the main file so the tags are available
4060
+ # for being used in the file name, but before building Composite tags
4061
+ # so tags from the alternate files may be used in the Composite tags
4062
+ sub ExtractAltInfo($)
4063
+ {
4064
+ my $self = shift;
4065
+ # extract information from alternate files if necessary
4066
+ my ($g8, $altExifTool);
4067
+ foreach $g8 (sort keys %{$$self{ALT_EXIFTOOL}}) {
4068
+ $altExifTool = $$self{ALT_EXIFTOOL}{$g8};
4069
+ next if $$altExifTool{DID_EXTRACT}; # avoid extracting twice
4070
+ $$altExifTool{OPTIONS} = $$self{OPTIONS};
4071
+ $$altExifTool{GLOBAL_TIME_OFFSET} = $$self{GLOBAL_TIME_OFFSET};
4072
+ $$altExifTool{REQ_TAG_LOOKUP} = $$self{REQ_TAG_LOOKUP};
4073
+ my $fileName = $$altExifTool{ALT_FILE};
4074
+ # allow tags from the main file to be used in the alternate file names
4075
+ # (eg. -file1 '$originalfilename')
4076
+ if ($fileName =~ /\$/) {
4077
+ my @tags = reverse sort keys %{$$self{VALUE}};
4078
+ $fileName = $self->InsertTagValues(\@tags, $fileName, 'Warn');
4079
+ next unless defined $fileName;
4080
+ }
4081
+ $altExifTool->ExtractInfo($fileName);
4082
+ # set family 8 group name for all tags
4083
+ foreach (keys %{$$altExifTool{VALUE}}) {
4084
+ my $ex = $$altExifTool{TAG_EXTRA}{$_};
4085
+ $ex or $ex = $$altExifTool{TAG_EXTRA}{$_} = { };
4086
+ $$ex{G8} = $g8;
4087
+ }
4088
+ $$altExifTool{DID_EXTRACT} = 1;
4089
+ }
4090
+ }
4091
+
4060
4092
  #------------------------------------------------------------------------------
4061
4093
  # Get tag table name
4062
4094
  # Inputs: 0) ExifTool object reference, 1) tag key
@@ -4598,6 +4630,29 @@ sub RemoveTagsFromList($$$$;$)
4598
4630
  $_[0] = \@filteredTags; # update tag list
4599
4631
  }
4600
4632
 
4633
+ #------------------------------------------------------------------------------
4634
+ # Copy tags from alternate input file
4635
+ # Inputs: 0) ExifTool ref, 1) family 8 group, 2) list ref for tag keys to copy
4636
+ # - updates tag key list to match keys newly added to $self
4637
+ sub CopyAltInfo($$$)
4638
+ {
4639
+ my ($self, $g8, $tags) = @_;
4640
+ my ($tag, $vtag);
4641
+ return unless $g8 =~ /(\d+)/;
4642
+ my $et = $$self{ALT_EXIFTOOL}{$g8} or return;
4643
+ my $altOrder = ($1 + 1) * 100000; # increment file order
4644
+ foreach $tag (@$tags) {
4645
+ ($vtag = $tag) =~ s/( |$)/ #[$g8]/;
4646
+ unless (defined $$self{VALUE}{$vtag}) {
4647
+ $$self{VALUE}{$vtag} = $$et{VALUE}{$tag};
4648
+ $$self{TAG_INFO}{$vtag} = $$et{TAG_INFO}{$tag};
4649
+ $$self{TAG_EXTRA}{$vtag} = $$et{TAG_EXTRA}{$tag} || { };
4650
+ $$self{FILE_ORDER}{$vtag} = ($$et{FILE_ORDER}{$tag} || 0) + $altOrder;
4651
+ }
4652
+ $tag = $vtag;
4653
+ }
4654
+ }
4655
+
4601
4656
  #------------------------------------------------------------------------------
4602
4657
  # Set list of found tags from previously requested tags
4603
4658
  # Inputs: 0) ExifTool object reference
@@ -4624,7 +4679,7 @@ sub SetFoundTags($)
4624
4679
  my $tagHash = $$self{VALUE};
4625
4680
  my $reqTag;
4626
4681
  foreach $reqTag (@$reqTags) {
4627
- my (@matches, $group, $allGrp, $allTag, $byValue, $g8, $altOrder);
4682
+ my (@matches, $group, $allGrp, $allTag, $byValue, $g8);
4628
4683
  my $et = $self;
4629
4684
  if ($reqTag =~ /^(.*):(.+)/) {
4630
4685
  ($group, $tag) = ($1, $2);
@@ -4632,7 +4687,6 @@ sub SetFoundTags($)
4632
4687
  $allGrp = 1;
4633
4688
  } elsif ($reqTag =~ /\bfile(\d+):/i) {
4634
4689
  $g8 = "File$1";
4635
- $altOrder = ($1 + 1) * 100000;
4636
4690
  $et = $$self{ALT_EXIFTOOL}{$g8} || $self;
4637
4691
  $fileOrder = $$et{FILE_ORDER};
4638
4692
  $tagHash = $$et{VALUE};
@@ -4704,16 +4758,7 @@ sub SetFoundTags($)
4704
4758
  }
4705
4759
  # copy over necessary information for tags from alternate files
4706
4760
  if ($g8) {
4707
- my $tag;
4708
- foreach $tag (@matches) {
4709
- my $vtag = $tag;
4710
- $vtag =~ s/( |$)/ #[$g8]/;
4711
- $$self{VALUE}{$vtag} = $$et{VALUE}{$tag};
4712
- $$self{TAG_INFO}{$vtag} = $$et{TAG_INFO}{$tag};
4713
- $$self{TAG_EXTRA}{$vtag} = $$et{TAG_EXTRA}{$tag} || { };
4714
- $$self{FILE_ORDER}{$vtag} = ($$et{FILE_ORDER}{$tag} || 0) + $altOrder;
4715
- $tag = $vtag;
4716
- }
4761
+ $self->CopyAltInfo($g8, \@matches);
4717
4762
  # restore variables to original values for main file
4718
4763
  $fileOrder = $$self{FILE_ORDER};
4719
4764
  $tagHash = $$self{VALUE};
@@ -6409,12 +6454,12 @@ sub ProcessJPEG($$)
6409
6454
  my $htmlDump = $$self{HTML_DUMP};
6410
6455
  my %dumpParms = ( Out => $out );
6411
6456
  my ($ch, $s, $length, $md5, $md5size);
6412
- my ($success, $wantTrailer, $trailInfo, $foundSOS, %jumbfChunk);
6457
+ my ($success, $wantTrailer, $trailInfo, $foundSOS, $gotSize, %jumbfChunk);
6413
6458
  my (@iccChunk, $iccChunkCount, $iccChunksTotal, @flirChunk, $flirCount, $flirTotal);
6414
6459
  my ($preview, $scalado, @dqt, $subSampling, $dumpEnd, %extendedXMP);
6415
6460
 
6416
- # get pointer to MD5 object if it exists and we are the top-level JPEG
6417
- if ($$self{FILE_TYPE} eq 'JPEG' and not $$self{DOC_NUM}) {
6461
+ # get pointer to MD5 object if it exists and we are the top-level JPEG or JP2
6462
+ if ($$self{FILE_TYPE} =~ /^(JPEG|JP2)$/ and not $$self{DOC_NUM}) {
6418
6463
  $md5 = $$self{ImageDataMD5};
6419
6464
  $md5size = 0;
6420
6465
  }
@@ -6538,7 +6583,8 @@ sub ProcessJPEG($$)
6538
6583
  $self->HDump($segPos-4, $length+4, "[JPEG $markerName]", undef, 0x08);
6539
6584
  $dumpEnd = $segPos + $length;
6540
6585
  }
6541
- next unless $length >= 6;
6586
+ next if $length < 6 or $gotSize;
6587
+ $gotSize = 1; # (ignore subsequent SOF segments in probably corrupted JPEG)
6542
6588
  # extract some useful information
6543
6589
  my ($p, $h, $w, $n) = unpack('Cn2C', $$segDataPt);
6544
6590
  my $sof = GetTagTable('Image::ExifTool::JPEG::SOF');
@@ -6728,6 +6774,11 @@ sub ProcessJPEG($$)
6728
6774
  pop @$path;
6729
6775
  $verbose and print $out "JPEG SOD\n";
6730
6776
  $success = 1;
6777
+ if ($md5 and $$self{FILE_TYPE} eq 'JP2') {
6778
+ my $pos = $raf->Tell();
6779
+ $self->ImageDataMD5($raf, undef, 'SOD');
6780
+ $raf->Seek($pos, 0);
6781
+ }
6731
6782
  next if $verbose > 2 or $htmlDump;
6732
6783
  last; # all done parsing file
6733
6784
  } elsif (defined $markerLenBytes{$marker}) {
@@ -6802,7 +6853,7 @@ sub ProcessJPEG($$)
6802
6853
  } elsif ($marker == 0xe1) { # APP1 (EXIF, XMP, QVCI, PARROT)
6803
6854
  # (some Kodak cameras don't put a second "\0", and I have seen an
6804
6855
  # example where there was a second 4-byte APP1 segment header)
6805
- if ($$segDataPt =~ /^(.{0,4})Exif\0/is) {
6856
+ if ($$segDataPt =~ /^(.{0,4})Exif\0./is) {
6806
6857
  undef $dumpType; # (will be dumped here)
6807
6858
  # this is EXIF data --
6808
6859
  # get the data block (into a common variable)
@@ -7460,8 +7511,11 @@ sub ProcessJPEG($$)
7460
7511
  }
7461
7512
  } elsif ($marker == 0x51) { # SIZ (J2C)
7462
7513
  my ($w, $h) = unpack('x2N2', $$segDataPt);
7463
- $self->FoundTag('ImageWidth', $w);
7464
- $self->FoundTag('ImageHeight', $h);
7514
+ unless ($gotSize) {
7515
+ $gotSize = 1;
7516
+ $self->FoundTag('ImageWidth', $w);
7517
+ $self->FoundTag('ImageHeight', $h);
7518
+ }
7465
7519
  } elsif (($marker & 0xf0) != 0xe0) {
7466
7520
  $dumpType = "$markerName segment";
7467
7521
  $desc = "[JPEG $markerName]"; # (other known JPEG segments)
@@ -7801,6 +7855,9 @@ sub DoProcessTIFF($$;$)
7801
7855
  if ($$self{TIFF_TYPE} eq 'TIFF') {
7802
7856
  $self->FoundTag(PageCount => $$self{PageCount}) if $$self{MultiPage};
7803
7857
  }
7858
+ if ($$self{ImageDataMD5} and $$self{A100DataOffset} and $raf->Seek($$self{A100DataOffset},0)) {
7859
+ $self->ImageDataMD5($raf, undef, 'A100');
7860
+ }
7804
7861
  return 1;
7805
7862
  }
7806
7863
  #
@@ -1,6 +1,6 @@
1
1
  Summary: perl module for image data extraction
2
2
  Name: perl-Image-ExifTool
3
- Version: 12.59
3
+ Version: 12.61
4
4
  Release: 1
5
5
  License: Artistic/GPL
6
6
  Group: Development/Libraries/Perl