exiftool_vendored 13.19.0 → 13.21.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: 19b270f0ce5b43c0bc65a0cf0f71fdea7426079ce467cb9e79a42ae9a5909c12
4
- data.tar.gz: d989e4609455211361660c40fdec7c81ac3809d35030fd08ee0406fcf220be1e
3
+ metadata.gz: e09f4452fe21aa8e743a6060c2eab2bd13d43b65eceb0a3665f5c85d58db0103
4
+ data.tar.gz: 33e426b70e4a07102f6d60c61d1e162fbc5164198be900b9548f665e4a58f03a
5
5
  SHA512:
6
- metadata.gz: c4f5c17319320481c245bf7009a86055da882a2374fb4e5c4f59b5ac31b82dba1f094e54adc442759fe3758ceeeab2e1d8f75b73efbdff57e1214ef871b8d12e
7
- data.tar.gz: c657963e15956834d70bde5bf04c64446e1361a5e170eaef59a1d42b54acaeef54428654dd96c2d18ffef7548752fcd757e345d6a130076684f70ec1095eb033
6
+ metadata.gz: 5195564935d181ce7d5338fe53be6b88918ddcef2042d41045dc6dae27046aac9fe4317e0e3d333882315339bf11f8811d00084fa9274e3c57388cafe8c179d4
7
+ data.tar.gz: a04e8fc3f16ba37322ba42c7e6ec9bd8b7662232975b0f7cf6ee9483cc78ce1e7b4e136df76f1e6b7f3682a3a17b2084a4ac1fc35e3d4bc38448129b0ac88a79
data/bin/Changes CHANGED
@@ -7,6 +7,29 @@ RSS feed: https://exiftool.org/rss.xml
7
7
  Note: The most recent production release is Version 13.10. (Other versions are
8
8
  considered development releases, and are not uploaded to MetaCPAN.)
9
9
 
10
+ Feb. 20, 2025 - Version 13.21
11
+
12
+ - Patched issue that could result in runtime warning for some video files
13
+ - Fixed a bug that could cause a compiler error when using the -plot option
14
+
15
+ Feb. 20, 2025 - Version 13.20
16
+
17
+ - Added new -plot option for generating SVG-format plots from tag values
18
+ - Added a new Olympus CameraType
19
+ - Added a new Nikon Z LensID (thanks Warren Hatch)
20
+ - Overhauled decoding of Nikon AF tags (thanks Warren Hatch)
21
+ - Decode timed GPS from yet another model dashcam
22
+ - Decode more information from AAE files
23
+ - Decode more tags from DJI videos
24
+ - Updated Windows launcher (thanks Oliver Betz)
25
+ - Enhanced -w option to be available for use with the -csv output
26
+ - Attempted to patch a problem writing some PDF files
27
+ - Fail if a required module is missing when attempting to write a formatted
28
+ date/time value instead of falling back to write as unformatted
29
+ - Minor change to WebP lossless FileType text
30
+ - API Changes:
31
+ - Added Plot option
32
+
10
33
  Feb. 10, 2025 - Version 13.19
11
34
 
12
35
  - Added read/write support for PDF and XMP-pdfx SourceModified
@@ -14,11 +37,11 @@ Feb. 10, 2025 - Version 13.19
14
37
  - Decode timed GPS from Rexing V1-4k dashcam
15
38
  - Decode more information from AAE files
16
39
  - Made a new icon for the Windows EXE application
17
- - Changed family 3 groups for ICO files so the first icon is in the Doc1
18
- instead of the Main group
19
40
  - Improved handling of ICC_Profile in HEIC images:
20
41
  - Profiles for sub-images are extracted as sub-documents
21
42
  - Allow only the profile of the main image to be written
43
+ - Changed family 3 groups for ICO files so the first icon is in the Doc1
44
+ instead of the Main group
22
45
  - Updated Sony decoding for ILCE-1M2 (thanks Jos Roost)
23
46
 
24
47
  Feb. 3, 2025 - Version 13.18
