exiftool-vendored.exe 12.55.0 → 12.60.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 (61) hide show
  1. package/bin/exiftool_files/Changes +97 -4
  2. package/bin/exiftool_files/README +19 -19
  3. package/bin/exiftool_files/arg_files/xmp2exif.args +4 -1
  4. package/bin/exiftool_files/config_files/example.config +1 -0
  5. package/bin/exiftool_files/config_files/rotate_regions.config +1 -1
  6. package/bin/exiftool_files/exiftool.pl +198 -123
  7. package/bin/exiftool_files/fmt_files/kml.fmt +3 -0
  8. package/bin/exiftool_files/fmt_files/kml_track.fmt +3 -0
  9. package/bin/exiftool_files/lib/Image/ExifTool/AIFF.pm +2 -2
  10. package/bin/exiftool_files/lib/Image/ExifTool/APE.pm +2 -2
  11. package/bin/exiftool_files/lib/Image/ExifTool/BuildTagLookup.pm +25 -19
  12. package/bin/exiftool_files/lib/Image/ExifTool/Canon.pm +33 -7
  13. package/bin/exiftool_files/lib/Image/ExifTool/CanonRaw.pm +5 -1
  14. package/bin/exiftool_files/lib/Image/ExifTool/DJI.pm +28 -2
  15. package/bin/exiftool_files/lib/Image/ExifTool/Exif.pm +107 -20
  16. package/bin/exiftool_files/lib/Image/ExifTool/FlashPix.pm +92 -9
  17. package/bin/exiftool_files/lib/Image/ExifTool/FujiFilm.pm +9 -4
  18. package/bin/exiftool_files/lib/Image/ExifTool/GPS.pm +7 -2
  19. package/bin/exiftool_files/lib/Image/ExifTool/Geotag.pm +30 -7
  20. package/bin/exiftool_files/lib/Image/ExifTool/InfiRay.pm +227 -0
  21. package/bin/exiftool_files/lib/Image/ExifTool/JPEG.pm +53 -7
  22. package/bin/exiftool_files/lib/Image/ExifTool/Jpeg2000.pm +5 -5
  23. package/bin/exiftool_files/lib/Image/ExifTool/LIF.pm +10 -2
  24. package/bin/exiftool_files/lib/Image/ExifTool/LNK.pm +5 -4
  25. package/bin/exiftool_files/lib/Image/ExifTool/MIE.pm +3 -3
  26. package/bin/exiftool_files/lib/Image/ExifTool/MPEG.pm +2 -2
  27. package/bin/exiftool_files/lib/Image/ExifTool/MakerNotes.pm +3 -2
  28. package/bin/exiftool_files/lib/Image/ExifTool/Minolta.pm +6 -7
  29. package/bin/exiftool_files/lib/Image/ExifTool/MinoltaRaw.pm +2 -1
  30. package/bin/exiftool_files/lib/Image/ExifTool/Nikon.pm +1199 -1325
  31. package/bin/exiftool_files/lib/Image/ExifTool/NikonCustom.pm +2 -2
  32. package/bin/exiftool_files/lib/Image/ExifTool/NikonSettings.pm +1 -1
  33. package/bin/exiftool_files/lib/Image/ExifTool/Olympus.pm +88 -6
  34. package/bin/exiftool_files/lib/Image/ExifTool/OpenEXR.pm +32 -15
  35. package/bin/exiftool_files/lib/Image/ExifTool/PNG.pm +89 -3
  36. package/bin/exiftool_files/lib/Image/ExifTool/PanasonicRaw.pm +27 -1
  37. package/bin/exiftool_files/lib/Image/ExifTool/Pentax.pm +8 -5
  38. package/bin/exiftool_files/lib/Image/ExifTool/PhaseOne.pm +14 -1
  39. package/bin/exiftool_files/lib/Image/ExifTool/Photoshop.pm +38 -7
  40. package/bin/exiftool_files/lib/Image/ExifTool/QuickTime.pm +44 -13
  41. package/bin/exiftool_files/lib/Image/ExifTool/QuickTimeStream.pl +63 -20
  42. package/bin/exiftool_files/lib/Image/ExifTool/README +19 -2
  43. package/bin/exiftool_files/lib/Image/ExifTool/RIFF.pm +34 -13
  44. package/bin/exiftool_files/lib/Image/ExifTool/Rawzor.pm +2 -2
  45. package/bin/exiftool_files/lib/Image/ExifTool/Real.pm +2 -2
  46. package/bin/exiftool_files/lib/Image/ExifTool/Ricoh.pm +2 -1
  47. package/bin/exiftool_files/lib/Image/ExifTool/Sigma.pm +5 -4
  48. package/bin/exiftool_files/lib/Image/ExifTool/SigmaRaw.pm +9 -3
  49. package/bin/exiftool_files/lib/Image/ExifTool/Sony.pm +28 -1
  50. package/bin/exiftool_files/lib/Image/ExifTool/TagLookup.pm +4691 -4624
  51. package/bin/exiftool_files/lib/Image/ExifTool/TagNames.pod +511 -117
  52. package/bin/exiftool_files/lib/Image/ExifTool/VCard.pm +19 -5
  53. package/bin/exiftool_files/lib/Image/ExifTool/Validate.pm +5 -5
  54. package/bin/exiftool_files/lib/Image/ExifTool/WriteExif.pl +42 -0
  55. package/bin/exiftool_files/lib/Image/ExifTool/WriteXMP.pl +1 -1
  56. package/bin/exiftool_files/lib/Image/ExifTool/Writer.pl +150 -36
  57. package/bin/exiftool_files/lib/Image/ExifTool/XMP.pm +19 -4
  58. package/bin/exiftool_files/lib/Image/ExifTool/XMP2.pl +2 -1
  59. package/bin/exiftool_files/lib/Image/ExifTool.pm +248 -54
  60. package/bin/exiftool_files/lib/Image/ExifTool.pod +94 -58
  61. package/package.json +2 -2
