exiftool_vendored 12.32.0 → 12.36.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 +77 -3
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +2 -2
- data/bin/exiftool +57 -39
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +7 -2
- data/bin/lib/Image/ExifTool/CBOR.pm +85 -31
- data/bin/lib/Image/ExifTool/Canon.pm +28 -3
- data/bin/lib/Image/ExifTool/Charset.pm +2 -0
- data/bin/lib/Image/ExifTool/Exif.pm +109 -3
- data/bin/lib/Image/ExifTool/FLIR.pm +33 -8
- data/bin/lib/Image/ExifTool/ICC_Profile.pm +96 -4
- data/bin/lib/Image/ExifTool/JSON.pm +4 -2
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +111 -12
- data/bin/lib/Image/ExifTool/MacOS.pm +2 -2
- data/bin/lib/Image/ExifTool/Nikon.pm +637 -16
- data/bin/lib/Image/ExifTool/NikonCustom.pm +5 -1
- data/bin/lib/Image/ExifTool/NikonSettings.pm +67 -11
- data/bin/lib/Image/ExifTool/Olympus.pm +5 -1
- data/bin/lib/Image/ExifTool/PDF.pm +5 -3
- data/bin/lib/Image/ExifTool/QuickTime.pm +21 -2
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +2 -2
- data/bin/lib/Image/ExifTool/README +6 -2
- data/bin/lib/Image/ExifTool/Sony.pm +31 -11
- data/bin/lib/Image/ExifTool/TagInfoXML.pm +9 -4
- data/bin/lib/Image/ExifTool/TagLookup.pm +5054 -4455
- data/bin/lib/Image/ExifTool/TagNames.pod +1185 -23
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +10 -0
- data/bin/lib/Image/ExifTool/Writer.pl +45 -3
- data/bin/lib/Image/ExifTool/XMP.pm +111 -25
- data/bin/lib/Image/ExifTool/XMP2.pl +3 -1
- data/bin/lib/Image/ExifTool.pm +83 -19
- data/bin/lib/Image/ExifTool.pod +9 -1
- data/bin/perl-Image-ExifTool.spec +1 -1
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +2 -2
@@ -15,12 +15,12 @@ use vars qw($VERSION);
|
|
15
15
|
use Image::ExifTool qw(:DataAccess :Utils);
|
16
16
|
use Image::ExifTool::JSON;
|
17
17
|
|
18
|
-
$VERSION = '1.
|
18
|
+
$VERSION = '1.01';
|
19
19
|
|
20
20
|
sub ProcessCBOR($$$);
|
21
21
|
sub ReadCBORValue($$$$);
|
22
22
|
|
23
|
-
# optional CBOR type
|
23
|
+
# optional CBOR type code
|
24
24
|
my %cborType6 = (
|
25
25
|
0 => 'date/time string',
|
26
26
|
1 => 'epoch-based date/time',
|
@@ -78,6 +78,7 @@ sub ReadCBORValue($$$$)
|
|
78
78
|
return(undef, 'Truncated CBOR data', $pos) if $pos >= $end;
|
79
79
|
my $verbose = $$et{OPTIONS}{Verbose};
|
80
80
|
my $indent = $$et{INDENT};
|
81
|
+
my $dumpStart = $pos;
|
81
82
|
my $fmt = Get8u($dataPt, $pos++);
|
82
83
|
my $dat = $fmt & 0x1f;
|
83
84
|
my ($num, $val, $err, $size);
|
@@ -95,28 +96,22 @@ sub ReadCBORValue($$$$)
|
|
95
96
|
$num = ReadValue($dataPt, $pos, $format, 1, $size);
|
96
97
|
$pos += $size;
|
97
98
|
}
|
98
|
-
my
|
99
|
-
if (
|
100
|
-
|
101
|
-
|
102
|
-
delete $$et{cbor_pre};
|
103
|
-
}
|
104
|
-
if (defined $$et{cbor_opt}) {
|
105
|
-
$opt = ", $$et{cbor_opt}:";
|
106
|
-
delete $$et{cbor_opt};
|
107
|
-
}
|
99
|
+
my $pre = '';
|
100
|
+
if (defined $$et{cbor_pre} and $fmt != 6) {
|
101
|
+
$pre = $$et{cbor_pre};
|
102
|
+
delete $$et{cbor_pre};
|
108
103
|
}
|
109
104
|
if ($fmt == 0) { # positive integer
|
110
105
|
$val = $num;
|
111
|
-
$et->VPrint(1, "$$et{INDENT} ${pre}int
|
106
|
+
$et->VPrint(1, "$$et{INDENT} ${pre}int+: $val\n");
|
112
107
|
} elsif ($fmt == 1) { # negative integer
|
113
108
|
$val = -1 * $num;
|
114
|
-
$et->VPrint(1, "$$et{INDENT} ${pre}int
|
109
|
+
$et->VPrint(1, "$$et{INDENT} ${pre}int-: $val\n");
|
115
110
|
} elsif ($fmt == 2 or $fmt == 3) { # byte/UTF8 string
|
116
111
|
return(undef, 'Truncated CBOR string value', $pos) if $pos + $num > $end;
|
117
112
|
if ($num < 0) { # (should not happen in C2PA)
|
118
113
|
my $string = '';
|
119
|
-
$$et{INDENT} .= '
|
114
|
+
$$et{INDENT} .= ' ';
|
120
115
|
for (;;) {
|
121
116
|
($val, $err, $pos) = ReadCBORValue($et, $dataPt, $pos, $end);
|
122
117
|
return(undef, $err, $pos) if $err;
|
@@ -125,26 +120,34 @@ sub ReadCBORValue($$$$)
|
|
125
120
|
$string .= $val;
|
126
121
|
}
|
127
122
|
$$et{INDENT} = $indent;
|
128
|
-
return($string, undef, $pos); # return concatenated
|
123
|
+
return($string, undef, $pos); # return concatenated byte/text string
|
129
124
|
} else {
|
130
125
|
$val = substr($$dataPt, $pos, $num);
|
131
126
|
}
|
132
127
|
$pos += $num;
|
133
|
-
if ($fmt == 2) {
|
134
|
-
$et->VPrint(1, "$$et{INDENT} ${pre}byte
|
135
|
-
|
128
|
+
if ($fmt == 2) { # (byte string)
|
129
|
+
$et->VPrint(1, "$$et{INDENT} ${pre}byte: <binary data ".length($val)." bytes>\n");
|
130
|
+
my $dat = $val;
|
131
|
+
$val = \$dat; # use scalar reference for binary data
|
132
|
+
} else { # (text string)
|
133
|
+
$val = $et->Decode($val, 'UTF8');
|
134
|
+
$et->VPrint(1, "$$et{INDENT} ${pre}text: '${val}'\n");
|
136
135
|
}
|
137
|
-
$et->VPrint(1, "$$et{INDENT} ${pre}text$opt '${val}'\n");
|
138
136
|
} elsif ($fmt == 4 or $fmt == 5) { # list/hash
|
139
137
|
if ($fmt == 4) {
|
140
|
-
$et->VPrint(1, "$$et{INDENT} ${pre}list
|
138
|
+
$et->VPrint(1, "$$et{INDENT} ${pre}list: <$num elements>\n");
|
141
139
|
} else {
|
142
|
-
$et->VPrint(1, "$$et{INDENT} ${pre}hash
|
140
|
+
$et->VPrint(1, "$$et{INDENT} ${pre}hash: <$num pairs>\n");
|
143
141
|
$num *= 2;
|
144
142
|
}
|
145
|
-
$$et{INDENT} .= '
|
143
|
+
$$et{INDENT} .= ' ';
|
146
144
|
my $i = 0;
|
147
145
|
my @list;
|
146
|
+
Image::ExifTool::HexDump($dataPt, $pos - $dumpStart,
|
147
|
+
Start => $dumpStart,
|
148
|
+
DataPos => $$et{cbor_datapos},
|
149
|
+
Prefix => $$et{INDENT},
|
150
|
+
) if $verbose > 2;
|
148
151
|
while ($num) {
|
149
152
|
$$et{cbor_pre} = "$i) ";
|
150
153
|
if ($fmt == 4) {
|
@@ -162,6 +165,7 @@ sub ReadCBORValue($$$$)
|
|
162
165
|
push @list, $val;
|
163
166
|
--$num;
|
164
167
|
}
|
168
|
+
$dumpStart = $pos;
|
165
169
|
$$et{INDENT} = $indent;
|
166
170
|
if ($fmt == 5) {
|
167
171
|
my ($i, @keys);
|
@@ -174,9 +178,40 @@ sub ReadCBORValue($$$$)
|
|
174
178
|
} else {
|
175
179
|
$val = \@list;
|
176
180
|
}
|
177
|
-
} elsif ($fmt == 6) { # optional
|
178
|
-
|
181
|
+
} elsif ($fmt == 6) { # optional tag
|
182
|
+
if ($verbose) {
|
183
|
+
my $str = "$num (" . ($cborType6{$num} || 'unknown') . ')';
|
184
|
+
my $spc = $$et{cbor_pre} ? (' ' x length $$et{cbor_pre}) : '';
|
185
|
+
$et->VPrint(1, "$$et{INDENT} $spc<CBOR optional type $str>\n");
|
186
|
+
Image::ExifTool::HexDump($dataPt, $pos - $dumpStart,
|
187
|
+
Start => $dumpStart,
|
188
|
+
DataPos => $$et{cbor_datapos},
|
189
|
+
Prefix => $$et{INDENT} . ' ',
|
190
|
+
) if $verbose > 2;
|
191
|
+
}
|
192
|
+
# read next value (note: in the case of multiple tags,
|
193
|
+
# this nesting will apply the tags in the correct order)
|
179
194
|
($val, $err, $pos) = ReadCBORValue($et, $dataPt, $pos, $end);
|
195
|
+
$dumpStart = $pos;
|
196
|
+
# convert some values according to the optional tag number (untested)
|
197
|
+
if ($num == 0 and not ref $val) { # date/time string
|
198
|
+
require Image::ExifTool::XMP;
|
199
|
+
$val = Image::ExifTool::XMP::ConvertXMPDate($val);
|
200
|
+
} elsif ($num == 1 and not ref $val) { # epoch-based date/time
|
201
|
+
if (Image::ExifTool::IsFloat($val)) {
|
202
|
+
my $dec = ($val == int($val)) ? undef : 6;
|
203
|
+
$val = Image::ExifTool::ConvertUnixTime($val, 1, $dec);
|
204
|
+
}
|
205
|
+
} elsif (($num == 2 or $num == 3) and ref($val) eq 'SCALAR') { # pos/neg bignum
|
206
|
+
my $big = 0;
|
207
|
+
$big = 256 * $big + Get8u($val,$_) foreach 0..(length($$val) - 1);
|
208
|
+
$val = $num==2 ? $big : -$big;
|
209
|
+
} elsif (($num == 4 or $num == 5) and # decimal fraction or bigfloat
|
210
|
+
ref($val) eq 'ARRAY' and @$val == 2 and
|
211
|
+
Image::ExifTool::IsInt($$val[0]) and Image::ExifTool::IsInt($$val[1]))
|
212
|
+
{
|
213
|
+
$val = $$val[1] * ($num == 4 ? 10 : 2) ** $$val[0];
|
214
|
+
}
|
180
215
|
} elsif ($fmt == 7) {
|
181
216
|
if ($dat == 31) {
|
182
217
|
undef $val; # "break" = end of indefinite array/hash (not used in C2PA)
|
@@ -202,10 +237,16 @@ sub ReadCBORValue($$$$)
|
|
202
237
|
} else {
|
203
238
|
return(undef, "Invalid CBOR type 7 variant $num", $pos);
|
204
239
|
}
|
205
|
-
$et->VPrint(1, "$$et{INDENT} ${pre}typ7
|
240
|
+
$et->VPrint(1, "$$et{INDENT} ${pre}typ7: ".(defined $val ? $val : '<break>')."\n");
|
206
241
|
} else {
|
207
242
|
return(undef, "Unknown CBOR format $fmt", $pos);
|
208
243
|
}
|
244
|
+
Image::ExifTool::HexDump($dataPt, $pos - $dumpStart,
|
245
|
+
Start => $dumpStart,
|
246
|
+
DataPos => $$et{cbor_datapos},
|
247
|
+
Prefix => $$et{INDENT} . ' ',
|
248
|
+
MaxLen => $verbose < 5 ? ($verbose == 3 ? 96 : 2048) : undef,
|
249
|
+
) if $verbose > 2;
|
209
250
|
return($val, $err, $pos);
|
210
251
|
}
|
211
252
|
|
@@ -219,15 +260,28 @@ sub ProcessCBOR($$$)
|
|
219
260
|
my $dataPt = $$dirInfo{DataPt};
|
220
261
|
my $pos = $$dirInfo{DirStart};
|
221
262
|
my $end = $pos + $$dirInfo{DirLen};
|
263
|
+
my ($val, $err, $tag, $i);
|
264
|
+
|
222
265
|
$et->VerboseDir('CBOR', undef, $$dirInfo{DirLen});
|
223
|
-
|
224
|
-
|
266
|
+
|
267
|
+
$$et{cbor_datapos} = $$dirInfo{DataPos} + $$dirInfo{Base};
|
268
|
+
|
225
269
|
while ($pos < $end) {
|
226
270
|
($val, $err, $pos) = ReadCBORValue($et, $dataPt, $pos, $end);
|
227
271
|
$err and $et->Warn($err), last;
|
228
|
-
ref $val eq 'HASH'
|
229
|
-
|
230
|
-
|
272
|
+
if (ref $val eq 'HASH') {
|
273
|
+
foreach $tag (@{$$val{_ordered_keys_}}) {
|
274
|
+
Image::ExifTool::JSON::ProcessTag($et, $tagTablePtr, $tag, $$val{$tag});
|
275
|
+
}
|
276
|
+
} elsif (ref $val eq 'ARRAY') {
|
277
|
+
for ($i=0; $i<@$val; ++$i) {
|
278
|
+
Image::ExifTool::JSON::ProcessTag($et, $tagTablePtr, "Item$i", $$val[$i]);
|
279
|
+
}
|
280
|
+
} elsif ($val eq '0') {
|
281
|
+
$et->VPrint(1, "$$et{INDENT} <CBOR end>\n");
|
282
|
+
last; # (treat as padding)
|
283
|
+
} else {
|
284
|
+
$et->VPrint(1, "$$et{INDENT} Unknown value: $val\n");
|
231
285
|
}
|
232
286
|
}
|
233
287
|
return 1;
|
@@ -88,7 +88,7 @@ sub ProcessCTMD($$$);
|
|
88
88
|
sub ProcessExifInfo($$$);
|
89
89
|
sub SwapWords($);
|
90
90
|
|
91
|
-
$VERSION = '4.
|
91
|
+
$VERSION = '4.54';
|
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)
|
@@ -187,7 +187,7 @@ $VERSION = '4.51';
|
|
187
187
|
37.2 => 'Tamron AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical [IF] Macro (A20)', #38
|
188
188
|
37.3 => 'Tamron SP AF 17-50mm f/2.8 XR Di II VC LD Aspherical [IF]', #34
|
189
189
|
37.4 => 'Tamron AF 18-270mm f/3.5-6.3 Di II VC LD Aspherical [IF] Macro', #forum2937
|
190
|
-
38 => 'Canon EF 80-200mm f/4.5-5.6', #32
|
190
|
+
38 => 'Canon EF 80-200mm f/4.5-5.6 II', #32 (II added ref https://github.com/Exiv2/exiv2/issues/1906)
|
191
191
|
39 => 'Canon EF 75-300mm f/4-5.6',
|
192
192
|
40 => 'Canon EF 28-80mm f/3.5-5.6',
|
193
193
|
41 => 'Canon EF 28-90mm f/4-5.6', #32
|
@@ -595,6 +595,10 @@ $VERSION = '4.51';
|
|
595
595
|
'61182.21' => 'Canon RF 70-200mm F4L IS USM', #42
|
596
596
|
'61182.22' => 'Canon RF 50mm F1.8 STM', #42
|
597
597
|
'61182.23' => 'Canon RF 14-35mm F4L IS USM', #IB
|
598
|
+
'61182.24' => 'Canon RF 100-400mm F5.6-8 IS USM', #42
|
599
|
+
'61182.25' => 'Canon RF 100-400mm F5.6-8 IS USM + RF1.4x', #42 (NC)
|
600
|
+
'61182.26' => 'Canon RF 100-400mm F5.6-8 IS USM + RF2x', #42 (NC)
|
601
|
+
'61182.27' => 'Canon RF 16mm F2.8 STM', #42
|
598
602
|
#'61182.xx' => 'Canon RF 100mm F2.8L MACRO IS USM',
|
599
603
|
65535 => 'n/a',
|
600
604
|
);
|
@@ -950,6 +954,7 @@ $VERSION = '4.51';
|
|
950
954
|
0x80000435 => 'EOS Rebel T8i / 850D / X10i', #JR/PH
|
951
955
|
0x80000436 => 'EOS SL3 / 250D / Kiss X10', #25
|
952
956
|
0x80000437 => 'EOS 90D', #IB
|
957
|
+
0x80000450 => 'EOS R3', #42
|
953
958
|
0x80000453 => 'EOS R6', #PH
|
954
959
|
0x80000467 => 'PowerShot ZOOM',
|
955
960
|
0x80000468 => 'EOS M50 Mark II / Kiss M2', #IB
|
@@ -6731,7 +6736,17 @@ my %ciMaxFocal = (
|
|
6731
6736
|
PrintConvInv => '$val =~ s/ ?m$//; IsFloat($val) ? $val : 655.35',
|
6732
6737
|
},
|
6733
6738
|
# 22 - values: 0, 1
|
6734
|
-
|
6739
|
+
23 => { #JohnMoyer (forum12925)
|
6740
|
+
Name => 'ShutterMode',
|
6741
|
+
PrintConv => {
|
6742
|
+
0 => 'Mechanical',
|
6743
|
+
1 => 'Electronic First Curtain',
|
6744
|
+
2 => 'Electronic',
|
6745
|
+
# 3 => ?
|
6746
|
+
# 21 => ?
|
6747
|
+
# 22 => ?
|
6748
|
+
},
|
6749
|
+
},
|
6735
6750
|
25 => { #PH
|
6736
6751
|
Name => 'FlashExposureLock',
|
6737
6752
|
PrintConv => \%offOn,
|
@@ -6765,6 +6780,10 @@ my %ciMaxFocal = (
|
|
6765
6780
|
278 => 'Canon RF 70-200mm F4L IS USM', #42
|
6766
6781
|
280 => 'Canon RF 50mm F1.8 STM', #42
|
6767
6782
|
281 => 'Canon RF 14-35mm F4L IS USM', #42/IB
|
6783
|
+
283 => 'Canon RF 100-400mm F5.6-8 IS USM', #42
|
6784
|
+
284 => 'Canon RF 100-400mm F5.6-8 IS USM + RF1.4x', #42 (NC)
|
6785
|
+
285 => 'Canon RF 100-400mm F5.6-8 IS USM + RF2x', #42 (NC)
|
6786
|
+
288 => 'Canon RF 16mm F2.8 STM', #42
|
6768
6787
|
#xxx => 'Canon RF 100mm F2.8L MACRO IS USM',
|
6769
6788
|
# Note: add new RF lenses to %canonLensTypes with ID 61182
|
6770
6789
|
},
|
@@ -8740,6 +8759,7 @@ my %filterConv = (
|
|
8740
8759
|
# --> ignored when reading, but offsets are updated when writing
|
8741
8760
|
CMT1 => { # (CR3 files)
|
8742
8761
|
Name => 'IFD0',
|
8762
|
+
PreservePadding => 1,
|
8743
8763
|
SubDirectory => {
|
8744
8764
|
TagTable => 'Image::ExifTool::Exif::Main',
|
8745
8765
|
ProcessProc => \&Image::ExifTool::ProcessTIFF,
|
@@ -8748,6 +8768,7 @@ my %filterConv = (
|
|
8748
8768
|
},
|
8749
8769
|
CMT2 => { # (CR3 files)
|
8750
8770
|
Name => 'ExifIFD',
|
8771
|
+
PreservePadding => 1,
|
8751
8772
|
SubDirectory => {
|
8752
8773
|
TagTable => 'Image::ExifTool::Exif::Main',
|
8753
8774
|
ProcessProc => \&Image::ExifTool::ProcessTIFF,
|
@@ -8756,6 +8777,7 @@ my %filterConv = (
|
|
8756
8777
|
},
|
8757
8778
|
CMT3 => { # (CR3 files)
|
8758
8779
|
Name => 'MakerNoteCanon',
|
8780
|
+
PreservePadding => 1,
|
8759
8781
|
SubDirectory => {
|
8760
8782
|
TagTable => 'Image::ExifTool::Canon::Main',
|
8761
8783
|
ProcessProc => \&ProcessCMT3,
|
@@ -8764,6 +8786,7 @@ my %filterConv = (
|
|
8764
8786
|
},
|
8765
8787
|
CMT4 => { # (CR3 files)
|
8766
8788
|
Name => 'GPSInfo',
|
8789
|
+
PreservePadding => 1,
|
8767
8790
|
SubDirectory => {
|
8768
8791
|
TagTable => 'Image::ExifTool::GPS::Main',
|
8769
8792
|
ProcessProc => \&Image::ExifTool::ProcessTIFF,
|
@@ -8774,6 +8797,7 @@ my %filterConv = (
|
|
8774
8797
|
THMB => {
|
8775
8798
|
Name => 'ThumbnailImage',
|
8776
8799
|
Groups => { 2 => 'Preview' },
|
8800
|
+
PreservePadding => 1,
|
8777
8801
|
RawConv => 'substr($val, 16)',
|
8778
8802
|
Binary => 1,
|
8779
8803
|
},
|
@@ -8788,6 +8812,7 @@ my %filterConv = (
|
|
8788
8812
|
WRITE_PROC => 'Image::ExifTool::QuickTime::WriteQuickTime',
|
8789
8813
|
CNOP => {
|
8790
8814
|
Name => 'CanonVRD',
|
8815
|
+
PreservePadding => 1,
|
8791
8816
|
SubDirectory => {
|
8792
8817
|
TagTable => 'Image::ExifTool::CanonVRD::Main',
|
8793
8818
|
WriteProc => 'Image::ExifTool::CanonVRD::WriteCanonDR4',
|
@@ -6,6 +6,8 @@
|
|
6
6
|
# Revisions: 2009/08/28 - P. Harvey created
|
7
7
|
# 2010/01/20 - P. Harvey complete re-write
|
8
8
|
# 2010/07/16 - P. Harvey added UTF-16 support
|
9
|
+
#
|
10
|
+
# Notes: Charset lookups are generated using my convertCharset script
|
9
11
|
#------------------------------------------------------------------------------
|
10
12
|
|
11
13
|
package Image::ExifTool::Charset;
|
@@ -56,7 +56,7 @@ use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber %intFormat
|
|
56
56
|
use Image::ExifTool qw(:DataAccess :Utils);
|
57
57
|
use Image::ExifTool::MakerNotes;
|
58
58
|
|
59
|
-
$VERSION = '4.
|
59
|
+
$VERSION = '4.38';
|
60
60
|
|
61
61
|
sub ProcessExif($$$);
|
62
62
|
sub WriteExif($$$);
|
@@ -265,6 +265,7 @@ sub BINARY_DATA_LIMIT { return 10 * 1024 * 1024; }
|
|
265
265
|
32892 => 'Sequential Color Filter', #JR (Sony ARQ)
|
266
266
|
34892 => 'Linear Raw', #2
|
267
267
|
51177 => 'Depth Map', # (DNG 1.5)
|
268
|
+
52527 => 'Semantic Mask', # (DNG 1.6)
|
268
269
|
);
|
269
270
|
|
270
271
|
%orientation = (
|
@@ -291,6 +292,7 @@ sub BINARY_DATA_LIMIT { return 10 * 1024 * 1024; }
|
|
291
292
|
9 => 'Depth map of reduced-resolution image', # (DNG 1.5)
|
292
293
|
16 => 'Enhanced image data', # (DNG 1.5)
|
293
294
|
0x10001 => 'Alternate reduced-resolution image', # (DNG 1.2)
|
295
|
+
0x10004 => 'Semantic Mask', # (DNG 1.6)
|
294
296
|
0xffffffff => 'invalid', #(found in E5700 NEF's)
|
295
297
|
BITMASK => {
|
296
298
|
0 => 'Reduced resolution',
|
@@ -366,6 +368,7 @@ my %opcodeInfo = (
|
|
366
368
|
11 => 'DeltaPerColumn',
|
367
369
|
12 => 'ScalePerRow',
|
368
370
|
13 => 'ScalePerColumn',
|
371
|
+
14 => 'WarpRectilinear2', # (DNG 1.6)
|
369
372
|
},
|
370
373
|
PrintConvInv => undef, # (so the inverse conversion is not performed)
|
371
374
|
);
|
@@ -3038,12 +3041,12 @@ my %opcodeInfo = (
|
|
3038
3041
|
},
|
3039
3042
|
},
|
3040
3043
|
#
|
3041
|
-
# DNG tags 0xc6XX and
|
3044
|
+
# DNG tags 0xc6XX, 0xc7XX and 0xcdXX (ref 2 unless otherwise stated)
|
3042
3045
|
#
|
3043
3046
|
0xc612 => {
|
3044
3047
|
Name => 'DNGVersion',
|
3045
3048
|
Notes => q{
|
3046
|
-
tags 0xc612-
|
3049
|
+
tags 0xc612-0xcd3b are defined by the DNG specification unless otherwise
|
3047
3050
|
noted. See L<https://helpx.adobe.com/photoshop/digital-negative.html> for
|
3048
3051
|
the specification
|
3049
3052
|
},
|
@@ -4041,6 +4044,97 @@ my %opcodeInfo = (
|
|
4041
4044
|
Protected => 1,
|
4042
4045
|
WriteGroup => 'IFD0',
|
4043
4046
|
},
|
4047
|
+
0xcd2d => { # DNG 1.6
|
4048
|
+
Name => 'ProfileGainTableMap',
|
4049
|
+
Writable => 'undef',
|
4050
|
+
WriteGroup => 'SubIFD',
|
4051
|
+
Protected => 1,
|
4052
|
+
Binary => 1,
|
4053
|
+
},
|
4054
|
+
0xcd2e => { # DNG 1.6
|
4055
|
+
Name => 'SemanticName',
|
4056
|
+
# Writable => 'string',
|
4057
|
+
WriteGroup => 'SubIFD' #? (NC) Semantic Mask IFD (only for Validate)
|
4058
|
+
},
|
4059
|
+
0xcd30 => { # DNG 1.6
|
4060
|
+
Name => 'SemanticInstanceIFD',
|
4061
|
+
# Writable => 'string',
|
4062
|
+
WriteGroup => 'SubIFD' #? (NC) Semantic Mask IFD (only for Validate)
|
4063
|
+
},
|
4064
|
+
0xcd31 => { # DNG 1.6
|
4065
|
+
Name => 'CalibrationIlluminant3',
|
4066
|
+
Writable => 'int16u',
|
4067
|
+
WriteGroup => 'IFD0',
|
4068
|
+
Protected => 1,
|
4069
|
+
SeparateTable => 'LightSource',
|
4070
|
+
PrintConv => \%lightSource,
|
4071
|
+
},
|
4072
|
+
0xcd32 => { # DNG 1.6
|
4073
|
+
Name => 'CameraCalibration3',
|
4074
|
+
Writable => 'rational64s',
|
4075
|
+
WriteGroup => 'IFD0',
|
4076
|
+
Count => -1,
|
4077
|
+
Protected => 1,
|
4078
|
+
},
|
4079
|
+
0xcd33 => { # DNG 1.6
|
4080
|
+
Name => 'ColorMatrix3',
|
4081
|
+
Writable => 'rational64s',
|
4082
|
+
WriteGroup => 'IFD0',
|
4083
|
+
Count => -1,
|
4084
|
+
Protected => 1,
|
4085
|
+
},
|
4086
|
+
0xcd34 => { # DNG 1.6
|
4087
|
+
Name => 'ForwardMatrix3',
|
4088
|
+
Writable => 'rational64s',
|
4089
|
+
WriteGroup => 'IFD0',
|
4090
|
+
Count => -1,
|
4091
|
+
Protected => 1,
|
4092
|
+
},
|
4093
|
+
0xcd35 => { # DNG 1.6
|
4094
|
+
Name => 'IlluminantData1',
|
4095
|
+
Writable => 'undef',
|
4096
|
+
WriteGroup => 'IFD0',
|
4097
|
+
Protected => 1,
|
4098
|
+
},
|
4099
|
+
0xcd36 => { # DNG 1.6
|
4100
|
+
Name => 'IlluminantData2',
|
4101
|
+
Writable => 'undef',
|
4102
|
+
WriteGroup => 'IFD0',
|
4103
|
+
Protected => 1,
|
4104
|
+
},
|
4105
|
+
0xcd37 => { # DNG 1.6
|
4106
|
+
Name => 'IlluminantData3',
|
4107
|
+
Writable => 'undef',
|
4108
|
+
WriteGroup => 'IFD0',
|
4109
|
+
Protected => 1,
|
4110
|
+
},
|
4111
|
+
0xcd38 => { # DNG 1.6
|
4112
|
+
Name => 'MaskSubArea',
|
4113
|
+
# Writable => 'int32u',
|
4114
|
+
WriteGroup => 'SubIFD', #? (NC) Semantic Mask IFD (only for Validate)
|
4115
|
+
Count => 4,
|
4116
|
+
},
|
4117
|
+
0xcd39 => { # DNG 1.6
|
4118
|
+
Name => 'ProfileHueSatMapData3',
|
4119
|
+
%longBin,
|
4120
|
+
Writable => 'float',
|
4121
|
+
WriteGroup => 'IFD0',
|
4122
|
+
Count => -1,
|
4123
|
+
Protected => 1,
|
4124
|
+
},
|
4125
|
+
0xcd3a => { # DNG 1.6
|
4126
|
+
Name => 'ReductionMatrix3',
|
4127
|
+
Writable => 'rational64s',
|
4128
|
+
WriteGroup => 'IFD0',
|
4129
|
+
Count => -1,
|
4130
|
+
Protected => 1,
|
4131
|
+
},
|
4132
|
+
0xcd3b => { # DNG 1.6
|
4133
|
+
Name => 'RGBTables',
|
4134
|
+
Writable => 'undef',
|
4135
|
+
WriteGroup => 'IFD0',
|
4136
|
+
Protected => 1,
|
4137
|
+
},
|
4044
4138
|
0xea1c => { #13
|
4045
4139
|
Name => 'Padding',
|
4046
4140
|
Binary => 1,
|
@@ -4722,11 +4816,23 @@ my %subSecConv = (
|
|
4722
4816
|
},
|
4723
4817
|
GPSPosition => {
|
4724
4818
|
Groups => { 2 => 'Location' },
|
4819
|
+
Writable => 1,
|
4820
|
+
WriteAlso => {
|
4821
|
+
GPSLatitude => '$val =~ /(.*?)( ?[NS])?,/ ? $1 : undef',
|
4822
|
+
GPSLatitudeRef => '$val =~ /(-?)(.*?) ?([NS]?),/ ? ($3 || ($1 ? "S" : "N")) : undef',
|
4823
|
+
GPSLongitude => '$val =~ /, ?(.*?)( ?[EW]?)$/ ? $1 : undef',
|
4824
|
+
GPSLongitudeRef => '$val =~ /, ?(-?)(.*?) ?([EW]?)$/ ? ($3 || ($1 ? "W" : "E")) : undef',
|
4825
|
+
},
|
4725
4826
|
Require => {
|
4726
4827
|
0 => 'GPSLatitude',
|
4727
4828
|
1 => 'GPSLongitude',
|
4728
4829
|
},
|
4729
4830
|
Priority => 0,
|
4831
|
+
Notes => q{
|
4832
|
+
when written, writes GPSLatitude, GPSLatitudeRef, GPSLongitude and
|
4833
|
+
GPSLongitudeRef. This tag may be written using the same coordinate
|
4834
|
+
format as provided by Google Maps when right-clicking on a location
|
4835
|
+
},
|
4730
4836
|
ValueConv => '(length($val[0]) or length($val[1])) ? "$val[0] $val[1]" : undef',
|
4731
4837
|
PrintConv => '"$prt[0], $prt[1]"',
|
4732
4838
|
},
|
@@ -24,7 +24,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
24
24
|
use Image::ExifTool::Exif;
|
25
25
|
use Image::ExifTool::GPS;
|
26
26
|
|
27
|
-
$VERSION = '1.
|
27
|
+
$VERSION = '1.19';
|
28
28
|
|
29
29
|
sub ProcessFLIR($$;$);
|
30
30
|
sub ProcessFLIRText($$$);
|
@@ -99,7 +99,7 @@ my %float8g = ( Format => 'float', PrintConv => 'sprintf("%.8g",$val)' );
|
|
99
99
|
NOTES => q{
|
100
100
|
Information extracted from FLIR FFF images and the APP1 FLIR segment of JPEG
|
101
101
|
images. These tags may also be extracted from the first frame of an FLIR
|
102
|
-
SEQ file.
|
102
|
+
SEQ file, or all frames if the ExtractEmbedded option is used.
|
103
103
|
},
|
104
104
|
"_header" => {
|
105
105
|
Name => 'FFFHeader',
|
@@ -1457,6 +1457,7 @@ sub ProcessFLIR($$;$)
|
|
1457
1457
|
my $raf = $$dirInfo{RAF} || new File::RandomAccess($$dirInfo{DataPt});
|
1458
1458
|
my $verbose = $et->Options('Verbose');
|
1459
1459
|
my $out = $et->Options('TextOut');
|
1460
|
+
my $base = $raf->Tell();
|
1460
1461
|
my ($i, $hdr, $buff, $rec);
|
1461
1462
|
|
1462
1463
|
# read and verify FFF header
|
@@ -1485,15 +1486,18 @@ sub ProcessFLIR($$;$)
|
|
1485
1486
|
my $ver = Get32u(\$hdr, 0x14);
|
1486
1487
|
last if $ver >= 100 and $ver < 200; # (have seen 100 and 101 - PH)
|
1487
1488
|
ToggleByteOrder();
|
1488
|
-
|
1489
|
+
next unless $i;
|
1490
|
+
return 0 if $$et{DOC_NUM};
|
1491
|
+
$et->Warn("Unsupported FLIR $type version");
|
1492
|
+
return 1;
|
1489
1493
|
}
|
1490
1494
|
|
1491
1495
|
# read the FLIR record directory
|
1492
1496
|
my $pos = Get32u(\$hdr, 0x18);
|
1493
1497
|
my $num = Get32u(\$hdr, 0x1c);
|
1494
|
-
unless ($raf->Seek($pos) and $raf->Read($buff, $num * 0x20) == $num * 0x20) {
|
1498
|
+
unless ($raf->Seek($base+$pos) and $raf->Read($buff, $num * 0x20) == $num * 0x20) {
|
1495
1499
|
$et->Warn('Truncated FLIR FFF directory');
|
1496
|
-
return 1;
|
1500
|
+
return $$et{DOC_NUM} ? 0 : 1;
|
1497
1501
|
}
|
1498
1502
|
|
1499
1503
|
unless ($tagTablePtr) {
|
@@ -1504,6 +1508,7 @@ sub ProcessFLIR($$;$)
|
|
1504
1508
|
# process the header data
|
1505
1509
|
$et->HandleTag($tagTablePtr, '_header', $hdr);
|
1506
1510
|
|
1511
|
+
my $success = 1;
|
1507
1512
|
my $oldIndent = $$et{INDENT};
|
1508
1513
|
$$et{INDENT} .= '| ';
|
1509
1514
|
$et->VerboseDir($type, $num);
|
@@ -1533,12 +1538,22 @@ sub ProcessFLIR($$;$)
|
|
1533
1538
|
$verbose and printf $out "%s%d) FLIR Record 0x%.2x, offset 0x%.4x, length 0x%.4x\n",
|
1534
1539
|
$$et{INDENT}, $i, $recType, $recPos, $recLen;
|
1535
1540
|
|
1536
|
-
|
1537
|
-
|
1541
|
+
# skip RawData records for embedded documents
|
1542
|
+
if ($recType == 1 and $$et{DOC_NUM}) {
|
1543
|
+
$raf->Seek($base+$recPos+$recLen) or $success = 0, last;
|
1544
|
+
next;
|
1545
|
+
}
|
1546
|
+
unless ($raf->Seek($base+$recPos) and $raf->Read($rec, $recLen) == $recLen) {
|
1547
|
+
if ($$et{DOC_NUM}) {
|
1548
|
+
$success = 0; # abort processing more documents
|
1549
|
+
} else {
|
1550
|
+
$et->Warn('Invalid FLIR record');
|
1551
|
+
}
|
1538
1552
|
last;
|
1539
1553
|
}
|
1540
1554
|
if ($$tagTablePtr{$recType}) {
|
1541
1555
|
$et->HandleTag($tagTablePtr, $recType, undef,
|
1556
|
+
Base => $base,
|
1542
1557
|
DataPt => \$rec,
|
1543
1558
|
DataPos => $recPos,
|
1544
1559
|
Start => 0,
|
@@ -1550,7 +1565,17 @@ sub ProcessFLIR($$;$)
|
|
1550
1565
|
}
|
1551
1566
|
delete $$et{SET_GROUP0};
|
1552
1567
|
$$et{INDENT} = $oldIndent;
|
1553
|
-
|
1568
|
+
|
1569
|
+
# extract information from subsequent frames in SEQ file if ExtractEmbedded is used
|
1570
|
+
if ($$dirInfo{RAF} and $et->Options('ExtractEmbedded') and not $$et{DOC_NUM}) {
|
1571
|
+
for (;;) {
|
1572
|
+
$$et{DOC_NUM} = $$et{DOC_COUNT} + 1;
|
1573
|
+
last unless ProcessFLIR($et, $dirInfo, $tagTablePtr);
|
1574
|
+
# (DOC_COUNT will be incremented automatically if we extracted any tags)
|
1575
|
+
}
|
1576
|
+
delete $$et{DOC_NUM};
|
1577
|
+
}
|
1578
|
+
return $success;
|
1554
1579
|
}
|
1555
1580
|
|
1556
1581
|
#------------------------------------------------------------------------------
|