exiftool_vendored 12.97.0 → 12.99.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
},
|