@@ -47,7 +47,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
47
47
  use Image::ExifTool::Exif;
48
48
  use Image::ExifTool::GPS;
49
49
 
50
- $VERSION = '2.83';
50
+ $VERSION = '2.84';
51
51
 
52
52
  sub ProcessMOV($$;$);
53
53
  sub ProcessKeys($$$);
@@ -419,6 +419,18 @@ my %channelLabel = (
419
419
  0x1ffff => 'Discrete_65535',
420
420
  );
421
421
 
422
+ my %qtFlags = ( #12
423
+ 0 => 'undef', 22 => 'unsigned int', 71 => 'float[2] size',
424
+ 1 => 'UTF-8', 23 => 'float', 72 => 'float[4] rect',
425
+ 2 => 'UTF-16', 24 => 'double', 74 => 'int64s',
426
+ 3 => 'ShiftJIS', 27 => 'BMP', 75 => 'int8u',
427
+ 4 => 'UTF-8 sort', 28 => 'QT atom', 76 => 'int16u',
428
+ 5 => 'UTF-16 sort', 65 => 'int8s', 77 => 'int32u',
429
+ 13 => 'JPEG', 66 => 'int16s', 78 => 'int64u',
430
+ 14 => 'PNG', 67 => 'int32s', 79 => 'double[3][3]',
431
+ 21 => 'signed int', 70 => 'float[2] point',
432
+ );
433
+
422
434
  # properties which don't get inherited from the parent
