exiftool_vendored 12.59.0 → 12.61.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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