exiftool-vendored.pl 12.80.0 → 12.84.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.
- package/bin/Changes +81 -0
- package/bin/MANIFEST +6 -18
- package/bin/META.json +1 -1
- package/bin/META.yml +1 -1
- package/bin/README +4 -2
- package/bin/build_geolocation +872 -0
- package/bin/config_files/example.config +2 -2
- package/bin/exiftool +61 -17
- package/bin/fmt_files/gpx.fmt +2 -1
- package/bin/fmt_files/gpx_wpt.fmt +2 -1
- package/bin/lib/Image/ExifTool/Apple.pm +51 -7
- package/bin/lib/Image/ExifTool/BuildTagLookup.pm +47 -31
- package/bin/lib/Image/ExifTool/CanonVRD.pm +19 -6
- package/bin/lib/Image/ExifTool/DJI.pm +29 -0
- package/bin/lib/Image/ExifTool/Exif.pm +19 -2
- package/bin/lib/Image/ExifTool/FujiFilm.pm +20 -7
- package/bin/lib/Image/ExifTool/GM.pm +552 -0
- package/bin/lib/Image/ExifTool/Geolocation.dat +0 -0
- package/bin/lib/Image/ExifTool/Geolocation.pm +423 -178
- package/bin/lib/Image/ExifTool/Geotag.pm +26 -13
- package/bin/lib/Image/ExifTool/M2TS.pm +32 -4
- package/bin/lib/Image/ExifTool/MakerNotes.pm +2 -2
- package/bin/lib/Image/ExifTool/Microsoft.pm +1 -1
- package/bin/lib/Image/ExifTool/Nikon.pm +337 -27
- package/bin/lib/Image/ExifTool/NikonCustom.pm +55 -1
- package/bin/lib/Image/ExifTool/Olympus.pm +1 -0
- package/bin/lib/Image/ExifTool/OpenEXR.pm +21 -3
- package/bin/lib/Image/ExifTool/PNG.pm +3 -3
- package/bin/lib/Image/ExifTool/QuickTime.pm +45 -24
- package/bin/lib/Image/ExifTool/QuickTimeStream.pl +66 -30
- package/bin/lib/Image/ExifTool/README +2 -0
- package/bin/lib/Image/ExifTool/Sony.pm +16 -7
- package/bin/lib/Image/ExifTool/TagLookup.pm +4827 -4778
- package/bin/lib/Image/ExifTool/TagNames.pod +953 -620
- package/bin/lib/Image/ExifTool/WriteQuickTime.pl +32 -9
- package/bin/lib/Image/ExifTool/Writer.pl +169 -130
- package/bin/lib/Image/ExifTool/XMP.pm +4 -2
- package/bin/lib/Image/ExifTool/XMP2.pl +3 -0
- package/bin/lib/Image/ExifTool.pm +106 -48
- package/bin/lib/Image/ExifTool.pod +47 -25
- package/bin/perl-Image-ExifTool.spec +1 -1
- package/bin/pp_build_exe.args +4 -4
- package/package.json +3 -3
|
@@ -364,8 +364,8 @@ $Image::ExifTool::QuickTime::Keys{PREFERRED} = 3;
|
|
|
364
364
|
|
|
365
365
|
# Add user-defined cities to the Geolocation lookup
|
|
366
366
|
@Image::ExifTool::UserDefined::Geolocation = (
|
|
367
|
-
# (city,region,
|
|
368
|
-
['Sinemorets','
|
|
367
|
+
# (city,region,subregion,country_code,country,timezone,feature_code,population,lat,lon)
|
|
368
|
+
['Sinemorets','burgas','Obshtina Tsarevo','BG','','Europe/Sofia','PPL',400,42.06115,27.97833],
|
|
369
369
|
);
|
|
370
370
|
|
|
371
371
|
#------------------------------------------------------------------------------
|
package/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.84';
|
|
15
15
|
|
|
16
16
|
# add our 'lib' directory to the include list BEFORE 'use Image::ExifTool'
|
|
17
17
|
my $exePath;
|
|
@@ -217,7 +217,7 @@ my $tmpFile; # temporary file to delete on exit
|
|
|
217
217
|
my $tmpText; # temporary text file
|
|
218
218
|
my $validFile; # flag indicating we processed a valid file
|
|
219
219
|
my $verbose; # verbose setting
|
|
220
|
-
my $vout; # verbose output file reference (\*STDOUT or \*STDERR)
|
|
220
|
+
my $vout; # verbose output file reference (\*STDOUT or \*STDERR by default)
|
|
221
221
|
my $windowTitle; # title for console window
|
|
222
222
|
my %wroteHEAD; # list of output txt files to which we wrote HEAD
|
|
223
223
|
my $xml; # flag for XML-formatted output
|
|
@@ -723,17 +723,23 @@ for (;;) {
|
|
|
723
723
|
require Image::ExifTool::Geolocation;
|
|
724
724
|
my ($i, $entry);
|
|
725
725
|
print "Geolocation database:\n" unless $quiet;
|
|
726
|
-
|
|
726
|
+
my $isAlt = $mt->Options('GeolocAltNames') ? ',AltNames' : '';
|
|
727
|
+
$isAlt = '' if $isAlt and not Image::ExifTool::Geolocation::ReadAltNames();
|
|
728
|
+
print "City,Region,Subregion,CountryCode,Country,TimeZone,FeatureCode,Population,Latitude,Longitude$isAlt\n";
|
|
727
729
|
Image::ExifTool::Geolocation::SortDatabase('City') if $sortOpt;
|
|
728
730
|
my $minPop = $mt->Options('GeolocMinPop');
|
|
729
731
|
my $feature = $mt->Options('GeolocFeature') || '';
|
|
730
732
|
my $neg = $feature =~ s/^-//;
|
|
731
733
|
my %fcodes = map { lc($_) => 1 } split /\s*,\s*/, $feature;
|
|
734
|
+
my @isUTF8 = (0,1,2,4); # items that need converting from UTF8
|
|
735
|
+
push @isUTF8, 10 if $isAlt;
|
|
732
736
|
for ($i=0; ; ++$i) {
|
|
733
|
-
my @entry = Image::ExifTool::Geolocation::GetEntry($i,$langOpt) or last;
|
|
737
|
+
my @entry = Image::ExifTool::Geolocation::GetEntry($i,$langOpt,1) or last;
|
|
734
738
|
next if $minPop and $entry[7] < $minPop;
|
|
735
739
|
next if %fcodes and $neg ? $fcodes{lc $entry[6]} : not $fcodes{lc $entry[6]};
|
|
736
|
-
|
|
740
|
+
push @entry, Image::ExifTool::Geolocation::GetAltNames($i,1) if $isAlt;
|
|
741
|
+
$_ = defined $_ ? $mt->Decode($_, 'UTF8') : '' foreach @entry[@isUTF8];
|
|
742
|
+
pop @entry if $isAlt and not $entry[10];
|
|
737
743
|
print join(',', @entry), "\n";
|
|
738
744
|
}
|
|
739
745
|
} else { # 'g(\d*)'
|
|
@@ -1160,7 +1166,7 @@ for (;;) {
|
|
|
1160
1166
|
if (/^p(-?)$/ or /^printformat(-?)$/i) {
|
|
1161
1167
|
my $fmt = shift;
|
|
1162
1168
|
if ($pass) {
|
|
1163
|
-
LoadPrintFormat($fmt, $1);
|
|
1169
|
+
LoadPrintFormat($fmt, $1 || $binaryOutput);
|
|
1164
1170
|
# load MWG module now if necessary
|
|
1165
1171
|
if (not $useMWG and grep /^mwg:/i, @requestTags) {
|
|
1166
1172
|
$useMWG = 1;
|
|
@@ -1365,11 +1371,11 @@ for (;;) {
|
|
|
1365
1371
|
$useMWG = 1;
|
|
1366
1372
|
} elsif (/^([-\w]+:)*(filename|directory|testname)\b/i) {
|
|
1367
1373
|
$doSetFileName = 1;
|
|
1368
|
-
} elsif (/^([-\w]+:)*(geotag|geotime|geosync)\b/i) {
|
|
1374
|
+
} elsif (/^([-\w]+:)*(geotag|geotime|geosync|geolocate)\b/i) {
|
|
1369
1375
|
if (lc $2 eq 'geotime') {
|
|
1370
1376
|
$addGeotime = '';
|
|
1371
1377
|
} else {
|
|
1372
|
-
# add geotag/geosync commands first
|
|
1378
|
+
# add geotag/geosync/geolocate commands first
|
|
1373
1379
|
unshift @newValues, pop @newValues;
|
|
1374
1380
|
if (lc $2 eq 'geotag' and (not defined $addGeotime or $addGeotime) and length $val) {
|
|
1375
1381
|
$addGeotime = ($1 || '') . 'Geotime<DateTimeOriginal#';
|
|
@@ -2175,7 +2181,7 @@ sub GetImageInfo($$)
|
|
|
2175
2181
|
|
|
2176
2182
|
my $lineCount = 0;
|
|
2177
2183
|
my ($fp, $outfile, $append);
|
|
2178
|
-
if ($textOut and $verbose and not $tagOut) {
|
|
2184
|
+
if ($textOut and ($verbose or $et->Options('PrintCSV')) and not $tagOut) {
|
|
2179
2185
|
($fp, $outfile, $append) = OpenOutputFile($orig);
|
|
2180
2186
|
$fp or EFile($file), ++$countBad, return;
|
|
2181
2187
|
# delete file if we exit prematurely (unless appending)
|
|
@@ -2238,6 +2244,14 @@ sub GetImageInfo($$)
|
|
|
2238
2244
|
if (%printFmt) {
|
|
2239
2245
|
$et->Options(Duplicates => 1);
|
|
2240
2246
|
$et->Options(RequestTags => \@requestTags);
|
|
2247
|
+
if ($printFmt{SetTags}) {
|
|
2248
|
+
# initialize options so we can set any tags we want
|
|
2249
|
+
$$et{TAGS_FROM_FILE} = 1;
|
|
2250
|
+
$et->Options(MakerNotes => 1);
|
|
2251
|
+
$et->Options(Struct => 2);
|
|
2252
|
+
$et->Options(List => 1);
|
|
2253
|
+
$et->Options(CoordFormat => '%d %d %.8f') unless $et->Options('CoordFormat');
|
|
2254
|
+
}
|
|
2241
2255
|
} else {
|
|
2242
2256
|
@foundTags = @tags;
|
|
2243
2257
|
}
|
|
@@ -2290,15 +2304,15 @@ sub GetImageInfo($$)
|
|
|
2290
2304
|
# output using print format file (-p) option
|
|
2291
2305
|
my ($type, $doc, $grp, $lastDoc, $cache);
|
|
2292
2306
|
$fileTrailer = '';
|
|
2293
|
-
# repeat for each
|
|
2294
|
-
if (
|
|
2307
|
+
# repeat for each sub-document if necessary
|
|
2308
|
+
if ($$et{DOC_COUNT}) {
|
|
2295
2309
|
# (cache tag keys if there are sub-documents)
|
|
2296
2310
|
$lastDoc = $$et{DOC_COUNT} and $cache = { };
|
|
2297
2311
|
} else {
|
|
2298
2312
|
$lastDoc = 0;
|
|
2299
2313
|
}
|
|
2300
2314
|
for ($doc=0; $doc<=$lastDoc; ++$doc) {
|
|
2301
|
-
my $skipBody;
|
|
2315
|
+
my ($skipBody, $opt);
|
|
2302
2316
|
foreach $type (qw(HEAD SECT IF BODY ENDS TAIL)) {
|
|
2303
2317
|
my $prf = $printFmt{$type} or next;
|
|
2304
2318
|
if ($type eq 'HEAD' and defined $outfile) {
|
|
@@ -2306,6 +2320,12 @@ sub GetImageInfo($$)
|
|
|
2306
2320
|
$wroteHEAD{$outfile} = 1;
|
|
2307
2321
|
}
|
|
2308
2322
|
next if $type eq 'BODY' and $skipBody;
|
|
2323
|
+
# silence "IF" warnings and warnings for subdocuments > 1
|
|
2324
|
+
if ($type eq 'IF' or ($doc > 1 and not $$et{OPTIONS}{IgnoreMinorErrors})) {
|
|
2325
|
+
$opt = 'Silent';
|
|
2326
|
+
} else {
|
|
2327
|
+
$opt = 'Warn';
|
|
2328
|
+
}
|
|
2309
2329
|
if ($lastDoc) {
|
|
2310
2330
|
if ($doc) {
|
|
2311
2331
|
next if $type eq 'HEAD' or $type eq 'TAIL'; # only repeat SECT/IF/BODY/ENDS
|
|
@@ -2315,7 +2335,6 @@ sub GetImageInfo($$)
|
|
|
2315
2335
|
}
|
|
2316
2336
|
}
|
|
2317
2337
|
my @lines;
|
|
2318
|
-
my $opt = $type eq 'IF' ? 'Silent' : 'Warn'; # silence "IF" warnings
|
|
2319
2338
|
foreach (@$prf) {
|
|
2320
2339
|
my $line = $et->InsertTagValues($_, \@foundTags, $opt, $grp, $cache);
|
|
2321
2340
|
if ($type eq 'IF') {
|
|
@@ -4110,6 +4129,7 @@ sub AddPrintFormat($)
|
|
|
4110
4129
|
push @{$printFmt{$type}}, $expr;
|
|
4111
4130
|
# add to list of requested tags
|
|
4112
4131
|
push @requestTags, $expr =~ /\$\{?((?:[-\w]+:)*[-\w?*]+)/g;
|
|
4132
|
+
$printFmt{SetTags} = 1 if $expr =~ /\bSetTags\b/;
|
|
4113
4133
|
}
|
|
4114
4134
|
|
|
4115
4135
|
#------------------------------------------------------------------------------
|
|
@@ -5631,7 +5651,7 @@ it from subsequent text (and must be used if subsequent text begins with an
|
|
|
5631
5651
|
alphanumeric character, hyphen, underline, colon or number sign). Use C<$$>
|
|
5632
5652
|
to represent a C<$> symbol, and C<$/> for a newline. When the string
|
|
5633
5653
|
argument is used (ie. I<STR>), a newline is added to the end of the string
|
|
5634
|
-
unless B<-p-> is specified.
|
|
5654
|
+
unless B<-p-> is specified or the B<-b> option is used.
|
|
5635
5655
|
|
|
5636
5656
|
Multiple B<-p> options may be used. Lines beginning with C<#[HEAD]> and
|
|
5637
5657
|
C<#[TAIL]> are output before the first processed file and after the last
|
|
@@ -5657,7 +5677,7 @@ with this command:
|
|
|
5657
5677
|
|
|
5658
5678
|
produces output like this:
|
|
5659
5679
|
|
|
5660
|
-
-- Generated by ExifTool 12.
|
|
5680
|
+
-- Generated by ExifTool 12.84 --
|
|
5661
5681
|
File: a.jpg - 2003:10:31 15:44:19
|
|
5662
5682
|
(f/5.6, 1/60s, ISO 100)
|
|
5663
5683
|
File: b.jpg - 2006:05:23 11:57:38
|
|
@@ -6435,8 +6455,9 @@ otherwise family 0 is assumed. The B<-l> option may be combined with
|
|
|
6435
6455
|
B<-listf>, B<-listr> or B<-listwf> to add file descriptions to the list.
|
|
6436
6456
|
The B<-lang> option may be combined with B<-listx> to output descriptions in
|
|
6437
6457
|
a single language, and the B<-sort> and/or B<-lang> options may be combined
|
|
6438
|
-
with B<-listgeo>. Also, the API GeolocMinPop
|
|
6439
|
-
apply to the B<-listgeo> output. Here are some
|
|
6458
|
+
with B<-listgeo>. Also, the API GeolocMinPop, GeolocFeature and
|
|
6459
|
+
GeolocAltNames options apply to the B<-listgeo> output. Here are some
|
|
6460
|
+
examples:
|
|
6440
6461
|
|
|
6441
6462
|
-list # list all tag names
|
|
6442
6463
|
-list -EXIF:All # list all EXIF tags
|
|
@@ -6538,6 +6559,10 @@ examples. Also see "geotag.html" in the full ExifTool distribution and the
|
|
|
6538
6559
|
L<Image::ExifTool Options|Image::ExifTool/Options> for more details and for
|
|
6539
6560
|
information about geotag configuration options.
|
|
6540
6561
|
|
|
6562
|
+
The API Geolocation option may be set to the value "geotag" to also write
|
|
6563
|
+
the name, province/state and country of the nearest city while geotagging.
|
|
6564
|
+
See L<https://exiftool.org/geolocation.html> for details.
|
|
6565
|
+
|
|
6541
6566
|
=item B<-globalTimeShift> I<SHIFT>
|
|
6542
6567
|
|
|
6543
6568
|
Shift all formatted date/time values by the specified amount when reading.
|
|
@@ -6886,6 +6911,19 @@ sources. An equivalent to the above commands using this feature would be:
|
|
|
6886
6911
|
|
|
6887
6912
|
exiftool -tagsfromfile @ -keywords -api nodups a.jpg
|
|
6888
6913
|
|
|
6914
|
+
C<SetTags>
|
|
6915
|
+
|
|
6916
|
+
Used to set tags in extracted images. With no arguments, copies all tags
|
|
6917
|
+
from the source file to the embedded image:
|
|
6918
|
+
|
|
6919
|
+
exiftool -p '${previewimage;SetTags}' -b a.arw > preview.jpg
|
|
6920
|
+
|
|
6921
|
+
Arguments may be added to copy or set specific tags. Arguments take exactly
|
|
6922
|
+
the same form as those on the command line when copying or writing tags,
|
|
6923
|
+
but without the leading dash. For example:
|
|
6924
|
+
|
|
6925
|
+
exiftool -p '${previewimage;SetTags("comment=test","title<filename")}' ...
|
|
6926
|
+
|
|
6889
6927
|
=head1 WINDOWS UNICODE FILE NAMES
|
|
6890
6928
|
|
|
6891
6929
|
In Windows, command-line arguments are specified using the current code page
|
|
@@ -7435,6 +7473,12 @@ Geotag an image (C<a.jpg>) from position information in a GPS track log
|
|
|
7435
7473
|
DateTimeOriginal is used for geotagging. Local system time is assumed
|
|
7436
7474
|
unless DateTimeOriginal contains a timezone.
|
|
7437
7475
|
|
|
7476
|
+
=item exiftool -geotag track.log -geolocate=geotag a.jpg
|
|
7477
|
+
|
|
7478
|
+
Geotag an image and also write geolocation information of the nearest city
|
|
7479
|
+
(city name, state/province and country). Read here for more details about
|
|
7480
|
+
the Geolocation feature: L<https://exiftool.org/geolocation.html#Write>
|
|
7481
|
+
|
|
7438
7482
|
=item exiftool -geotag t.log -geotime='2009:04:02 13:41:12-05:00' a.jpg
|
|
7439
7483
|
|
|
7440
7484
|
Geotag an image with the GPS position for a specific time.
|
package/bin/fmt_files/gpx.fmt
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
# 2018/01/04 - PH Added IF to be sure position exists
|
|
12
12
|
# 2018/01/06 - PH Use DateFmt function instead of -d option
|
|
13
13
|
# 2019/10/24 - PH Preserve sub-seconds in GPSDateTime value
|
|
14
|
+
# 2024/04/11 - PH Use %f feature in GPSDateTime formatting
|
|
14
15
|
#
|
|
15
16
|
# Notes: 1) Input file(s) must contain GPSLatitude and GPSLongitude.
|
|
16
17
|
# 2) The -ee3 option is to extract the full track from video files.
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
#[IF] $gpslatitude $gpslongitude
|
|
33
34
|
#[BODY]<trkpt lat="$gpslatitude#" lon="$gpslongitude#">
|
|
34
35
|
#[BODY] <ele>$gpsaltitude#</ele>
|
|
35
|
-
#[BODY] <time>${gpsdatetime#;
|
|
36
|
+
#[BODY] <time>${gpsdatetime#;DateFmt("%Y-%m-%dT%H:%M:%S%fZ")}</time>
|
|
36
37
|
#[BODY]</trkpt>
|
|
37
38
|
#[TAIL]</trkseg>
|
|
38
39
|
#[TAIL]</trk>
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
# 2018/01/04 - PH Added IF to be sure position exists
|
|
13
13
|
# 2018/01/06 - PH Use DateFmt function instead of -d option
|
|
14
14
|
# 2019/10/24 - PH Preserve sub-seconds in GPSDateTime value
|
|
15
|
+
# 2024/04/11 - PH Use %f feature in GPSDateTime formatting
|
|
15
16
|
#
|
|
16
17
|
# Notes: 1) Input file(s) must contain GPSLatitude and GPSLongitude.
|
|
17
18
|
# 2) The -ee3 option is to extract the full track from video files.
|
|
@@ -30,7 +31,7 @@
|
|
|
30
31
|
#[IF] $gpslatitude $gpslongitude
|
|
31
32
|
#[BODY]<wpt lat="$gpslatitude#" lon="$gpslongitude#">
|
|
32
33
|
#[BODY] <ele>$gpsaltitude#</ele>
|
|
33
|
-
#[BODY] <time>${gpsdatetime#;
|
|
34
|
+
#[BODY] <time>${gpsdatetime#;DateFmt("%Y-%m-%dT%H:%M:%S%fZ")}</time>
|
|
34
35
|
#[BODY] <name>$filename</name>
|
|
35
36
|
#[BODY] <link href="$directory/$filename"/>
|
|
36
37
|
#[BODY] <sym>Scenic Area</sym>
|
|
@@ -16,7 +16,7 @@ use vars qw($VERSION);
|
|
|
16
16
|
use Image::ExifTool::Exif;
|
|
17
17
|
use Image::ExifTool::PLIST;
|
|
18
18
|
|
|
19
|
-
$VERSION = '1.
|
|
19
|
+
$VERSION = '1.12';
|
|
20
20
|
|
|
21
21
|
sub ConvertPLIST($$);
|
|
22
22
|
|
|
@@ -128,6 +128,7 @@ sub ConvertPLIST($$);
|
|
|
128
128
|
1 => 'ProRAW',
|
|
129
129
|
2 => 'Portrait',
|
|
130
130
|
10 => 'Photo',
|
|
131
|
+
12 => 'Photo (12)', #PH (NC)
|
|
131
132
|
},
|
|
132
133
|
},
|
|
133
134
|
0x0015 => { # (ImageGroupIdentifier, ref 2)
|
|
@@ -154,12 +155,17 @@ sub ConvertPLIST($$);
|
|
|
154
155
|
},
|
|
155
156
|
# 0x001b - (PhotosRenderEffect, ref 2)
|
|
156
157
|
# 0x001c - (BracketedCaptureSequenceNumber, ref 2)
|
|
158
|
+
# 0x001c - Flash, 2="On" (ref PH)
|
|
157
159
|
0x001d => { #2
|
|
158
160
|
Name => 'LuminanceNoiseAmplitude',
|
|
159
161
|
Writable => 'rational64s',
|
|
160
162
|
},
|
|
161
163
|
# 0x001e - (OriginatingAppID, ref 2)
|
|
162
|
-
|
|
164
|
+
0x001f => {
|
|
165
|
+
Name => 'PhotosAppFeatureFlags', #2
|
|
166
|
+
Notes => 'set if person or pet detected in image', #PH
|
|
167
|
+
Writable => 'int32s',
|
|
168
|
+
},
|
|
163
169
|
0x0020 => { # (ImageCaptureRequestIdentifier, ref 2)
|
|
164
170
|
Name => 'ImageCaptureRequestID',
|
|
165
171
|
Writable => 'string',
|
|
@@ -170,6 +176,17 @@ sub ConvertPLIST($$);
|
|
|
170
176
|
Writable => 'rational64s',
|
|
171
177
|
},
|
|
172
178
|
# 0x0022 - (ARKitPhoto, ref 2)
|
|
179
|
+
0x0023 => {
|
|
180
|
+
Name => 'AFPerformance', #2
|
|
181
|
+
Writable => 'int32s',
|
|
182
|
+
Count => 2,
|
|
183
|
+
Notes => q{
|
|
184
|
+
first number maybe related to focus distance, last number maybe related to
|
|
185
|
+
focus accuracy
|
|
186
|
+
},
|
|
187
|
+
PrintConv => 'my @a=split " ",$val; sprintf("%d %d %d",$a[0],$a[1]>>28,$a[1]&0xfffffff)',
|
|
188
|
+
PrintConvInv => 'my @a=split " ",$val; sprintf("%d %d",$a[0],($a[1]<<28)+$a[2])',
|
|
189
|
+
},
|
|
173
190
|
# 0x0023 - int32s[2] (AFPerformance, ref 2)
|
|
174
191
|
# 0x0024 - (AFExternalOffset, ref 2)
|
|
175
192
|
0x0025 => { # (StillImageSceneFlags, ref 2)
|
|
@@ -196,7 +213,21 @@ sub ConvertPLIST($$);
|
|
|
196
213
|
},
|
|
197
214
|
# 0x002C - (SpatialOverCaptureImageType, ref 2)
|
|
198
215
|
# 0x002D - (CCT, ref 2)
|
|
216
|
+
0x002d => { #PH
|
|
217
|
+
Name => 'ColorTemperature',
|
|
218
|
+
Writable => 'int32s',
|
|
219
|
+
},
|
|
199
220
|
# 0x002E - (ApsMode, ref 2)
|
|
221
|
+
0x002e => { #PH
|
|
222
|
+
Name => 'CameraType',
|
|
223
|
+
Writable => 'int32s',
|
|
224
|
+
PrintConv => {
|
|
225
|
+
0 => 'Back Wide Angle',
|
|
226
|
+
1 => 'Back Normal',
|
|
227
|
+
6 => 'Front',
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
# 0x002e - set to 0 for 0.5x (crop?) (ref PH)
|
|
200
231
|
0x002F => { #2
|
|
201
232
|
Name => 'FocusPosition',
|
|
202
233
|
Writable => 'int32s',
|
|
@@ -209,7 +240,9 @@ sub ConvertPLIST($$);
|
|
|
209
240
|
# 0x0032 - (IntelligentDistortionCorrection, ref 2)
|
|
210
241
|
# 0x0033 - (NRFStatus, ref 2)
|
|
211
242
|
# 0x0034 - (NRFInputBracketCount, ref 2)
|
|
243
|
+
# 0x0034 - 1 for flash on, otherwise doesn't exist (ref PH)
|
|
212
244
|
# 0x0035 - (NRFRegisteredBracketCount, ref 2)
|
|
245
|
+
# 0x0035 - 0 for flash on, otherwise doesn't exist (ref PH)
|
|
213
246
|
# 0x0036 - (LuxLevel, ref 2)
|
|
214
247
|
# 0x0037 - (LastFocusingMethod, ref 2)
|
|
215
248
|
0x0038 => { # (TimeOfFlightAssistedAutoFocusEstimatorMeasuredDepth, ref 2)
|
|
@@ -219,8 +252,10 @@ sub ConvertPLIST($$);
|
|
|
219
252
|
},
|
|
220
253
|
# 0x0039 - (TimeOfFlightAssistedAutoFocusEstimatorROIType, ref 2)
|
|
221
254
|
# 0x003A - (NRFSRLStatus, ref 2)
|
|
255
|
+
# 0x003a - non-zero if a person was in the image? (ref PH)
|
|
222
256
|
# 0x003B - (SystemPressureLevel, ref 2)
|
|
223
257
|
# 0x003C - (CameraControlsStatisticsMaster, ref 2)
|
|
258
|
+
# 0x003c - 4=rear cam, 1=front cam? (ref PH)
|
|
224
259
|
0x003D => { # (TimeOfFlightAssistedAutoFocusEstimatorSensorConfidence, ref 2)
|
|
225
260
|
Name => 'AFConfidence',
|
|
226
261
|
Writable => 'int32s',
|
|
@@ -237,6 +272,7 @@ sub ConvertPLIST($$);
|
|
|
237
272
|
},
|
|
238
273
|
0x0040 => { #2
|
|
239
274
|
Name => 'SemanticStyle',
|
|
275
|
+
Notes => '_1=Tone, _2=Warm, _3=1.Std,2.Vibrant,3.Rich Contrast,4.Warm,5.Cool', #PH
|
|
240
276
|
ValueConv => \&ConvertPLIST,
|
|
241
277
|
},
|
|
242
278
|
0x0041 => { # (SemanticStyleKey_RenderingVersion, ref 2)
|
|
@@ -249,20 +285,28 @@ sub ConvertPLIST($$);
|
|
|
249
285
|
},
|
|
250
286
|
# 0x0043 - (SemanticStyleKey_ToneBias, ref 2)
|
|
251
287
|
# 0x0044 - (SemanticStyleKey_WarmthBias, ref 2)
|
|
252
|
-
0x0045
|
|
253
|
-
Name => 'FrontFacingCamera',
|
|
254
|
-
Writable => 'int32s',
|
|
255
|
-
PrintConv => { 0 => 'No', 1 => 'Yes' }, #PH (NC)
|
|
256
|
-
},
|
|
288
|
+
# 0x0045 - (FrontFacing, ref 2) (not for iPhone15, ref PH)
|
|
257
289
|
# 0x0046 - (TimeOfFlightAssistedAutoFocusEstimatorContainsBlindSpot, ref 2)
|
|
258
290
|
# 0x0047 - (LeaderFollowerAutoFocusLeaderDepth, ref 2)
|
|
259
291
|
# 0x0048 - (LeaderFollowerAutoFocusLeaderFocusMethod, ref 2)
|
|
260
292
|
# 0x0049 - (LeaderFollowerAutoFocusLeaderConfidence, ref 2)
|
|
261
293
|
# 0x004A - (LeaderFollowerAutoFocusLeaderROIType, ref 2)
|
|
294
|
+
# 0x004a - 2=back normal, 4=back wide angle, 5=front (ref PH)
|
|
262
295
|
# 0x004B - (ZeroShutterLagFailureReason, ref 2)
|
|
263
296
|
# 0x004C - (TimeOfFlightAssistedAutoFocusEstimatorMSPMeasuredDepth, ref 2)
|
|
264
297
|
# 0x004D - (TimeOfFlightAssistedAutoFocusEstimatorMSPSensorConfidence, ref 2)
|
|
265
298
|
# 0x004E - (Camera, ref 2)
|
|
299
|
+
0x004e => {
|
|
300
|
+
Name => 'Apple_0x004e',
|
|
301
|
+
Unknown => 1,
|
|
302
|
+
# first number is 0 for front cam, 1 for either back cam (ref PH)
|
|
303
|
+
ValueConv => \&ConvertPLIST,
|
|
304
|
+
},
|
|
305
|
+
0x004f => {
|
|
306
|
+
Name => 'Apple_0x004f',
|
|
307
|
+
Unknown => 1,
|
|
308
|
+
ValueConv => \&ConvertPLIST,
|
|
309
|
+
}
|
|
266
310
|
);
|
|
267
311
|
|
|
268
312
|
# PLIST-format CMTime structure (ref PH)
|
|
@@ -35,7 +35,7 @@ use Image::ExifTool::Sony;
|
|
|
35
35
|
use Image::ExifTool::Validate;
|
|
36
36
|
use Image::ExifTool::MacOS;
|
|
37
37
|
|
|
38
|
-
$VERSION = '3.
|
|
38
|
+
$VERSION = '3.56';
|
|
39
39
|
@ISA = qw(Exporter);
|
|
40
40
|
|
|
41
41
|
sub NumbersFirst($$);
|
|
@@ -95,16 +95,9 @@ my %tweakOrder = (
|
|
|
95
95
|
Lytro => 'SigmaRaw',
|
|
96
96
|
PhotoMechanic => 'FotoStation',
|
|
97
97
|
Microsoft => 'PhotoMechanic',
|
|
98
|
-
'Microsoft::MP'=> 'Microsoft::MP1',
|
|
99
98
|
GIMP => 'Microsoft',
|
|
100
|
-
'Nikon::CameraSettingsD300' => 'Nikon::ShotInfoD300b',
|
|
101
|
-
'Pentax::LensData' => 'Pentax::LensInfo2',
|
|
102
|
-
'Sony::SRF2' => 'Sony::SRF',
|
|
103
99
|
DarwinCore => 'AFCP',
|
|
104
|
-
|
|
105
|
-
'MWG::Keywords' => 'MWG::Regions',
|
|
106
|
-
'MWG::Collections' => 'MWG::Keywords',
|
|
107
|
-
'GoPro::fdsc' => 'GoPro::KBAT',
|
|
100
|
+
MWG => 'Shortcuts',
|
|
108
101
|
);
|
|
109
102
|
|
|
110
103
|
# list of all recognized Format strings
|
|
@@ -671,6 +664,18 @@ will extract all available information even for tags not listed.
|
|
|
671
664
|
Tags in these tables are referred to as "pseudo" tags because their
|
|
672
665
|
information is not stored in the file itself. As such, B<Writable> tags in
|
|
673
666
|
these tables may be changed without having to rewrite the file.
|
|
667
|
+
},
|
|
668
|
+
GM => q{
|
|
669
|
+
These tags are extracted from GM/Cosworth PDR (Performance Data Recorder)
|
|
670
|
+
information found in videos from General Motors cars such as Corvette and
|
|
671
|
+
Camero.
|
|
672
|
+
|
|
673
|
+
Use the API L<PrintCSV|../ExifTool.html#PrintCSV> option to output all timed
|
|
674
|
+
PDR data in CSV format at greatly increased speed and with much lower memory
|
|
675
|
+
usage. This option prints the numerical values for each channel in CSV
|
|
676
|
+
format, suitable for import into RaceRender. In this output, the gear
|
|
677
|
+
numbers for Neutral and Reverse are changed to -1 and -100 respectively for
|
|
678
|
+
compatibility with RaceRender.
|
|
674
679
|
},
|
|
675
680
|
PodTrailer => q{
|
|
676
681
|
~head1 NOTES
|
|
@@ -708,7 +713,7 @@ my %shortcutNotes = (
|
|
|
708
713
|
color space when deleting all other metadata
|
|
709
714
|
},
|
|
710
715
|
CommonIFD0 => q{
|
|
711
|
-
common metadata tags found in IFD0 of TIFF-format images. Used to
|
|
716
|
+
common metadata tags found in IFD0 of TIFF-format images. Used to simplify
|
|
712
717
|
deletion of all metadata from these images. See
|
|
713
718
|
L<FAQ number 7|../faq.html#Q7> for details
|
|
714
719
|
},
|
|
@@ -852,7 +857,7 @@ sub new
|
|
|
852
857
|
my ($tagID, $binaryTable, $noID, $hexID, $isIPTC, $isXMP);
|
|
853
858
|
$isIPTC = 1 if $writeProc and $writeProc eq \&Image::ExifTool::IPTC::WriteIPTC;
|
|
854
859
|
# generate flattened tag names for structure fields if this is an XMP table
|
|
855
|
-
if ($$table{GROUPS} and $$table{GROUPS}{0} eq 'XMP') {
|
|
860
|
+
if ($$table{GROUPS} and $$table{GROUPS}{0} eq 'XMP' or $$vars{ADD_FLATTENED}) {
|
|
856
861
|
Image::ExifTool::XMP::AddFlattenedTags($table);
|
|
857
862
|
$isXMP = 1;
|
|
858
863
|
}
|
|
@@ -1526,7 +1531,8 @@ TagID: foreach $tagID (@keys) {
|
|
|
1526
1531
|
my $fullName = ($strName =~ / / ? '' : 'XMP ') . "$strName Struct";
|
|
1527
1532
|
my $info = $tagNameInfo{$fullName} = [ ];
|
|
1528
1533
|
my $tag;
|
|
1529
|
-
|
|
1534
|
+
my $order = $$struct{SORT_ORDER} || [ sort keys %$struct ];
|
|
1535
|
+
foreach $tag (@$order) {
|
|
1530
1536
|
my $tagInfo = $$struct{$tag};
|
|
1531
1537
|
next unless ref $tagInfo eq 'HASH' and $tag ne 'NAMESPACE' and $tag ne 'GROUPS';
|
|
1532
1538
|
warn "WARNING: $strName Struct containes $tag\n" if $Image::ExifTool::specialTags{$tag};
|
|
@@ -1539,6 +1545,8 @@ TagID: foreach $tagID (@keys) {
|
|
|
1539
1545
|
push @vals, $writable;
|
|
1540
1546
|
$structs{$writable} = 1;
|
|
1541
1547
|
$writable = "=$writable";
|
|
1548
|
+
} elsif (defined $$tagInfo{Writable}) {
|
|
1549
|
+
$writable = 'no';
|
|
1542
1550
|
} else {
|
|
1543
1551
|
$writable = 'string';
|
|
1544
1552
|
}
|
|
@@ -1548,7 +1556,7 @@ TagID: foreach $tagID (@keys) {
|
|
|
1548
1556
|
# handle PrintConv lookups in Structure elements
|
|
1549
1557
|
my $printConv = $$tagInfo{PrintConv};
|
|
1550
1558
|
if (ref $printConv eq 'HASH') {
|
|
1551
|
-
foreach (sort keys %$printConv) {
|
|
1559
|
+
foreach (sort { NumbersFirst($a,$b) } keys %$printConv) {
|
|
1552
1560
|
next if /^(OTHER|BITMASK)$/;
|
|
1553
1561
|
push @vals, "$_ = $$printConv{$_}";
|
|
1554
1562
|
}
|
|
@@ -1822,24 +1830,7 @@ sub TweakOrder($$)
|
|
|
1822
1830
|
local $_;
|
|
1823
1831
|
my ($sortedTables, $tweakOrder) = @_;
|
|
1824
1832
|
my @tweak = sort keys %$tweakOrder;
|
|
1825
|
-
my (%
|
|
1826
|
-
# flag files which have a "Main" table
|
|
1827
|
-
foreach (@$sortedTables) {
|
|
1828
|
-
$addedMain{$1} = 0 if /^Image::ExifTool::(\w+)::(\w+)/ and $2 eq 'Main';
|
|
1829
|
-
}
|
|
1830
|
-
# make sure that the main table always comes first in each file
|
|
1831
|
-
foreach (@$sortedTables) {
|
|
1832
|
-
if (/^Image::ExifTool::(\w+)::(\w+)/) {
|
|
1833
|
-
if ($addedMain{$1}) {
|
|
1834
|
-
next if $2 eq 'Main'; # don't add again
|
|
1835
|
-
} elsif (defined $addedMain{$1}) {
|
|
1836
|
-
push @sorted, "Image::ExifTool::${1}::Main" if $2 ne 'Main';
|
|
1837
|
-
$addedMain{$1} = 1;
|
|
1838
|
-
}
|
|
1839
|
-
}
|
|
1840
|
-
push @sorted, $_;
|
|
1841
|
-
}
|
|
1842
|
-
@$sortedTables = @sorted;
|
|
1833
|
+
my (@sorted, %hasMain, %module, $entry);
|
|
1843
1834
|
# apply manual tweaks
|
|
1844
1835
|
while (@tweak) {
|
|
1845
1836
|
my $table = shift @tweak;
|
|
@@ -1858,6 +1849,31 @@ sub TweakOrder($$)
|
|
|
1858
1849
|
}
|
|
1859
1850
|
@$sortedTables = (@notMoving, @moving, @after);
|
|
1860
1851
|
}
|
|
1852
|
+
# flag modules which have a "Main" table, and organize tables by module name
|
|
1853
|
+
foreach (@$sortedTables) {
|
|
1854
|
+
if (not /^Image::ExifTool::(\w+)::(\w+)/) {
|
|
1855
|
+
push @sorted, $_;
|
|
1856
|
+
} else {
|
|
1857
|
+
$hasMain{$1} = 1 if $2 eq 'Main';
|
|
1858
|
+
push @sorted, $module{$1} = [ ] unless $module{$1};
|
|
1859
|
+
push @{$module{$1}}, $_;
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
# force MWG::Composite table first
|
|
1863
|
+
my @mwg = ( 'Image::ExifTool::MWG::Composite' );
|
|
1864
|
+
/Composite/ or push @mwg, $_ foreach @{$module{MWG}};
|
|
1865
|
+
@{$module{MWG}} = @mwg;
|
|
1866
|
+
# make sure that the main table always comes first in each file
|
|
1867
|
+
# and that all other tables from this group follow
|
|
1868
|
+
@$sortedTables = ( );
|
|
1869
|
+
foreach $entry (@sorted) {
|
|
1870
|
+
ref $entry or push(@$sortedTables, $entry), next;
|
|
1871
|
+
$$entry[0] =~ /^Image::ExifTool::(\w+)::(\w+)/ or die 'Internal error';
|
|
1872
|
+
my $main = "Image::ExifTool::$1::Main";
|
|
1873
|
+
# main table must come first (even if it doesn't exist)
|
|
1874
|
+
push @$sortedTables, $main if $hasMain{$1};
|
|
1875
|
+
$_ eq $main or push(@$sortedTables, $_) foreach @$entry;
|
|
1876
|
+
}
|
|
1861
1877
|
}
|
|
1862
1878
|
|
|
1863
1879
|
#------------------------------------------------------------------------------
|
|
@@ -23,7 +23,7 @@ use vars qw($VERSION);
|
|
|
23
23
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
24
24
|
use Image::ExifTool::Canon;
|
|
25
25
|
|
|
26
|
-
$VERSION = '1.
|
|
26
|
+
$VERSION = '1.41';
|
|
27
27
|
|
|
28
28
|
sub ProcessCanonVRD($$;$);
|
|
29
29
|
sub WriteCanonVRD($$;$);
|
|
@@ -1020,6 +1020,18 @@ my $blankFooter = "CANON OPTIONAL DATA\0" . ("\0" x 42) . "\xff\xd9";
|
|
|
1020
1020
|
# 0x10018 - fmt=8: 0
|
|
1021
1021
|
# 0x10020 - fmt=2: ''
|
|
1022
1022
|
0x10021 => 'CustomPictureStyle', # (string)
|
|
1023
|
+
0x10100 => { #forum15965
|
|
1024
|
+
Name => 'Rating',
|
|
1025
|
+
PrintConv => {
|
|
1026
|
+
0 => 'Unrated',
|
|
1027
|
+
1 => 1,
|
|
1028
|
+
2 => 2,
|
|
1029
|
+
3 => 3,
|
|
1030
|
+
4 => 4,
|
|
1031
|
+
5 => 5,
|
|
1032
|
+
4294967295 => 'Rejected',
|
|
1033
|
+
},
|
|
1034
|
+
},
|
|
1023
1035
|
0x10101 => {
|
|
1024
1036
|
Name => 'CheckMark',
|
|
1025
1037
|
PrintConv => {
|
|
@@ -1427,15 +1439,16 @@ my $blankFooter = "CANON OPTIONAL DATA\0" . ("\0" x 42) . "\xff\xd9";
|
|
|
1427
1439
|
4 => 'CropY',
|
|
1428
1440
|
5 => 'CropWidth',
|
|
1429
1441
|
6 => 'CropHeight',
|
|
1442
|
+
7 => 'CropRotation',
|
|
1430
1443
|
8 => {
|
|
1431
|
-
Name => '
|
|
1444
|
+
Name => 'CropAngle',
|
|
1432
1445
|
Format => 'double',
|
|
1433
1446
|
PrintConv => 'sprintf("%.7g",$val)',
|
|
1434
1447
|
PrintConvInv => '$val',
|
|
1435
1448
|
},
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
#
|
|
1449
|
+
10 => 'CropOriginalWidth',
|
|
1450
|
+
11 => 'CropOriginalHeight',
|
|
1451
|
+
# 12 double - value: 100
|
|
1439
1452
|
);
|
|
1440
1453
|
|
|
1441
1454
|
# DR4 Stamp Tool tags (ref PH)
|
|
@@ -1758,7 +1771,7 @@ sub ProcessDR4($$;$)
|
|
|
1758
1771
|
} else {
|
|
1759
1772
|
# load DR4 file into memory
|
|
1760
1773
|
my $buff;
|
|
1761
|
-
$raf->Read($buff, 8) == 8 and $buff
|
|
1774
|
+
$raf->Read($buff, 8) == 8 and $buff =~ /^IIII[\x04|\x05]\0\x04\0/ or return 0;
|
|
1762
1775
|
$et->SetFileType();
|
|
1763
1776
|
$raf->Seek(0, 2) or return $err = 1;
|
|
1764
1777
|
$dirLen = $raf->Tell();
|
|
@@ -19,6 +19,7 @@ use Image::ExifTool::GPS;
|
|
|
19
19
|
$VERSION = '1.09';
|
|
20
20
|
|
|
21
21
|
sub ProcessDJIInfo($$$);
|
|
22
|
+
sub Process_djmd($$$);
|
|
22
23
|
|
|
23
24
|
my %convFloat2 = (
|
|
24
25
|
PrintConv => 'sprintf("%+.2f", $val)',
|
|
@@ -186,6 +187,34 @@ my %convFloat2 = (
|
|
|
186
187
|
},
|
|
187
188
|
);
|
|
188
189
|
|
|
190
|
+
# TODO - eventually add ability to decode this?
|
|
191
|
+
%Image::ExifTool::DJI::djmd = (
|
|
192
|
+
PROCESS_PROC => \&Process_djmd,
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
#------------------------------------------------------------------------------
|
|
196
|
+
# Process DJI djmd timed data from Action4 videos (ref PH)
|
|
197
|
+
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
|
|
198
|
+
# Returns: 1 on success
|
|
199
|
+
# TODO: work in progress
|
|
200
|
+
sub Process_djmd($$$)
|
|
201
|
+
{
|
|
202
|
+
my ($et, $dirInfo, $tagTbl) = @_;
|
|
203
|
+
my $dataPt = $$dirInfo{DataPt};
|
|
204
|
+
my ($pos, $bit, $val) = (6, 0, 0);
|
|
205
|
+
for (;;) {
|
|
206
|
+
my $v = Get8u($dataPt, $pos);
|
|
207
|
+
$val += ($v & 0x7f) << $bit;
|
|
208
|
+
last unless $v & 0x80;
|
|
209
|
+
++$pos;
|
|
210
|
+
$bit += 7;
|
|
211
|
+
}
|
|
212
|
+
$pos += 49;
|
|
213
|
+
my @a = unpack("x${pos}fxfxfxfx3fxfxf", $$dataPt);
|
|
214
|
+
print "$val @a\n";
|
|
215
|
+
return 1;
|
|
216
|
+
}
|
|
217
|
+
|
|
189
218
|
#------------------------------------------------------------------------------
|
|
190
219
|
# Process DJI info (ref PH)
|
|
191
220
|
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
|