423
435
  my %dontInherit = (
424
436
  ispe => 1, # size of parent may be different
@@ -435,15 +447,16 @@ my %dupDirOK = ( ipco => 1, '----' => 1 );
435
447
  my %eeStd = ( stco => 'stbl', co64 => 'stbl', stsz => 'stbl', stz2 => 'stbl',
436
448
  stsc => 'stbl', stts => 'stbl' );
437
449
 
450
+ # atoms required for generating ImageDataMD5
451
+ my %md5Box = ( vide => { %eeStd }, soun => { %eeStd } );
452
+
438
453
  # boxes and their containers for the various handler types that we want to save
439
454
  # when the ExtractEmbedded is enabled (currently only the 'gps ' container name is
440
455
  # used, but others have been checked against all available sample files and may be
441
456
  # useful in the future if the names are used for different boxes on other locations)
442
457
  my %eeBox = (
443
458
  # (note: vide is only processed if specific atoms exist in the VideoSampleDesc)
444
- vide => { %eeStd,
445
- JPEG => 'stsd',
446
- },
459
+ vide => { %eeStd, JPEG => 'stsd' },
447
460
  text => { %eeStd },
448
461
  meta => { %eeStd },
449
462
  sbtl => { %eeStd },
@@ -1159,7 +1172,10 @@ my %eeBox2 = (
1159
1172
  },
1160
1173
  {
1161
1174
  Name => 'GarminGPS',
1162
- Condition => '$$valPt=~/^\x9b\x63\x0f\x8d\x63\x74\x40\xec\x82\x04\xbc\x5f\xf5\x09\x17\x28/ and $$self{OPTIONS}{ExtractEmbedded}',
1175
+ Condition => q{
1176
+ $$valPt=~/^\x9b\x63\x0f\x8d\x63\x74\x40\xec\x82\x04\xbc\x5f\xf5\x09\x17\x28/ and
1177
+ $$self{OPTIONS}{ExtractEmbedded}
1178
+ },
1163
1179
  SubDirectory => {
1164
1180
  TagTable => 'Image::ExifTool::QuickTime::Stream',
1165
1181
  ProcessProc => \&ProcessGarminGPS,
@@ -1961,7 +1977,7 @@ my %eeBox2 = (
1961
1977
  Name => 'SanyoMOV',
1962
1978
  Condition => q{
1963
1979
  $$valPt =~ /^SANYO DIGITAL CAMERA\0/ and
1964
- $self->{VALUE}->{FileType} eq "MOV"
1980
+ $$self{FileType} eq "MOV"
1965
1981
  },
1966
1982
  SubDirectory => {
1967
1983
  TagTable => 'Image::ExifTool::Sanyo::MOV',
@@ -1972,7 +1988,7 @@ my %eeBox2 = (
1972
1988
  Name => 'SanyoMP4',
1973
1989
  Condition => q{
1974
1990
  $$valPt =~ /^SANYO DIGITAL CAMERA\0/ and
1975
- $self->{VALUE}->{FileType} eq "MP4"
1991
+ $$self{FileType} eq "MP4"
1976
1992
  },
1977
1993
  SubDirectory => {
1978
1994
  TagTable => 'Image::ExifTool::Sanyo::MP4',
@@ -7146,7 +7162,7 @@ my %eeBox2 = (
7146
7162
  $$self{AudioFormat} = $val;
7147
7163
  return undef unless $val =~ /^[\w ]{4}$/i;
7148
7164
  # check for protected audio format
7149
- $self->OverrideFileType('M4P') if $val eq 'drms' and $$self{VALUE}{FileType} eq 'M4A';
7165
+ $self->OverrideFileType('M4P') if $val eq 'drms' and $$self{FileType} eq 'M4A';
7150
7166
  return $val;
7151
7167
  },
7152
7168
  # see this link for print conversions (not complete):
@@ -8768,6 +8784,16 @@ sub HandleItemInfo($)
8768
8784
  $et->VPrint(0, "$$et{INDENT} [snip $snip bytes]\n") if $snip;
8769
8785
  }
8770
8786
  }
8787
+ # do MD5 checksum of AVIF "av01" image data
8788
+ if ($type eq 'av01' and $$et{ImageDataMD5}) {
8789
+ my $md5 = $$et{ImageDataMD5};
8790
+ my $tot = 0;
8791
+ foreach $extent (@{$$item{Extents}}) {
8792
+ $raf->Seek($$extent[1] + $base, 0) or $et->Warn('Seek error in av01 image data'), last;
8793
+ $tot += $et->ImageDataMD5($raf, $$extent[2], 'av01 image', 1);
8794
+ }
8795
+ $et->VPrint(0, "$$et{INDENT}(ImageDataMD5: $tot bytes of av01 data)\n") if $tot;
8796
+ }
8771
8797
  next unless $name;
8772
8798
  # assemble the data for this item
8773
8799
  undef $buff;
@@ -9270,7 +9296,8 @@ sub ProcessMOV($$;$)
9270
9296
  $$raf{NoBuffer} = 1 if $fast; # disable buffering in FastScan mode
9271
9297
 
9272
9298
  my $ee = $$et{OPTIONS}{ExtractEmbedded};
9273
- if ($ee) {
9299
+ my $md5 = $$et{ImageDataMD5};
9300
+ if ($ee or $md5) {
9274
9301
  $unkOpt = $$et{OPTIONS}{Unknown};
9275
9302
  require 'Image/ExifTool/QuickTimeStream.pl';
9276
9303
  }
@@ -9352,7 +9379,7 @@ sub ProcessMOV($$;$)
9352
9379
  # set flag to store additional information for ExtractEmbedded option
9353
9380
  my $handlerType = $$et{HandlerType};
9354
9381
  if ($eeBox{$handlerType} and $eeBox{$handlerType}{$tag}) {
9355
- if ($ee) {
9382
+ if ($ee or $md5) {
9356
9383
  # (there is another 'gps ' box with a track log that doesn't contain offsets)
9357
9384
  if ($tag ne 'gps ' or $eeBox{$handlerType}{$tag} eq $dirID) {
9358
9385
  $eeTag = 1;
@@ -9364,6 +9391,9 @@ sub ProcessMOV($$;$)
9364
9391
  } elsif ($ee and $ee > 1 and $eeBox2{$handlerType} and $eeBox2{$handlerType}{$tag}) {
9365
9392
  $eeTag = 1;
9366
9393
  $$et{OPTIONS}{Unknown} = 1;
9394
+ } elsif ($md5 and $md5Box{$handlerType} and $md5Box{$handlerType}{$tag}) {
9395
+ $eeTag = 1;
9396
+ $$et{OPTIONS}{Unknown} = 1;
9367
9397
  }
9368
9398
  my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
9369
9399
 
@@ -9596,7 +9626,7 @@ ItemID: foreach $id (keys %$items) {
9596
9626
  }
9597
9627
  if ($tag eq 'stbl') {
9598
9628
  # process sample data when exiting SampleTable box if extracting embedded
9599
- ProcessSamples($et) if $ee;
9629
+ ProcessSamples($et) if $ee or $md5;
9600
9630
  } elsif ($tag eq 'minf') {
9601
9631
  $$et{HandlerType} = ''; # reset handler type at end of media info box
9602
9632
  }
@@ -9656,6 +9686,7 @@ ItemID: foreach $id (keys %$items) {
9656
9686
  }
9657
9687
  }
9658
9688
  $langInfo or $langInfo = $tagInfo;
9689
+ my $str = $qtFlags{$flags} ? " ($qtFlags{$flags})" : '';
9659
9690
  $et->VerboseInfo($tag, $langInfo,
9660
9691
  Value => ref $value ? $$value : $value,
9661
9692
  DataPt => \$val,
@@ -9664,7 +9695,7 @@ ItemID: foreach $id (keys %$items) {
9664
9695
  Size => $len,
9665
9696
  Format => $format,
9666
9697
  Index => $index,
9667
- Extra => sprintf(", Type='${type}', Flags=0x%x, Lang=0x%.4x",$flags,$lang),
9698
+ Extra => sprintf(", Type='${type}', Flags=0x%x%s, Lang=0x%.4x",$flags,$str,$lang),
9668
9699
  ) if $verbose;
9669
9700
  # use "Keys" in path instead of ItemList if this was defined by a Keys tag
9670
9701
  my $isKey = $$tagInfo{Groups} && $$tagInfo{Groups}{1} && $$tagInfo{Groups}{1} eq 'Keys';
@@ -9793,7 +9824,7 @@ ItemID: foreach $id (keys %$items) {
9793
9824
  ++$index if defined $index;
9794
9825
  }
9795
9826
  # tweak file type based on track content ("iso*" and "dash" ftyp only)
9796
- if ($topLevel and $$et{VALUE}{FileType} and $$et{VALUE}{FileType} eq 'MP4' and
9827
+ if ($topLevel and $$et{FileType} and $$et{FileType} eq 'MP4' and
9797
9828
  $$et{save_ftyp} and $$et{HasHandler} and $$et{save_ftyp} =~ /^(iso|dash)/ and
9798
9829
  $$et{HasHandler}{soun} and not $$et{HasHandler}{vide})
9799
9830
  {
@@ -81,12 +81,15 @@ my %processByMetaFormat = (
81
81
  ctbx => 1, # ('marl' in GM videos)
82
82
  );
83
83
 
84
- # data lengths for each INSV record type
84
+ # data lengths for each INSV/INSP record type
85
85
  my %insvDataLen = (
86
+ 0x200 => 0, # PreivewImage (any size) (a duplicate of PreviewImage in APP2 of INSP files)
86
87
  0x300 => 0, # accelerometer (could be either 20 or 56 bytes)
87
88
  0x400 => 16, # exposure (ref 6)
88
89
  0x600 => 8, # timestamps (ref 6)
89
90
  0x700 => 53, # GPS
91
+ # 0x900 => 48, # ? (Insta360 X3)
92
+ # 0xb00 => 10, # ? (Insta360 X3)
90
93
  );
91
94
 
92
95
  # limit the default amount of data we read for some record types
@@ -596,6 +599,8 @@ my %insvLimit = (
596
599
  0x1a => 'Firmware',
597
600
  0x2a => {
598
601
  Name => 'Parameters',
602
+ # (see https://exiftool.org/forum/index.php?msg=78942)
603
+ Notes => 'number of lenses, 6-axis orientation of each lens, raw resolution',
599
604
  ValueConv => '$val =~ tr/_/ /; $val',
600
605
  },
601
606
  );
@@ -1122,23 +1127,37 @@ sub Process_text($$$;$)
1122
1127
  # Inputs: 0) ExifTool ref
1123
1128
  # Notes: Also accesses ExifTool RAF*, SET_GROUP1, HandlerType, MetaFormat,
1124
1129
  # ee*, and avcC elements (* = must exist)
1130
+ # - may be called either due to ExtractEmbedded option, or ImageDataMD5 requested
1131
+ # - MD5 includes only video and audio data
1125
1132
  sub ProcessSamples($)
1126
1133
  {
1127
1134
  my $et = shift;
1128
1135
  my ($raf, $ee) = @$et{qw(RAF ee)};
1129
- my ($i, $buff, $pos, $hdrLen, $hdrFmt, @time, @dur, $oldIndent);
1136
+ my ($i, $buff, $pos, $hdrLen, $hdrFmt, @time, @dur, $oldIndent, $md5);
1130
1137
 
1131
1138
  return unless $ee;
1132
1139
  delete $$et{ee}; # use only once
1133
1140
 
1134
- # only process specific types of video streams
1141
+ my $eeOpt = $et->Options('ExtractEmbedded');
1135
1142
  my $type = $$et{HandlerType} || '';
1136
1143
  if ($type eq 'vide') {
1137
- if ($$ee{avcC}) { $type = 'avcC' }
1138
- elsif ($$ee{JPEG}) { $type = 'JPEG' }
1139
- else { return }
1144
+ # only process specific types of video streams
1145
+ $md5 = $$et{ImageDataMD5};
1146
+ # only process specific video types if ExtractEmbedded was used
1147
+ # (otherwise we are only here to calculate the audio/video MD5)
1148
+ if ($eeOpt) {
1149
+ if ($$ee{avcC}) { $type = 'avcC' }
1150
+ elsif ($$ee{JPEG}) { $type = 'JPEG' }
1151
+ else { return unless $md5 }
1152
+ }
1153
+ } elsif ($type eq 'soun') {
1154
+ $md5 = $$et{ImageDataMD5};
1155
+ return unless $md5;
1156
+ } else {
1157
+ return unless $eeOpt; # (don't do MD5 on other types)
1140
1158
  }
1141
1159
 
1160
+ my $md5size = 0;
1142
1161
  my ($start, $size) = @$ee{qw(start size)};
1143
1162
  #
1144
1163
  # determine sample start offsets from chunk offsets (stco) and sample-to-chunk table (stsc),
@@ -1157,13 +1176,16 @@ sub ProcessSamples($)
1157
1176
  $timeDelta = shift @$stts;
1158
1177
  }
1159
1178
  my $ts = $$et{MediaTS} || 1;
1179
+ my @chunkSize; # total size of each chunk
1160
1180
  foreach $chunkStart (@$stco) {
1161
1181
  if ($iChunk >= $nextChunk and @$stsc) {
1162
1182
  ($startChunk, $samplesPerChunk, $descIdx) = @{shift @$stsc};
1163
1183
  $nextChunk = $$stsc[0][0] if @$stsc;
1164
1184
  }
1165
1185
  @$size < @$start + $samplesPerChunk and $et->WarnOnce('Sample size error'), last;
1186
+ last unless defined $chunkStart and length $chunkStart;
1166
1187
  my $sampleStart = $chunkStart;
1188
+ my $chunkSize = 0;
1167
1189
  Sample: for ($i=0; ; ) {
1168
1190
  push @$start, $sampleStart;
1169
1191
  if (defined $time) {
@@ -1181,12 +1203,19 @@ Sample: for ($i=0; ; ) {
1181
1203
  --$timeCount;
1182
1204
  }
1183
1205
  # (eventually should use the description indices: $descIdx)
1206
+ $chunkSize += $$size[$#$start];
1184
1207
  last if ++$i >= $samplesPerChunk;
1185
1208
  $sampleStart += $$size[$#$start];
1186
1209
  }
1210
+ push @chunkSize, $chunkSize;
1187
1211
  ++$iChunk;
1188
1212
  }
1189
1213
  @$start == @$size or $et->WarnOnce('Incorrect sample start/size count'), return;
1214
+ # process as chunks if we are only interested in calculating MD5
1215
+ if ($type eq 'soun' or $type eq 'vide') {
1216
+ $start = $stco;
1217
+ $size = \@chunkSize;
1218
+ }
1190
1219
  }
1191
1220
  #
1192
1221
  # extract and parse the sample data
@@ -1218,6 +1247,10 @@ Sample: for ($i=0; ; ) {
1218
1247
  my $size = $$size[$i];
1219
1248
  next unless $raf->Seek($$start[$i], 0) and $raf->Read($buff, $size) == $size;
1220
1249
 
1250
+ if ($md5) {
1251
+ $md5->add($buff);
1252
+ $md5size += length $buff;
1253
+ }
1221
1254
  if ($type eq 'avcC') {
1222
1255
  next if length($buff) <= $hdrLen;
1223
1256
  # scan through all NAL units and send them to ParseH264Video()
@@ -1344,6 +1377,8 @@ Sample: for ($i=0; ; ) {
1344
1377
  SetGPSDateTime($et, $tagTbl, $time[$i]) if $$et{FoundGPSLatitude} and not $$et{FoundGPSDateTime};
1345
1378
  }
1346
1379
  if ($verbose) {
1380
+ my $str = $type eq 'soun' ? 'Audio' : 'Video';
1381
+ $et->VPrint(0, "$$et{INDENT}(ImageDataMD5: $md5size bytes of $str data)\n") if $md5size;
1347
1382
  $$et{INDENT} = $oldIndent;
1348
1383
  $et->VPrint(0, "--------------------------\n");
1349
1384
  }
@@ -1485,7 +1520,7 @@ sub ProcessFreeGPS($$$)
1485
1520
  # Kenwood dashcam sometimes stores absolute year and local time
1486
1521
  # (but sometimes year since 2000 and UTC time in same video!)
1487
1522
  require Time::Local;
1488
- my $time = Image::ExifTool::TimeLocal($sec,$min,$hr,$day,$mon-1,$yr-1900);
1523
+ my $time = Image::ExifTool::TimeLocal($sec,$min,$hr,$day,$mon-1,$yr);
1489
1524
  ($sec,$min,$hr,$day,$mon,$yr) = gmtime($time);
1490
1525
  $yr += 1900;
1491
1526
  ++$mon;
@@ -2758,7 +2793,6 @@ sub ProcessInsta360($;$)
2758
2793
  my ($id, $len) = unpack('vV', $buff);
2759
2794
  ($epos -= $len) + $trailerLen < 0 and last;
2760
2795
  $raf->Seek($epos, 2) or last;
2761
- my $dlen = $insvDataLen{$id};
2762
2796
  if ($verbose) {
2763
2797
  $et->VPrint(0, sprintf("Insta360 Record 0x%x (offset 0x%x, %d bytes):\n", $id, $fileEnd + $epos, $len));
2764
2798
  }
@@ -2771,20 +2805,25 @@ sub ProcessInsta360($;$)
2771
2805
  # 2. 20 byte records
2772
2806
  # 0000: c1 d8 d9 0b 00 00 00 00 f5 83 14 80 df 7f fe 7f [................]
2773
2807
  # 0010: fe 7f 01 80
2774
- if ($id == 0x300) {
2775
- if ($len % 20 and not $len % 56) {
2776
- $dlen = 56;
2777
- } elsif ($len % 56 and not $len % 20) {
2778
- $dlen = 20;
2779
- } else {
2780
- if ($raf->Read($buff, 20) == 20) {
2781
- if (substr($buff, 16, 3) eq "\0\0\0") {
2782
- $dlen = 56;
2783
- } else {
2784
- $dlen = 20;
2808
+ my $dlen = $insvDataLen{$id};
2809
+ if (defined $dlen and not $dlen) {
2810
+ if ($id == 0x300) {
2811
+ if ($len % 20 and not $len % 56) {
2812
+ $dlen = 56;
2813
+ } elsif ($len % 56 and not $len % 20) {
2814
+ $dlen = 20;
2815
+ } else {
2816
+ if ($raf->Read($buff, 20) == 20) {
2817
+ if (substr($buff, 16, 3) eq "\0\0\0") {
2818
+ $dlen = 56;
2819
+ } else {
2820
+ $dlen = 20;
2821
+ }
2785
2822
  }
2823
+ $raf->Seek($epos, 2) or last;
2786
2824
  }
2787
- $raf->Seek($epos, 2) or last;
2825
+ } elsif ($id == 0x200) {
2826
+ $dlen = $len;
2788
2827
  }
2789
2828
  }
2790
2829
  # limit the number of records we read if necessary
@@ -2798,6 +2837,8 @@ sub ProcessInsta360($;$)
2798
2837
  if ($dlen) {
2799
2838
  if ($len % $dlen) {
2800
2839
  $et->Warn(sprintf('Unexpected Insta360 record 0x%x length',$id));
2840
+ } elsif ($id == 0x200) {
2841
+ $et->FoundTag(PreviewImage => $buff);
2801
2842
  } elsif ($id == 0x300) {
2802
2843
  for ($p=0; $p<$len; $p+=$dlen) {
2803
2844
  $$et{DOC_NUM} = ++$$et{DOC_COUNT};
@@ -2915,6 +2956,7 @@ sub ProcessGarminGPS($$$)
2915
2956
  my $epoch = (66 * 365 + 17) * 24 * 3600; # time is relative to Jan 1, 1904
2916
2957
  my $scl = 180 / (32768 * 65536); # scaling factor for lat/lon
2917
2958
  $et->VerboseDir('GarminGPS');
2959
+ $$et{SET_GROUP1} = 'Garmin';
2918
2960
  while ($pos + 20 <= $dataLen) {
2919
2961
  $$et{DOC_NUM} = ++$$et{DOC_COUNT};
2920
2962
  my $time = Image::ExifTool::ConvertUnixTime(Get32u($dataPt, $pos) - $epoch) . 'Z';
@@ -2929,6 +2971,7 @@ sub ProcessGarminGPS($$$)
2929
2971
  $pos += 20;
2930
2972
  }
2931
2973
  delete $$et{DOC_NUM};
2974
+ delete $$et{SET_GROUP1};
2932
2975
  return 1;
2933
2976
  }
2934
2977
 
@@ -249,6 +249,13 @@ key:
249
249
  within this atom. Currently used only for Canon CNTH atom,
250
250
  which contains garbage after the first contained atom.
251
251
 
252
+ NIKON_OFFSETS [Nikon Encrypted tables only] Pointer to int32u NumberOffsets
253
+ for offset-type encrypted Nikon directories. When set,
254
+ directory and decryption lengths are calculated automatically.
255
+
256
+ ALLOW_REPROCESS Flag to allow reprocessing of another directory at this
257
+ same location in the file, bypassing recursion avoidance test.
258
+
252
259
  DATAMEMBER : BinaryData tables only. A reference to a list of sorted tag ID's
253
260
  which must be extracted as data members when writing. Must also list "var_"
254
261
  format tags and tags with Hook so offsets are properly calculated if the table
@@ -404,6 +411,10 @@ numerical, and generated automatically otherwise.
404
411
 
405
412
  'IsComposite' - flag set for Composite tags
406
413
 
414
+ 'IsImageData' - flag set if this is an image data offset to
415
+ be included in ImageDataMD5 calculation. Must have an
416
+ OffsetPair entry which is the ID of the corresponding size.
417
+
407
418
  'IsOffset' - flag set if the tag represents an offset to some
408
419
  data, and causes value will be adjusted to an absolute file
409
420
  offset. If set to 2, the offset base of the parent directory
@@ -465,6 +476,10 @@ numerical, and generated automatically otherwise.
465
476
  documentation, padded to the number of digits given by the
466
477
  PrintHex value.
467
478
 
479
+ 'PrintInt' - remove decimal part of tag ID in HTML tag name
480
+ documentation. (To avoid confusing ExifTool users because
481
+ the LensType decimal numbers are for internal use only.)
482
+
468
483
  'PrintSort' - causes PrintConv values to be sorted by value
469
484
  rather than key in the HTML tag name documentation.
470
485
 
@@ -713,7 +728,7 @@ numerical, and generated automatically otherwise.
713
728
  BitShift are applied before evaluating RawConv.
714
729
 
715
730
  BitShift : [Mask tags only] Bit shift for Mask-ed values. If not
716
- specified, set to the number of trailing bits in the Mask.
731
+ specified, set to the number of trailing zero bits in Mask.
717
732
  When reading, the value is shifted right by this number of
718
733
  bits after the Mask is applied.
719
734
 
@@ -1003,7 +1018,9 @@ numerical, and generated automatically otherwise.
1003
1018
  current Base. This is a Perl expression which may use
1004
1019
  $valuePtr to represent the location of the tag value in the
1005
1020
  file, or $val for the value itself. If not specified, a Start
1006
- of '$valuePtr' is assumed.
1021
+ of '$valuePtr' is assumed. Subdirectories in BinaryData may
1022
+ also use $dirStart to represent the offset of the current
1023
+ directory start relative to the start of the data block.
1007
1024
 
1008
1025
  OffsetPt : [EXIF directories only] If specified, this is a Perl
1009
1026
  expression that gives the position of a 32-bit word in the
@@ -30,7 +30,7 @@ use strict;
30
30
  use vars qw($VERSION $AUTOLOAD);
31
31
  use Image::ExifTool qw(:DataAccess :Utils);
32
32
 
33
- $VERSION = '1.61';
33
+ $VERSION = '1.64';
34
34
 
35
35
  sub ConvertTimecode($);
36
36
  sub ProcessSGLT($$$);
@@ -38,6 +38,13 @@ sub ProcessSLLT($$$);
38
38
  sub ProcessLucas($$$);
39
39
  sub WriteRIFF($$);
40
40
 
41
+ # RIFF chunks containing image data (to include in ImageDataMD5 digest)
42
+ my %isImageData = (
43
+ LIST_movi => 1, # (AVI: contains ##db, ##dc, ##wb)
44
+ data => 1, # (WAV)
45
+ 'VP8 '=>1, VP8L=>1, ANIM=>1, ANMF=>1, ALPH=>1, # (WebP)
46
+ );
47
+
41
48
  # recognized RIFF variants
42
49
  my %riffType = (
43
50
  'WAVE' => 'WAV', 'AVI ' => 'AVI', 'WEBP' => 'WEBP',
@@ -1522,7 +1529,7 @@ my %code2charset = (
1522
1529
  },
1523
1530
  # (can't calculate duration like this for compressed audio types)
1524
1531
  RawConv => q{
1525
- return undef if $$self{VALUE}{FileType} =~ /^(LA|OFR|PAC|WV)$/;
1532
+ return undef if $$self{FileType} =~ /^(LA|OFR|PAC|WV)$/;
1526
1533
  return(($val[0] and not ($val[2] or $val[3])) ? $val[1] / $val[0] : undef);
1527
1534
  },
1528
1535
  PrintConv => 'ConvertDuration($val)',
@@ -1980,6 +1987,7 @@ sub ProcessRIFF($$)
1980
1987
  my $unknown = $et->Options('Unknown');
1981
1988
  my $validate = $et->Options('Validate');
1982
1989
  my $ee = $et->Options('ExtractEmbedded');
1990
+ my $md5 = $$et{ImageDataMD5};
1983
1991
 
1984
1992
  # verify this is a valid RIFF file
1985
1993
  return 0 unless $raf->Read($buff, 12) == 12;
@@ -1996,7 +2004,7 @@ sub ProcessRIFF($$)
1996
2004
  $$raf{NoBuffer} = 1 if $et->Options('FastScan'); # disable buffering in FastScan mode
1997
2005
  $mime = $riffMimeType{$type} if $type;
1998
2006
  $et->SetFileType($type, $mime);
1999
- $$et{VALUE}{FileType} .= ' (RF64)' if $rf64;
2007
+ $$et{VALUE}{FileType} .= ' (RF64)' if $rf64 and $$et{VALUE}{FileType};
2000
2008
  $$et{RIFFStreamType} = ''; # initialize stream type
2001
2009
  $$et{RIFFStreamCodec} = []; # initialize codec array
2002
2010
  SetByteOrder('II');
@@ -2059,6 +2067,10 @@ sub ProcessRIFF($$)
2059
2067
  # (in LIST_movi chunk: ##db = uncompressed DIB, ##dc = compressed DIB, ##wb = audio data)
2060
2068
  if ($tagInfo or (($verbose or $unknown) and $tag !~ /^(data|idx1|LIST_movi|RIFF|\d{2}(db|dc|wb))$/)) {
2061
2069
  $raf->Read($buff, $len2) == $len2 or $err=1, last;
2070
+ if ($md5 and $isImageData{$tag}) {
2071
+ $md5->add($buff);
2072
+ $et->VPrint(0, "$$et{INDENT}(ImageDataMD5: '${tag}' chunk, $len2 bytes)\n");
2073
+ }
2062
2074
  my $setGroups;
2063
2075
  if ($tagInfo and ref $tagInfo eq 'HASH' and $$tagInfo{SetGroups}) {
2064
2076
  $setGroups = $$et{SET_GROUP0} = $$et{SET_GROUP1} = $$tagInfo{SetGroups};
@@ -2085,18 +2097,27 @@ sub ProcessRIFF($$)
2085
2097
  # extract information from remaining file as an embedded file
2086
2098
  $$et{DOC_NUM} = ++$$et{DOC_COUNT};
2087
2099
  next; # (must not increment $pos)
2088
- } elsif ($tag eq 'LIST_movi' and $ee) {
2089
- next; # parse into movi chunk
2090
2100
  } else {
2091
- if ($len > 0x7fffffff and not $et->Options('LargeFileSupport')) {
2092
- $et->Warn("Stopped parsing at large $tag chunk (LargeFileSupport not set)");
2093
- last;
2101
+ my $rewind;
2102
+ # do MD5 if required
2103
+ if ($md5 and $isImageData{$tag}) {
2104
+ $rewind = $raf->Tell();
2105
+ $et->ImageDataMD5($raf, $len2, "'${tag}' chunk");
2094
2106
  }
2095
- if ($validate and $len2) {
2096
- # (must actually try to read something after seeking to detect error)
2097
- $raf->Seek($len2-1, 1) and $raf->Read($buff, 1) == 1 or $err = 1, last;
2098
- } else {
2099
- $raf->Seek($len2, 1) or $err=1, last;
2107
+ if ($tag eq 'LIST_movi' and $ee) {
2108
+ $raf->Seek($rewind, 0) or $err = 1, last if $rewind;
2109
+ next; # parse into movi chunk
2110
+ } elsif (not $rewind) {
2111
+ if ($len > 0x7fffffff and not $et->Options('LargeFileSupport')) {
2112
+ $et->Warn("Stopped parsing at large $tag chunk (LargeFileSupport not set)");
2113
+ last;
2114
+ }
2115
+ if ($validate and $len2) {
2116
+ # (must actually try to read something after seeking to detect error)
2117
+ $raf->Seek($len2-1, 1) and $raf->Read($buff, 1) == 1 or $err = 1, last;
2118
+ } else {
2119
+ $raf->Seek($len2, 1) or $err=1, last;
2120
+ }
2100
2121
  }
2101
2122
  }
2102
2123
  $pos += $len2;
@@ -14,7 +14,7 @@ use strict;
14
14
  use vars qw($VERSION);
15
15
  use Image::ExifTool qw(:DataAccess :Utils);
16
16
 
17
- $VERSION = '1.05';
17
+ $VERSION = '1.06';
18
18
 
19
19
  # currently support this version Rawzor images
20
20
  my $implementedRawzorVersion = 199; # (up to version 1.99)
@@ -138,7 +138,7 @@ sub ProcessRWZ($$)
138
138
  }
139
139
  # set OriginalFileType from FileType of original file
140
140
  # then change FileType and MIMEType to indicate a Rawzor image
141
- my $origFileType = $$et{VALUE}{FileType};
141
+ my $origFileType = $$et{FileType};
142
142
  if ($origFileType) {
143
143
  $et->HandleTag($tagTablePtr, OriginalFileType => $origFileType);
144
144
  $et->OverrideFileType('RWZ');
@@ -16,7 +16,7 @@ use vars qw($VERSION);
16
16
  use Image::ExifTool qw(:DataAccess :Utils);
17
17
  use Image::ExifTool::Canon;
18
18
 
19
- $VERSION = '1.06';
19
+ $VERSION = '1.07';
20
20
 
21
21
  sub ProcessRealMeta($$$);
22
22
  sub ProcessRealProperties($$$);
@@ -608,7 +608,7 @@ sub ProcessReal($$)
608
608
  } else {
609
609
  last if $tag eq 'DATA'; # stop normal parsing at DATA tag
610
610
  }
611
- if ($size & 0x80000000) {
611
+ if ($size & 0x80000000 or $size < 10) {
612
612
  $et->Warn('Bad chunk header');
613
613
  last;
614
614
  }
@@ -19,7 +19,7 @@ use vars qw($VERSION);
19
19
  use Image::ExifTool qw(:DataAccess :Utils);
20
20
  use Image::ExifTool::Exif;
21
21
 
22
- $VERSION = '1.35';
22
+ $VERSION = '1.36';
23
23
 
24
24
  sub ProcessRicohText($$$);
25
25
  sub ProcessRicohRMETA($$$);
@@ -949,6 +949,7 @@ sub ProcessRicohText($$$)
949
949
 
950
950
  my $data = substr($$dataPt, $dirStart, $dirLen);
951
951
  return 1 if $data =~ /^\0/; # blank Ricoh maker notes
952
+ $et->VerboseDir('RicohText', undef, $dirLen);
952
953
  # validate text maker notes
953
954
  unless ($data =~ /^(Rev|Rv)/) {
954
955
  $et->Warn('Bad Ricoh maker notes');
@@ -19,15 +19,13 @@ use strict;
19
19
  use vars qw($VERSION %sigmaLensTypes);
20
20
  use Image::ExifTool::Exif;
21
21
 
22
- $VERSION = '1.32';
22
+ $VERSION = '1.34';
23
23
 
24
24
  # sigma LensType lookup (ref IB)
25
25
  %sigmaLensTypes = (
26
26
  Notes => q{
27
27
  Sigma LensType values are hexadecimal numbers stored as a string (without
28
- the leading "0x"). Decimal values have been added to differentiate lenses
29
- which would otherwise have the same LensType, and are used by the Composite
30
- LensID tag when attempting to identify the specific lens model.
28
+ the leading "0x").
31
29
  },
32
30
  # 0x0 => 'Sigma 50mm F2.8 EX Macro', (0x0 used for other lenses too)
33
31
  # 0x8 - 18-125mm LENSARANGE@18mm=22-4
@@ -255,6 +253,7 @@ $VERSION = '1.32';
255
253
  0x6023 => 'Sigma 20mm F2 DG DN | C', #IB
256
254
  0x6025 => 'Sigma 20mm F1.4 DG DN | A', #IB
257
255
  0x6026 => 'Sigma 24mm F1.4 DG DN | A', #IB
256
+ 0x602c => "Sigma 50mm F1.4 DG DN | A (2023)", #IB
258
257
  0x8005 => 'Sigma 35mm F1.4 DG HSM | A', #PH (012)
259
258
  0x8009 => 'Sigma 18-35mm F1.8 DC HSM | A', #PH
260
259
  0x8900 => 'Sigma 70-300mm F4-5.6 DG OS', #PH (SD15)
@@ -556,6 +555,7 @@ $VERSION = '1.32';
556
555
  SeparateTable => 'LensType',
557
556
  PrintHex => 1,
558
557
  PrintConv => \%sigmaLensTypes,
558
+ PrintInt => 1,
559
559
  },{ #PH
560
560
  Name => 'LensType',
561
561
  Condition => '$$self{MakerNoteSigmaVer} >= 3',
@@ -564,6 +564,7 @@ $VERSION = '1.32';
564
564
  SeparateTable => 'LensType',
565
565
  PrintHex => 1,
566
566
  PrintConv => \%sigmaLensTypes,
567
+ PrintInt => 1,
567
568
  }],
568
569
  0x002a => { #PH
569
570
  Name => 'LensFocalRange',
@@ -16,7 +16,7 @@ use vars qw($VERSION);
16
16
  use Image::ExifTool qw(:DataAccess :Utils);
17
17
  use Image::ExifTool::Sigma;
18
18
 
19
- $VERSION = '1.29';
19
+ $VERSION = '1.30';
20
20
 
21
21
  sub ProcessX3FHeader($$$);
22
22
  sub ProcessX3FDirectory($$$);
@@ -545,10 +545,16 @@ sub ProcessX3FDirectory($$$)
545
545
  if ($$tagInfo{Name} eq 'PreviewImage') {
546
546
  # check image header to see if this is a JPEG preview image
547
547
  $raf->Read($buff, 28) == 28 or return 'Error reading PreviewImage header';
548
- # ignore all image data but JPEG compressed (version 2.0, type 2, format 18)
549
- next unless $buff =~ /^SECi\0\0\x02\0\x02\0\0\0\x12\0\0\0/;
550
548
  $offset += 28;
551
549
  $len -= 28;
550
+ # ignore all image data but JPEG compressed (version 2.0, type 2, format 18)
551
+ unless ($buff =~ /^SECi\0\0\x02\0\x02\0\0\0\x12\0\0\0/) {
552
+ # do MD5 on non-preview data if requested
553
+ if ($$et{ImageDataMD5} and substr($buff,8,1) ne "\x02") {
554
+ $et->ImageDataMD5($raf, $len, 'SigmaRaw IMAG');
555
+ }
556
+ next;
557
+ }
552
558
  $raf->Read($buff, $len) == $len or return "Error reading PreviewImage data";
553
559
  # check fore EXIF segment, and extract this image as the JpgFromRaw
554
560
  if ($buff =~ /^\xff\xd8\xff\xe1/) {