data/bin/MANIFEST CHANGED
@@ -211,6 +211,11 @@ html/install.html
211
211
  html/metafiles.html
212
212
  html/mistakes.html
213
213
  html/overview.png
214
+ html/plot.html
215
+ html/plot1.svg
216
+ html/plot2.svg
217
+ html/plot3.svg
218
+ html/plot4.svg
214
219
  html/standards.html
215
220
  html/struct.html
216
221
  html/style.css
@@ -398,6 +403,7 @@ lib/Image/ExifTool/PhaseOne.pm
398
403
  lib/Image/ExifTool/PhotoCD.pm
399
404
  lib/Image/ExifTool/PhotoMechanic.pm
400
405
  lib/Image/ExifTool/Photoshop.pm
406
+ lib/Image/ExifTool/Plot.pm
401
407
  lib/Image/ExifTool/PostScript.pm
402
408
  lib/Image/ExifTool/PrintIM.pm
403
409
  lib/Image/ExifTool/Protobuf.pm
data/bin/META.json CHANGED
@@ -50,5 +50,5 @@
50
50
  }
51
51
  },
52
52
  "release_status" : "stable",
53
- "version" : "13.19"
53
+ "version" : "13.21"
54
54
  }
data/bin/META.yml CHANGED
@@ -31,4 +31,4 @@ recommends:
31
31
  Time::HiRes: '0'
32
32
  requires:
33
33
  perl: '5.004'
34
- version: '13.19'
34
+ version: '13.21'
data/bin/README CHANGED
@@ -109,8 +109,8 @@ your home directory, then you would type the following commands in a
109
109
  terminal window to extract and run ExifTool:
110
110
 
111
111
  cd ~/Desktop
112
- gzip -dc Image-ExifTool-13.19.tar.gz | tar -xf -
113
- cd Image-ExifTool-13.19
112
+ gzip -dc Image-ExifTool-13.21.tar.gz | tar -xf -
113
+ cd Image-ExifTool-13.21
114
114
  ./exiftool t/images/ExifTool.jpg
115
115
 
116
116
  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 = '13.19';
14
+ my $version = '13.21';
15
15
 
16
16
  # add our 'lib' directory to the include list BEFORE 'use Image::ExifTool'
17
17
  my $exePath;
@@ -52,7 +52,7 @@ sub EncodeXML($);
52
52
  sub FormatXML($$$);
53
53
  sub EscapeJSON($;$);
54
54
  sub FormatJSON($$$;$);
55
- sub PrintCSV();
55
+ sub PrintCSV(;$);
56
56
  sub AddGroups($$$$);
57
57
  sub ConvertBinary($);
58
58
  sub IsEqual($$);
@@ -189,6 +189,7 @@ my $outFormat; # -1=Canon format, 0=same-line, 1=tag names, 2=values only
189
189
  my $outOpt; # output file or directory name
190
190
  my $overwriteOrig; # flag to overwrite original file (1=overwrite, 2=in place)
191
191
  my $pause; # pause before returning
192
+ my $plot; # flag for plot output format
192
193
  my $preserveTime; # flag to preserve times of updated files (2=preserve FileCreateDate only)
193
194
  my $progress; # flag to calculate total files to process (0=calculate but don't display)
194
195
  my $progressCount; # count of files processed
@@ -216,6 +217,7 @@ my $structOpt; # output structured XMP information (JSON and XML output onl
216
217
  my $tabFormat; # non-zero for tab output format
217
218
  my $tagOut; # flag for separate text output file for each tag
218
219
  my $textOut; # extension for text output file (or undef for no output)
220
+ my $textOut2; # complete file name for single text output file
219
221
  my $textOverwrite; # flag to overwrite existing text output file (2=append, 3=over+append)
220
222
  my $tmpFile; # temporary file to delete on exit
221
223
  my $tmpText; # temporary text file
@@ -459,8 +461,8 @@ undef %filterExt;
459
461
  undef %ignore;
460
462
  undef %outComma;
461
463
  undef %outTrailer;
462
- undef %printFmt;
463
464
  undef %preserveTime;
