exiftool_vendored 12.97.0 → 12.99.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 +4 -4
- data/bin/Changes +28 -1
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +2 -2
- data/bin/config_files/example.config +2 -1
- data/bin/exiftool +235 -45
- data/bin/lib/File/RandomAccess.pm +5 -2
- data/bin/lib/Image/ExifTool/APP12.pm +3 -2
- data/bin/lib/Image/ExifTool/Canon.pm +2 -1
- data/bin/lib/Image/ExifTool/Import.pm +7 -3
- data/bin/lib/Image/ExifTool/InDesign.pm +4 -3
- data/bin/lib/Image/ExifTool/JSON.pm +3 -4
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +2 -1
- data/bin/lib/Image/ExifTool/Lytro.pm +2 -2
- data/bin/lib/Image/ExifTool/M2TS.pm +8 -0
- data/bin/lib/Image/ExifTool/QuickTime.pm +17 -6
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +19 -2
- data/bin/lib/Image/ExifTool/Sony.pm +6 -1
- data/bin/lib/Image/ExifTool/TagLookup.pm +3 -1
- data/bin/lib/Image/ExifTool/TagNames.pod +8 -6
- data/bin/lib/Image/ExifTool/WritePDF.pl +47 -21
- data/bin/lib/Image/ExifTool/WriteXMP.pl +16 -4
- data/bin/lib/Image/ExifTool/Writer.pl +16 -6
- data/bin/lib/Image/ExifTool/XMP.pm +8 -3
- data/bin/lib/Image/ExifTool/XMPStruct.pl +15 -7
- data/bin/lib/Image/ExifTool.pm +34 -9
- data/bin/lib/Image/ExifTool.pod +31 -8
- data/bin/perl-Image-ExifTool.spec +1 -1
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 857ae11921e86ed35a6ca857a912acf876501c139db5e5646b08ebab6a30d02c
|
|
4
|
+
data.tar.gz: 27bb568a8097d27f5519718fc010df5acddc3976d465bb872492f4bb29f03e7f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a60c7457c7f88cff4e5f7c78c95463f9f04961ccb67e318518c0b5d86fb9782f043dc422155e33e7309f6e1db3567545d5aab6a597c764f40ec642dde0973c10
|
|
7
|
+
data.tar.gz: e97a2b5852aa0fd3b8debe38ff11abe65c3850a681526cb40aa65e03dafabcdc0560371b544218918a32221a314b08c5fd0041184a5dcfe7b8f76ad26f9ea537
|
data/bin/Changes
CHANGED
|
@@ -7,6 +7,33 @@ RSS feed: https://exiftool.org/rss.xml
|
|
|
7
7
|
Note: The most recent production release is Version 12.76. (Other versions are
|
|
8
8
|
considered development releases, and are not uploaded to MetaCPAN.)
|
|
9
9
|
|
|
10
|
+
Oct. 18, 2024 - Version 12.99
|
|
11
|
+
|
|
12
|
+
- Added -diff option to compare the metadata in two files
|
|
13
|
+
- Added a new Canon lens (thanks Norbert Wasser)
|
|
14
|
+
- Decode GPS from 70mai A810 dashcam videos
|
|
15
|
+
- Decode a new QuickTime tag
|
|
16
|
+
- Patched to recognize C2PA APP11 JUMBF header with incorrect byte order
|
|
17
|
+
written by buggy Microsoft software
|
|
18
|
+
- Patched to maintain order of entries in a JSON object when reading
|
|
19
|
+
- Patched to maintain order of CSV columns when setting tags from a CSV file
|
|
20
|
+
- Patched to maintain order of XMP lang-alt entries when writing/copying
|
|
21
|
+
- Fixed typo in an APP12 tag name
|
|
22
|
+
- API Changes:
|
|
23
|
+
- Structured values returned as HASH references with the Struct option may
|
|
24
|
+
contain a new "_ordered_keys_" entry used to preserve the order of the
|
|
25
|
+
entries
|
|
26
|
+
- Added the OrderedKeys method to
|
|
27
|
+
return the ordered or sorted keys from a returned structure value
|
|
28
|
+
|
|
29
|
+
Oct. 8, 2024 - Version 12.98
|
|
30
|
+
|
|
31
|
+
- Added write support for PDF files with huge offsets
|
|
32
|
+
- Added a number of new Sony LensType values (thanks Jos Roost)
|
|
33
|
+
- Require -v4 or higher to output "JPG RST" lines
|
|
34
|
+
- Patched problem with -fast option when reading HEIC file via a pipe
|
|
35
|
+
- Patched to avoid hang when reading some corrupted XMP
|
|
36
|
+
|
|
10
37
|
Sept. 25, 2024 - Version 12.97
|
|
11
38
|
|
|
12
39
|
- Added ability to ignore up to 4095 bytes of garbage at the end of an INDD
|
|
@@ -143,7 +170,7 @@ June 7, 2024 - Version 12.86
|
|
|
143
170
|
- Patched some Olympus WB_RBLevels tags to allow 4 values to be written as per
|
|
144
171
|
some newer models
|
|
145
172
|
- Fixed issue when writing IPTC date tags with a date/time value containing
|
|
146
|
-
subseconds with 4 or more digits
|
|
173
|
+
subseconds with 4 or more digits
|
|
147
174
|
|
|
148
175
|
May 21, 2024 - Version 12.85
|
|
149
176
|
|
data/bin/META.json
CHANGED
data/bin/META.yml
CHANGED
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-12.
|
|
113
|
-
cd Image-ExifTool-12.
|
|
112
|
+
gzip -dc Image-ExifTool-12.99.tar.gz | tar -xf -
|
|
113
|
+
cd Image-ExifTool-12.99
|
|
114
114
|
./exiftool t/images/ExifTool.jpg
|
|
115
115
|
|
|
116
116
|
Note: These commands extract meta information from one of the test images.
|
|
@@ -82,7 +82,8 @@
|
|
|
82
82
|
},
|
|
83
83
|
# add more user-defined EXIF tags here...
|
|
84
84
|
},
|
|
85
|
-
# the Geotag feature writes
|
|
85
|
+
# the Geotag feature writes GPSPitch and GPSRoll tags, but these
|
|
86
|
+
# aren't standard EXIF so we define custom tags here:
|
|
86
87
|
'Image::ExifTool::GPS::Main' => {
|
|
87
88
|
# Example 2. GPS:GPSPitch
|
|
88
89
|
0xd000 => {
|
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.
|
|
14
|
+
my $version = '12.99';
|
|
15
15
|
|
|
16
16
|
# add our 'lib' directory to the include list BEFORE 'use Image::ExifTool'
|
|
17
17
|
my $exePath;
|
|
@@ -56,6 +56,8 @@ sub PrintCSV();
|
|
|
56
56
|
sub AddGroups($$$$);
|
|
57
57
|
sub ConvertBinary($);
|
|
58
58
|
sub IsEqual($$);
|
|
59
|
+
sub Printable($);
|
|
60
|
+
sub LengthUTF8($);
|
|
59
61
|
sub Infile($;$);
|
|
60
62
|
sub AddSetTagsFile($;$);
|
|
61
63
|
sub Warning($$);
|
|
@@ -150,6 +152,7 @@ my $csvAdd; # flag to add CSV information to existing lists
|
|
|
150
152
|
my $csvDelim; # delimiter for CSV files
|
|
151
153
|
my $csvSaveCount; # save counter for last CSV file loaded
|
|
152
154
|
my $deleteOrig; # 0=restore original files, 1=delete originals, 2=delete w/o asking
|
|
155
|
+
my $diff; # file name for comparing differences
|
|
153
156
|
my $disableOutput; # flag to disable normal output
|
|
154
157
|
my $doSetFileName; # flag set if FileName may be written
|
|
155
158
|
my $doUnzip; # flag to extract info from .gz and .bz2 files
|
|
@@ -256,11 +259,13 @@ my %optArgs = (
|
|
|
256
259
|
'-csvdelim' => 1,
|
|
257
260
|
'-d' => 1, '-dateformat' => 1,
|
|
258
261
|
'-D' => 0, # necessary to avoid matching lower-case equivalent
|
|
262
|
+
'-diff' => 1,
|
|
259
263
|
'-echo' => 1, '-echo#' => 1,
|
|
260
264
|
'-efile' => 1, '-efile#' => 1, '-efile!' => 1, '-efile#!' => 1,
|
|
261
265
|
'-ext' => 1, '--ext' => 1, '-ext+' => 1, '--ext+' => 1,
|
|
262
266
|
'-extension' => 1, '--extension' => 1, '-extension+' => 1, '--extension+' => 1,
|
|
263
267
|
'-fileorder' => 1, '-fileorder#' => 1,
|
|
268
|
+
'-file#' => 1,
|
|
264
269
|
'-geotag' => 1,
|
|
265
270
|
'-globaltimeshift' => 1,
|
|
266
271
|
'-i' => 1, '-ignore' => 1,
|
|
@@ -332,7 +337,7 @@ sub Exit {
|
|
|
332
337
|
exit shift;
|
|
333
338
|
}
|
|
334
339
|
# my warning and error routines (NEVER say "die"!)
|
|
335
|
-
sub Warn
|
|
340
|
+
sub Warn {
|
|
336
341
|
if ($quiet < 2 or $_[0] =~ /^Error/) {
|
|
337
342
|
my $oldWarn = $SIG{'__WARN__'};
|
|
338
343
|
delete $SIG{'__WARN__'};
|
|
@@ -472,6 +477,7 @@ undef $comma;
|
|
|
472
477
|
undef $csv;
|
|
473
478
|
undef $csvAdd;
|
|
474
479
|
undef $deleteOrig;
|
|
480
|
+
undef $diff;
|
|
475
481
|
undef $disableOutput;
|
|
476
482
|
undef $doSetFileName;
|
|
477
483
|
undef $doUnzip;
|
|
@@ -943,6 +949,11 @@ for (;;) {
|
|
|
943
949
|
next;
|
|
944
950
|
}
|
|
945
951
|
(/^D$/ or $a eq 'decimal') and $showTagID = 'D', next;
|
|
952
|
+
if (/^diff$/i) {
|
|
953
|
+
$diff = shift;
|
|
954
|
+
defined $diff or Error("Expecting file name for -$_ option\n"), $badCmd=1;
|
|
955
|
+
next;
|
|
956
|
+
}
|
|
946
957
|
/^delete_original(!?)$/i and $deleteOrig = ($1 ? 2 : 1), next;
|
|
947
958
|
/^list_dir$/i and $listDir = 1, next;
|
|
948
959
|
(/^e$/ or $a eq '-composite') and $mt->Options(Composite => 0), next;
|
|
@@ -1501,8 +1512,11 @@ if ($overwriteOrig > 1 and $outOpt) {
|
|
|
1501
1512
|
next;
|
|
1502
1513
|
}
|
|
1503
1514
|
|
|
1504
|
-
if ($tagOut and ($csv or %printFmt or $tabFormat or $xml or
|
|
1505
|
-
|
|
1515
|
+
if (($tagOut or defined $diff) and ($csv or $json or %printFmt or $tabFormat or $xml or
|
|
1516
|
+
($verbose and $html)))
|
|
1517
|
+
{
|
|
1518
|
+
my $opt = $tagOut ? '-W' : '-diff';
|
|
1519
|
+
Warn "Sorry, $opt may not be combined with -csv, -htmlDump, -j, -p, -t or -X\n";
|
|
1506
1520
|
$rtnVal = 1;
|
|
1507
1521
|
next;
|
|
1508
1522
|
}
|
|
@@ -1757,9 +1771,14 @@ if (@newValues) {
|
|
|
1757
1771
|
$rtnVal = 1;
|
|
1758
1772
|
next;
|
|
1759
1773
|
}
|
|
1760
|
-
if ($isWriting
|
|
1761
|
-
|
|
1762
|
-
|
|
1774
|
+
if ($isWriting) {
|
|
1775
|
+
if (defined $diff) {
|
|
1776
|
+
Error "Can't use -diff option when writing tags\n";
|
|
1777
|
+
next;
|
|
1778
|
+
} elsif (@tags and not $outOpt) {
|
|
1779
|
+
my ($tg, $s) = @tags > 1 ? ("$tags[0] ...", 's') : ($tags[0], '');
|
|
1780
|
+
Warn "Ignored superfluous tag name$s or invalid option$s: -$tg\n";
|
|
1781
|
+
}
|
|
1763
1782
|
}
|
|
1764
1783
|
# save current state of new values if setting values from target file
|
|
1765
1784
|
# or if we may be translating to a different format
|
|
@@ -1804,8 +1823,7 @@ if ($outOpt) {
|
|
|
1804
1823
|
$type = Image::ExifTool::GetFileExtension($outOpt);
|
|
1805
1824
|
$type = uc($outOpt) unless defined $type;
|
|
1806
1825
|
}
|
|
1807
|
-
|
|
1808
|
-
$rtnVal = 1;
|
|
1826
|
+
Error "Can't write $type files\n";
|
|
1809
1827
|
next;
|
|
1810
1828
|
}
|
|
1811
1829
|
$scanWritable = $type unless CanCreate($type);
|
|
@@ -1903,10 +1921,7 @@ if (@dbKeys) {
|
|
|
1903
1921
|
# process all specified files
|
|
1904
1922
|
ProcessFiles($mt);
|
|
1905
1923
|
|
|
1906
|
-
if
|
|
1907
|
-
Warn "No file with specified extension\n";
|
|
1908
|
-
$rtnVal = 1;
|
|
1909
|
-
}
|
|
1924
|
+
Error "No file with specified extension\n" if $filtered and not $validFile;
|
|
1910
1925
|
|
|
1911
1926
|
# print CSV information if necessary
|
|
1912
1927
|
PrintCSV() if $csv and not $isWriting;
|
|
@@ -2014,7 +2029,7 @@ Exit $rtnValApp; # all done
|
|
|
2014
2029
|
sub GetImageInfo($$)
|
|
2015
2030
|
{
|
|
2016
2031
|
my ($et, $orig) = @_;
|
|
2017
|
-
my (@foundTags, $info, $file, $ind, $g8);
|
|
2032
|
+
my (@foundTags, @found2, $info, $info2, $et2, $file, $file2, $ind, $g8);
|
|
2018
2033
|
|
|
2019
2034
|
# set window title for this file if necessary
|
|
2020
2035
|
if (defined $windowTitle) {
|
|
@@ -2151,7 +2166,7 @@ sub GetImageInfo($$)
|
|
|
2151
2166
|
}
|
|
2152
2167
|
# can't make use of $info if verbose because we must reprocess
|
|
2153
2168
|
# the file anyway to generate the verbose output
|
|
2154
|
-
undef $info if $verbose or defined $fastCondition;
|
|
2169
|
+
undef $info if $verbose or defined $fastCondition or defined $diff;
|
|
2155
2170
|
} elsif ($file =~ s/^(\@JSON:)(.*)/$1/) {
|
|
2156
2171
|
# read JSON file from command line
|
|
2157
2172
|
my $dat = $2;
|
|
@@ -2183,7 +2198,7 @@ sub GetImageInfo($$)
|
|
|
2183
2198
|
|
|
2184
2199
|
my $lineCount = 0;
|
|
2185
2200
|
my ($fp, $outfile, $append);
|
|
2186
|
-
if ($textOut and ($verbose or $et->Options('PrintCSV')) and not $tagOut) {
|
|
2201
|
+
if ($textOut and ($verbose or $et->Options('PrintCSV')) and not ($tagOut or defined $diff)) {
|
|
2187
2202
|
($fp, $outfile, $append) = OpenOutputFile($orig);
|
|
2188
2203
|
$fp or EFile($file), ++$countBad, return;
|
|
2189
2204
|
# delete file if we exit prematurely (unless appending)
|
|
@@ -2228,7 +2243,7 @@ sub GetImageInfo($$)
|
|
|
2228
2243
|
require Image::ExifTool::HTML;
|
|
2229
2244
|
my $f = Image::ExifTool::HTML::EscapeHTML($file);
|
|
2230
2245
|
print "<!-- $f -->\n";
|
|
2231
|
-
} elsif (not ($json or $xml)) {
|
|
2246
|
+
} elsif (not ($json or $xml or defined $diff)) {
|
|
2232
2247
|
$o = \*STDOUT if ($multiFile and not $quiet) or $progress;
|
|
2233
2248
|
}
|
|
2234
2249
|
}
|
|
@@ -2257,10 +2272,37 @@ sub GetImageInfo($$)
|
|
|
2257
2272
|
} else {
|
|
2258
2273
|
@foundTags = @tags;
|
|
2259
2274
|
}
|
|
2275
|
+
if (defined $diff) {
|
|
2276
|
+
$file2 = FilenameSPrintf($diff, $orig);
|
|
2277
|
+
if ($file eq $file2) {
|
|
2278
|
+
Warn "Error: Diffing file with itself - $file2\n";
|
|
2279
|
+
EFile($file);
|
|
2280
|
+
++$countBad;
|
|
2281
|
+
return;
|
|
2282
|
+
}
|
|
2283
|
+
if ($et->Exists($file2)) {
|
|
2284
|
+
$showGroup = 1 unless defined $showGroup;
|
|
2285
|
+
$allGroup = 1 unless defined $allGroup;
|
|
2286
|
+
$et->Options(Duplicates => 1, Sort => "Group$showGroup", Verbose => 0);
|
|
2287
|
+
$et2 = Image::ExifTool->new;
|
|
2288
|
+
$et2->Options(%{$$et{OPTIONS}});
|
|
2289
|
+
@found2 = @foundTags;
|
|
2290
|
+
$info2 = $et2->ImageInfo($file2, \@found2);
|
|
2291
|
+
} else {
|
|
2292
|
+
$info2 = { Error => "Diff file not found" };
|
|
2293
|
+
}
|
|
2294
|
+
if ($$info2{Error}) {
|
|
2295
|
+
Warn "Error: $$info2{Error} - $file2\n";
|
|
2296
|
+
EFile($file);
|
|
2297
|
+
++$countBad;
|
|
2298
|
+
return;
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2260
2301
|
# extract the information
|
|
2261
2302
|
$info = $et->ImageInfo(Infile($pipe), \@foundTags);
|
|
2262
2303
|
$et->Options(Duplicates => $oldDups);
|
|
2263
2304
|
}
|
|
2305
|
+
|
|
2264
2306
|
# all done now if we already wrote output text file (eg. verbose option)
|
|
2265
2307
|
if ($fp) {
|
|
2266
2308
|
if (defined $outfile) {
|
|
@@ -2274,7 +2316,7 @@ sub GetImageInfo($$)
|
|
|
2274
2316
|
}
|
|
2275
2317
|
}
|
|
2276
2318
|
if ($info->{Error}) {
|
|
2277
|
-
Warn "Error:
|
|
2319
|
+
Warn "Error: $$info{Error} - $file\n";
|
|
2278
2320
|
EFile($file);
|
|
2279
2321
|
++$countBad;
|
|
2280
2322
|
return;
|
|
@@ -2298,6 +2340,105 @@ sub GetImageInfo($$)
|
|
|
2298
2340
|
$tmpText = $outfile unless $append;
|
|
2299
2341
|
}
|
|
2300
2342
|
|
|
2343
|
+
# print differences if requested
|
|
2344
|
+
if (defined $diff) {
|
|
2345
|
+
my (%done2, $wasDiff, @diffs, @groupTags2);
|
|
2346
|
+
my $v = $verbose || 0;
|
|
2347
|
+
print $fp "======== diff < $file > $file2\n";
|
|
2348
|
+
my ($g2, $same) = (0, 0); # start with $g2 false, but not equal to '' to avoid infinite loop
|
|
2349
|
+
for (;;) {
|
|
2350
|
+
my $tag = shift @foundTags;
|
|
2351
|
+
my ($g, $tag2);
|
|
2352
|
+
if (defined $tag) {
|
|
2353
|
+
$g = $et->GetGroup($tag, $showGroup);
|
|
2354
|
+
} else {
|
|
2355
|
+
for (;;) {
|
|
2356
|
+
$tag2 = shift @found2;
|
|
2357
|
+
defined $tag2 or $g = '', last;
|
|
2358
|
+
$done2{$tag2} or $g = $et2->GetGroup($tag2, $showGroup), last;
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
if ($g ne $g2) {
|
|
2362
|
+
my $t2;
|
|
2363
|
+
# add any outstanding tags from diff file not yet handled in previous group ($g2)
|
|
2364
|
+
foreach $t2 (@groupTags2) {
|
|
2365
|
+
next if $done2{$t2};
|
|
2366
|
+
my $val2 = $et2->GetValue($t2);
|
|
2367
|
+
next unless defined $val2;
|
|
2368
|
+
my $name = $outFormat < 1 ? $et2->GetDescription($t2) : GetTagName($t2);
|
|
2369
|
+
my $len = LengthUTF8($name);
|
|
2370
|
+
my $pad = $outFormat < 2 ? ' ' x ($len < 32 ? 32 - $len : 0) : '';
|
|
2371
|
+
if ($allGroup) {
|
|
2372
|
+
my $grp = "[$g2]";
|
|
2373
|
+
$grp .= ' ' x (15 - length($grp)) if length($grp) < 15 and $outFormat < 2;
|
|
2374
|
+
push @diffs, sprintf "> %s %s%s: %s\n", $grp, $name, $pad, Printable($val2);
|
|
2375
|
+
} else {
|
|
2376
|
+
push @diffs, sprintf "> %s%s: %s\n", $name, $pad, Printable($val2);
|
|
2377
|
+
}
|
|
2378
|
+
$done2{$t2} = 1;
|
|
2379
|
+
}
|
|
2380
|
+
my $str = '';
|
|
2381
|
+
($v > 1 or $same) and $str = " ($same same tag" . ($same==1 ? '' : 's') . ')';
|
|
2382
|
+
if (not $allGroup) {
|
|
2383
|
+
print $fp "---- $g2 ----$str\n" if $g2 and ($str or @diffs);
|
|
2384
|
+
} elsif ($str and $g2) {
|
|
2385
|
+
printf $fp " %-13s%s\n", $g2, $str;
|
|
2386
|
+
}
|
|
2387
|
+
# print all differences for this group
|
|
2388
|
+
@diffs and print($fp @diffs), $wasDiff = 1, @diffs = ();
|
|
2389
|
+
last unless $g;
|
|
2390
|
+
($g2, $same) = ($g, 0);
|
|
2391
|
+
# build list of all tags in the new group of the diff file
|
|
2392
|
+
@groupTags2 = ();
|
|
2393
|
+
foreach $t2 (@found2) {
|
|
2394
|
+
$done2{$t2} or $g ne $et2->GetGroup($t2, $showGroup) or push @groupTags2, $t2;
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
next unless defined $tag;
|
|
2398
|
+
my $val = $et->GetValue($tag);
|
|
2399
|
+
next unless defined $val; # (just in case)
|
|
2400
|
+
my $name = GetTagName($tag);
|
|
2401
|
+
# get matching tag key from diff file
|
|
2402
|
+
my @tags2 = grep /^$name( |$)/, @groupTags2;
|
|
2403
|
+
$name = $et->GetDescription($tag) if $outFormat < 1;
|
|
2404
|
+
my ($val2, $t2);
|
|
2405
|
+
foreach $t2 (@tags2) {
|
|
2406
|
+
next if $done2{$t2};
|
|
2407
|
+
$tag2 = $t2;
|
|
2408
|
+
$val2 = $et2->GetValue($t2);
|
|
2409
|
+
last;
|
|
2410
|
+
}
|
|
2411
|
+
if (defined $val2 and IsEqual($val, $val2)) {
|
|
2412
|
+
++$same;
|
|
2413
|
+
} else {
|
|
2414
|
+
my $len = LengthUTF8($name);
|
|
2415
|
+
my $pad = $outFormat < 2 ? ' ' x ($len < 32 ? 32 - $len : 0) : '';
|
|
2416
|
+
if ($allGroup) {
|
|
2417
|
+
my $grp = "[$g]";
|
|
2418
|
+
$grp .= ' ' x (15 - length($grp)) if length($grp) < 15 and $outFormat < 2;
|
|
2419
|
+
push @diffs, sprintf "< %s %s%s: %s\n", $grp, $name, $pad, Printable($val);
|
|
2420
|
+
if (defined $val2) {
|
|
2421
|
+
$v < 3 and $grp = ' ' x length($grp), $name = ' ' x $len;
|
|
2422
|
+
push @diffs, sprintf "> %s %s%s: %s\n", $grp, $name, $pad, Printable($val2);
|
|
2423
|
+
}
|
|
2424
|
+
} else {
|
|
2425
|
+
push @diffs, sprintf "< %s%s: %s\n", $name, $pad, Printable($val);
|
|
2426
|
+
$v < 3 and $name = ' ' x $len;
|
|
2427
|
+
push @diffs, sprintf "> %s%s %s\n", $name, $pad, Printable($val2) if defined $val2;
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
$done2{$tag2} = 1 if defined $tag2;
|
|
2431
|
+
}
|
|
2432
|
+
print $fp "(no metadata differences)\n" unless $wasDiff;
|
|
2433
|
+
undef $tmpText;
|
|
2434
|
+
if (defined $outfile) {
|
|
2435
|
+
++$created{$outfile};
|
|
2436
|
+
close($fp);
|
|
2437
|
+
undef $tmpText;
|
|
2438
|
+
}
|
|
2439
|
+
++$count;
|
|
2440
|
+
return;
|
|
2441
|
+
}
|
|
2301
2442
|
# restore state of comma flag for this file if appending
|
|
2302
2443
|
$comma = $outComma{$outfile} if $append and ($textOverwrite & 0x02);
|
|
2303
2444
|
|
|
@@ -2766,21 +2907,7 @@ TAG: foreach $tag (@foundTags) {
|
|
|
2766
2907
|
# pad description to a constant length
|
|
2767
2908
|
# (get actual character length when using alternate languages
|
|
2768
2909
|
# because these descriptions may contain UTF8-encoded characters)
|
|
2769
|
-
my $padLen = $wid;
|
|
2770
|
-
if (not $fixLen) {
|
|
2771
|
-
$padLen -= length $desc;
|
|
2772
|
-
} elsif ($fixLen == 1) {
|
|
2773
|
-
$padLen -= length Encode::decode_utf8($desc);
|
|
2774
|
-
} else {
|
|
2775
|
-
my $gcstr = eval { Unicode::GCString->new(Encode::decode_utf8($desc)) };
|
|
2776
|
-
if ($gcstr) {
|
|
2777
|
-
$padLen -= $gcstr->columns;
|
|
2778
|
-
} else {
|
|
2779
|
-
$padLen -= length Encode::decode_utf8($desc);
|
|
2780
|
-
Warning($et, 'Unicode::GCString problem. Columns may be misaligned');
|
|
2781
|
-
$fixLen = 1;
|
|
2782
|
-
}
|
|
2783
|
-
}
|
|
2910
|
+
my $padLen = $wid - LengthUTF8($desc);
|
|
2784
2911
|
$padLen = 0 if $padLen < 0;
|
|
2785
2912
|
$buff .= $desc . (' ' x $padLen) . ": $val\n";
|
|
2786
2913
|
} elsif ($outFormat == 2) {
|
|
@@ -3011,7 +3138,7 @@ sub SetImageInfo($$$)
|
|
|
3011
3138
|
}
|
|
3012
3139
|
$found = 1;
|
|
3013
3140
|
$verbose and print $vout "Setting new values from $csv database\n";
|
|
3014
|
-
foreach $tag (
|
|
3141
|
+
foreach $tag (OrderedKeys($csvInfo)) {
|
|
3015
3142
|
next if $tag =~ /\b(SourceFile|Directory|FileName)$/i; # don't write these
|
|
3016
3143
|
my ($rtn, $wrn) = $et->SetNewValue($tag, $$csvInfo{$tag},
|
|
3017
3144
|
Protected => 1, AddValue => $csvAdd,
|
|
@@ -3427,8 +3554,7 @@ sub FormatXML($$$)
|
|
|
3427
3554
|
} elsif (ref $val eq 'HASH') {
|
|
3428
3555
|
$gt = " rdf:parseType='Resource'>";
|
|
3429
3556
|
my $val2 = '';
|
|
3430
|
-
|
|
3431
|
-
foreach (@keys) {
|
|
3557
|
+
foreach (OrderedKeys($val)) {
|
|
3432
3558
|
# (some variable-namespace XML structure fields may have a different group)
|
|
3433
3559
|
my ($ns, $tg) = ($grp, $_);
|
|
3434
3560
|
if (/^(.*?):(.*)/) {
|
|
@@ -3520,8 +3646,7 @@ sub FormatJSON($$$;$)
|
|
|
3520
3646
|
} elsif (ref $val eq 'HASH') {
|
|
3521
3647
|
my ($bra, $ket, $sep) = $json == 1 ? ('{','}',':') : ('Array(',')',' =>');
|
|
3522
3648
|
print $fp $bra;
|
|
3523
|
-
|
|
3524
|
-
foreach (@keys) {
|
|
3649
|
+
foreach (OrderedKeys($val)) {
|
|
3525
3650
|
print $fp ',' if $comma;
|
|
3526
3651
|
my $key = EscapeJSON($_, 1);
|
|
3527
3652
|
print $fp qq(\n$ind $key$sep );
|
|
@@ -3678,6 +3803,52 @@ sub IsEqual($$)
|
|
|
3678
3803
|
return 1;
|
|
3679
3804
|
}
|
|
3680
3805
|
|
|
3806
|
+
#------------------------------------------------------------------------------
|
|
3807
|
+
# Get the printable rendition of a value
|
|
3808
|
+
# Inputs: 0) value (may be a reference)
|
|
3809
|
+
# Returns: de-referenced value
|
|
3810
|
+
sub Printable($)
|
|
3811
|
+
{
|
|
3812
|
+
my $val = shift;
|
|
3813
|
+
if (ref $val) {
|
|
3814
|
+
if ($structOpt) {
|
|
3815
|
+
require Image::ExifTool::XMP;
|
|
3816
|
+
$val = Image::ExifTool::XMP::SerializeStruct($mt, $val);
|
|
3817
|
+
} elsif (ref $val eq 'ARRAY') {
|
|
3818
|
+
$val = join($listSep, @$val);
|
|
3819
|
+
} elsif (ref $val eq 'SCALAR') {
|
|
3820
|
+
$val = '(Binary data '.length($$val).' bytes)';
|
|
3821
|
+
}
|
|
3822
|
+
}
|
|
3823
|
+
$val =~ tr/\0-\x1f\x7f/./; # translate unprintable characters
|
|
3824
|
+
return $val;
|
|
3825
|
+
}
|
|
3826
|
+
|
|
3827
|
+
#------------------------------------------------------------------------------
|
|
3828
|
+
# Get character length of a UTF-8 string
|
|
3829
|
+
# Inputs: 0) string
|
|
3830
|
+
# Returns: number of characters (not bytes) in the UTF-8 string
|
|
3831
|
+
sub LengthUTF8($)
|
|
3832
|
+
{
|
|
3833
|
+
my $str = shift;
|
|
3834
|
+
my $len;
|
|
3835
|
+
if (not $fixLen) {
|
|
3836
|
+
$len = length $str;
|
|
3837
|
+
} elsif ($fixLen == 1) {
|
|
3838
|
+
$len = length Encode::decode_utf8($str);
|
|
3839
|
+
} else {
|
|
3840
|
+
my $gcstr = eval { Unicode::GCString->new(Encode::decode_utf8($str)) };
|
|
3841
|
+
if ($gcstr) {
|
|
3842
|
+
$len = $gcstr->columns;
|
|
3843
|
+
} else {
|
|
3844
|
+
$len = length Encode::decode_utf8($str);
|
|
3845
|
+
Warning($mt, 'Unicode::GCString problem. Columns may be misaligned');
|
|
3846
|
+
$fixLen = 1;
|
|
3847
|
+
}
|
|
3848
|
+
}
|
|
3849
|
+
return $len;
|
|
3850
|
+
}
|
|
3851
|
+
|
|
3681
3852
|
#------------------------------------------------------------------------------
|
|
3682
3853
|
# Add tag list for copying tags from specified file
|
|
3683
3854
|
# Inputs: 0) set tags file name (or FMT), 1) options for SetNewValuesFromFile()
|
|
@@ -4867,6 +5038,7 @@ L<Other options|/Other options>
|
|
|
4867
5038
|
|
|
4868
5039
|
L<Special features|/Special features>
|
|
4869
5040
|
|
|
5041
|
+
-diff FILE2 Compare metadata with another file
|
|
4870
5042
|
-geotag TRKFILE Geotag images from specified GPS log
|
|
4871
5043
|
-globalTimeShift SHIFT Shift all formatted date/time values
|
|
4872
5044
|
-use MODULE Add features from plug-in module
|
|
@@ -5662,7 +5834,7 @@ with this command:
|
|
|
5662
5834
|
|
|
5663
5835
|
produces output like this:
|
|
5664
5836
|
|
|
5665
|
-
-- Generated by ExifTool 12.
|
|
5837
|
+
-- Generated by ExifTool 12.99 --
|
|
5666
5838
|
File: a.jpg - 2003:10:31 15:44:19
|
|
5667
5839
|
(f/5.6, 1/60s, ISO 100)
|
|
5668
5840
|
File: b.jpg - 2006:05:23 11:57:38
|
|
@@ -6204,9 +6376,10 @@ B<-fileNUM> option is used to read an alternate file and the corresponding
|
|
|
6204
6376
|
family 8 group name is specified for the tag. See the B<-fileNUM> option
|
|
6205
6377
|
details for more information.
|
|
6206
6378
|
|
|
6207
|
-
5) The B<-a> option
|
|
6208
|
-
the values of duplicate tags are accessible
|
|
6209
|
-
(such as a family 4 instance number, eg.
|
|
6379
|
+
5) The B<-a> (Duplicates) option is implied when B<-if> is used without a
|
|
6380
|
+
fast I<NUM>, and the values of duplicate tags are accessible by specifying a
|
|
6381
|
+
group name in the expression (such as a family 4 instance number, eg.
|
|
6382
|
+
C<$Copy1:TAG>, C<$Copy2:TAG>, etc).
|
|
6210
6383
|
|
|
6211
6384
|
6) A special "OK" UserParam is available to test the success of the previous
|
|
6212
6385
|
command when B<-execute> was used, and may be used like any other tag in the
|
|
@@ -6472,9 +6645,9 @@ B<-f> adds 'flags' and 'struct' attributes if applicable. The flags are
|
|
|
6472
6645
|
formatted as a comma-separated list of the following possible values:
|
|
6473
6646
|
Avoid, Binary, List, Mandatory, Permanent, Protected, Unknown and Unsafe
|
|
6474
6647
|
(see the L<Tag Name documentation|Image::ExifTool::TagNames>). For XMP List
|
|
6475
|
-
tags, the list type (Alt, Bag or Seq) is
|
|
6476
|
-
|
|
6477
|
-
|
|
6648
|
+
tags, the list type (Alt, Bag or Seq) is also given, and flattened structure
|
|
6649
|
+
tags are indicated by a Flattened flag with 'struct' giving the ID of the
|
|
6650
|
+
parent structure.
|
|
6478
6651
|
|
|
6479
6652
|
Note that none of the B<-list> options require an input I<FILE>.
|
|
6480
6653
|
|
|
@@ -6496,6 +6669,23 @@ names, even if they begin with a dash (C<->).
|
|
|
6496
6669
|
|
|
6497
6670
|
=over 5
|
|
6498
6671
|
|
|
6672
|
+
=item B<-diff> I<FILE2>
|
|
6673
|
+
|
|
6674
|
+
Compare metadata in I<FILE> with I<FILE2>. The I<FILE2> name may include
|
|
6675
|
+
filename formatting codes (see the B<-w> option). All extracted tags from
|
|
6676
|
+
the files are compared, but the extracted tags may be controlled by adding
|
|
6677
|
+
B<-TAG> or B<--TAG> options. For example, below is a command to compare all
|
|
6678
|
+
the same-named files in two different directories, ignoring the System tags:
|
|
6679
|
+
|
|
6680
|
+
exiftool DIR1 -diff DIR2/%f.%e --system:all
|
|
6681
|
+
|
|
6682
|
+
The B<-g> and B<-G> options may be used to organize the output by the
|
|
6683
|
+
specified family of groups, with B<-G1> being the default. The B<-a> option
|
|
6684
|
+
is implied. Adding B<-v> includes a count of the number of tags that are
|
|
6685
|
+
the same in each group. The following text formatting options are valid
|
|
6686
|
+
when B<-diff> is used: B<-c>, B<-charset>, B<-d>, B<-E>, B<-L>, B<-lang>,
|
|
6687
|
+
B<-n>, B<-s>, B<-sep>, B<-struct> and B<-w>.
|
|
6688
|
+
|
|
6499
6689
|
=item B<-geotag> I<TRKFILE>
|
|
6500
6690
|
|
|
6501
6691
|
Geotag images from the specified GPS track log file. Using the B<-geotag>
|
|
@@ -41,7 +41,7 @@ require 5.002;
|
|
|
41
41
|
require Exporter;
|
|
42
42
|
|
|
43
43
|
use vars qw($VERSION @ISA @EXPORT_OK);
|
|
44
|
-
$VERSION = '1.
|
|
44
|
+
$VERSION = '1.13';
|
|
45
45
|
@ISA = qw(Exporter);
|
|
46
46
|
|
|
47
47
|
sub Read($$$);
|
|
@@ -158,7 +158,10 @@ sub Seek($$;$)
|
|
|
158
158
|
$self->Slurp(); # read whole file into buffer
|
|
159
159
|
$newPos = $num + $self->{LEN}; # relative to end of file
|
|
160
160
|
}
|
|
161
|
-
if ($newPos >= 0
|
|
161
|
+
if ($newPos >= 0 and
|
|
162
|
+
# can't go backwards in unbuffered non-seekable file
|
|
163
|
+
(not $self->{NoBuffer} or $newPos >= $self->{POS}))
|
|
164
|
+
{
|
|
162
165
|
$self->{POS} = $newPos;
|
|
163
166
|
$rtnVal = 1;
|
|
164
167
|
}
|
|
@@ -14,7 +14,7 @@ use strict;
|
|
|
14
14
|
use vars qw($VERSION);
|
|
15
15
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
16
16
|
|
|
17
|
-
$VERSION = '1.
|
|
17
|
+
$VERSION = '1.14';
|
|
18
18
|
|
|
19
19
|
sub ProcessAPP12($$$);
|
|
20
20
|
sub ProcessDucky($$$);
|
|
@@ -72,7 +72,7 @@ sub WriteDucky($$$);
|
|
|
72
72
|
StrobeTime => { },
|
|
73
73
|
Resolution => { },
|
|
74
74
|
Protect => { },
|
|
75
|
-
|
|
75
|
+
ContTake => { },
|
|
76
76
|
ImageSize => { PrintConv => '$val=~tr/-/x/;$val' },
|
|
77
77
|
ColorMode => { },
|
|
78
78
|
Zoom => { },
|
|
@@ -278,6 +278,7 @@ sub ProcessAPP12($$$)
|
|
|
278
278
|
$tagInfo = { Name => ucfirst $tag };
|
|
279
279
|
# put in Camera group if information in "Camera" section
|
|
280
280
|
$$tagInfo{Groups} = { 2 => 'Camera' } if $section =~ /camera/i;
|
|
281
|
+
$et->VPrint(0, $$et{INDENT}, "[adding APP12:$$tagInfo{Name}]\n");
|
|
281
282
|
AddTagToTable($tagTablePtr, $tag, $tagInfo);
|
|
282
283
|
}
|
|
283
284
|
$et->FoundTag($tagInfo, $val);
|
|
@@ -88,7 +88,7 @@ sub ProcessCTMD($$$);
|
|
|
88
88
|
sub ProcessExifInfo($$$);
|
|
89
89
|
sub SwapWords($);
|
|
90
90
|
|
|
91
|
-
$VERSION = '4.
|
|
91
|
+
$VERSION = '4.82';
|
|
92
92
|
|
|
93
93
|
# Note: Removed 'USM' from 'L' lenses since it is redundant - PH
|
|
94
94
|
# (or is it? Ref 32 shows 5 non-USM L-type lenses)
|
|
@@ -6999,6 +6999,7 @@ my %ciMaxFocal = (
|
|
|
6999
6999
|
314 => 'Canon RF 24-105mm F2.8 L IS USM Z', #42
|
|
7000
7000
|
315 => 'Canon RF-S 10-18mm F4.5-6.3 IS STM', #42
|
|
7001
7001
|
316 => 'Canon RF 35mm F1.4 L VCM', #42
|
|
7002
|
+
317 => 'Canon RF-S 3.9mm F3.5 STM DUAL FISHEYE', #42
|
|
7002
7003
|
318 => 'Canon RF 28-70mm F2.8 IS STM', #42
|
|
7003
7004
|
# Note: add new RF lenses to %canonLensTypes with ID 61182
|
|
7004
7005
|
},
|