exiftool_vendored 12.59.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.
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