exiftool_vendored 12.59.0 → 12.60.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a40c897eadb8162344b81eedcedd1888cfac911d28c1e5542f8e3d323af06768
4
- data.tar.gz: a761f6527a380e369e78c34d2c061a9652ae63a3da0b7e70be1854fb8b728ee6
3
+ metadata.gz: 348c2538720f815bacaf609de1dbb52e18f720663ea9e2194c92941b5f80d5ec
4
+ data.tar.gz: 124c2564aba8f2fa4af8b2bf16c654b46624031b38bb64e6ed4ed3d6cc2fb596
5
5
  SHA512:
6
- metadata.gz: 7edad248448957b58317b1621b2ae5b0c67276ee988ec1fb043403f299d6b0476ab7e79f4a15c345f9c655ff79518235350797b65b4b94cc5f80759511a44759
7
- data.tar.gz: a4cec80d9709c1145958d4c6590349bdf6b0fc18f041e62962fc736a660d0243a29abc5c68e481198c9b42e584cedc7f1536081c0c59ffd57f90caac704fb0ad
6
+ metadata.gz: b32a41d3586f914940ddfc5f3f947c323006f627ce6c3a050f34111817776e26a4a5e535f56194998ec38aa5ea7f27e350388fbbd517dd366d826324c9dcd9e4
7
+ data.tar.gz: 9b3d5cb69b62ca6bc41293ec56110e0c28e7510561303bc8c3f3eb0ee01500f5c92dd8ff60ace8f53c54c64a28c92cfa84b0fbebe7238cb190872433c62f4103
data/bin/Changes CHANGED
@@ -4,9 +4,27 @@ ExifTool Version History
4
4
 
5
5
  RSS feed: https://exiftool.org/rss.xml
6
6
 
7
- Note: The most recent production release is Version 12.50. (Other versions are
7
+ Note: The most recent production release is Version 12.60. (Other versions are
8
8
  considered development releases, and are not uploaded to MetaCPAN.)
9
9
 
10
+ Apr. 5, 2023 - Version 12.60 (production release)
11
+
12
+ - Added a new Sony FileFormat value
13
+ - Added Validate warning about duplicate EXIF
14
+ - Added ability to edit JPEG APP1 EXIF segment with incorrect header
15
+ - Decode a few new Sony ARW tags
16
+ - Improved -htmldump of non-EXIF-based maker notes
17
+ - Enhanced -geotag from CSV files support GPSSpeed (with variable units),
18
+ "bearing" for GPSTrack, and GPSDateTime in format "dd.mm.YYYY HH:MM:SS"
19
+ - Enhanced ImageDataMD5 to also support CRW, RAF, X3F and AVIF images
20
+ - Enhanced -efile option to also record updated and created file names
21
+ - Family 8 group names may now also be used in Composite Require/Desire tags
22
+ - Fixed handling of undefined tags in -if conditions to conform with
23
+ documentation and match -p and -tagsFromFile behaviour when -m or -f option
24
+ is used
25
+ - Fixed problem where setting the Geotime value didn't work when using an
26
+ advanced-formatting expression containing a greater-than symbol (>)
27
+
10
28
  Mar. 28, 2023 - Version 12.59
11
29
 
12
30
  - COMPATIBILITY WARNING: Changed the calculated ImageDataMD5 for JPEG images
@@ -20,14 +38,13 @@ Mar. 28, 2023 - Version 12.59
20
38
  - Decode a new Olympus tag and improved decoding of another (thanks Herb)
21
39
  - Decode a couple of new PanasonicRaw tags
22
40
  - Decode image coordinates for a couple more VNT object types
23
- - Enhanced ImageDataMD5 to also support MRW, CR3, PNG, MOV/MP4 and RIFF-based
24
- files
41
+ - Enhanced ImageDataMD5 to also support MRW, CR3, IIQ, PNG, MOV/MP4 and some
42
+ RIFF-based files
25
43
  - Improved verbose messages when deleting NikonApp trailer
26
44
  - Patched to avoid structure warnings when copying tags from Nikon files
27
45
  containing NKSC metadata
28
46
  - Fixed %-C filename format code to work properly with the -fileOrder and
29
47
  -progress options
30
- - Fixed new ImageDataMD5 tag to work properly with PhaseOne IIQ files
31
48
  - Fixed potential ValueConv warning when reading LIF files
32
49
  - API Changes:
33
50
  - Added SetAlternateFile method
@@ -196,6 +213,8 @@ Nov. 8, 2022 - Version 12.50 (production release)
196
213
  - Fixed inconsistent year and time zone for Kenwood dashcam timed GPS in MP4
197
214
  videos
198
215
 
216
+ History of older versions (back to Nov. 19, 2003 - Version 1.00) -->
217
+
199
218
  Oct. 19, 2022 - Version 12.49
200
219
 
201
220
  - Added read support for Windows ICO and CUR files
@@ -363,8 +382,6 @@ June 1, 2022 - Version 12.42 (production release)
363
382
  - Patched to allow PDF Encrypt object to be "null"
364
383
  - Fixed bug reading ICC_Profile 'meta' tags
365
384
 
366
- History of older versions (back to Nov. 19, 2003 - Version 1.00) -->
367
-
368
385
  Apr. 7, 2022 - Version 12.41
369
386
 
370
387
  - Added support for "OM SYSTEM" maker notes
data/bin/MANIFEST CHANGED
@@ -532,6 +532,7 @@ t/ExifTool_31.out
532
532
  t/ExifTool_32.out
533
533
  t/ExifTool_33.out
534
534
  t/ExifTool_34.out
535
+ t/ExifTool_35.out
535
536
  t/ExifTool_4.out
536
537
  t/ExifTool_5.out
537
538
  t/ExifTool_6.out
data/bin/META.json CHANGED
@@ -47,5 +47,5 @@
47
47
  }