465
+ undef %printFmt;
464
466
  undef %seqFileDir;
465
467
  undef %setTags;
466
468
  undef %setTagsList;
@@ -1176,6 +1178,7 @@ for (;;) {
1176
1178
  }
1177
1179
  /^overwrite_original$/i and $overwriteOrig = 1, next;
1178
1180
  /^overwrite_original_in_place$/i and $overwriteOrig = 2, next;
1181
+ /^plot$/i and require Image::ExifTool::Plot and $plot = Image::ExifTool::Plot->new, next;
1179
1182
  if (/^p(-?)$/ or /^printformat(-?)$/i) {
1180
1183
  my $fmt = shift;
1181
1184
  if ($pass) {
@@ -1466,15 +1469,10 @@ if (not @files and not $outOpt and not @newValues) {
1466
1469
  # print help
1467
1470
  unless ((@tags and not $outOpt) or @files or @newValues or $geoOnly) {
1468
1471
  if ($doGlob and $doGlob == 2) {
1469
- Warn "No matching files\n";
1470
- $rtnVal = 1;
1471
- next;
1472
- }
1473
- if ($outOpt) {
1474
- Warn "Nothing to write\n";
1475
- $rtnVal = 1;
1472
+ Error "No matching files\n";
1476
1473
  next;
1477
1474
  }
1475
+ $outOpt and Error("Nothing to write\n"), next;
1478
1476
  unless ($helped) {
1479
1477
  # catch warnings if we have problems running perldoc
1480
1478
  local $SIG{'__WARN__'} = sub { $evalWarning = $_[0] };
@@ -1499,38 +1497,34 @@ unless ((@tags and not $outOpt) or @files or @newValues or $geoOnly) {
1499
1497
  if (defined $deleteOrig and (@newValues or @tags)) {
1500
1498
  if (not @newValues) {
1501
1499
  my $verb = $deleteOrig ? 'deleting' : 'restoring from';
1502
- Warn "Can't specify tags when $verb originals\n";
1500
+ Error "Can't specify tags when $verb originals\n";
1503
1501
  } elsif ($deleteOrig) {
1504
- Warn "Can't use -delete_original when writing.\n";
1505
- Warn "Maybe you meant -overwrite_original ?\n";
1502
+ Error "Can't use -delete_original when writing.\n";
1503
+ Error "Maybe you meant -overwrite_original ?\n";
1506
1504
  } else {
1507
- Warn "It makes no sense to use -restore_original when writing\n";
1505
+ Error "It makes no sense to use -restore_original when writing\n";
1508
1506
  }
1509
- $rtnVal = 1;
1510
1507
  next;
1511
1508
  }
1512
1509
 
1513
1510
  if ($overwriteOrig > 1 and $outOpt) {
1514
- Warn "Can't overwrite in place when -o option is used\n";
1515
- $rtnVal = 1;
1511
+ Error "Can't overwrite in place when -o option is used\n";
1516
1512
  next;
1517
1513
  }
1518
1514
 
1519
- if (($tagOut or defined $diff) and ($csv or $json or %printFmt or $tabFormat or $xml or
1515
+ if (($tagOut or defined $diff) and ($csv or $json or %printFmt or $tabFormat or $xml or $plot or
1520
1516
  ($verbose and $html)))
1521
1517
  {
1522
1518
  my $opt = $tagOut ? '-W' : '-diff';
1523
- Warn "Sorry, $opt may not be combined with -csv, -htmlDump, -j, -p, -t or -X\n";
1524
- $rtnVal = 1;
1519
+ Error "Sorry, $opt may not be combined with -csv, -htmlDump, -j, -p, -t or -X\n";
1525
1520
  next;
1526
1521
  }
1527
1522
 
1528
1523
  if ($csv and $csv eq 'CSV' and not $isWriting) {
1529
1524
  $json = 0; # (not compatible)
1530
1525
  if ($textOut) {
1531
- Warn "Sorry, -w may not be combined with -csv\n";
1532
- $rtnVal = 1;
1533
- next;
1526
+ $textOut2 = $textOut;
1527
+ undef $textOut;
1534
1528
  }
1535
1529
  if ($binaryOutput) {
1536
1530
  $binaryOutput = 0;
@@ -1542,6 +1536,31 @@ if ($csv and $csv eq 'CSV' and not $isWriting) {
1542
1536
  }
1543
1537
  require Image::ExifTool::XMP if $setCharset;
1544
1538
  }
1539
+ if ($plot and $textOut) {
1540
+ $textOut2 = $textOut;
1541
+ undef $textOut;
1542
+ }
1543
+ if ($textOut2) {
1544
+ if ($textOverwrite > 1) {
1545
+ Error "Can not append to multi-file output format\n";
1546
+ undef $textOut2;
1547
+ next;
1548
+ }
1549
+ if (not $textOverwrite and $mt->Exists($textOut2, 1)) {
1550
+ Error "Output file $textOut2 already exists\n";
1551
+ undef $textOut2;
1552
+ next;
1553
+ }
1554
+ CreateDirectory($textOut2); # create directory if necessary
1555
+ if ($mt->Open(\*OUTFILE, $textOut2, '>')) {
1556
+ $tmpText = $textOut2; # delete if command aborted
1557
+ $textOut2 = \*OUTFILE;
1558
+ } else {
1559
+ Error("Error creating $textOut2\n");
1560
+ undef $textOut2;
1561
+ next;
1562
+ }
1563
+ }
1545
1564
 
1546
1565
  if ($escapeHTML or $json) {
1547
1566
  # must be UTF8 for HTML conversion and JSON output
@@ -1555,7 +1574,7 @@ if ($escapeHTML or $json) {
1555
1574
  # set sort option
1556
1575
  if ($sortOpt) {
1557
1576
  # (note that -csv sorts alphabetically by default anyway if more than 1 file)
1558
- my $sort = ($outFormat > 0 or $xml or $json or $csv) ? 'Tag' : 'Descr';
1577
+ my $sort = ($outFormat > 0 or $xml or $json or $csv or $plot) ? 'Tag' : 'Descr';
1559
1578
  $mt->Options(Sort => $sort, Sort2 => $sort);
1560
1579
  }
1561
1580
 
@@ -1566,7 +1585,11 @@ if ($mt->Options('Struct') and not $structOpt) {
1566
1585
  }
1567
1586
 
1568
1587
  # set up for RDF/XML, JSON and PHP output formats
1569
- if ($xml) {
1588
+ if ($plot) {
1589
+ undef $joinLists;
1590
+ $mt->Options(List => 1);
1591
+ $plot->Settings($mt->Options('Plot'));
1592
+ } elsif ($xml) {
1570
1593
  require Image::ExifTool::XMP; # for EscapeXML()
1571
1594
  my $charset = $mt->Options('Charset');
1572
1595
  # standard XML encoding names for supported Charset settings
@@ -1638,11 +1661,10 @@ if (Image::ExifTool::IsPC()) {
1638
1661
  unless (@files) {
1639
1662
  unless ($outOpt) {
1640
1663
  if ($doGlob and $doGlob == 2) {
1641
- Warn "No matching files\n";
1664
+ Error "No matching files\n";
1642
1665
  } else {
1643
- Warn "No file specified\n";
1666
+ Error "No file specified\n";
1644
1667
  }
1645
- $rtnVal = 1;
1646
1668
  next;
1647
1669
  }
1648
1670
  push @files, ''; # create file from nothing
@@ -1705,8 +1727,7 @@ if (@newValues) {
1705
1727
  next; # set tags from dynamic file later
1706
1728
  }
1707
1729
  unless ($mt->Exists($newVal) or $newVal eq '-') {
1708
- Warn "File '${newVal}' does not exist for -tagsFromFile option\n";
1709
- $rtnVal = 1;
1730
+ Error "File '${newVal}' does not exist for -tagsFromFile option\n";
1710
1731
  next Command;
1711
1732
  }
1712
1733
  my $setTags = $setTags{$newVal};
@@ -1770,19 +1791,20 @@ if (@newValues) {
1770
1791
  }
1771
1792
  }
1772
1793
  unless ($isWriting or $outOpt or @tags) {
1773
- Warn "Nothing to do.\n";
1774
- $rtnVal = 1;
1794
+ Error "Nothing to do.\n";
1775
1795
  next;
1776
1796
  }
1777
1797
  } elsif (grep /^(\*:)?\*$/, @exclude) {
1778
- Warn "All tags excluded -- nothing to do.\n";
1779
- $rtnVal = 1;
1798
+ Error "All tags excluded -- nothing to do.\n";
1780
1799
  next;
1781
1800
  }
1782
1801
  if ($isWriting) {
1783
1802
  if (defined $diff) {
1784
1803
  Error "Can't use -diff option when writing tags\n";
1785
1804
  next;
1805
+ } elsif ($plot) {
1806
+ Error "Can't use -plot option when writing tags\n";
1807
+ next;
1786
1808
  } elsif (@tags and not $outOpt and not $csv) {
1787
1809
  my ($tg, $s) = @tags > 1 ? ("$tags[0] ...", 's') : ($tags[0], '');
1788
1810
  Warn "Ignored superfluous tag name$s or invalid option$s: -$tg\n";
@@ -1931,9 +1953,6 @@ ProcessFiles($mt);
1931
1953
 
1932
1954
  Error "No file with specified extension\n" if $filtered and not $validFile;
1933
1955
 
1934
- # print CSV information if necessary
1935
- PrintCSV() if $csv and not $isWriting;
1936
-
1937
1956
  # print folder/file trailer if necessary
1938
1957
  if ($textOut) {
1939
1958
  foreach (keys %outTrailer) {
@@ -1949,6 +1968,28 @@ if ($textOut) {
1949
1968
  } else {
1950
1969
  print $sectTrailer if $sectTrailer;
1951
1970
  print $fileTrailer if $fileTrailer and not $fileHeader;
1971
+ # print CSV information if necessary
1972
+ my $err;
1973
+ PrintCSV($textOut2) if $csv and not $isWriting;
1974
+ # print SVG plot
1975
+ if ($plot) {
1976
+ $plot->Draw($textOut2 || \*STDOUT);
1977
+ if ($$plot{Error}) {
1978
+ Error("Error: $$plot{Error}\n");
1979
+ $err = 1;
1980
+ } elsif ($$plot{Warn}) {
1981
+ Warn("Warning: $$plot{Warn}\n");
1982
+ }
1983
+ }
1984
+ if ($textOut2) {
1985
+ close($textOut2) or $err = 1;
1986
+ if ($err) {
1987
+ $mt->Unlink($tmpText);
1988
+ } else {
1989
+ $created{$textOut2} = 1;
1990
+ }
1991
+ undef $tmpText;
1992
+ }
1952
1993
  }
1953
1994
 
1954
1995
  my $totWr = $countGoodWr + $countBadWr + $countSameWr + $countCopyWr +
@@ -1993,7 +2034,7 @@ if (defined $deleteOrig) {
1993
2034
  # print summary
1994
2035
  my $tot = $count + $countBad;
1995
2036
  if ($countDir or $totWr or $countFailed or $tot > 1 or $textOut or %countLink) {
1996
- my $o = (($html or $json or $xml or %printFmt or $csv) and not $textOut) ? \*STDERR : $vout;
2037
+ my $o = (($html or $json or $xml or %printFmt or $csv or $plot) and not $textOut) ? \*STDERR : $vout;
1997
2038
  printf($o "%5d directories scanned\n", $countDir) if $countDir;
1998
2039
  printf($o "%5d directories created\n", $countNewDir) if $countNewDir;
1999
2040
  printf($o "%5d files failed condition\n", $countFailed) if $countFailed;
@@ -2005,7 +2046,7 @@ if (defined $deleteOrig) {
2005
2046
  printf($o "%5d files weren't created due to errors\n", $countBadCr) if $countBadCr;
2006
2047
  printf($o "%5d image files read\n", $count) if ($tot+$countFailed)>1 or ($countDir and not $totWr);
2007
2048
  printf($o "%5d files could not be read\n", $countBad) if $countBad;
2008
- printf($o "%5d output files created\n", scalar(keys %created)) if $textOut;
2049
+ printf($o "%5d output files created\n", scalar(keys %created)) if $textOut or $textOut2;
2009
2050
  printf($o "%5d output files appended\n", scalar(keys %appended)) if %appended;
2010
2051
  printf($o "%5d hard links created\n", $countLink{Hard} || 0) if $countLink{Hard} or $countLink{BadHard};
2011
2052
  printf($o "%5d hard links could not be created\n", $countLink{BadHard}) if $countLink{BadHard};
@@ -2210,7 +2251,7 @@ sub GetImageInfo($$)
2210
2251
 
2211
2252
  my $lineCount = 0;
2212
2253
  my ($fp, $outfile, $append);
2213
- if ($textOut and ($verbose or $et->Options('PrintCSV')) and not ($tagOut or defined $diff)) {
2254
+ if ($textOut and ($verbose or $et->Options('PrintCSV')) and not ($tagOut or defined $diff or $plot)) {
2214
2255
  ($fp, $outfile, $append) = OpenOutputFile($orig);
2215
2256
  $fp or EFile($file), ++$countBad, return;
2216
2257
  # delete file if we exit prematurely (unless appending)
@@ -2250,7 +2291,7 @@ sub GetImageInfo($$)
2250
2291
  }
2251
2292
  # print file/progress message
2252
2293
  my $o;
2253
- unless ($binaryOutput or $textOut or %printFmt or $html > 1 or $csv) {
2294
+ unless ($binaryOutput or $textOut or %printFmt or $html > 1 or $csv or $plot) {
2254
2295
  if ($html) {
2255
2296
  require Image::ExifTool::HTML;
2256
2297
  my $f = Image::ExifTool::HTML::EscapeHTML($file);
@@ -2353,7 +2394,7 @@ sub GetImageInfo($$)
2353
2394
  unless (defined $outfile or $tagOut) {
2354
2395
  ($fp, $outfile, $append) = OpenOutputFile($orig);
2355
2396
  $fp or EFile($file), ++$countBad, return;
2356
- $tmpText = $outfile unless $append;
2397
+ $tmpText = $outfile if defined $outfile and not $append;
2357
2398
  }
2358
2399
 
2359
2400
  # print differences if requested
@@ -2464,9 +2505,8 @@ T2: foreach $t2 (@tags2) {
2464
2505
  $done2{$tag2} = 1 if defined $tag2;
2465
2506
  }
2466
2507
  print $fp "(no metadata differences)\n" unless $wasDiff;
2467
- undef $tmpText;
2468
2508
  if (defined $outfile) {
2469
- ++$created{$outfile};
2509
+ $created{$outfile} = 1;
2470
2510
  close($fp);
2471
2511
  undef $tmpText;
2472
2512
  }
@@ -2541,6 +2581,17 @@ T2: foreach $t2 (@tags2) {
2541
2581
  delete $printFmt{HEAD} unless defined $outfile; # print header only once per output file
2542
2582
  my $errs = $et->GetInfo('Warning', 'Error');
2543
2583
  PrintErrors($et, $errs, $file) and EFile($file);
2584
+ } elsif ($plot) {
2585
+ # add points from this file to the plot
2586
+ my $tagExtra = $$et{TAG_EXTRA};
2587
+ my ($tag, %docNum);
2588
+ foreach $tag (keys %$info) {
2589
+ next unless $$tagExtra{$tag} and $$tagExtra{$tag}{G3};
2590
+ $docNum{$tag} = $1 if $$tagExtra{$tag}{G3} =~ /(\d+)/;
2591
+ }
2592
+ $$plot{DocNum} = \%docNum;
2593
+ $$plot{EE} = 1 if $et->Options('ExtractEmbedded');
2594
+ $plot->AddPoints($info, \@foundTags);
2544
2595
  } elsif (not $disableOutput) {
2545
2596
  my ($tag, $line, %noDups, %csvInfo, $bra, $ket, $sep, $quote);
2546
2597
  if ($fp) {
@@ -3773,8 +3824,10 @@ sub FormatCSV($)
3773
3824
 
3774
3825
  #------------------------------------------------------------------------------
3775
3826
  # Print accumulated CSV information
3776
- sub PrintCSV()
3827
+ # Inputs: 0) file ref
3828
+ sub PrintCSV(;$)
3777
3829
  {
3830
+ my $fp = shift || \*STDOUT;
3778
3831
  my ($file, $lcTag, @tags);
3779
3832
 
3780
3833
  @csvTags or @csvTags = sort keys %csvTags;
@@ -3782,7 +3835,7 @@ sub PrintCSV()
3782
3835
  foreach $lcTag (@csvTags) {
3783
3836
  push @tags, FormatCSV($csvTags{$lcTag}) if $csvTags{$lcTag};
3784
3837
  }
3785
- print join($csvDelim, 'SourceFile', @tags), "\n";
3838
+ print $fp join($csvDelim, 'SourceFile', @tags), "\n";
3786
3839
  my $empty = defined($forcePrint) ? $forcePrint : '';
3787
3840
  foreach $file (@csvFiles) {
3788
3841
  my @vals = (FormatCSV($file)); # start with full file name
@@ -3793,7 +3846,7 @@ sub PrintCSV()
3793
3846
  defined $val or push(@vals,$empty), next;
3794
3847
  push @vals, FormatCSV($val);
3795
3848
  }
3796
- print join($csvDelim, @vals), "\n";
3849
+ print $fp join($csvDelim, @vals), "\n";
3797
3850
  }
3798
3851
  }
3799
3852
 
@@ -4127,9 +4180,8 @@ sub ProcessFiles($;$)
4127
4180
  $filtered = 1;
4128
4181
  Progress($vout, "-------- $file (wrong extension)") if $verbose;
4129
4182
  } else {
4130
- Warn "Error: File not found - $file\n";
4183
+ Error "Error: File not found - $file\n";
4131
4184
  FileNotFound($file);
4132
- $rtnVal = 1;
4133
4185
  }
4134
4186
  } else {
4135
4187
  $validFile = 1;
@@ -5102,6 +5154,7 @@ L<Input-output text formatting|/Input-output text formatting>
5102
5154
  -n (--printConv) No print conversion
5103
5155
  -p[-] STR (-printFormat) Print output in specified format
5104
5156
  -php Export tags as a PHP Array
5157
+ -plot Output tags as SVG plot file
5105
5158
  -s[NUM] (-short) Short output format (-s for tag names)
5106
5159
  -S (-veryShort) Very short output format
5107
5160
  -sep STR (-separator) Set separator string for list items
@@ -5680,14 +5733,16 @@ option may be used to split them back into separate items when importing.
5680
5733
  Special feature: B<-csv>+=I<CSVFILE> may be used to add items to existing
5681
5734
  lists. This affects only list-type tags. Also applies to the B<-j> option.
5682
5735
 
5683
- Note that this option is fundamentally different than all other output
5684
- format options because it requires information from all input files to be
5685
- buffered in memory before the output is written. This may result in
5686
- excessive memory usage when processing a very large number of files with a
5687
- single command. Also, it makes this option incompatible with the B<-w> and
5688
- B<-W> options. When processing a large number of files, it is recommended
5689
- to either use the JSON (B<-j>) or XML (B<-X>) output format, or use B<-p> to
5690
- generate a fixed-column CSV file instead of using the B<-csv> option.
5736
+ Note that this and the B<-plot> options are fundamentally different than all
5737
+ other output format options because they require information from all input
5738
+ files to be buffered in memory before the output is written. This may
5739
+ result in excessive memory usage when processing a very large number of
5740
+ files with a single command. Also, when used with B<-csv>, the B<-w> option
5741
+ changes to specify a complete file name with no filename formatting codes or
5742
+ append mode allowed, and B<-W> may not be used. When processing a large
5743
+ number of files, it is recommended to either use the JSON (B<-j>) or XML
5744
+ (B<-X>) output format, or use B<-p> to generate a fixed-column CSV file
5745
+ instead of using the B<-csv> option.
5691
5746
 
5692
5747
  =item B<-csvDelim> I<STR>
5693
5748
 
@@ -5986,7 +6041,7 @@ with this command:
5986
6041
 
5987
6042
  produces output like this:
5988
6043
 
5989
- -- Generated by ExifTool 13.19 --
6044
+ -- Generated by ExifTool 13.21 --
5990
6045
  File: a.jpg - 2003:10:31 15:44:19
5991
6046
  (f/5.6, 1/60s, ISO 100)
5992
6047
  File: b.jpg - 2006:05:23 11:57:38
@@ -6035,6 +6090,21 @@ showing how this could be used in a PHP script:
6035
6090
  print_r($array);
6036
6091
  ?>
6037
6092
 
6093
+ =item B<-plot>
6094
+
6095
+ Write output for all specified tags and all input files as a single
6096
+ SVG-formatted plot. When combined with this feature, the B<-w> option
6097
+ argument is a complete file name with no format codes and the append feature
6098
+ may not be used. Each tag specified on the command line represents a
6099
+ dataset in the plot (or more for array values or if the Split plot setting
6100
+ is used). Non-numerical values are ignored. Each input file may contribute
6101
+ multiple points to a dataset if it contains sub-documents and the B<-ee>
6102
+ option is used, or if the tag value is a delimited string of numbers (valid
6103
+ delimiters are: space, comma, semicolon, tab and newline). Line, Scatter
6104
+ and Histogram plot types are available. See the API Plot Option and
6105
+ L<https://exiftool.org/plot.html> for more details and information about the
6106
+ plot settings.
6107
+
6038
6108
  =item B<-s>[I<NUM>] (B<-short>)
6039
6109
 
6040
6110
  Short output format. Prints tag names instead of descriptions. Add I<NUM>
@@ -6172,6 +6242,10 @@ ways to create a single output file from multiple source files:
6172
6242
  # 3. With the -W option (see the -W option below)
6173
6243
  exiftool -W+! out.txt FILE1 FILE2 ...
6174
6244
 
6245
+ 3) The B<-w> option changes when used with a multi-file output format
6246
+ (B<-csv> or B<-plot>). With these, the argument of B<-w> is a complete file
6247
+ name with no formatting codes, and the append feature may not be used.
6248
+
6175
6249
  Advanced features:
6176
6250
 
6177
6251
  A substring of the original file name, directory or extension may be taken
@@ -6460,13 +6534,13 @@ across directory boundaries if multiple input directories are specified.
6460
6534
  =item B<-i> I<DIR> (B<-ignore>)
6461
6535
 
6462
6536
  Ignore specified directory name. I<DIR> may be either an individual folder
6463
- name, or a full path. If a full path is specified, it must match the
6464
- Directory tag exactly to be ignored. Use multiple B<-i> options to ignore
6465
- more than one directory name. A special I<DIR> value of C<SYMLINKS> (case
6466
- sensitive) may be specified to avoid recursing into directories which are
6537
+ name, or a full path, and is case sensitive. If a full path is specified,
6538
+ it must match the Directory tag exactly to be ignored. Use multiple B<-i>
6539
+ options to ignore more than one directory name. A special I<DIR> value of
6540
+ C<SYMLINKS> may be specified to avoid recursing into directories which are
6467
6541
  symbolic links when the B<-r> option is used. As well, a value of C<HIDDEN>
6468
- (case sensitive) may be used to ignore files with names that start with a
6469
- "." (ie. hidden files on Unix systems) when scanning a directory.
6542
+ may be used to ignore files with names that start with a "." (ie. hidden
6543
+ files on Unix systems) when scanning a directory.
6470
6544
 
6471
6545
  =item B<-if>[I<NUM>] I<EXPR>
6472
6546