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
@@ -12,7 +12,7 @@ require Exporter;
|
|
12
12
|
|
13
13
|
use vars qw($VERSION @ISA @EXPORT_OK);
|
14
14
|
|
15
|
-
$VERSION = '1.
|
15
|
+
$VERSION = '1.13';
|
16
16
|
@ISA = qw(Exporter);
|
17
17
|
@EXPORT_OK = qw(ReadCSV ReadJSON);
|
18
18
|
|
@@ -87,6 +87,7 @@ sub ReadCSV($$;$$)
|
|
87
87
|
$fileInfo{$tags[$i]} =
|
88
88
|
(defined $missingValue and $vals[$i] eq $missingValue) ? undef : $vals[$i];
|
89
89
|
}
|
90
|
+
$fileInfo{_ordered_keys_} = \@tags;
|
90
91
|
# figure out the file name to use
|
91
92
|
if ($fileInfo{SourceFile}) {
|
92
93
|
$$database{$fileInfo{SourceFile}} = \%fileInfo;
|
@@ -173,7 +174,7 @@ Tok: for (;;) {
|
|
173
174
|
}
|
174
175
|
# see what type of object this is
|
175
176
|
if ($tok eq '{') { # object (hash)
|
176
|
-
$rtnVal = { } unless defined $rtnVal;
|
177
|
+
$rtnVal = { _ordered_keys_ => [ ] } unless defined $rtnVal;
|
177
178
|
for (;;) {
|
178
179
|
# read "KEY":"VALUE" pairs
|
179
180
|
unless (defined $key) {
|
@@ -189,6 +190,7 @@ Tok: for (;;) {
|
|
189
190
|
$pos = pos $$buffPt;
|
190
191
|
return undef unless defined $val;
|
191
192
|
$$rtnVal{$key} = $val;
|
193
|
+
push @{$$rtnVal{_ordered_keys_}}, $key;
|
192
194
|
undef $key;
|
193
195
|
}
|
194
196
|
# scan to delimiting ',' or bounding '}'
|
@@ -345,7 +347,9 @@ option for a list of valid character sets.
|
|
345
347
|
These functions return an error string, or undef on success and populate the
|
346
348
|
database hash with entries from the CSV or JSON file. Entries are keyed
|
347
349
|
based on the SourceFile column of the CSV or JSON information, and are
|
348
|
-
stored as hash lookups of tag name/value for each SourceFile.
|
350
|
+
stored as hash lookups of tag name/value for each SourceFile. The order
|
351
|
+
of the keys (CSV column order or order in a JSON object) is stored as an
|
352
|
+
ARRAY reference in a special "_ordered_keys_" element of this hash.
|
349
353
|
|
350
354
|
=back
|
351
355
|
|
@@ -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.09';
|
18
18
|
|
19
19
|
# map for writing metadata to InDesign files (currently only write XMP)
|
20
20
|
my %indMap = (
|
@@ -104,9 +104,10 @@ sub ProcessIND($$)
|
|
104
104
|
# this must be null padding or we have a possible error
|
105
105
|
last if $hdr =~ /^\0+$/;
|
106
106
|
# (could be up to 4095 bytes of non-null garbage plus 4095 null bytes from ExifTool)
|
107
|
-
$raf->Read($buff,
|
107
|
+
$raf->Read($buff, 8192) and $hdr .= $buff;
|
108
|
+
my $n = length $hdr;
|
108
109
|
$hdr =~ s/\0+$//; # remove trailing nulls
|
109
|
-
if (length($hdr) > 4095) {
|
110
|
+
if ($n > 8190 or length($hdr) > 4095) {
|
110
111
|
$err = 'Corrupt file or unsupported InDesign version';
|
111
112
|
last;
|
112
113
|
}
|
@@ -14,7 +14,7 @@ use vars qw($VERSION);
|
|
14
14
|
use Image::ExifTool qw(:DataAccess :Utils);
|
15
15
|
use Image::ExifTool::Import;
|
16
16
|
|
17
|
-
$VERSION = '1.
|
17
|
+
$VERSION = '1.09';
|
18
18
|
|
19
19
|
sub ProcessJSON($$);
|
20
20
|
sub ProcessTag($$$$%);
|
@@ -92,8 +92,7 @@ sub ProcessTag($$$$%)
|
|
92
92
|
return unless $et->Options('Struct') > 1;
|
93
93
|
}
|
94
94
|
# support hashes with ordered keys
|
95
|
-
|
96
|
-
foreach (@keys) {
|
95
|
+
foreach (Image::ExifTool::OrderedKeys($val)) {
|
97
96
|
my $tg = $tag . ((/^\d/ and $tag =~ /\d$/) ? '_' : '') . ucfirst;
|
98
97
|
$tg =~ s/([^a-zA-Z])([a-z])/$1\U$2/g;
|
99
98
|
ProcessTag($et, $tagTablePtr, $tg, $$val{$_}, %flags, Flat => 1);
|
@@ -155,7 +154,7 @@ sub ProcessJSON($$)
|
|
155
154
|
|
156
155
|
# extract tags from JSON database
|
157
156
|
foreach $key (sort keys %database) {
|
158
|
-
foreach $tag (
|
157
|
+
foreach $tag (Image::ExifTool::OrderedKeys($database{$key})) {
|
159
158
|
my $val = $database{$key}{$tag};
|
160
159
|
# (ignore SourceFile if generated automatically by ReadJSON)
|
161
160
|
next if $tag eq 'SourceFile' and defined $val and $val eq '*';
|
@@ -16,7 +16,7 @@ use strict;
|
|
16
16
|
use vars qw($VERSION);
|
17
17
|
use Image::ExifTool qw(:DataAccess :Utils);
|
18
18
|
|
19
|
-
$VERSION = '1.
|
19
|
+
$VERSION = '1.41';
|
20
20
|
|
21
21
|
sub ProcessJpeg2000Box($$$);
|
22
22
|
sub ProcessJUMD($$$);
|
@@ -574,6 +574,7 @@ my %j2cMarker = (
|
|
574
574
|
2 => {
|
575
575
|
Name => 'CompatibleBrands',
|
576
576
|
Format => 'undef[$size-8]',
|
577
|
+
List => 1, # (for documentation only)
|
577
578
|
# ignore any entry with a null, and return others as a list
|
578
579
|
ValueConv => 'my @a=($val=~/.{4}/sg); @a=grep(!/\0/,@a); \@a',
|
579
580
|
},
|
@@ -15,7 +15,7 @@ use vars qw($VERSION);
|
|
15
15
|
use Image::ExifTool qw(:DataAccess :Utils);
|
16
16
|
use Image::ExifTool::Import;
|
17
17
|
|
18
|
-
$VERSION = '1.
|
18
|
+
$VERSION = '1.04';
|
19
19
|
|
20
20
|
sub ExtractTags($$$);
|
21
21
|
|
@@ -106,7 +106,7 @@ sub ExtractTags($$$)
|
|
106
106
|
my ($et, $meta, $parent) = @_;
|
107
107
|
ref $meta eq 'HASH' or $et->Warn('Invalid LFP metadata'), return;
|
108
108
|
my ($key, $val, $name, $tagTablePtr);
|
109
|
-
foreach $key (
|
109
|
+
foreach $key (Image::ExifTool::OrderedKeys($meta)) {
|
110
110
|
my $tag = $parent . ucfirst($key);
|
111
111
|
foreach $val (ref $$meta{$key} eq 'ARRAY' ? @{$$meta{$key}} : $$meta{$key}) {
|
112
112
|
ref $val eq 'HASH' and ExtractTags($et, $val, $tag), next;
|
@@ -328,6 +328,14 @@ sub ParsePID($$$$$)
|
|
328
328
|
$more = 1; # read past unknown 0x15 packets if ExtractEmbedded > 2
|
329
329
|
}
|
330
330
|
}
|
331
|
+
# still have a lot of questions about how to decode this...
|
332
|
+
# (see https://exiftool.org/forum/index.php?topic=16486 and ../testpics/gps_video/forum16486.ts)
|
333
|
+
# } elsif ($type == 6) {
|
334
|
+
# my @a = unpack('x17x2NNx2nx2nx2nx2Cx2a4x2a5x2Nx2Nx2nx2Nx2Nx2Nx2nx2nx2Nx2nx2n', $$dataPt . " ");
|
335
|
+
# my $hi = shift @a;
|
336
|
+
# $a[0] = Image::ExifTool::ConvertUnixTime(($a[0] + $hi * 4294967296) * 1e-6, undef, 6);
|
337
|
+
# print "@a\n";
|
338
|
+
# $more = 1;
|
331
339
|
} elsif ($type < 0) {
|
332
340
|
if ($$dataPt =~ /^(.{164})?(.{24})A[NS][EW]/s) {
|
333
341
|
# (Blueskysea B4K, Novatek NT96670)
|
@@ -48,7 +48,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
48
48
|
use Image::ExifTool::Exif;
|
49
49
|
use Image::ExifTool::GPS;
|
50
50
|
|
51
|
-
$VERSION = '3.
|
51
|
+
$VERSION = '3.04';
|
52
52
|
|
53
53
|
sub ProcessMOV($$;$);
|
54
54
|
sub ProcessKeys($$$);
|
@@ -901,6 +901,7 @@ my %userDefined = (
|
|
901
901
|
Writable => 1,
|
902
902
|
},
|
903
903
|
# '35AX'? - seen "AT" (Yada RoadCam Pro 4K dashcam)
|
904
|
+
cust => 'CustomInfo', # 70mai A810
|
904
905
|
);
|
905
906
|
|
906
907
|
# stuff seen in 'skip' atom (70mai Pro Plus+ MP4 videos)
|
@@ -935,6 +936,7 @@ my %userDefined = (
|
|
935
936
|
2 => {
|
936
937
|
Name => 'CompatibleBrands',
|
937
938
|
Format => 'undef[$size-8]',
|
939
|
+
List => 1, # (for documentation only)
|
938
940
|
# ignore any entry with a null, and return others as a list
|
939
941
|
ValueConv => 'my @a=($val=~/.{4}/sg); @a=grep(!/\0/,@a); \@a',
|
940
942
|
},
|
@@ -2551,7 +2553,7 @@ my %userDefined = (
|
|
2551
2553
|
TTID => { Name => 'TomTomID', ValueConv => 'unpack("x4H*",$val)' },
|
2552
2554
|
TTVI => { Name => 'TomTomVI', Format => 'int32u', Unknown => 1 }, # seen: "0 1 61 508 508"
|
2553
2555
|
# TTVD seen: "normal 720p 60fps 60fps 16/9 wide 1x"
|
2554
|
-
TTVD => { Name => 'TomTomVD', ValueConv => 'my @a = ($val =~ /[\x20-\x7f]+/g); "@a"' },
|
2556
|
+
TTVD => { Name => 'TomTomVD', ValueConv => 'my @a = ($val =~ /[\x20-\x7f]+/g); "@a"', List => 1 },
|
2555
2557
|
);
|
2556
2558
|
|
2557
2559
|
# User-specific media data atoms (ref 11)
|
@@ -3350,6 +3352,7 @@ my %userDefined = (
|
|
3350
3352
|
PrintConv => '"Track $val"',
|
3351
3353
|
},
|
3352
3354
|
# cdep (Structural Dependency QT tag?)
|
3355
|
+
# fall - ? int32u, seen: 2
|
3353
3356
|
);
|
3354
3357
|
|
3355
3358
|
# track aperture mode dimensions atoms
|
@@ -6743,6 +6746,13 @@ my %userDefined = (
|
|
6743
6746
|
Avoid => 1,
|
6744
6747
|
%iso8601Date,
|
6745
6748
|
},
|
6749
|
+
# (mdta)com.apple.quicktime.scene-illuminance
|
6750
|
+
'scene-illuminance' => {
|
6751
|
+
Name => 'SceneIlluminance',
|
6752
|
+
Notes => 'milli-lux',
|
6753
|
+
ValueConv => 'unpack("N", $val)',
|
6754
|
+
Writable => 0, # (don't make this writable because it is found in timed metadata)
|
6755
|
+
},
|
6746
6756
|
#
|
6747
6757
|
# seen in Apple ProRes RAW file
|
6748
6758
|
#
|
@@ -7392,6 +7402,7 @@ my %userDefined = (
|
|
7392
7402
|
# alac - 28 bytes
|
7393
7403
|
# adrm - AAX DRM atom? 148 bytes
|
7394
7404
|
# aabd - AAX unknown 17kB (contains 'aavd' strings)
|
7405
|
+
# dapa - ? 203 bytes
|
7395
7406
|
);
|
7396
7407
|
|
7397
7408
|
# AMR decode config box (ref 3)
|
@@ -9151,7 +9162,7 @@ sub HandleItemInfo($)
|
|
9151
9162
|
$et->ProcessDirectory(\%dirInfo, $subTable, $proc);
|
9152
9163
|
delete $$et{DOC_NUM};
|
9153
9164
|
}
|
9154
|
-
$raf->Seek($curPos, 0); # seek back to original position
|
9165
|
+
$raf->Seek($curPos, 0) or $et->Warn('Seek error'), last; # seek back to original position
|
9155
9166
|
pop @{$$et{PATH}};
|
9156
9167
|
}
|
9157
9168
|
# process the item properties now that we should know their associations and document numbers
|
@@ -9577,7 +9588,7 @@ sub ProcessMOV($$;$)
|
|
9577
9588
|
if ($tag eq 'ftyp' and $size >= 12) {
|
9578
9589
|
# read ftyp atom to see what type of file this is
|
9579
9590
|
if ($raf->Read($buff, $size-8) == $size-8) {
|
9580
|
-
$raf->Seek(-($size-8), 1);
|
9591
|
+
$raf->Seek(-($size-8), 1) or $et->Warn('Seek error'), return 0;
|
9581
9592
|
my $type = substr($buff, 0, 4);
|
9582
9593
|
$$et{save_ftyp} = $type;
|
9583
9594
|
# see if we know the extension for this file type
|
@@ -9629,7 +9640,7 @@ sub ProcessMOV($$;$)
|
|
9629
9640
|
# a zero size isn't legal for contained atoms, but Canon uses it to
|
9630
9641
|
# terminate the CNTH atom (eg. CanonEOS100D.mov), so tolerate it here
|
9631
9642
|
my $pos = $raf->Tell() - 4;
|
9632
|
-
$raf->Seek(0,2);
|
9643
|
+
$raf->Seek(0,2) or $et->Warn('Seek error'), return 0;
|
9633
9644
|
my $str = $$dirInfo{DirName} . ' with ' . ($raf->Tell() - $pos) . ' bytes';
|
9634
9645
|
$et->VPrint(0,"$$et{INDENT}\[Terminator found in $str remaining]");
|
9635
9646
|
} else {
|
@@ -9638,7 +9649,7 @@ sub ProcessMOV($$;$)
|
|
9638
9649
|
if ($$tagTablePtr{"$tag-size"}) {
|
9639
9650
|
my $pos = $raf->Tell();
|
9640
9651
|
unless ($fast) {
|
9641
|
-
$raf->Seek(0, 2);
|
9652
|
+
$raf->Seek(0, 2) or $et->Warn('Seek error'), return 0;
|
9642
9653
|
$et->HandleTag($tagTablePtr, "$tag-size", $raf->Tell() - $pos);
|
9643
9654
|
}
|
9644
9655
|
$et->HandleTag($tagTablePtr, "$tag-offset", $pos) if $$tagTablePtr{"$tag-offset"};
|
@@ -109,7 +109,7 @@ my %insvLimit = (
|
|
109
109
|
The tags below are extracted from timed metadata in QuickTime and other
|
110
110
|
formats of video files when the ExtractEmbedded option is used. Although
|
111
111
|
most of these tags are combined into the single table below, ExifTool
|
112
|
-
currently reads
|
112
|
+
currently reads 78 different formats of timed GPS metadata from video files.
|
113
113
|
},
|
114
114
|
VARS => { NO_ID => 1 },
|
115
115
|
GPSLatitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', RawConv => '$$self{FoundGPSLatitude} = 1; $val' },
|
@@ -2163,9 +2163,26 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
2163
2163
|
push(@xtra, $1 => $2), next;
|
2164
2164
|
}
|
2165
2165
|
|
2166
|
+
} elsif ($$dataPt =~ m/^.{30}A.{20}VV/) {
|
2167
|
+
|
2168
|
+
$debug and $et->FoundTag(GPSType => 17);
|
2169
|
+
# 70mai A810 dashcam (note: no timestamps in the samples I have)
|
2170
|
+
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 ed 01 00 00 [..@.freeGPS ....]
|
2171
|
+
# 0010: 03 00 ed 01 00 00 00 0f 00 00 70 08 00 00 41 66 [..........p...Af]
|
2172
|
+
# 0020: 13 7d 1e 3c 11 dc 03 5d 01 00 00 01 00 00 00 23 [.}.<...].......#]
|
2173
|
+
# 0030: 00 00 00 56 56 00 00 00 00 00 00 00 00 00 00 00 [...VV...........]
|
2174
|
+
# 0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
2175
|
+
SetByteOrder('II');
|
2176
|
+
SetGPSDateTime($et, $tagTbl, $$dirInfo{SampleTime});
|
2177
|
+
$lat = Get32s($dataPt, 31) / 1e5;
|
2178
|
+
$lon = Get32s($dataPt, 35) / 1e5;
|
2179
|
+
$spd = Get32s($dataPt, 43); # (seems to be km/h but not confirmed)
|
2180
|
+
# offset 475 - int16u=N string[N] - some sort of settings?:
|
2181
|
+
# eg. "\x15\x00{pA:V,rA:V,sF:0,tF:2}"
|
2182
|
+
|
2166
2183
|
} else {
|
2167
2184
|
|
2168
|
-
$debug and $et->FoundTag(GPSType =>
|
2185
|
+
$debug and $et->FoundTag(GPSType => 18);
|
2169
2186
|
# (look for binary GPS as stored by Nextbase 512G, ref PH)
|
2170
2187
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 78 01 00 00 [....freeGPS x...]
|
2171
2188
|
# 0010: 78 2e 78 78 00 00 00 00 00 00 00 00 00 00 00 00 [x.xx............]
|
@@ -34,7 +34,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
34
34
|
use Image::ExifTool::Exif;
|
35
35
|
use Image::ExifTool::Minolta;
|
36
36
|
|
37
|
-
$VERSION = '3.
|
37
|
+
$VERSION = '3.70';
|
38
38
|
|
39
39
|
sub ProcessSRF($$$);
|
40
40
|
sub ProcessSR2($$$);
|
@@ -170,6 +170,7 @@ sub PrintInvLensSpec($;$$);
|
|
170
170
|
32885 => 'Sony FE 16-35mm F2.8 GM II', #JR
|
171
171
|
32886 => 'Sony FE 300mm F2.8 GM OSS', #JR
|
172
172
|
32887 => 'Sony E PZ 16-50mm F3.5-5.6 OSS II', #JR
|
173
|
+
32888 => 'Sony FE 85mm F1.4 GM II', #JR
|
173
174
|
|
174
175
|
# (comment this out so LensID will report the LensModel, which is more useful)
|
175
176
|
# 32952 => 'Metabones Canon EF Speed Booster Ultra', #JR (corresponds to 184, but 'Advanced' mode, LensMount reported as E-mount)
|
@@ -241,6 +242,8 @@ sub PrintInvLensSpec($;$$);
|
|
241
242
|
49474.9 => 'Viltrox 75mm F1.2 E', #JR
|
242
243
|
'49474.10' => 'Viltrox 20mm F2.8 FE', #JR
|
243
244
|
49475 => 'Tamron 50-300mm F4.5-6.3 Di III VC VXD', #JR (Model A069)
|
245
|
+
49476 => 'Tamron 28-300mm F4-7.1 Di III VC VXD', #JR (Model A074)
|
246
|
+
49477 => 'Tamron 90mm F2.8 Di III Macro VXD', #JR (Model F072)
|
244
247
|
|
245
248
|
49712 => 'Tokina FiRIN 20mm F2 FE AF', # (firmware Ver.01)
|
246
249
|
49713 => 'Tokina FiRIN 100mm F2.8 FE MACRO', # (firmware Ver.01)
|
@@ -299,6 +302,7 @@ sub PrintInvLensSpec($;$$);
|
|
299
302
|
50547 => 'Sigma 10-18mm F2.8 DC DN | C', #JR (023)
|
300
303
|
50548 => 'Sigma 15mm F1.4 DG DN DIAGONAL FISHEYE | A', #JR (024)
|
301
304
|
50549 => 'Sigma 50mm F1.2 DG DN | A', #JR (024)
|
305
|
+
50550 => 'Sigma 28-105mm F2.8 DG DN | A', #JR (024)
|
302
306
|
50551 => 'Sigma 28-45mm F1.8 DG DN | A', #JR (024)
|
303
307
|
|
304
308
|
50992 => 'Voigtlander SUPER WIDE-HELIAR 15mm F4.5 III', #JR
|
@@ -315,6 +319,7 @@ sub PrintInvLensSpec($;$$);
|
|
315
319
|
51003 => 'Voigtlander NOKTON 35mm F1.2 Aspherical SE', #JR
|
316
320
|
51006 => 'Voigtlander APO-LANTHAR 35mm F2 Aspherical', #JR
|
317
321
|
51007 => 'Voigtlander NOKTON 50mm F1 Aspherical', #JR
|
322
|
+
51008 => 'Voigtlander NOKTON 75mm F1.5 Aspherical', #JR
|
318
323
|
|
319
324
|
# lenses listed in the Sigma MC-11 list, but not yet seen:
|
320
325
|
# 504xx => 'Sigma 18-200mm F3.5-6.3 DC MACRO OS HSM | C + MC-11', # (014)
|
@@ -8686,7 +8686,6 @@ my %tagExists = (
|
|
8686
8686
|
'cont' => 1,
|
8687
8687
|
'contactnames' => 1,
|
8688
8688
|
'containerversion' => 1,
|
8689
|
-
'contake' => 1,
|
8690
8689
|
'contentbranding' => 1,
|
8691
8690
|
'contentdescribes' => 1,
|
8692
8691
|
'contentdescription' => 1,
|
@@ -8709,6 +8708,7 @@ my %tagExists = (
|
|
8709
8708
|
'contrastadjustment' => 1,
|
8710
8709
|
'contrastinfo' => 1,
|
8711
8710
|
'controller' => 1,
|
8711
|
+
'conttake' => 1,
|
8712
8712
|
'convergenceangle' => 1,
|
8713
8713
|
'convergencebaseimage' => 1,
|
8714
8714
|
'convergencedistance' => 1,
|
@@ -8820,6 +8820,7 @@ my %tagExists = (
|
|
8820
8820
|
'customfunctionsd30' => 1,
|
8821
8821
|
'customfunctionsd60' => 1,
|
8822
8822
|
'customfunctionsunknown' => 1,
|
8823
|
+
'custominfo' => 1,
|
8823
8824
|
'customsettingsd3' => 1,
|
8824
8825
|
'customsettingsd300' => 1,
|
8825
8826
|
'customsettingsd300s' => 1,
|
@@ -12014,6 +12015,7 @@ my %tagExists = (
|
|
12014
12015
|
'scenebalancealgorithmrevision' => 1,
|
12015
12016
|
'sceneclassification' => 1,
|
12016
12017
|
'scenecolorimetryestimates' => 1,
|
12018
|
+
'sceneilluminance' => 1,
|
12017
12019
|
'scheduleitemid' => 1,
|
12018
12020
|
'schemeinfo' => 1,
|
12019
12021
|
'schemetype' => 1,
|
@@ -12,7 +12,7 @@ meta information extracted from or written to a file.
|
|
12
12
|
=head1 TAG TABLES
|
13
13
|
|
14
14
|
The tables listed below give the names of all tags recognized by ExifTool.
|
15
|
-
They contain a total of
|
15
|
+
They contain a total of 28150 tags, with 17488 unique tag names.
|
16
16
|
|
17
17
|
B<Tag ID>, B<Index#> or B<Sequence> is given in the first column of each
|
18
18
|
table. A B<Tag ID> is the computer-readable equivalent of a tag name, and
|
@@ -26108,7 +26108,7 @@ the image undisplayable.
|
|
26108
26108
|
------ -------- --------
|
26109
26109
|
0 MajorBrand no
|
26110
26110
|
1 MinorVersion no
|
26111
|
-
2 CompatibleBrands no
|
26111
|
+
2 CompatibleBrands no+
|
26112
26112
|
|
26113
26113
|
=head3 Jpeg2000 ImageHeader Tags
|
26114
26114
|
|
@@ -26163,7 +26163,7 @@ from any tags found in this segment.
|
|
26163
26163
|
------ -------- --------
|
26164
26164
|
'Aperture' Aperture no
|
26165
26165
|
'ColorMode' ColorMode no
|
26166
|
-
'
|
26166
|
+
'ContTake' ContTake no
|
26167
26167
|
'ExpBias' ExposureCompensation no
|
26168
26168
|
'FNumber' FNumber no
|
26169
26169
|
'FWare' FirmwareVersion no
|
@@ -29846,6 +29846,7 @@ for the official QuickTime specification.
|
|
29846
29846
|
'PICT' PreviewPICT no
|
29847
29847
|
'_htc' HTCInfo QuickTime HTCInfo
|
29848
29848
|
'ardt' ARDroneFile no
|
29849
|
+
'cust' CustomInfo no
|
29849
29850
|
'frea' Kodak_frea Kodak frea
|
29850
29851
|
'free' KodakFree Kodak Free
|
29851
29852
|
Pittasoft QuickTime Pittasoft
|
@@ -29897,7 +29898,7 @@ for the official QuickTime specification.
|
|
29897
29898
|
The tags below are extracted from timed metadata in QuickTime and other
|
29898
29899
|
formats of video files when the ExtractEmbedded option is used. Although
|
29899
29900
|
most of these tags are combined into the single table below, ExifTool
|
29900
|
-
currently reads
|
29901
|
+
currently reads 78 different formats of timed GPS metadata from video files.
|
29901
29902
|
|
29902
29903
|
Tag Name Writable
|
29903
29904
|
-------- --------
|
@@ -30163,6 +30164,7 @@ changed via the config file.
|
|
30163
30164
|
'producer' Producer yes
|
30164
30165
|
'publisher' Publisher yes
|
30165
30166
|
'rating.user' UserRating yes
|
30167
|
+
'scene-illuminance' SceneIlluminance no
|
30166
30168
|
'software' Software yes
|
30167
30169
|
'still-image-time' StillImageTime no
|
30168
30170
|
'title' Title yes
|
@@ -30230,7 +30232,7 @@ Tags found in Pittasoft Blackvue dashcam "free" data.
|
|
30230
30232
|
------ -------- --------
|
30231
30233
|
0 MajorBrand no
|
30232
30234
|
1 MinorVersion no
|
30233
|
-
2 CompatibleBrands no
|
30235
|
+
2 CompatibleBrands no+
|
30234
30236
|
|
30235
30237
|
=head3 QuickTime OtherMeta Tags
|
30236
30238
|
|
@@ -31280,7 +31282,7 @@ Tags found in TomTom Bandit Action Cam MP4 videos.
|
|
31280
31282
|
'TTAD' TomTomAD QuickTime Stream
|
31281
31283
|
'TTHL' TomTomHL? no
|
31282
31284
|
'TTID' TomTomID no
|
31283
|
-
'TTVD' TomTomVD no
|
31285
|
+
'TTVD' TomTomVD no+
|
31284
31286
|
'TTVI' TomTomVI? no
|
31285
31287
|
|
31286
31288
|
=head3 QuickTime HintTrackInfo Tags
|
@@ -184,11 +184,19 @@ sub GetFreeEntries($)
|
|
184
184
|
{
|
185
185
|
my $dict = shift;
|
186
186
|
my %xrefFree;
|
187
|
-
#
|
188
|
-
# so we can simplify things for now and only support this type of entry
|
187
|
+
# we write xref stream entries in 'CNn' or 'CNNn' format (with 8-byte 'NN' offset),
|
189
188
|
my $w = $$dict{W};
|
190
|
-
if (ref $w eq 'ARRAY'
|
191
|
-
my $
|
189
|
+
if (ref $w eq 'ARRAY') {
|
190
|
+
my $bytes = "@$w";
|
191
|
+
my $fmt;
|
192
|
+
if ($bytes eq '1 4 2') {
|
193
|
+
$fmt = 'CNn';
|
194
|
+
} elsif ($bytes eq '1 8 2') {
|
195
|
+
$fmt = 'CNNn';
|
196
|
+
} else {
|
197
|
+
return \%xrefFree;
|
198
|
+
}
|
199
|
+
my $size = $$dict{_entry_size}; # this will be 7 for 'CNn' or 11 for 'CNNn'
|
192
200
|
my $index = $$dict{Index};
|
193
201
|
my $len = length $$dict{_stream};
|
194
202
|
# scan the table for free objects
|
@@ -200,7 +208,12 @@ sub GetFreeEntries($)
|
|
200
208
|
my $count = $$index[$i*2+1];
|
201
209
|
for ($j=0; $j<$count; ++$j) {
|
202
210
|
last if $pos + $size > $len;
|
203
|
-
my @t = unpack("x$pos
|
211
|
+
my @t = unpack("x$pos $fmt", $$dict{_stream});
|
212
|
+
if (@t == 4) {
|
213
|
+
$t[1] = $t[1] * 4294967296 + $t[2];
|
214
|
+
$t[2] = $t[3];
|
215
|
+
@t = 3;
|
216
|
+
}
|
204
217
|
# add entry if object was free
|
205
218
|
$xrefFree{$start+$j} = [ $t[1], $t[2], 'f' ] if $t[0] == 0;
|
206
219
|
$pos += $size; # step to next entry
|
@@ -657,24 +670,37 @@ sub WritePDF($$)
|
|
657
670
|
$newXRef{$nextObject++} = [ Tell($outfile) - $$et{PDFBase} + length($/), 0, 'n' ];
|
658
671
|
$$mainDict{Size} = $nextObject;
|
659
672
|
# create xref stream and Index entry
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
my
|
666
|
-
|
667
|
-
$
|
668
|
-
|
669
|
-
|
670
|
-
$
|
671
|
-
|
673
|
+
my $bits = 4;
|
674
|
+
Restart: for (;;) {
|
675
|
+
$$mainDict{W} = [ 1, $bits, 2 ]; # int8u, int32u/int64u, int16u ('CNn' or 'CNNn')
|
676
|
+
$$mainDict{Index} = [ ];
|
677
|
+
$$mainDict{_stream} = '';
|
678
|
+
my @ids = sort { $a <=> $b } keys %newXRef;
|
679
|
+
while (@ids) {
|
680
|
+
my $startID = $ids[0];
|
681
|
+
for (;;) {
|
682
|
+
$id = shift @ids;
|
683
|
+
my ($pos, $gen, $type) = @{$newXRef{$id}};
|
684
|
+
if ($pos > 0xffffffff) {
|
685
|
+
if ($bits == 4) {
|
686
|
+
# switch to 64-bit integer offsets
|
687
|
+
$bits = 8;
|
688
|
+
next Restart;
|
689
|
+
}
|
690
|
+
}
|
691
|
+
if ($bits == 4) {
|
692
|
+
$$mainDict{_stream} .= pack('CNn', $type eq 'f' ? 0 : 1, $pos, $gen);
|
693
|
+
} else {
|
694
|
+
my $hi = int($pos / 4294967296);
|
695
|
+
my $lo = $pos - $hi * 4294967296;
|
696
|
+
$$mainDict{_stream} .= pack('CNNn', $type eq 'f' ? 0 : 1, $hi, $lo, $gen);
|
697
|
+
}
|
698
|
+
last if not @ids or $ids[0] != $id + 1;
|
672
699
|
}
|
673
|
-
|
674
|
-
|
700
|
+
# add Index entries for this section of the xref stream
|
701
|
+
push @{$$mainDict{Index}}, $startID, $id - $startID + 1;
|
675
702
|
}
|
676
|
-
|
677
|
-
push @{$$mainDict{Index}}, $startID, $id - $startID + 1;
|
703
|
+
last;
|
678
704
|
}
|
679
705
|
# write the xref stream object
|
680
706
|
$keyExt = "$id 0 obj"; # (set anyway, but xref stream should NOT be encrypted)
|
@@ -925,19 +925,31 @@ sub WriteXMP($$;$)
|
|
925
925
|
# get hash of all information we want to change
|
926
926
|
# (sorted by tag name so alternate languages come last, but with structures
|
927
927
|
# first so flattened tags may be used to override individual structure elements)
|
928
|
-
my (@tagInfoList, $delLangPath, %delLangPaths, %delAllLang, $firstNewPath);
|
928
|
+
my (@tagInfoList, @structList, $delLangPath, %delLangPaths, %delAllLang, $firstNewPath, @langTags);
|
929
929
|
my $writeGroup = $$dirInfo{WriteGroup};
|
930
930
|
foreach $tagInfo (sort ByTagName $et->GetNewTagInfoList()) {
|
931
931
|
next unless $et->GetGroup($tagInfo, 0) eq 'XMP';
|
932
932
|
next if $$tagInfo{Name} eq 'XMP'; # (ignore full XMP block if we didn't write it already)
|
933
933
|
next if $writeGroup and $writeGroup ne $$et{NEW_VALUE}{$tagInfo}{WriteGroup};
|
934
|
-
if ($$tagInfo{
|
935
|
-
|
934
|
+
if ($$tagInfo{LangCode}) {
|
935
|
+
push @langTags, $tagInfo
|
936
|
+
} elsif ($$tagInfo{Struct}) {
|
937
|
+
push @structList, $tagInfo;
|
936
938
|
} else {
|
937
939
|
push @tagInfoList, $tagInfo;
|
938
940
|
}
|
939
941
|
}
|
940
|
-
|
942
|
+
if (@langTags) {
|
943
|
+
# keep original order in which lang-alt entries were added
|
944
|
+
foreach $tagInfo (sort { $$et{NEW_VALUE}{$a}{Order} <=> $$et{NEW_VALUE}{$b}{Order} } @langTags) {
|
945
|
+
if ($$tagInfo{Struct}) {
|
946
|
+
push @structList, $tagInfo;
|
947
|
+
} else {
|
948
|
+
push @tagInfoList, $tagInfo;
|
949
|
+
}
|
950
|
+
}
|
951
|
+
}
|
952
|
+
foreach $tagInfo (@structList, @tagInfoList) {
|
941
953
|
my @delPaths; # list of deleted paths
|
942
954
|
my $tag = $$tagInfo{TagID};
|
943
955
|
my $path = GetPropertyPath($tagInfo);
|
@@ -295,10 +295,11 @@ my %ignorePrintConv = map { $_ => 1 } qw(OTHER BITMASK Notes);
|
|
295
295
|
# CreateGroups - hash of all family 0 group names where tag may be created
|
296
296
|
# WriteGroup - group name where information is being written (correct case)
|
297
297
|
# WantGroup - group name as specified in call to function (case insensitive)
|
298
|
-
# Next - pointer to next new value hash (if more than one)
|
298
|
+
# Next - pointer to next new value hash (if more than one for this tag)
|
299
299
|
# NoReplace - set if value was created with Replace=0
|
300
300
|
# AddBefore - number of list items added by a subsequent Replace=0 call
|
301
|
-
# IsNVH -
|
301
|
+
# IsNVH - flag indicating this is a new value hash
|
302
|
+
# Order - counter to indicate the order that new value hashes were created
|
302
303
|
# Shift - shift value
|
303
304
|
# Save - counter used by SaveNewValues()/RestoreNewValues()
|
304
305
|
# MAKER_NOTE_FIXUP - pointer to fixup if necessary for a maker note value
|
@@ -317,7 +318,7 @@ sub SetNewValue($;$$%)
|
|
317
318
|
|
318
319
|
unless (defined $tag) {
|
319
320
|
delete $$self{NEW_VALUE};
|
320
|
-
$$self{SAVE_COUNT} = 0;
|
321
|
+
$$self{SAVE_COUNT} = $$self{NV_COUNT} = 0;
|
321
322
|
$$self{DEL_GROUP} = { };
|
322
323
|
return 1;
|
323
324
|
}
|
@@ -1389,8 +1390,16 @@ sub SetNewValuesFromFile($$;@)
|
|
1389
1390
|
return $info if $$info{Error} and $$info{Error} eq 'Error opening file';
|
1390
1391
|
delete $$srcExifTool{VALUE}{Error}; # delete so we can check this later
|
1391
1392
|
|
1392
|
-
# sort tags in
|
1393
|
-
my @tags
|
1393
|
+
# sort tags in file order with priority tags last
|
1394
|
+
my (@tags, @prio);
|
1395
|
+
foreach (sort { $$srcExifTool{FILE_ORDER}{$a} <=> $$srcExifTool{FILE_ORDER}{$b} } keys %$info) {
|
1396
|
+
if (/ /) {
|
1397
|
+
push @tags, $_;
|
1398
|
+
} else {
|
1399
|
+
push @prio, $_;
|
1400
|
+
}
|
1401
|
+
}
|
1402
|
+
push @tags, @prio;
|
1394
1403
|
#
|
1395
1404
|
# simply transfer all tags from source image if no tags specified
|
1396
1405
|
#
|
@@ -3896,6 +3905,7 @@ sub GetNewValueHash($$;$$$$)
|
|
3896
3905
|
TagInfo => $tagInfo,
|
3897
3906
|
WriteGroup => $writeGroup,
|
3898
3907
|
IsNVH => 1, # set flag so we can recognize a new value hash
|
3908
|
+
Order => $$self{NV_COUNT}++,
|
3899
3909
|
};
|
3900
3910
|
# add entry to our NEW_VALUE hash
|
3901
3911
|
if ($$self{NEW_VALUE}{$tagInfo}) {
|
@@ -4023,7 +4033,7 @@ sub RemoveNewValuesForGroup($$)
|
|
4023
4033
|
#------------------------------------------------------------------------------
|
4024
4034
|
# Get list of tagInfo hashes for all new data
|
4025
4035
|
# Inputs: 0) ExifTool object reference, 1) optional tag table pointer
|
4026
|
-
# Returns: list of tagInfo hashes
|
4036
|
+
# Returns: list of tagInfo hashes in no particular order
|
4027
4037
|
sub GetNewTagInfoList($;$)
|
4028
4038
|
{
|
4029
4039
|
my ($self, $tagTablePtr) = @_;
|
@@ -50,7 +50,7 @@ use Image::ExifTool::Exif;
|
|
50
50
|
use Image::ExifTool::GPS;
|
51
51
|
require Exporter;
|
52
52
|
|
53
|
-
$VERSION = '3.
|
53
|
+
$VERSION = '3.67';
|
54
54
|
@ISA = qw(Exporter);
|
55
55
|
@EXPORT_OK = qw(EscapeXML UnescapeXML);
|
56
56
|
|
@@ -3777,8 +3777,13 @@ sub ParseXMPElement($$$;$$$$)
|
|
3777
3777
|
|
3778
3778
|
# extract property attributes
|
3779
3779
|
my ($parseResource, %attrs, @attrs);
|
3780
|
-
|
3781
|
-
|
3780
|
+
# this hangs Perl (v5.18.4) for a specific capture string [patched in ExifTool 12.98]
|
3781
|
+
# while ($attrs =~ m/(\S+?)\s*=\s*(['"])(.*?)\2/sg) {
|
3782
|
+
while ($attrs =~ /(\S+?)\s*=\s*(['"])/g) {
|
3783
|
+
my ($attr, $quote) = ($1, $2);
|
3784
|
+
my $p0 = pos($attrs);
|
3785
|
+
last unless $attrs =~ /$quote/g;
|
3786
|
+
my $val = substr($attrs, $p0, pos($attrs)-$p0-1);
|
3782
3787
|
# handle namespace prefixes (defined by xmlns:PREFIX, or used with PREFIX:tag)
|
3783
3788
|
if ($attr =~ /(.*?):/) {
|
3784
3789
|
if ($1 eq 'xmlns') {
|