48
48
  },
49
49
  "release_status" : "stable",
50
- "version" : "12.59"
50
+ "version" : "12.60"
51
51
  }
data/bin/META.yml CHANGED
@@ -28,4 +28,4 @@ recommends:
28
28
  Time::HiRes: 0
29
29
  requires:
30
30
  perl: 5.004
31
- version: 12.59
31
+ version: 12.60
data/bin/README CHANGED
@@ -107,8 +107,8 @@ your home directory, then you would type the following commands in a
107
107
  terminal window to extract and run ExifTool:
108
108
 
109
109
  cd ~/Desktop
110
- gzip -dc Image-ExifTool-12.59.tar.gz | tar -xf -
111
- cd Image-ExifTool-12.59
110
+ gzip -dc Image-ExifTool-12.60.tar.gz | tar -xf -
111
+ cd Image-ExifTool-12.60
112
112
  ./exiftool t/images/ExifTool.jpg
113
113
 
114
114
  Note: These commands extract meta information from one of the test images.
data/bin/exiftool CHANGED
@@ -11,7 +11,7 @@ use strict;
11
11
  use warnings;
12
12
  require 5.004;
13
13
 
14
- my $version = '12.59';
14
+ my $version = '12.60';
15
15
 
16
16
  # add our 'lib' directory to the include list BEFORE 'use Image::ExifTool'
17
17
  BEGIN {
@@ -922,12 +922,14 @@ for (;;) {
922
922
  $mt->Options(Duplicates => 1);
923
923
  next;
924
924
  }
925
- if (/^efile(\d)?(!)?$/i) {
925
+ if (/^efile(\d+)?(!)?$/i) {
926
926
  my $arg = shift;
927
927
  defined $arg or Error("Expecting file name for -$_ option\n"), $badCmd=1, next;
928
- $efile[0] = $arg if not $1 or $1 & 0x01;
929
- $efile[1] = $arg if $1 and $1 & 0x02;
930
- $efile[2] = $arg if $1 and $1 & 0x04;
928
+ $efile[0] = $arg if not $1 or $1 & 0x01;# error
929
+ $efile[1] = $arg if $1 and $1 & 0x02; # unchanged
930
+ $efile[2] = $arg if $1 and $1 & 0x04; # failed -if condition
931
+ $efile[3] = $arg if $1 and $1 & 0x08; # updated
932
+ $efile[4] = $arg if $1 and $1 & 0x016; # created
931
933
  unlink $arg if $2;
932
934
  next;
933
935
  }
@@ -1337,7 +1339,7 @@ for (;;) {
1337
1339
  AddSetTagsFile($setTagsFile = '@') if not $setTagsFile and /(<|>)/;
1338
1340
  if ($setTagsFile) {
1339
1341
  push @{$setTags{$setTagsFile}}, $_;
1340
- if (/>/) {
1342
+ if ($1 eq '>') {
1341
1343
  $useMWG = 1 if /^(.*>\s*)?mwg:/si;
1342
1344
  if (/\b(filename|directory|testname)#?$/i) {
1343
1345
  $doSetFileName = 1;
@@ -2083,6 +2085,7 @@ sub GetImageInfo($$)
2083
2085
  push @delFiles, $original;
2084
2086
  } elsif ($et->Rename($original, $file)) {
2085
2087
  $verbose and print $vout "Restored from $original\n";
2088
+ EFile($file, 3);
2086
2089
  ++$countGoodWr;
2087
2090
  } else {
2088
2091
  Warn "Error renaming $original\n";
@@ -3042,6 +3045,7 @@ sub SetImageInfo($$$)
3042
3045
  $r3 = $et->SetSystemTags($file);
3043
3046
  }
3044
3047
  if ($r0 > 0 or $r1 > 0 or $r2 > 0 or $r3 > 0) {
3048
+ EFile($infile, 3);
3045
3049
  ++$countGoodWr;
3046
3050
  } elsif ($r0 < 0 or $r1 < 0 or $r2 < 0 or $r3 < 0) {
3047
3051
  EFile($infile);
@@ -3156,6 +3160,7 @@ sub SetImageInfo($$$)
3156
3160
  $preserveTime{$file} = [ $aTime, $mTime, $cTime ];
3157
3161
  }
3158
3162
  }
3163
+ EFile($infile, 3);
3159
3164
  ++$countGoodWr;
3160
3165
  } else {
3161
3166
  close(NEW_FILE);
@@ -3171,6 +3176,7 @@ sub SetImageInfo($$$)
3171
3176
  # simply rename temporary file to replace original
3172
3177
  # (if we didn't already rename it to add "_original")
3173
3178
  } elsif ($et->Rename($tmpFile, $dstFile)) {
3179
+ EFile($infile, 3);
3174
3180
  ++$countGoodWr;
3175
3181
  } else {
3176
3182
  my $newFile = $tmpFile;
@@ -3188,21 +3194,26 @@ sub SetImageInfo($$$)
3188
3194
  # (don't delete tmp file now because it is all we have left)
3189
3195
  ++$countBadWr;
3190
3196
  } else {
3197
+ EFile($infile, 3);
3191
3198
  ++$countGoodWr;
3192
3199
  }
3193
3200
  }
3194
3201
  } elsif ($overwriteOrig) {
3195
3202
  # erase original file
3203
+ EFile($infile, 3);
3196
3204
  $et->Unlink($file) or Warn "Error erasing original $file\n";
3197
3205
  ++$countGoodWr;
3198
3206
  } else {
3207
+ EFile($infile, 4);
3199
3208
  ++$countGoodCr;
3200
3209
  }
3201
3210
  } else {
3202
3211
  # this file was created from scratch, not edited
3212
+ EFile($infile, 4);
3203
3213
  ++$countGoodCr;
3204
3214
  }
3205
3215
  } else {
3216
+ EFile($infile, 3);
3206
3217
  ++$countGoodWr;
3207
3218
  }
3208
3219
  } elsif ($success) {
@@ -4439,7 +4450,7 @@ sub ReadStayOpen($)
4439
4450
 
4440
4451
  #------------------------------------------------------------------------------
4441
4452
  # Add new entry to -efile output file
4442
- # Inputs: 0) file name, 1) -efile option number (0=error, 1=same, 2=failed)
4453
+ # Inputs: 0) file name, 1) -efile option number (0=error, 1=same, 2=failed, 3=updated, 4=created)
4443
4454
  sub EFile($$)
4444
4455
  {
4445
4456
  my $entry = shift;
@@ -5301,12 +5312,12 @@ escaped. The inverse conversion is applied when writing tags.
5301
5312
 
5302
5313
  =item B<-f> (B<-forcePrint>)
5303
5314
 
5304
- Force printing of tags even if their values are not found. This option only
5305
- applies when specific tags are requested on the command line (ie. not with
5306
- wildcards or by C<-all>). With this option, a dash (C<->) is printed for
5307
- the value of any missing tag, but the dash may be changed via the API
5308
- MissingTagValue option. May also be used to add a 'flags' attribute to the
5309
- B<-listx> output, or to allow tags to be deleted when writing with the
5315
+ Force printing of tags even if they don't exist. This option applies to
5316
+ tags specified on the command line, or with the B<-p>, B<-if> or
5317
+ B<-tagsFromFile> options. When B<-f> is used, the value of any missing tag
5318
+ is set to a dash (C<->) by default, but this may be configured via the API
5319
+ MissingTagValue option. B<-f> is also used to add a 'flags' attribute to
5320
+ the B<-listx> output, or to allow tags to be deleted when writing with the
5310
5321
  B<-csv>=I<CSVFILE> feature.
5311
5322
 
5312
5323
  =item B<-g>[I<NUM>][:I<NUM>...] (B<-groupHeadings>)
@@ -5530,7 +5541,7 @@ with this command:
5530
5541
 
5531
5542
  produces output like this:
5532
5543
 
5533
- -- Generated by ExifTool 12.59 --
5544
+ -- Generated by ExifTool 12.60 --
5534
5545
  File: a.jpg - 2003:10:31 15:44:19
5535
5546
  (f/5.6, 1/60s, ISO 100)
5536
5547
  File: b.jpg - 2006:05:23 11:57:38
@@ -6512,10 +6523,11 @@ exit status of the command (see L</EXIT STATUS>).
6512
6523
 
6513
6524
  Save the names of files giving errors (I<NUM> missing or 1), files that were
6514
6525
  unchanged (I<NUM> is 2), files that fail the B<-if> condition (I<NUM> is 4),
6515
- or any combination thereof by summing I<NUM> (eg. B<-efile3> is the same
6516
- has having both B<-efile> and B<-efile2> options with the same I<ERRFILE>).
6517
- By default, file names are appended to any existing I<ERRFILE>, but
6518
- I<ERRFILE> is overwritten if an exclamation point is added to the option
6526
+ files that were updated (I<NUM> is 8), files that were created (I<NUM> is
6527
+ 16), or any combination thereof by summing I<NUM> (eg. B<-efile3> is the
6528
+ same has having both B<-efile> and B<-efile2> options with the same
6529
+ I<ERRFILE>). By default, file names are appended to any existing I<ERRFILE>,
6530
+ but I<ERRFILE> is overwritten if an exclamation point is added to the option
6519
6531
  (eg. B<-efile!>). Saves the name of the file specified by the B<-srcfile>
6520
6532
  option if applicable.
6521
6533
 
@@ -6533,10 +6545,10 @@ option no longer suppresses the output "{readyNUM}" message.
6533
6545
  =item B<-file>I<NUM> I<ALTFILE>
6534
6546
 
6535
6547
  Read tags from an alternate source file. These tags are accessed via the
6536
- family 8 group name (eg. C<File1:TAG>, C<File2:TAG>, etc). I<ALTFILE> may
6537
- contain filename formatting codes %d, %f and %e. Among other things, this
6538
- allows tags from different files to be compared and combined using the
6539
- B<-if> and B<-p> options.
6548
+ family 8 group name (eg. C<File1:TAG> for the B<-file1> option, C<File2:TAG>
6549
+ for B<-file2>, etc). I<ALTFILE> may contain filename formatting codes %d,
6550
+ %f and %e. Among other things, this allows tags from different files to be
6551
+ compared and combined using the B<-if> and B<-p> options.
6540
6552
 
6541
6553
  =item B<-list_dir>
6542
6554
 
@@ -21,7 +21,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
21
21
  use Image::ExifTool::Exif;
22
22
  use Image::ExifTool::Canon;
23
23
 
24
- $VERSION = '1.59';
24
+ $VERSION = '1.60';
25
25
 
26
26
  sub WriteCRW($$);
27
27
  sub ProcessCanonRaw($$$);
@@ -698,6 +698,10 @@ sub ProcessCanonRaw($$$)
698
698
  $format ne 'string' and not $subdir;
699
699
  } else {
700
700
  $valueDataPos = $ptr;
701
+ # do MD5 of image data if requested
702
+ if ($$et{ImageDataMD5} and $tagID == 0x2005) {
703
+ $raf->Seek($ptr, 0) and $et->ImageDataMD5($raf, $size, 'raw');
704
+ }
701
705
  if ($size <= 512 or ($verbose > 2 and $size <= 65536)
702
706
  or ($tagInfo and ($$tagInfo{SubDirectory}
703
707
  or grep(/^$$tagInfo{Name}$/i, $et->GetRequestedTags()) )))
@@ -56,7 +56,7 @@ use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber %intFormat
56
56
  use Image::ExifTool qw(:DataAccess :Utils);
57
57
  use Image::ExifTool::MakerNotes;
58
58
 
59
- $VERSION = '4.43';
59
+ $VERSION = '4.44';
60
60
 
61
61
  sub ProcessExif($$$);
62
62
  sub WriteExif($$$);
@@ -1511,9 +1511,10 @@ my %opcodeInfo = (
1511
1511
  0x7031 => {
1512
1512
  Name => 'VignettingCorrection',
1513
1513
  Notes => 'found in Sony ARW images',
1514
- Protected => 1,
1515
1514
  Writable => 'int16s',
1516
1515
  WriteGroup => 'SubIFD',
1516
+ Permanent => 1,
1517
+ Protected => 1,
1517
1518
  PrintConv => {
1518
1519
  256 => 'Off',
1519
1520
  257 => 'Auto',
@@ -1524,17 +1525,19 @@ my %opcodeInfo = (
1524
1525
  0x7032 => {
1525
1526
  Name => 'VignettingCorrParams', #forum7640
1526
1527
  Notes => 'found in Sony ARW images',
1527
- Protected => 1,
1528
1528
  Writable => 'int16s',
1529
1529
  WriteGroup => 'SubIFD',
1530
1530
  Count => 17,
1531
+ Permanent => 1,
1532
+ Protected => 1,
1531
1533
  },
1532
1534
  0x7034 => {
1533
1535
  Name => 'ChromaticAberrationCorrection',
1534
1536
  Notes => 'found in Sony ARW images',
1535
- Protected => 1,
1536
1537
  Writable => 'int16s',
1537
1538
  WriteGroup => 'SubIFD',
1539
+ Permanent => 1,
1540
+ Protected => 1,
1538
1541
  PrintConv => {
1539
1542
  0 => 'Off',
1540
1543
  1 => 'Auto',
@@ -1544,17 +1547,19 @@ my %opcodeInfo = (
1544
1547
  0x7035 => {
1545
1548
  Name => 'ChromaticAberrationCorrParams', #forum6509
1546
1549
  Notes => 'found in Sony ARW images',
1547
- Protected => 1,
1548
1550
  Writable => 'int16s',
1549
1551
  WriteGroup => 'SubIFD',
1550
1552
  Count => 33,
1553
+ Permanent => 1,
1554
+ Protected => 1,
1551
1555
  },
1552
1556
  0x7036 => {
1553
1557
  Name => 'DistortionCorrection',
1554
1558
  Notes => 'found in Sony ARW images',
1555
- Protected => 1,
1556
1559
  Writable => 'int16s',
1557
1560
  WriteGroup => 'SubIFD',
1561
+ Permanent => 1,
1562
+ Protected => 1,
1558
1563
  PrintConv => {
1559
1564
  0 => 'Off',
1560
1565
  1 => 'Auto',
@@ -1565,10 +1570,38 @@ my %opcodeInfo = (
1565
1570
  0x7037 => {
1566
1571
  Name => 'DistortionCorrParams', #forum6509
1567
1572
  Notes => 'found in Sony ARW images',
1568
- Protected => 1,
1569
1573
  Writable => 'int16s',
1570
1574
  WriteGroup => 'SubIFD',
1571
1575
  Count => 17,
1576
+ Permanent => 1,
1577
+ Protected => 1,
1578
+ },
1579
+ 0x7038 => { #github#195 (Sony ARW)
1580
+ Name => 'SonyRawImageSize',
1581
+ Notes => 'size of actual image in Sony ARW files',
1582
+ Writable => 'int32u',
1583
+ WriteGroup => 'SubIFD',
1584
+ Count => 2,
1585
+ Permanent => 1,
1586
+ Protected => 1,
1587
+ },
1588
+ 0x7310 => { #github#195 (Sony ARW)
1589
+ Name => 'BlackLevel',
1590
+ Notes => 'found in Sony ARW images',
1591
+ Writable => 'int16u',
1592
+ WriteGroup => 'SubIFD',
1593
+ Count => 4,
1594
+ Permanent => 1,
1595
+ Protected => 1,
1596
+ },
1597
+ 0x7313 => { #github#195 (Sony ARW)
1598
+ Name => 'WB_RGGBLevels',
1599
+ Notes => 'found in Sony ARW images',
1600
+ Writable => 'int16s',
1601
+ WriteGroup => 'SubIFD',
1602
+ Count => 4,
1603
+ Permanent => 1,
1604
+ Protected => 1,
1572
1605
  },
1573
1606
  0x74c7 => { #IB (in ARW images from some Sony cameras)
1574
1607
  Name => 'SonyCropTopLeft',
@@ -5893,9 +5926,7 @@ sub ProcessExif($$$)
5893
5926
  my $base = $$dirInfo{Base} || 0;
5894
5927
  my $firstBase = $base;
5895
5928
  my $raf = $$dirInfo{RAF};
5896
- my $verbose = $et->Options('Verbose');
5897
- my $validate = $et->Options('Validate');
5898
- my $saveFormat = $et->Options('SaveFormat');
5929
+ my ($verbose,$validate,$saveFormat) = @{$$et{OPTIONS}}{qw(Verbose Validate SaveFormat)};
5899
5930
  my $htmlDump = $$et{HTML_DUMP};
5900
5931
  my $success = 1;
5901
5932
  my ($tagKey, $dirSize, $makerAddr, $strEnc, %offsetInfo, $offName, $nextOffName, $doMD5);
@@ -5914,7 +5945,12 @@ sub ProcessExif($$$)
5914
5945
  $isExif and $$et{FILE_TYPE} =~ /^(JPEG|TIFF|PSD)$/)
5915
5946
  {
5916
5947
  my $path = $et->MetadataPath();
5917
- unless ($path =~ /^(JPEG-APP1-IFD0|TIFF-IFD0|PSD-EXIFInfo-IFD0)$/) {
5948
+ if ($path =~ /^(JPEG-APP1-IFD0|TIFF-IFD0|PSD-EXIFInfo-IFD0)$/) {
5949
+ unless ($$et{DOC_NUM}) {
5950
+ $et->Warn("Duplicate EXIF at $path") if $$et{HasExif};
5951
+ $$et{HasExif} = 1;
5952
+ }
5953
+ } else {
5918
5954
  if ($Image::ExifTool::MWG::strict) {
5919
5955
  $et->Warn("Ignored non-standard EXIF at $path");
5920
5956
  return 0;
@@ -6378,10 +6414,10 @@ sub ProcessExif($$$)
6378
6414
  $tval .= " ($rational)" if defined $rational;
6379
6415
  if ($htmlDump) {
6380
6416
  my ($tagName, $colName);
6381
- if ($tagID == 0x927c and $dirName eq 'ExifIFD') {
6382
- $tagName = 'MakerNotes';
6383
- } elsif ($tagInfo) {
6417
+ if ($tagInfo) {
6384
6418
  $tagName = $$tagInfo{Name};
6419
+ } elsif ($tagID == 0x927c and $dirName eq 'ExifIFD') {
6420
+ $tagName = 'MakerNotes';
6385
6421
  } else {
6386
6422
  $tagName = sprintf("Tag 0x%.4x",$tagID);
6387
6423
  }
@@ -6456,6 +6492,9 @@ sub ProcessExif($$$)
6456
6492
  }
6457
6493
  # add value data block (underlining maker notes data)
6458
6494
  $et->HDump($exifDumpPos,$size,"$tagName value",'SAME', $flag, $sid);
6495
+ if ($subdir and $$tagInfo{MakerNotes} and $$tagInfo{NotIFD}) {
6496
+ $et->HDump($exifDumpPos,$size,"$tagName value",undef,undef,$$dirInfo{OffsetName});
6497
+ }
6459
6498
  }
6460
6499
  } else {
6461
6500
  if ($tagID <= $lastID and not $inMakerNotes) {
@@ -1671,11 +1671,11 @@ sub ProcessRAF($$)
1671
1671
  my ($rafNum, $ifdNum) = ('','');
1672
1672
  foreach $offset (0x5c, 0x64, 0x78, 0x80) {
1673
1673
  last if $offset >= $jpos;
1674
- unless ($raf->Seek($offset, 0) and $raf->Read($buff, 4)) {
1674
+ unless ($raf->Seek($offset, 0) and $raf->Read($buff, 8)) {
1675
1675
  $warn = 1;
1676
1676
  last;
1677
1677
  }
1678
- my $start = unpack('N',$buff);
1678
+ my ($start, $len) = unpack('N2',$buff);
1679
1679
  next unless $start;
1680
1680
  if ($offset == 0x64 or $offset == 0x80) {
1681
1681
  # parse FujiIFD directory
@@ -1686,7 +1686,10 @@ sub ProcessRAF($$)
1686
1686
  $$et{SET_GROUP1} = "FujiIFD$ifdNum";
1687
1687
  my $tagTablePtr = GetTagTable('Image::ExifTool::FujiFilm::IFD');
1688
1688
  # this is TIFF-format data only for some models, so no warning if it fails
1689
- $et->ProcessTIFF(\%dirInfo, $tagTablePtr, \&Image::ExifTool::ProcessTIFF);
1689
+ unless ($et->ProcessTIFF(\%dirInfo, $tagTablePtr, \&Image::ExifTool::ProcessTIFF)) {
1690
+ # do MD5 of image data if necessary
1691
+ $et->ImageDataMD5($raf, $len, 'raw') if $$et{ImageDataMD5} and $raf->Seek($start,0);
1692
+ }
1690
1693
  delete $$et{SET_GROUP1};
1691
1694
  $ifdNum = ($ifdNum || 1) + 1;
1692
1695
  } else {
@@ -29,7 +29,7 @@ use vars qw($VERSION);
29
29
  use Image::ExifTool qw(:Public);
30
30
  use Image::ExifTool::GPS;
31
31
 
32
- $VERSION = '1.70';
32
+ $VERSION = '1.71';
33
33
 
34
34
  sub JITTER() { return 2 } # maximum time jitter
35
35
 
@@ -92,7 +92,7 @@ my %isOrient = ( dir => 1, pitch => 1, roll => 1 ); # test for orientation key
92
92
  # tags which may exist separately in some formats (eg. CSV)
93
93
  my %sepTags = ( dir => 1, pitch => 1, roll => 1, track => 1, speed => 1 );
94
94
 
95
- # conversion factors for GPSSpeed
95
+ # conversion factors for GPSSpeed (standard EXIF units only)
96
96
  my %speedConv = (
97
97
  'K' => 1.852, # km/h per knot
98
98
  'M' => 1.150779448, # mph per knot
@@ -102,7 +102,14 @@ my %speedConv = (
102
102
  'mph' => 'M',
103
103
  );
104
104
 
105
- my $secPerDay = 24 * 3600; # a useful constant
105
+ # all recognized speed conversion factors (non-EXIF included)
106
+ my %otherConv = (
107
+ 'km/h' => 1.852,
108
+ 'mph' => 1.150779448,
109
+ 'm/s' => 0.514444,
110
+ );
111
+
112
+ my $secPerDay = 24 * 3600; # a useful constant
106
113
 
107
114
  #------------------------------------------------------------------------------
108
115
  # Load GPS track log file
@@ -140,6 +147,7 @@ sub LoadTrackLog($$;$)
140
147
  my ($raf, $from, $time, $isDate, $noDate, $noDateChanged, $lastDate, $dateFlarm);
141
148
  my ($nmeaStart, $fixSecs, @fixTimes, $lastFix, %nmea, @csvHeadings, $sortFixes);
142
149
  my ($canCut, $cutPDOP, $cutHDOP, $cutSats, $e0, $e1, @tmp, $trackFile, $trackTime);
150
+ my $scaleSpeed;
143
151
 
144
152
  unless (eval { require Time::Local }) {
145
153
  return 'Geotag feature requires Time::Local installed';
@@ -246,7 +254,9 @@ sub LoadTrackLog($$;$)
246
254
  $format = 'CSV';
247
255
  # convert recognized headings to our parameter names
248
256
  foreach (@csvHeadings) {
257
+ my $head = $_;
249
258
  my $param;
259
+ my $xtra = '';
250
260
  s/^GPS ?//; # remove leading "GPS" to simplify regex patterns
251
261
  if (/^Time ?\(seconds\)$/i) { # DJI
252
262
  # DJI CSV log files have a column "Time(seconds)" which is seconds since
@@ -274,7 +284,16 @@ sub LoadTrackLog($$;$)
274
284
  /ref$/i and $param .= 'ref';
275
285
  } elsif (/^(Pos)?Alt/i) {
276
286
  $param = 'alt';
277
- } elsif (/^(Angle)?(Heading|Track)/i) {
287
+ } elsif (/^Speed/i) {
288
+ $param = 'speed';
289
+ # (recognize units in brackets)
290
+ if (m{\((mph|km/h|m/s)\)}) {
291
+ $scaleSpeed = $otherConv{$1};
292
+ $xtra = " in $1";
293
+ } else {
294
+ $xtra = ' in knots';
295
+ }
296
+ } elsif (/^(Angle)?(Heading|Track|Bearing)/i) {
278
297
  $param = 'track';
279
298
  } elsif (/^(Angle)?Pitch/i or /^Camera ?Elevation ?Angle/i) {
280
299
  $param = 'pitch';
@@ -284,10 +303,10 @@ sub LoadTrackLog($$;$)
284
303
  $param = 'dir';
285
304
  }
286
305
  if ($param) {
287
- $et->VPrint(2, "CSV column '${_}' is $param\n");
306
+ $et->VPrint(2, "CSV column '${head}' is $param$xtra\n");
288
307
  $_ = $param;
289
308
  } else {
290
- $et->VPrint(2, "CSV column '${_}' ignored\n");
309
+ $et->VPrint(2, "CSV column '${head}' ignored\n");
291
310
  $_ = ''; # ignore this column
292
311
  }
293
312
  }
@@ -479,9 +498,11 @@ DoneFix: $isDate = 1;
479
498
  my ($param, $date, $secs, %neg);
480
499
  foreach $param (@csvHeadings) {
481
500
  my $val = shift @vals;
482
- last unless defined $val;
501
+ last unless defined $val and length($val);
483
502
  next unless $param;
484
503
  if ($param eq 'datetime') {
504
+ # (fix formats like "24.07.2016 13:47:30")
505
+ $val =~ s/^(\d{2})[^\d](\d{2})[^\d](\d{4}) /$3:$2:$1 /;
485
506
  local $SIG{'__WARN__'} = sub { };
486
507
  my $dateTime = $et->InverseDateTime($val);
487
508
  if ($dateTime) {
@@ -510,6 +531,7 @@ DoneFix: $isDate = 1;
510
531
  $date = $trackTime;
511
532
  $secs = $val;
512
533
  } else {
534
+ $val /= $scaleSpeed if $scaleSpeed and $param eq 'speed';
513
535
  $$fix{$param} = $val;
514
536
  $$has{$param} = 1 if $sepTags{$param};
515
537
  }
@@ -1204,6 +1226,7 @@ Category: foreach $category (qw{pos track alt orient atemp}) {
1204
1226
  @r = $et->SetNewValue(GPSTrackRef => (defined $$tFix{track} ? 'T' : undef), %opts);
1205
1227
  my ($spd, $ref);
1206
1228
  if (defined($spd = $$tFix{speed})) {
1229
+ # convert to specified units if necessary
1207
1230
  $ref = $$et{OPTIONS}{GeoSpeedRef};
1208
1231
  if ($ref and defined $speedConv{$ref}) {
1209
1232
  $ref = $speedConv{$ref} if $speedConv{$speedConv{$ref}};
@@ -21,7 +21,7 @@ sub ProcessKodakPatch($$$);
21
21
  sub WriteUnknownOrPreview($$$);
22
22
  sub FixLeicaBase($$;$);
23
23
 
24
- $VERSION = '2.13';
24
+ $VERSION = '2.14';
25
25
 
26
26
  my $debug; # set to 1 to enable debugging code
27
27
 
@@ -92,6 +92,7 @@ my $debug; # set to 1 to enable debugging code
92
92
  {
93
93
  Name => 'MakerNoteDJIInfo',
94
94
  Condition => '$$valPt =~ /^\[ae_dbg_info:/',
95
+ NotIFD => 1,
95
96
  SubDirectory => { TagTable => 'Image::ExifTool::DJI::Info' },
96
97
  },
97
98
  {
@@ -489,14 +489,7 @@ sub ProcessMRW($$;$)
489
489
  $err and $et->Error("MRW format error", $$et{TIFF_TYPE} eq 'ARW');
490
490
  } else {
491
491
  $err and $et->Warn("MRW format error");
492
- if ($$et{ImageDataMD5}) {
493
- my ($num, $md5) = (0, $$et{ImageDataMD5});
494
- while ($raf->Read($data, 65536)) {
495
- $md5->add($data);
496
- $num += length $data;
497
- }
498
- $et->VPrint(0, "$$et{INDENT}(ImageDataMD5: $num bytes of raw data)\n");
499
- }
492
+ $et->ImageDataMD5($raf, undef, 'raw');
500
493
  }
501
494
  return $rtnVal;
502
495
  }
@@ -1542,12 +1542,7 @@ sub ProcessPNG($$)
1542
1542
  # skip over data chunks if possible/necessary
1543
1543
  } elsif (not $validate or $len > $chunkSizeLimit) {
1544
1544
  if ($md5) {
1545
- while ($len) {
1546
- my $n = $len > 65536 ? 65536 : $len;
1547
- $raf->Read($dbuf,$n) == $n or last;
1548
- $md5->add($dbuf);
1549
- $len -= $n;
1550
- }
1545
+ $et->ImageDataMD5($raf, $len);
1551
1546
  $raf->Read($cbuf, 4) == 4 or $et->Warn('Truncated data'), last;
1552
1547
  } else {
1553
1548
  $raf->Seek($len + 4, 1) or $et->Warn('Seek error'), last;
@@ -8784,6 +8784,16 @@ sub HandleItemInfo($)
8784
8784
  $et->VPrint(0, "$$et{INDENT} [snip $snip bytes]\n") if $snip;
8785
8785
  }
8786
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
+ }
8787
8797
  next unless $name;
8788
8798
  # assemble the data for this item
8789
8799
  undef $buff;
@@ -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.63';
33
+ $VERSION = '1.64';
34
34
 
35
35
  sub ConvertTimecode($);
36
36
  sub ProcessSGLT($$$);
@@ -2102,14 +2102,7 @@ sub ProcessRIFF($$)
2102
2102
  # do MD5 if required
2103
2103
  if ($md5 and $isImageData{$tag}) {
2104
2104
  $rewind = $raf->Tell();
2105
- my $more = $len2;
2106
- while ($more) {
2107
- my $n = $more > 65536 ? 65536 : $more;
2108
- $raf->Read($buff, $n) == $n or $err = 1, last;
2109
- $md5->add($buff);
2110
- $more -= $n;
2111
- }
2112
- $et->VPrint(0, "$$et{INDENT}(ImageDataMD5: '${tag}' chunk, $len2 bytes)\n");
2105
+ $et->ImageDataMD5($raf, $len2, "'${tag}' chunk");
2113
2106
  }
2114
2107
  if ($tag eq 'LIST_movi' and $ee) {
2115
2108
  $raf->Seek($rewind, 0) or $err = 1, last if $rewind;
@@ -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');
@@ -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/) {
@@ -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.59';
38
38
 
39
39
  sub ProcessSRF($$$);
40
40
  sub ProcessSR2($$$);
@@ -1957,6 +1957,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 );
1957
1957
  '3 3 3 0' => 'ARW 2.3.3', #JR (ILCE-9)
1958
1958
  '3 3 5 0' => 'ARW 2.3.5', #JR (DSC-HX99)
1959
1959
  '4 0 0 0' => 'ARW 4.0', # (ILCE-7SM3)
1960
+ '4 0 1 0' => 'ARW 4.0.1', #github#195 (ZV-E1)
1960
1961
  # what about cRAW images?
1961
1962
  },
1962
1963
  },
@@ -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
@@ -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}";
@@ -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
@@ -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.60';
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 and AVIF images, MOV/MP4
1830
+ videos, and some RIFF-based files. The MD5 includes the main image data,
1831
+ 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
  );
@@ -3731,13 +3733,21 @@ COMPOSITE_TAG:
3731
3733
  next COMPOSITE_TAG;
3732
3734
  }
3733
3735
  }
3736
+ my ($i, $key, @keys, $altFile);
3737
+ my $et = $self;
3738
+ # get tags from alternate file if a family 8 group was specified
3739
+ if ($reqTag =~ /\b(File\d+):/i and $$self{ALT_EXIFTOOL}{$1}) {
3740
+ $et = $$self{ALT_EXIFTOOL}{$1};
3741
+ $altFile = $1;
3742
+ }
3734
3743
  # (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};
3744
+ for ($key=$name, $i=$$et{DUPL_TAG}{$name} || 0; ; --$i) {
3745
+ push @keys, $key if defined $$et{VALUE}{$key};
3738
3746
  last if $i <= 0;
3739
3747
  $key = "$name ($i)";
3740
3748
  }
3749
+ # make sure the necessary information is available from the alternate file
3750
+ $self->CopyAltInfo($altFile, \@keys) if $altFile;
3741
3751
  # find first matching tag
3742
3752
  $key = $self->GroupMatches($reqGroup, \@keys);
3743
3753
  $reqTag = $key || "$name (0)";
@@ -4598,6 +4608,29 @@ sub RemoveTagsFromList($$$$;$)
4598
4608
  $_[0] = \@filteredTags; # update tag list
4599
4609
  }
4600
4610
 
4611
+ #------------------------------------------------------------------------------
4612
+ # Copy tags from alternate input file
4613
+ # Inputs: 0) ExifTool ref, 1) family 8 group, 2) list ref for tag keys to copy
4614
+ # - updates tag key list to match keys newly added to $self
4615
+ sub CopyAltInfo($$$)
4616
+ {
4617
+ my ($self, $g8, $tags) = @_;
4618
+ my ($tag, $vtag);
4619
+ return unless $g8 =~ /(\d+)/;
4620
+ my $et = $$self{ALT_EXIFTOOL}{$g8} or return;
4621
+ my $altOrder = ($1 + 1) * 100000; # increment file order
4622
+ foreach $tag (@$tags) {
4623
+ ($vtag = $tag) =~ s/( |$)/ #[$g8]/;
4624
+ unless (defined $$self{VALUE}{$vtag}) {
4625
+ $$self{VALUE}{$vtag} = $$et{VALUE}{$tag};
4626
+ $$self{TAG_INFO}{$vtag} = $$et{TAG_INFO}{$tag};
4627
+ $$self{TAG_EXTRA}{$vtag} = $$et{TAG_EXTRA}{$tag} || { };
4628
+ $$self{FILE_ORDER}{$vtag} = ($$et{FILE_ORDER}{$tag} || 0) + $altOrder;
4629
+ }
4630
+ $tag = $vtag;
4631
+ }
4632
+ }
4633
+
4601
4634
  #------------------------------------------------------------------------------
4602
4635
  # Set list of found tags from previously requested tags
4603
4636
  # Inputs: 0) ExifTool object reference
@@ -4624,7 +4657,7 @@ sub SetFoundTags($)
4624
4657
  my $tagHash = $$self{VALUE};
4625
4658
  my $reqTag;
4626
4659
  foreach $reqTag (@$reqTags) {
4627
- my (@matches, $group, $allGrp, $allTag, $byValue, $g8, $altOrder);
4660
+ my (@matches, $group, $allGrp, $allTag, $byValue, $g8);
4628
4661
  my $et = $self;
4629
4662
  if ($reqTag =~ /^(.*):(.+)/) {
4630
4663
  ($group, $tag) = ($1, $2);
@@ -4632,7 +4665,6 @@ sub SetFoundTags($)
4632
4665
  $allGrp = 1;
4633
4666
  } elsif ($reqTag =~ /\bfile(\d+):/i) {
4634
4667
  $g8 = "File$1";
4635
- $altOrder = ($1 + 1) * 100000;
4636
4668
  $et = $$self{ALT_EXIFTOOL}{$g8} || $self;
4637
4669
  $fileOrder = $$et{FILE_ORDER};
4638
4670
  $tagHash = $$et{VALUE};
@@ -4704,16 +4736,7 @@ sub SetFoundTags($)
4704
4736
  }
4705
4737
  # copy over necessary information for tags from alternate files
4706
4738
  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
- }
4739
+ $self->CopyAltInfo($g8, \@matches);
4717
4740
  # restore variables to original values for main file
4718
4741
  $fileOrder = $$self{FILE_ORDER};
4719
4742
  $tagHash = $$self{VALUE};
@@ -6802,7 +6825,7 @@ sub ProcessJPEG($$)
6802
6825
  } elsif ($marker == 0xe1) { # APP1 (EXIF, XMP, QVCI, PARROT)
6803
6826
  # (some Kodak cameras don't put a second "\0", and I have seen an
6804
6827
  # example where there was a second 4-byte APP1 segment header)
6805
- if ($$segDataPt =~ /^(.{0,4})Exif\0/is) {
6828
+ if ($$segDataPt =~ /^(.{0,4})Exif\0./is) {
6806
6829
  undef $dumpType; # (will be dumped here)
6807
6830
  # this is EXIF data --
6808
6831
  # get the data block (into a common variable)
@@ -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.60
4
4
  Release: 1
5
5
  License: Artistic/GPL
6
6
  Group: Development/Libraries/Perl
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ExiftoolVendored
4
- VERSION = Gem::Version.new('12.59.0')
4
+ VERSION = Gem::Version.new('12.60.0')
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exiftool_vendored
3
3
  version: !ruby/object:Gem::Version
4
- version: 12.59.0
4
+ version: 12.60.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew McEachen
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-04-03 00:00:00.000000000 Z
12
+ date: 2023-04-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: exiftool