line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
2
|
|
|
|
|
|
|
# File: Exif.pm |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# Description: Read EXIF/TIFF meta information |
5
|
|
|
|
|
|
|
# |
6
|
|
|
|
|
|
|
# Revisions: 11/25/2003 - P. Harvey Created |
7
|
|
|
|
|
|
|
# 02/06/2004 - P. Harvey Moved processing functions from ExifTool |
8
|
|
|
|
|
|
|
# 03/19/2004 - P. Harvey Check PreviewImage for validity |
9
|
|
|
|
|
|
|
# 11/11/2004 - P. Harvey Split off maker notes into MakerNotes.pm |
10
|
|
|
|
|
|
|
# 12/13/2004 - P. Harvey Added AUTOLOAD to load write routines |
11
|
|
|
|
|
|
|
# |
12
|
|
|
|
|
|
|
# References: 0) http://www.exif.org/Exif2-2.PDF |
13
|
|
|
|
|
|
|
# 1) http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf |
14
|
|
|
|
|
|
|
# 2) http://www.adobe.com/products/dng/pdfs/dng_spec_1_3_0_0.pdf |
15
|
|
|
|
|
|
|
# 3) http://www.awaresystems.be/imaging/tiff/tifftags.html |
16
|
|
|
|
|
|
|
# 4) http://www.remotesensing.org/libtiff/TIFFTechNote2.html |
17
|
|
|
|
|
|
|
# 5) http://www.exif.org/dcf.PDF |
18
|
|
|
|
|
|
|
# 6) http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html |
19
|
|
|
|
|
|
|
# 7) http://www.fine-view.com/jp/lab/doc/ps6ffspecsv2.pdf |
20
|
|
|
|
|
|
|
# 8) http://www.ozhiker.com/electronics/pjmt/jpeg_info/meta.html |
21
|
|
|
|
|
|
|
# 9) http://hul.harvard.edu/jhove/tiff-tags.html |
22
|
|
|
|
|
|
|
# 10) http://partners.adobe.com/public/developer/en/tiff/TIFFPM6.pdf |
23
|
|
|
|
|
|
|
# 11) Robert Mucke private communication |
24
|
|
|
|
|
|
|
# 12) http://www.broomscloset.com/closet/photo/exif/TAG2000-22_DIS12234-2.PDF |
25
|
|
|
|
|
|
|
# 13) http://www.microsoft.com/whdc/xps/wmphoto.mspx |
26
|
|
|
|
|
|
|
# 14) http://www.asmail.be/msg0054681802.html |
27
|
|
|
|
|
|
|
# 15) http://crousseau.free.fr/imgfmt_raw.htm |
28
|
|
|
|
|
|
|
# 16) http://www.cybercom.net/~dcoffin/dcraw/ |
29
|
|
|
|
|
|
|
# 17) http://www.digitalpreservation.gov/formats/content/tiff_tags.shtml |
30
|
|
|
|
|
|
|
# 18) http://www.asmail.be/msg0055568584.html |
31
|
|
|
|
|
|
|
# 19) http://libpsd.graphest.com/files/Photoshop%20File%20Formats.pdf |
32
|
|
|
|
|
|
|
# 20) http://tiki-lounge.com/~raf/tiff/fields.html |
33
|
|
|
|
|
|
|
# 21) http://community.roxen.com/developers/idocs/rfc/rfc3949.html |
34
|
|
|
|
|
|
|
# 22) http://tools.ietf.org/html/draft-ietf-fax-tiff-fx-extension1-01 |
35
|
|
|
|
|
|
|
# 23) MetaMorph Stack (STK) Image File Format: |
36
|
|
|
|
|
|
|
# --> ftp://ftp.meta.moleculardevices.com/support/stack/STK.doc |
37
|
|
|
|
|
|
|
# 24) http://www.cipa.jp/std/documents/e/DC-008-2012_E.pdf (Exif 2.3) |
38
|
|
|
|
|
|
|
# 25) Vesa Kivisto private communication (7D) |
39
|
|
|
|
|
|
|
# 26) Jeremy Brown private communication |
40
|
|
|
|
|
|
|
# 27) Gregg Lee private communication |
41
|
|
|
|
|
|
|
# 28) http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/cinemadng/pdfs/CinemaDNG_Format_Specification_v1_1.pdf |
42
|
|
|
|
|
|
|
# 29) http://www.libtiff.org |
43
|
|
|
|
|
|
|
# 30) http://geotiff.maptools.org/spec/geotiffhome.html |
44
|
|
|
|
|
|
|
# 31) https://android.googlesource.com/platform/external/dng_sdk/+/refs/heads/master/source/dng_tag_codes.h |
45
|
|
|
|
|
|
|
# 32) Jeffry Friedl private communication |
46
|
|
|
|
|
|
|
# IB) Iliah Borg private communication (LibRaw) |
47
|
|
|
|
|
|
|
# JD) Jens Duttke private communication |
48
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
package Image::ExifTool::Exif; |
51
|
|
|
|
|
|
|
|
52
|
104
|
|
|
104
|
|
693
|
use strict; |
|
104
|
|
|
|
|
414
|
|
|
104
|
|
|
|
|
3740
|
|
53
|
104
|
|
|
|
|
10364
|
use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber %intFormat |
54
|
|
|
|
|
|
|
%lightSource %flash %compression %photometricInterpretation %orientation |
55
|
104
|
|
|
104
|
|
547
|
%subfileType %saveForValidate); |
|
104
|
|
|
|
|
210
|
|
56
|
104
|
|
|
104
|
|
541
|
use Image::ExifTool qw(:DataAccess :Utils); |
|
104
|
|
|
|
|
179
|
|
|
104
|
|
|
|
|
20562
|
|
57
|
104
|
|
|
104
|
|
57154
|
use Image::ExifTool::MakerNotes; |
|
104
|
|
|
|
|
481
|
|
|
104
|
|
|
|
|
1885091
|
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
$VERSION = '4.40'; |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
sub ProcessExif($$$); |
62
|
|
|
|
|
|
|
sub WriteExif($$$); |
63
|
|
|
|
|
|
|
sub CheckExif($$$); |
64
|
|
|
|
|
|
|
sub RebuildMakerNotes($$$); |
65
|
|
|
|
|
|
|
sub EncodeExifText($$); |
66
|
|
|
|
|
|
|
sub ValidateIFD($;$); |
67
|
|
|
|
|
|
|
sub ValidateImageData($$$;$); |
68
|
|
|
|
|
|
|
sub ProcessTiffIFD($$$); |
69
|
|
|
|
|
|
|
sub PrintParameter($$$); |
70
|
|
|
|
|
|
|
sub GetOffList($$$$$); |
71
|
|
|
|
|
|
|
sub PrintOpcode($$$); |
72
|
|
|
|
|
|
|
sub PrintLensInfo($); |
73
|
|
|
|
|
|
|
sub ConvertLensInfo($); |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
# size limit for loading binary data block into memory |
76
|
675
|
|
|
675
|
0
|
1975
|
sub BINARY_DATA_LIMIT { return 10 * 1024 * 1024; } |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# byte sizes for the various EXIF format types below |
79
|
|
|
|
|
|
|
@formatSize = (undef,1,1,2,4,8,1,1,2,4,8,4,8,4,2,8,8,8,8); |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
@formatName = ( |
82
|
|
|
|
|
|
|
undef, 'int8u', 'string', 'int16u', |
83
|
|
|
|
|
|
|
'int32u', 'rational64u','int8s', 'undef', |
84
|
|
|
|
|
|
|
'int16s', 'int32s', 'rational64s','float', |
85
|
|
|
|
|
|
|
'double', 'ifd', 'unicode', 'complex', |
86
|
|
|
|
|
|
|
'int64u', 'int64s', 'ifd64', # (new BigTIFF formats) |
87
|
|
|
|
|
|
|
); |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
# hash to look up EXIF format numbers by name |
90
|
|
|
|
|
|
|
# (format types are all lower case) |
91
|
|
|
|
|
|
|
%formatNumber = ( |
92
|
|
|
|
|
|
|
'int8u' => 1, # BYTE |
93
|
|
|
|
|
|
|
'string' => 2, # ASCII |
94
|
|
|
|
|
|
|
'int16u' => 3, # SHORT |
95
|
|
|
|
|
|
|
'int32u' => 4, # LONG |
96
|
|
|
|
|
|
|
'rational64u' => 5, # RATIONAL |
97
|
|
|
|
|
|
|
'int8s' => 6, # SBYTE |
98
|
|
|
|
|
|
|
'undef' => 7, # UNDEFINED |
99
|
|
|
|
|
|
|
'binary' => 7, # (same as undef) |
100
|
|
|
|
|
|
|
'int16s' => 8, # SSHORT |
101
|
|
|
|
|
|
|
'int32s' => 9, # SLONG |
102
|
|
|
|
|
|
|
'rational64s' => 10, # SRATIONAL |
103
|
|
|
|
|
|
|
'float' => 11, # FLOAT |
104
|
|
|
|
|
|
|
'double' => 12, # DOUBLE |
105
|
|
|
|
|
|
|
'ifd' => 13, # IFD (with int32u format) |
106
|
|
|
|
|
|
|
'unicode' => 14, # UNICODE [see Note below] |
107
|
|
|
|
|
|
|
'complex' => 15, # COMPLEX [see Note below] |
108
|
|
|
|
|
|
|
'int64u' => 16, # LONG8 [BigTIFF] |
109
|
|
|
|
|
|
|
'int64s' => 17, # SLONG8 [BigTIFF] |
110
|
|
|
|
|
|
|
'ifd64' => 18, # IFD8 (with int64u format) [BigTIFF] |
111
|
|
|
|
|
|
|
# Note: unicode and complex types are not yet properly supported by ExifTool. |
112
|
|
|
|
|
|
|
# These are types which have been observed in the Adobe DNG SDK code, but |
113
|
|
|
|
|
|
|
# aren't fully supported there either. We know the sizes, but that's about it. |
114
|
|
|
|
|
|
|
# We don't know if the unicode is null terminated, or the format for complex |
115
|
|
|
|
|
|
|
# (although I suspect it would be two 4-byte floats, real and imaginary). |
116
|
|
|
|
|
|
|
); |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
# lookup for integer format strings |
119
|
|
|
|
|
|
|
%intFormat = ( |
120
|
|
|
|
|
|
|
'int8u' => 1, |
121
|
|
|
|
|
|
|
'int16u' => 3, |
122
|
|
|
|
|
|
|
'int32u' => 4, |
123
|
|
|
|
|
|
|
'int8s' => 6, |
124
|
|
|
|
|
|
|
'int16s' => 8, |
125
|
|
|
|
|
|
|
'int32s' => 9, |
126
|
|
|
|
|
|
|
'ifd' => 13, |
127
|
|
|
|
|
|
|
'int64u' => 16, |
128
|
|
|
|
|
|
|
'int64s' => 17, |
129
|
|
|
|
|
|
|
'ifd64' => 18, |
130
|
|
|
|
|
|
|
); |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
# EXIF LightSource PrintConv values |
133
|
|
|
|
|
|
|
%lightSource = ( |
134
|
|
|
|
|
|
|
0 => 'Unknown', |
135
|
|
|
|
|
|
|
1 => 'Daylight', |
136
|
|
|
|
|
|
|
2 => 'Fluorescent', |
137
|
|
|
|
|
|
|
3 => 'Tungsten (Incandescent)', |
138
|
|
|
|
|
|
|
4 => 'Flash', |
139
|
|
|
|
|
|
|
9 => 'Fine Weather', |
140
|
|
|
|
|
|
|
10 => 'Cloudy', |
141
|
|
|
|
|
|
|
11 => 'Shade', |
142
|
|
|
|
|
|
|
12 => 'Daylight Fluorescent', # (D 5700 - 7100K) |
143
|
|
|
|
|
|
|
13 => 'Day White Fluorescent', # (N 4600 - 5500K) |
144
|
|
|
|
|
|
|
14 => 'Cool White Fluorescent', # (W 3800 - 4500K) |
145
|
|
|
|
|
|
|
15 => 'White Fluorescent', # (WW 3250 - 3800K) |
146
|
|
|
|
|
|
|
16 => 'Warm White Fluorescent', # (L 2600 - 3250K) |
147
|
|
|
|
|
|
|
17 => 'Standard Light A', |
148
|
|
|
|
|
|
|
18 => 'Standard Light B', |
149
|
|
|
|
|
|
|
19 => 'Standard Light C', |
150
|
|
|
|
|
|
|
20 => 'D55', |
151
|
|
|
|
|
|
|
21 => 'D65', |
152
|
|
|
|
|
|
|
22 => 'D75', |
153
|
|
|
|
|
|
|
23 => 'D50', |
154
|
|
|
|
|
|
|
24 => 'ISO Studio Tungsten', |
155
|
|
|
|
|
|
|
255 => 'Other', |
156
|
|
|
|
|
|
|
); |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
# EXIF Flash values |
159
|
|
|
|
|
|
|
%flash = ( |
160
|
|
|
|
|
|
|
OTHER => sub { |
161
|
|
|
|
|
|
|
# translate "Off" and "On" when writing |
162
|
|
|
|
|
|
|
my ($val, $inv) = @_; |
163
|
|
|
|
|
|
|
return undef unless $inv and $val =~ /^(off|on)$/i; |
164
|
|
|
|
|
|
|
return lc $val eq 'off' ? 0x00 : 0x01; |
165
|
|
|
|
|
|
|
}, |
166
|
|
|
|
|
|
|
0x00 => 'No Flash', |
167
|
|
|
|
|
|
|
0x01 => 'Fired', |
168
|
|
|
|
|
|
|
0x05 => 'Fired, Return not detected', |
169
|
|
|
|
|
|
|
0x07 => 'Fired, Return detected', |
170
|
|
|
|
|
|
|
0x08 => 'On, Did not fire', # not charged up? |
171
|
|
|
|
|
|
|
0x09 => 'On, Fired', |
172
|
|
|
|
|
|
|
0x0d => 'On, Return not detected', |
173
|
|
|
|
|
|
|
0x0f => 'On, Return detected', |
174
|
|
|
|
|
|
|
0x10 => 'Off, Did not fire', |
175
|
|
|
|
|
|
|
0x14 => 'Off, Did not fire, Return not detected', |
176
|
|
|
|
|
|
|
0x18 => 'Auto, Did not fire', |
177
|
|
|
|
|
|
|
0x19 => 'Auto, Fired', |
178
|
|
|
|
|
|
|
0x1d => 'Auto, Fired, Return not detected', |
179
|
|
|
|
|
|
|
0x1f => 'Auto, Fired, Return detected', |
180
|
|
|
|
|
|
|
0x20 => 'No flash function', |
181
|
|
|
|
|
|
|
0x30 => 'Off, No flash function', |
182
|
|
|
|
|
|
|
0x41 => 'Fired, Red-eye reduction', |
183
|
|
|
|
|
|
|
0x45 => 'Fired, Red-eye reduction, Return not detected', |
184
|
|
|
|
|
|
|
0x47 => 'Fired, Red-eye reduction, Return detected', |
185
|
|
|
|
|
|
|
0x49 => 'On, Red-eye reduction', |
186
|
|
|
|
|
|
|
0x4d => 'On, Red-eye reduction, Return not detected', |
187
|
|
|
|
|
|
|
0x4f => 'On, Red-eye reduction, Return detected', |
188
|
|
|
|
|
|
|
0x50 => 'Off, Red-eye reduction', |
189
|
|
|
|
|
|
|
0x58 => 'Auto, Did not fire, Red-eye reduction', |
190
|
|
|
|
|
|
|
0x59 => 'Auto, Fired, Red-eye reduction', |
191
|
|
|
|
|
|
|
0x5d => 'Auto, Fired, Red-eye reduction, Return not detected', |
192
|
|
|
|
|
|
|
0x5f => 'Auto, Fired, Red-eye reduction, Return detected', |
193
|
|
|
|
|
|
|
); |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
# TIFF Compression values |
196
|
|
|
|
|
|
|
# (values with format "Xxxxx XXX Compressed" are used to identify RAW file types) |
197
|
|
|
|
|
|
|
%compression = ( |
198
|
|
|
|
|
|
|
1 => 'Uncompressed', |
199
|
|
|
|
|
|
|
2 => 'CCITT 1D', |
200
|
|
|
|
|
|
|
3 => 'T4/Group 3 Fax', |
201
|
|
|
|
|
|
|
4 => 'T6/Group 4 Fax', |
202
|
|
|
|
|
|
|
5 => 'LZW', |
203
|
|
|
|
|
|
|
6 => 'JPEG (old-style)', #3 |
204
|
|
|
|
|
|
|
7 => 'JPEG', #4 |
205
|
|
|
|
|
|
|
8 => 'Adobe Deflate', #3 |
206
|
|
|
|
|
|
|
9 => 'JBIG B&W', #3 |
207
|
|
|
|
|
|
|
10 => 'JBIG Color', #3 |
208
|
|
|
|
|
|
|
99 => 'JPEG', #16 |
209
|
|
|
|
|
|
|
262 => 'Kodak 262', #16 |
210
|
|
|
|
|
|
|
32766 => 'Next', #3 |
211
|
|
|
|
|
|
|
32767 => 'Sony ARW Compressed', #16 |
212
|
|
|
|
|
|
|
32769 => 'Packed RAW', #PH (used by Epson, Nikon, Samsung) |
213
|
|
|
|
|
|
|
32770 => 'Samsung SRW Compressed', #PH |
214
|
|
|
|
|
|
|
32771 => 'CCIRLEW', #3 |
215
|
|
|
|
|
|
|
32772 => 'Samsung SRW Compressed 2', #PH (NX3000,NXmini) |
216
|
|
|
|
|
|
|
32773 => 'PackBits', |
217
|
|
|
|
|
|
|
32809 => 'Thunderscan', #3 |
218
|
|
|
|
|
|
|
32867 => 'Kodak KDC Compressed', #PH |
219
|
|
|
|
|
|
|
32895 => 'IT8CTPAD', #3 |
220
|
|
|
|
|
|
|
32896 => 'IT8LW', #3 |
221
|
|
|
|
|
|
|
32897 => 'IT8MP', #3 |
222
|
|
|
|
|
|
|
32898 => 'IT8BL', #3 |
223
|
|
|
|
|
|
|
32908 => 'PixarFilm', #3 |
224
|
|
|
|
|
|
|
32909 => 'PixarLog', #3 |
225
|
|
|
|
|
|
|
# 32910,32911 - Pixar reserved |
226
|
|
|
|
|
|
|
32946 => 'Deflate', #3 |
227
|
|
|
|
|
|
|
32947 => 'DCS', #3 |
228
|
|
|
|
|
|
|
33003 => 'Aperio JPEG 2000 YCbCr', #https://openslide.org/formats/aperio/ |
229
|
|
|
|
|
|
|
33005 => 'Aperio JPEG 2000 RGB', #https://openslide.org/formats/aperio/ |
230
|
|
|
|
|
|
|
34661 => 'JBIG', #3 |
231
|
|
|
|
|
|
|
34676 => 'SGILog', #3 |
232
|
|
|
|
|
|
|
34677 => 'SGILog24', #3 |
233
|
|
|
|
|
|
|
34712 => 'JPEG 2000', #3 |
234
|
|
|
|
|
|
|
34713 => 'Nikon NEF Compressed', #PH |
235
|
|
|
|
|
|
|
34715 => 'JBIG2 TIFF FX', #20 |
236
|
|
|
|
|
|
|
34718 => 'Microsoft Document Imaging (MDI) Binary Level Codec', #18 |
237
|
|
|
|
|
|
|
34719 => 'Microsoft Document Imaging (MDI) Progressive Transform Codec', #18 |
238
|
|
|
|
|
|
|
34720 => 'Microsoft Document Imaging (MDI) Vector', #18 |
239
|
|
|
|
|
|
|
34887 => 'ESRI Lerc', #LibTiff |
240
|
|
|
|
|
|
|
# 34888,34889 - ESRI reserved |
241
|
|
|
|
|
|
|
34892 => 'Lossy JPEG', # (DNG 1.4) |
242
|
|
|
|
|
|
|
34925 => 'LZMA2', #LibTiff |
243
|
|
|
|
|
|
|
34926 => 'Zstd', #LibTiff |
244
|
|
|
|
|
|
|
34927 => 'WebP', #LibTiff |
245
|
|
|
|
|
|
|
34933 => 'PNG', # (TIFF mail list) |
246
|
|
|
|
|
|
|
34934 => 'JPEG XR', # (TIFF mail list) |
247
|
|
|
|
|
|
|
65000 => 'Kodak DCR Compressed', #PH |
248
|
|
|
|
|
|
|
65535 => 'Pentax PEF Compressed', #Jens |
249
|
|
|
|
|
|
|
); |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
%photometricInterpretation = ( |
252
|
|
|
|
|
|
|
0 => 'WhiteIsZero', |
253
|
|
|
|
|
|
|
1 => 'BlackIsZero', |
254
|
|
|
|
|
|
|
2 => 'RGB', |
255
|
|
|
|
|
|
|
3 => 'RGB Palette', |
256
|
|
|
|
|
|
|
4 => 'Transparency Mask', |
257
|
|
|
|
|
|
|
5 => 'CMYK', |
258
|
|
|
|
|
|
|
6 => 'YCbCr', |
259
|
|
|
|
|
|
|
8 => 'CIELab', |
260
|
|
|
|
|
|
|
9 => 'ICCLab', #3 |
261
|
|
|
|
|
|
|
10 => 'ITULab', #3 |
262
|
|
|
|
|
|
|
32803 => 'Color Filter Array', #2 |
263
|
|
|
|
|
|
|
32844 => 'Pixar LogL', #3 |
264
|
|
|
|
|
|
|
32845 => 'Pixar LogLuv', #3 |
265
|
|
|
|
|
|
|
32892 => 'Sequential Color Filter', #JR (Sony ARQ) |
266
|
|
|
|
|
|
|
34892 => 'Linear Raw', #2 |
267
|
|
|
|
|
|
|
51177 => 'Depth Map', # (DNG 1.5) |
268
|
|
|
|
|
|
|
52527 => 'Semantic Mask', # (DNG 1.6) |
269
|
|
|
|
|
|
|
); |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
%orientation = ( |
272
|
|
|
|
|
|
|
1 => 'Horizontal (normal)', |
273
|
|
|
|
|
|
|
2 => 'Mirror horizontal', |
274
|
|
|
|
|
|
|
3 => 'Rotate 180', |
275
|
|
|
|
|
|
|
4 => 'Mirror vertical', |
276
|
|
|
|
|
|
|
5 => 'Mirror horizontal and rotate 270 CW', |
277
|
|
|
|
|
|
|
6 => 'Rotate 90 CW', |
278
|
|
|
|
|
|
|
7 => 'Mirror horizontal and rotate 90 CW', |
279
|
|
|
|
|
|
|
8 => 'Rotate 270 CW', |
280
|
|
|
|
|
|
|
); |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
%subfileType = ( |
283
|
|
|
|
|
|
|
0 => 'Full-resolution image', |
284
|
|
|
|
|
|
|
1 => 'Reduced-resolution image', |
285
|
|
|
|
|
|
|
2 => 'Single page of multi-page image', |
286
|
|
|
|
|
|
|
3 => 'Single page of multi-page reduced-resolution image', |
287
|
|
|
|
|
|
|
4 => 'Transparency mask', |
288
|
|
|
|
|
|
|
5 => 'Transparency mask of reduced-resolution image', |
289
|
|
|
|
|
|
|
6 => 'Transparency mask of multi-page image', |
290
|
|
|
|
|
|
|
7 => 'Transparency mask of reduced-resolution multi-page image', |
291
|
|
|
|
|
|
|
8 => 'Depth map', # (DNG 1.5) |
292
|
|
|
|
|
|
|
9 => 'Depth map of reduced-resolution image', # (DNG 1.5) |
293
|
|
|
|
|
|
|
16 => 'Enhanced image data', # (DNG 1.5) |
294
|
|
|
|
|
|
|
0x10001 => 'Alternate reduced-resolution image', # (DNG 1.2) |
295
|
|
|
|
|
|
|
0x10004 => 'Semantic Mask', # (DNG 1.6) |
296
|
|
|
|
|
|
|
0xffffffff => 'invalid', #(found in E5700 NEF's) |
297
|
|
|
|
|
|
|
BITMASK => { |
298
|
|
|
|
|
|
|
0 => 'Reduced resolution', |
299
|
|
|
|
|
|
|
1 => 'Single page', |
300
|
|
|
|
|
|
|
2 => 'Transparency mask', |
301
|
|
|
|
|
|
|
3 => 'TIFF/IT final page', #20 (repurposed as DepthMap repurposes by DNG 1.5) |
302
|
|
|
|
|
|
|
4 => 'TIFF-FX mixed raster content', #20 (repurposed as EnhancedImageData by DNG 1.5) |
303
|
|
|
|
|
|
|
}, |
304
|
|
|
|
|
|
|
); |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
# PrintConv for parameter tags |
307
|
|
|
|
|
|
|
%Image::ExifTool::Exif::printParameter = ( |
308
|
|
|
|
|
|
|
PrintConv => { |
309
|
|
|
|
|
|
|
0 => 'Normal', |
310
|
|
|
|
|
|
|
OTHER => \&Image::ExifTool::Exif::PrintParameter, |
311
|
|
|
|
|
|
|
}, |
312
|
|
|
|
|
|
|
); |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
# convert DNG UTF-8 string values (may be string or int8u format) |
315
|
|
|
|
|
|
|
my %utf8StringConv = ( |
316
|
|
|
|
|
|
|
Writable => 'string', |
317
|
|
|
|
|
|
|
Format => 'string', |
318
|
|
|
|
|
|
|
ValueConv => '$self->Decode($val, "UTF8")', |
319
|
|
|
|
|
|
|
ValueConvInv => '$self->Encode($val,"UTF8")', |
320
|
|
|
|
|
|
|
); |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
# ValueConv that makes long values binary type |
323
|
|
|
|
|
|
|
my %longBin = ( |
324
|
|
|
|
|
|
|
ValueConv => 'length($val) > 64 ? \$val : $val', |
325
|
|
|
|
|
|
|
ValueConvInv => '$val', |
326
|
|
|
|
|
|
|
LongBinary => 1, # flag to avoid decoding values of a large array |
327
|
|
|
|
|
|
|
); |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
# PrintConv for SampleFormat (0x153) |
330
|
|
|
|
|
|
|
my %sampleFormat = ( |
331
|
|
|
|
|
|
|
1 => 'Unsigned', # unsigned integer |
332
|
|
|
|
|
|
|
2 => 'Signed', # two's complement signed integer |
333
|
|
|
|
|
|
|
3 => 'Float', # IEEE floating point |
334
|
|
|
|
|
|
|
4 => 'Undefined', |
335
|
|
|
|
|
|
|
5 => 'Complex int', # complex integer (ref 3) |
336
|
|
|
|
|
|
|
6 => 'Complex float', # complex IEEE floating point (ref 3) |
337
|
|
|
|
|
|
|
); |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
# save the values of these tags for additional validation checks |
340
|
|
|
|
|
|
|
%saveForValidate = ( |
341
|
|
|
|
|
|
|
0x100 => 1, # ImageWidth |
342
|
|
|
|
|
|
|
0x101 => 1, # ImageHeight |
343
|
|
|
|
|
|
|
0x102 => 1, # BitsPerSample |
344
|
|
|
|
|
|
|
0x103 => 1, # Compression |
345
|
|
|
|
|
|
|
0x115 => 1, # SamplesPerPixel |
346
|
|
|
|
|
|
|
); |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
# conversions for DNG OpcodeList tags |
349
|
|
|
|
|
|
|
my %opcodeInfo = ( |
350
|
|
|
|
|
|
|
Writable => 'undef', |
351
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
352
|
|
|
|
|
|
|
Protected => 1, |
353
|
|
|
|
|
|
|
Binary => 1, |
354
|
|
|
|
|
|
|
ConvertBinary => 1, # needed because the ValueConv value is binary |
355
|
|
|
|
|
|
|
PrintConvColumns => 2, |
356
|
|
|
|
|
|
|
PrintConv => { |
357
|
|
|
|
|
|
|
OTHER => \&PrintOpcode, |
358
|
|
|
|
|
|
|
1 => 'WarpRectilinear', |
359
|
|
|
|
|
|
|
2 => 'WarpFisheye', |
360
|
|
|
|
|
|
|
3 => 'FixVignetteRadial', |
361
|
|
|
|
|
|
|
4 => 'FixBadPixelsConstant', |
362
|
|
|
|
|
|
|
5 => 'FixBadPixelsList', |
363
|
|
|
|
|
|
|
6 => 'TrimBounds', |
364
|
|
|
|
|
|
|
7 => 'MapTable', |
365
|
|
|
|
|
|
|
8 => 'MapPolynomial', |
366
|
|
|
|
|
|
|
9 => 'GainMap', |
367
|
|
|
|
|
|
|
10 => 'DeltaPerRow', |
368
|
|
|
|
|
|
|
11 => 'DeltaPerColumn', |
369
|
|
|
|
|
|
|
12 => 'ScalePerRow', |
370
|
|
|
|
|
|
|
13 => 'ScalePerColumn', |
371
|
|
|
|
|
|
|
14 => 'WarpRectilinear2', # (DNG 1.6) |
372
|
|
|
|
|
|
|
}, |
373
|
|
|
|
|
|
|
PrintConvInv => undef, # (so the inverse conversion is not performed) |
374
|
|
|
|
|
|
|
); |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
# main EXIF tag table |
377
|
|
|
|
|
|
|
%Image::ExifTool::Exif::Main = ( |
378
|
|
|
|
|
|
|
GROUPS => { 0 => 'EXIF', 1 => 'IFD0', 2 => 'Image'}, |
379
|
|
|
|
|
|
|
WRITE_PROC => \&WriteExif, |
380
|
|
|
|
|
|
|
CHECK_PROC => \&CheckExif, |
381
|
|
|
|
|
|
|
WRITE_GROUP => 'ExifIFD', # default write group |
382
|
|
|
|
|
|
|
SET_GROUP1 => 1, # set group1 name to directory name for all tags in table |
383
|
|
|
|
|
|
|
0x1 => { |
384
|
|
|
|
|
|
|
Name => 'InteropIndex', |
385
|
|
|
|
|
|
|
Description => 'Interoperability Index', |
386
|
|
|
|
|
|
|
Protected => 1, |
387
|
|
|
|
|
|
|
Writable => 'string', |
388
|
|
|
|
|
|
|
WriteGroup => 'InteropIFD', |
389
|
|
|
|
|
|
|
PrintConv => { |
390
|
|
|
|
|
|
|
R98 => 'R98 - DCF basic file (sRGB)', |
391
|
|
|
|
|
|
|
R03 => 'R03 - DCF option file (Adobe RGB)', |
392
|
|
|
|
|
|
|
THM => 'THM - DCF thumbnail file', |
393
|
|
|
|
|
|
|
}, |
394
|
|
|
|
|
|
|
}, |
395
|
|
|
|
|
|
|
0x2 => { #5 |
396
|
|
|
|
|
|
|
Name => 'InteropVersion', |
397
|
|
|
|
|
|
|
Description => 'Interoperability Version', |
398
|
|
|
|
|
|
|
Protected => 1, |
399
|
|
|
|
|
|
|
Writable => 'undef', |
400
|
|
|
|
|
|
|
Mandatory => 1, |
401
|
|
|
|
|
|
|
WriteGroup => 'InteropIFD', |
402
|
|
|
|
|
|
|
RawConv => '$val=~s/\0+$//; $val', # (some idiots add null terminators) |
403
|
|
|
|
|
|
|
}, |
404
|
|
|
|
|
|
|
0x0b => { #PH |
405
|
|
|
|
|
|
|
Name => 'ProcessingSoftware', |
406
|
|
|
|
|
|
|
Writable => 'string', |
407
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
408
|
|
|
|
|
|
|
Notes => 'used by ACD Systems Digital Imaging', |
409
|
|
|
|
|
|
|
}, |
410
|
|
|
|
|
|
|
0xfe => { |
411
|
|
|
|
|
|
|
Name => 'SubfileType', |
412
|
|
|
|
|
|
|
Notes => 'called NewSubfileType by the TIFF specification', |
413
|
|
|
|
|
|
|
Protected => 1, |
414
|
|
|
|
|
|
|
Writable => 'int32u', |
415
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
416
|
|
|
|
|
|
|
# set priority directory if this is the full resolution image |
417
|
|
|
|
|
|
|
DataMember => 'SubfileType', |
418
|
|
|
|
|
|
|
RawConv => q{ |
419
|
|
|
|
|
|
|
if ($val == ($val & 0x02)) { |
420
|
|
|
|
|
|
|
$self->SetPriorityDir() if $val == 0; |
421
|
|
|
|
|
|
|
$$self{PageCount} = ($$self{PageCount} || 0) + 1; |
422
|
|
|
|
|
|
|
$$self{MultiPage} = 1 if $val == 2 or $$self{PageCount} > 1; |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
$$self{SubfileType} = $val; |
425
|
|
|
|
|
|
|
}, |
426
|
|
|
|
|
|
|
PrintConv => \%subfileType, |
427
|
|
|
|
|
|
|
}, |
428
|
|
|
|
|
|
|
0xff => { |
429
|
|
|
|
|
|
|
Name => 'OldSubfileType', |
430
|
|
|
|
|
|
|
Notes => 'called SubfileType by the TIFF specification', |
431
|
|
|
|
|
|
|
Protected => 1, |
432
|
|
|
|
|
|
|
Writable => 'int16u', |
433
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
434
|
|
|
|
|
|
|
# set priority directory if this is the full resolution image |
435
|
|
|
|
|
|
|
RawConv => q{ |
436
|
|
|
|
|
|
|
if ($val == 1 or $val == 3) { |
437
|
|
|
|
|
|
|
$self->SetPriorityDir() if $val == 1; |
438
|
|
|
|
|
|
|
$$self{PageCount} = ($$self{PageCount} || 0) + 1; |
439
|
|
|
|
|
|
|
$$self{MultiPage} = 1 if $val == 3 or $$self{PageCount} > 1; |
440
|
|
|
|
|
|
|
} |
441
|
|
|
|
|
|
|
$val; |
442
|
|
|
|
|
|
|
}, |
443
|
|
|
|
|
|
|
PrintConv => { |
444
|
|
|
|
|
|
|
1 => 'Full-resolution image', |
445
|
|
|
|
|
|
|
2 => 'Reduced-resolution image', |
446
|
|
|
|
|
|
|
3 => 'Single page of multi-page image', |
447
|
|
|
|
|
|
|
}, |
448
|
|
|
|
|
|
|
}, |
449
|
|
|
|
|
|
|
0x100 => { |
450
|
|
|
|
|
|
|
Name => 'ImageWidth', |
451
|
|
|
|
|
|
|
# even though Group 1 is set dynamically we need to register IFD1 once |
452
|
|
|
|
|
|
|
# so it will show up in the group lists |
453
|
|
|
|
|
|
|
Groups => { 1 => 'IFD1' }, |
454
|
|
|
|
|
|
|
Protected => 1, |
455
|
|
|
|
|
|
|
Writable => 'int32u', |
456
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
457
|
|
|
|
|
|
|
# Note: priority 0 tags automatically have their priority increased for the |
458
|
|
|
|
|
|
|
# priority directory (the directory with a SubfileType of "Full-resolution image") |
459
|
|
|
|
|
|
|
Priority => 0, |
460
|
|
|
|
|
|
|
}, |
461
|
|
|
|
|
|
|
0x101 => { |
462
|
|
|
|
|
|
|
Name => 'ImageHeight', |
463
|
|
|
|
|
|
|
Notes => 'called ImageLength by the EXIF spec.', |
464
|
|
|
|
|
|
|
Protected => 1, |
465
|
|
|
|
|
|
|
Writable => 'int32u', |
466
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
467
|
|
|
|
|
|
|
Priority => 0, |
468
|
|
|
|
|
|
|
}, |
469
|
|
|
|
|
|
|
0x102 => { |
470
|
|
|
|
|
|
|
Name => 'BitsPerSample', |
471
|
|
|
|
|
|
|
Protected => 1, |
472
|
|
|
|
|
|
|
Writable => 'int16u', |
473
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
474
|
|
|
|
|
|
|
Count => -1, # can be 1 or 3: -1 means 'variable' |
475
|
|
|
|
|
|
|
Priority => 0, |
476
|
|
|
|
|
|
|
}, |
477
|
|
|
|
|
|
|
0x103 => { |
478
|
|
|
|
|
|
|
Name => 'Compression', |
479
|
|
|
|
|
|
|
Protected => 1, |
480
|
|
|
|
|
|
|
Writable => 'int16u', |
481
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
482
|
|
|
|
|
|
|
Mandatory => 1, |
483
|
|
|
|
|
|
|
DataMember => 'Compression', |
484
|
|
|
|
|
|
|
SeparateTable => 'Compression', |
485
|
|
|
|
|
|
|
RawConv => q{ |
486
|
|
|
|
|
|
|
Image::ExifTool::Exif::IdentifyRawFile($self, $val); |
487
|
|
|
|
|
|
|
return $$self{Compression} = $val; |
488
|
|
|
|
|
|
|
}, |
489
|
|
|
|
|
|
|
PrintConv => \%compression, |
490
|
|
|
|
|
|
|
Priority => 0, |
491
|
|
|
|
|
|
|
}, |
492
|
|
|
|
|
|
|
0x106 => { |
493
|
|
|
|
|
|
|
Name => 'PhotometricInterpretation', |
494
|
|
|
|
|
|
|
Protected => 1, |
495
|
|
|
|
|
|
|
Writable => 'int16u', |
496
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
497
|
|
|
|
|
|
|
PrintConv => \%photometricInterpretation, |
498
|
|
|
|
|
|
|
Priority => 0, |
499
|
|
|
|
|
|
|
}, |
500
|
|
|
|
|
|
|
0x107 => { |
501
|
|
|
|
|
|
|
Name => 'Thresholding', |
502
|
|
|
|
|
|
|
Protected => 1, |
503
|
|
|
|
|
|
|
Writable => 'int16u', |
504
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
505
|
|
|
|
|
|
|
PrintConv => { |
506
|
|
|
|
|
|
|
1 => 'No dithering or halftoning', |
507
|
|
|
|
|
|
|
2 => 'Ordered dither or halftone', |
508
|
|
|
|
|
|
|
3 => 'Randomized dither', |
509
|
|
|
|
|
|
|
}, |
510
|
|
|
|
|
|
|
}, |
511
|
|
|
|
|
|
|
0x108 => { |
512
|
|
|
|
|
|
|
Name => 'CellWidth', |
513
|
|
|
|
|
|
|
Protected => 1, |
514
|
|
|
|
|
|
|
Writable => 'int16u', |
515
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
516
|
|
|
|
|
|
|
}, |
517
|
|
|
|
|
|
|
0x109 => { |
518
|
|
|
|
|
|
|
Name => 'CellLength', |
519
|
|
|
|
|
|
|
Protected => 1, |
520
|
|
|
|
|
|
|
Writable => 'int16u', |
521
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
522
|
|
|
|
|
|
|
}, |
523
|
|
|
|
|
|
|
0x10a => { |
524
|
|
|
|
|
|
|
Name => 'FillOrder', |
525
|
|
|
|
|
|
|
Protected => 1, |
526
|
|
|
|
|
|
|
Writable => 'int16u', |
527
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
528
|
|
|
|
|
|
|
PrintConv => { |
529
|
|
|
|
|
|
|
1 => 'Normal', |
530
|
|
|
|
|
|
|
2 => 'Reversed', |
531
|
|
|
|
|
|
|
}, |
532
|
|
|
|
|
|
|
}, |
533
|
|
|
|
|
|
|
0x10d => { |
534
|
|
|
|
|
|
|
Name => 'DocumentName', |
535
|
|
|
|
|
|
|
Writable => 'string', |
536
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
537
|
|
|
|
|
|
|
}, |
538
|
|
|
|
|
|
|
0x10e => { |
539
|
|
|
|
|
|
|
Name => 'ImageDescription', |
540
|
|
|
|
|
|
|
Writable => 'string', |
541
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
542
|
|
|
|
|
|
|
Priority => 0, |
543
|
|
|
|
|
|
|
}, |
544
|
|
|
|
|
|
|
0x10f => { |
545
|
|
|
|
|
|
|
Name => 'Make', |
546
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
547
|
|
|
|
|
|
|
Writable => 'string', |
548
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
549
|
|
|
|
|
|
|
DataMember => 'Make', |
550
|
|
|
|
|
|
|
# remove trailing blanks and save as an ExifTool member variable |
551
|
|
|
|
|
|
|
RawConv => '$val =~ s/\s+$//; $$self{Make} = $val', |
552
|
|
|
|
|
|
|
# NOTE: trailing "blanks" (spaces) are removed from all EXIF tags which |
553
|
|
|
|
|
|
|
# may be "unknown" (filled with spaces) according to the EXIF spec. |
554
|
|
|
|
|
|
|
# This allows conditional replacement with "exiftool -TAG-= -TAG=VALUE". |
555
|
|
|
|
|
|
|
# - also removed are any other trailing whitespace characters |
556
|
|
|
|
|
|
|
}, |
557
|
|
|
|
|
|
|
0x110 => { |
558
|
|
|
|
|
|
|
Name => 'Model', |
559
|
|
|
|
|
|
|
Description => 'Camera Model Name', |
560
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
561
|
|
|
|
|
|
|
Writable => 'string', |
562
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
563
|
|
|
|
|
|
|
DataMember => 'Model', |
564
|
|
|
|
|
|
|
# remove trailing blanks and save as an ExifTool member variable |
565
|
|
|
|
|
|
|
RawConv => '$val =~ s/\s+$//; $$self{Model} = $val', |
566
|
|
|
|
|
|
|
}, |
567
|
|
|
|
|
|
|
0x111 => [ |
568
|
|
|
|
|
|
|
{ |
569
|
|
|
|
|
|
|
Condition => q[ |
570
|
|
|
|
|
|
|
$$self{TIFF_TYPE} eq 'MRW' and $$self{DIR_NAME} eq 'IFD0' and |
571
|
|
|
|
|
|
|
$$self{Model} =~ /^DiMAGE A200/ |
572
|
|
|
|
|
|
|
], |
573
|
|
|
|
|
|
|
Name => 'StripOffsets', |
574
|
|
|
|
|
|
|
IsOffset => 1, |
575
|
|
|
|
|
|
|
OffsetPair => 0x117, # point to associated byte counts |
576
|
|
|
|
|
|
|
# A200 stores this information in the wrong byte order!! |
577
|
|
|
|
|
|
|
ValueConv => '$val=join(" ",unpack("N*",pack("V*",split(" ",$val))));\$val', |
578
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
579
|
|
|
|
|
|
|
}, |
580
|
|
|
|
|
|
|
{ |
581
|
|
|
|
|
|
|
# (APP1 IFD2 is for Leica JPEG preview) |
582
|
|
|
|
|
|
|
Condition => q[ |
583
|
|
|
|
|
|
|
not ($$self{TIFF_TYPE} eq 'CR2' and $$self{DIR_NAME} eq 'IFD0') and |
584
|
|
|
|
|
|
|
not ($$self{TIFF_TYPE} =~ /^(DNG|TIFF)$/ and $$self{Compression} eq '7' and $$self{SubfileType} ne '0') and |
585
|
|
|
|
|
|
|
not ($$self{TIFF_TYPE} eq 'APP1' and $$self{DIR_NAME} eq 'IFD2') |
586
|
|
|
|
|
|
|
], |
587
|
|
|
|
|
|
|
Name => 'StripOffsets', |
588
|
|
|
|
|
|
|
IsOffset => 1, |
589
|
|
|
|
|
|
|
OffsetPair => 0x117, # point to associated byte counts |
590
|
|
|
|
|
|
|
ValueConv => 'length($val) > 32 ? \$val : $val', |
591
|
|
|
|
|
|
|
}, |
592
|
|
|
|
|
|
|
{ |
593
|
|
|
|
|
|
|
# PreviewImageStart in IFD0 of CR2 images |
594
|
|
|
|
|
|
|
Condition => '$$self{TIFF_TYPE} eq "CR2"', |
595
|
|
|
|
|
|
|
Name => 'PreviewImageStart', |
596
|
|
|
|
|
|
|
IsOffset => 1, |
597
|
|
|
|
|
|
|
OffsetPair => 0x117, |
598
|
|
|
|
|
|
|
Notes => q{ |
599
|
|
|
|
|
|
|
called StripOffsets in most locations, but it is PreviewImageStart in IFD0 |
600
|
|
|
|
|
|
|
of CR2 images and various IFD's of DNG images except for SubIFD2 where it is |
601
|
|
|
|
|
|
|
JpgFromRawStart |
602
|
|
|
|
|
|
|
}, |
603
|
|
|
|
|
|
|
DataTag => 'PreviewImage', |
604
|
|
|
|
|
|
|
Writable => 'int32u', |
605
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
606
|
|
|
|
|
|
|
Protected => 2, |
607
|
|
|
|
|
|
|
Permanent => 1, |
608
|
|
|
|
|
|
|
}, |
609
|
|
|
|
|
|
|
{ |
610
|
|
|
|
|
|
|
# PreviewImageStart in various IFD's of DNG images except SubIFD2 |
611
|
|
|
|
|
|
|
Condition => '$$self{DIR_NAME} ne "SubIFD2"', |
612
|
|
|
|
|
|
|
Name => 'PreviewImageStart', |
613
|
|
|
|
|
|
|
IsOffset => 1, |
614
|
|
|
|
|
|
|
OffsetPair => 0x117, |
615
|
|
|
|
|
|
|
DataTag => 'PreviewImage', |
616
|
|
|
|
|
|
|
Writable => 'int32u', |
617
|
|
|
|
|
|
|
WriteGroup => 'All', # (writes to specific group of associated Composite tag) |
618
|
|
|
|
|
|
|
Protected => 2, |
619
|
|
|
|
|
|
|
Permanent => 1, |
620
|
|
|
|
|
|
|
}, |
621
|
|
|
|
|
|
|
{ |
622
|
|
|
|
|
|
|
# JpgFromRawStart in various IFD's of DNG images except SubIFD2 |
623
|
|
|
|
|
|
|
Name => 'JpgFromRawStart', |
624
|
|
|
|
|
|
|
IsOffset => 1, |
625
|
|
|
|
|
|
|
OffsetPair => 0x117, |
626
|
|
|
|
|
|
|
DataTag => 'JpgFromRaw', |
627
|
|
|
|
|
|
|
Writable => 'int32u', |
628
|
|
|
|
|
|
|
WriteGroup => 'SubIFD2', |
629
|
|
|
|
|
|
|
Protected => 2, |
630
|
|
|
|
|
|
|
Permanent => 1, |
631
|
|
|
|
|
|
|
}, |
632
|
|
|
|
|
|
|
], |
633
|
|
|
|
|
|
|
0x112 => { |
634
|
|
|
|
|
|
|
Name => 'Orientation', |
635
|
|
|
|
|
|
|
Writable => 'int16u', |
636
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
637
|
|
|
|
|
|
|
PrintConv => \%orientation, |
638
|
|
|
|
|
|
|
Priority => 0, # so PRIORITY_DIR takes precedence |
639
|
|
|
|
|
|
|
}, |
640
|
|
|
|
|
|
|
0x115 => { |
641
|
|
|
|
|
|
|
Name => 'SamplesPerPixel', |
642
|
|
|
|
|
|
|
Protected => 1, |
643
|
|
|
|
|
|
|
Writable => 'int16u', |
644
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
645
|
|
|
|
|
|
|
Priority => 0, |
646
|
|
|
|
|
|
|
}, |
647
|
|
|
|
|
|
|
0x116 => { |
648
|
|
|
|
|
|
|
Name => 'RowsPerStrip', |
649
|
|
|
|
|
|
|
Protected => 1, |
650
|
|
|
|
|
|
|
Writable => 'int32u', |
651
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
652
|
|
|
|
|
|
|
Priority => 0, |
653
|
|
|
|
|
|
|
}, |
654
|
|
|
|
|
|
|
0x117 => [ |
655
|
|
|
|
|
|
|
{ |
656
|
|
|
|
|
|
|
Condition => q[ |
657
|
|
|
|
|
|
|
$$self{TIFF_TYPE} eq 'MRW' and $$self{DIR_NAME} eq 'IFD0' and |
658
|
|
|
|
|
|
|
$$self{Model} =~ /^DiMAGE A200/ |
659
|
|
|
|
|
|
|
], |
660
|
|
|
|
|
|
|
Name => 'StripByteCounts', |
661
|
|
|
|
|
|
|
OffsetPair => 0x111, # point to associated offset |
662
|
|
|
|
|
|
|
# A200 stores this information in the wrong byte order!! |
663
|
|
|
|
|
|
|
ValueConv => '$val=join(" ",unpack("N*",pack("V*",split(" ",$val))));\$val', |
664
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
665
|
|
|
|
|
|
|
}, |
666
|
|
|
|
|
|
|
{ |
667
|
|
|
|
|
|
|
# (APP1 IFD2 is for Leica JPEG preview) |
668
|
|
|
|
|
|
|
Condition => q[ |
669
|
|
|
|
|
|
|
not ($$self{TIFF_TYPE} eq 'CR2' and $$self{DIR_NAME} eq 'IFD0') and |
670
|
|
|
|
|
|
|
not ($$self{TIFF_TYPE} =~ /^(DNG|TIFF)$/ and $$self{Compression} eq '7' and $$self{SubfileType} ne '0') and |
671
|
|
|
|
|
|
|
not ($$self{TIFF_TYPE} eq 'APP1' and $$self{DIR_NAME} eq 'IFD2') |
672
|
|
|
|
|
|
|
], |
673
|
|
|
|
|
|
|
Name => 'StripByteCounts', |
674
|
|
|
|
|
|
|
OffsetPair => 0x111, # point to associated offset |
675
|
|
|
|
|
|
|
ValueConv => 'length($val) > 32 ? \$val : $val', |
676
|
|
|
|
|
|
|
}, |
677
|
|
|
|
|
|
|
{ |
678
|
|
|
|
|
|
|
# PreviewImageLength in IFD0 of CR2 images |
679
|
|
|
|
|
|
|
Condition => '$$self{TIFF_TYPE} eq "CR2"', |
680
|
|
|
|
|
|
|
Name => 'PreviewImageLength', |
681
|
|
|
|
|
|
|
OffsetPair => 0x111, |
682
|
|
|
|
|
|
|
Notes => q{ |
683
|
|
|
|
|
|
|
called StripByteCounts in most locations, but it is PreviewImageLength in |
684
|
|
|
|
|
|
|
IFD0 of CR2 images and various IFD's of DNG images except for SubIFD2 where |
685
|
|
|
|
|
|
|
it is JpgFromRawLength |
686
|
|
|
|
|
|
|
}, |
687
|
|
|
|
|
|
|
DataTag => 'PreviewImage', |
688
|
|
|
|
|
|
|
Writable => 'int32u', |
689
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
690
|
|
|
|
|
|
|
Protected => 2, |
691
|
|
|
|
|
|
|
Permanent => 1, |
692
|
|
|
|
|
|
|
}, |
693
|
|
|
|
|
|
|
{ |
694
|
|
|
|
|
|
|
# PreviewImageLength in various IFD's of DNG images except SubIFD2 |
695
|
|
|
|
|
|
|
Condition => '$$self{DIR_NAME} ne "SubIFD2"', |
696
|
|
|
|
|
|
|
Name => 'PreviewImageLength', |
697
|
|
|
|
|
|
|
OffsetPair => 0x111, |
698
|
|
|
|
|
|
|
DataTag => 'PreviewImage', |
699
|
|
|
|
|
|
|
Writable => 'int32u', |
700
|
|
|
|
|
|
|
WriteGroup => 'All', # (writes to specific group of associated Composite tag) |
701
|
|
|
|
|
|
|
Protected => 2, |
702
|
|
|
|
|
|
|
Permanent => 1, |
703
|
|
|
|
|
|
|
}, |
704
|
|
|
|
|
|
|
{ |
705
|
|
|
|
|
|
|
# JpgFromRawLength in SubIFD2 of DNG images |
706
|
|
|
|
|
|
|
Name => 'JpgFromRawLength', |
707
|
|
|
|
|
|
|
OffsetPair => 0x111, |
708
|
|
|
|
|
|
|
DataTag => 'JpgFromRaw', |
709
|
|
|
|
|
|
|
Writable => 'int32u', |
710
|
|
|
|
|
|
|
WriteGroup => 'SubIFD2', |
711
|
|
|
|
|
|
|
Protected => 2, |
712
|
|
|
|
|
|
|
Permanent => 1, |
713
|
|
|
|
|
|
|
}, |
714
|
|
|
|
|
|
|
], |
715
|
|
|
|
|
|
|
0x118 => { |
716
|
|
|
|
|
|
|
Name => 'MinSampleValue', |
717
|
|
|
|
|
|
|
Writable => 'int16u', |
718
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
719
|
|
|
|
|
|
|
}, |
720
|
|
|
|
|
|
|
0x119 => { |
721
|
|
|
|
|
|
|
Name => 'MaxSampleValue', |
722
|
|
|
|
|
|
|
Writable => 'int16u', |
723
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
724
|
|
|
|
|
|
|
}, |
725
|
|
|
|
|
|
|
0x11a => { |
726
|
|
|
|
|
|
|
Name => 'XResolution', |
727
|
|
|
|
|
|
|
Writable => 'rational64u', |
728
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
729
|
|
|
|
|
|
|
Mandatory => 1, |
730
|
|
|
|
|
|
|
Priority => 0, # so PRIORITY_DIR takes precedence |
731
|
|
|
|
|
|
|
}, |
732
|
|
|
|
|
|
|
0x11b => { |
733
|
|
|
|
|
|
|
Name => 'YResolution', |
734
|
|
|
|
|
|
|
Writable => 'rational64u', |
735
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
736
|
|
|
|
|
|
|
Mandatory => 1, |
737
|
|
|
|
|
|
|
Priority => 0, |
738
|
|
|
|
|
|
|
}, |
739
|
|
|
|
|
|
|
0x11c => { |
740
|
|
|
|
|
|
|
Name => 'PlanarConfiguration', |
741
|
|
|
|
|
|
|
Protected => 1, |
742
|
|
|
|
|
|
|
Writable => 'int16u', |
743
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
744
|
|
|
|
|
|
|
PrintConv => { |
745
|
|
|
|
|
|
|
1 => 'Chunky', |
746
|
|
|
|
|
|
|
2 => 'Planar', |
747
|
|
|
|
|
|
|
}, |
748
|
|
|
|
|
|
|
Priority => 0, |
749
|
|
|
|
|
|
|
}, |
750
|
|
|
|
|
|
|
0x11d => { |
751
|
|
|
|
|
|
|
Name => 'PageName', |
752
|
|
|
|
|
|
|
Writable => 'string', |
753
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
754
|
|
|
|
|
|
|
}, |
755
|
|
|
|
|
|
|
0x11e => { |
756
|
|
|
|
|
|
|
Name => 'XPosition', |
757
|
|
|
|
|
|
|
Writable => 'rational64u', |
758
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
759
|
|
|
|
|
|
|
}, |
760
|
|
|
|
|
|
|
0x11f => { |
761
|
|
|
|
|
|
|
Name => 'YPosition', |
762
|
|
|
|
|
|
|
Writable => 'rational64u', |
763
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
764
|
|
|
|
|
|
|
}, |
765
|
|
|
|
|
|
|
# FreeOffsets/FreeByteCounts are used by Ricoh for RMETA information |
766
|
|
|
|
|
|
|
# in TIFF images (not yet supported) |
767
|
|
|
|
|
|
|
0x120 => { |
768
|
|
|
|
|
|
|
Name => 'FreeOffsets', |
769
|
|
|
|
|
|
|
IsOffset => 1, |
770
|
|
|
|
|
|
|
OffsetPair => 0x121, |
771
|
|
|
|
|
|
|
ValueConv => 'length($val) > 32 ? \$val : $val', |
772
|
|
|
|
|
|
|
}, |
773
|
|
|
|
|
|
|
0x121 => { |
774
|
|
|
|
|
|
|
Name => 'FreeByteCounts', |
775
|
|
|
|
|
|
|
OffsetPair => 0x120, |
776
|
|
|
|
|
|
|
ValueConv => 'length($val) > 32 ? \$val : $val', |
777
|
|
|
|
|
|
|
}, |
778
|
|
|
|
|
|
|
0x122 => { |
779
|
|
|
|
|
|
|
Name => 'GrayResponseUnit', |
780
|
|
|
|
|
|
|
Writable => 'int16u', |
781
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
782
|
|
|
|
|
|
|
PrintConv => { #3 |
783
|
|
|
|
|
|
|
1 => 0.1, |
784
|
|
|
|
|
|
|
2 => 0.001, |
785
|
|
|
|
|
|
|
3 => 0.0001, |
786
|
|
|
|
|
|
|
4 => 0.00001, |
787
|
|
|
|
|
|
|
5 => 0.000001, |
788
|
|
|
|
|
|
|
}, |
789
|
|
|
|
|
|
|
}, |
790
|
|
|
|
|
|
|
0x123 => { |
791
|
|
|
|
|
|
|
Name => 'GrayResponseCurve', |
792
|
|
|
|
|
|
|
Binary => 1, |
793
|
|
|
|
|
|
|
}, |
794
|
|
|
|
|
|
|
0x124 => { |
795
|
|
|
|
|
|
|
Name => 'T4Options', |
796
|
|
|
|
|
|
|
PrintConv => { BITMASK => { |
797
|
|
|
|
|
|
|
0 => '2-Dimensional encoding', |
798
|
|
|
|
|
|
|
1 => 'Uncompressed', |
799
|
|
|
|
|
|
|
2 => 'Fill bits added', |
800
|
|
|
|
|
|
|
} }, #3 |
801
|
|
|
|
|
|
|
}, |
802
|
|
|
|
|
|
|
0x125 => { |
803
|
|
|
|
|
|
|
Name => 'T6Options', |
804
|
|
|
|
|
|
|
PrintConv => { BITMASK => { |
805
|
|
|
|
|
|
|
1 => 'Uncompressed', |
806
|
|
|
|
|
|
|
} }, #3 |
807
|
|
|
|
|
|
|
}, |
808
|
|
|
|
|
|
|
0x128 => { |
809
|
|
|
|
|
|
|
Name => 'ResolutionUnit', |
810
|
|
|
|
|
|
|
Notes => 'the value 1 is not standard EXIF', |
811
|
|
|
|
|
|
|
Writable => 'int16u', |
812
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
813
|
|
|
|
|
|
|
Mandatory => 1, |
814
|
|
|
|
|
|
|
PrintConv => { |
815
|
|
|
|
|
|
|
1 => 'None', |
816
|
|
|
|
|
|
|
2 => 'inches', |
817
|
|
|
|
|
|
|
3 => 'cm', |
818
|
|
|
|
|
|
|
}, |
819
|
|
|
|
|
|
|
Priority => 0, |
820
|
|
|
|
|
|
|
}, |
821
|
|
|
|
|
|
|
0x129 => { |
822
|
|
|
|
|
|
|
Name => 'PageNumber', |
823
|
|
|
|
|
|
|
Writable => 'int16u', |
824
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
825
|
|
|
|
|
|
|
Count => 2, |
826
|
|
|
|
|
|
|
}, |
827
|
|
|
|
|
|
|
0x12c => 'ColorResponseUnit', #9 |
828
|
|
|
|
|
|
|
0x12d => { |
829
|
|
|
|
|
|
|
Name => 'TransferFunction', |
830
|
|
|
|
|
|
|
Protected => 1, |
831
|
|
|
|
|
|
|
Writable => 'int16u', |
832
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
833
|
|
|
|
|
|
|
Count => 768, |
834
|
|
|
|
|
|
|
Binary => 1, |
835
|
|
|
|
|
|
|
}, |
836
|
|
|
|
|
|
|
0x131 => { |
837
|
|
|
|
|
|
|
Name => 'Software', |
838
|
|
|
|
|
|
|
Writable => 'string', |
839
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
840
|
|
|
|
|
|
|
DataMember => 'Software', |
841
|
|
|
|
|
|
|
RawConv => '$val =~ s/\s+$//; $$self{Software} = $val', # trim trailing blanks |
842
|
|
|
|
|
|
|
}, |
843
|
|
|
|
|
|
|
0x132 => { |
844
|
|
|
|
|
|
|
Name => 'ModifyDate', |
845
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
846
|
|
|
|
|
|
|
Notes => 'called DateTime by the EXIF spec.', |
847
|
|
|
|
|
|
|
Writable => 'string', |
848
|
|
|
|
|
|
|
Shift => 'Time', |
849
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
850
|
|
|
|
|
|
|
Validate => 'ValidateExifDate($val)', |
851
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
852
|
|
|
|
|
|
|
PrintConvInv => '$self->InverseDateTime($val,0)', |
853
|
|
|
|
|
|
|
}, |
854
|
|
|
|
|
|
|
0x13b => { |
855
|
|
|
|
|
|
|
Name => 'Artist', |
856
|
|
|
|
|
|
|
Groups => { 2 => 'Author' }, |
857
|
|
|
|
|
|
|
Notes => 'becomes a list-type tag when the MWG module is loaded', |
858
|
|
|
|
|
|
|
Writable => 'string', |
859
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
860
|
|
|
|
|
|
|
RawConv => '$val =~ s/\s+$//; $val', # trim trailing blanks |
861
|
|
|
|
|
|
|
}, |
862
|
|
|
|
|
|
|
0x13c => { |
863
|
|
|
|
|
|
|
Name => 'HostComputer', |
864
|
|
|
|
|
|
|
Writable => 'string', |
865
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
866
|
|
|
|
|
|
|
}, |
867
|
|
|
|
|
|
|
0x13d => { |
868
|
|
|
|
|
|
|
Name => 'Predictor', |
869
|
|
|
|
|
|
|
Protected => 1, |
870
|
|
|
|
|
|
|
Writable => 'int16u', |
871
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
872
|
|
|
|
|
|
|
PrintConv => { |
873
|
|
|
|
|
|
|
1 => 'None', |
874
|
|
|
|
|
|
|
2 => 'Horizontal differencing', |
875
|
|
|
|
|
|
|
3 => 'Floating point', # (DNG 1.5) |
876
|
|
|
|
|
|
|
34892 => 'Horizontal difference X2', # (DNG 1.5) |
877
|
|
|
|
|
|
|
34893 => 'Horizontal difference X4', # (DNG 1.5) |
878
|
|
|
|
|
|
|
34894 => 'Floating point X2', # (DNG 1.5) |
879
|
|
|
|
|
|
|
34895 => 'Floating point X4', # (DNG 1.5) |
880
|
|
|
|
|
|
|
}, |
881
|
|
|
|
|
|
|
}, |
882
|
|
|
|
|
|
|
0x13e => { |
883
|
|
|
|
|
|
|
Name => 'WhitePoint', |
884
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
885
|
|
|
|
|
|
|
Writable => 'rational64u', |
886
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
887
|
|
|
|
|
|
|
Count => 2, |
888
|
|
|
|
|
|
|
}, |
889
|
|
|
|
|
|
|
0x13f => { |
890
|
|
|
|
|
|
|
Name => 'PrimaryChromaticities', |
891
|
|
|
|
|
|
|
Writable => 'rational64u', |
892
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
893
|
|
|
|
|
|
|
Count => 6, |
894
|
|
|
|
|
|
|
Priority => 0, |
895
|
|
|
|
|
|
|
}, |
896
|
|
|
|
|
|
|
0x140 => { |
897
|
|
|
|
|
|
|
Name => 'ColorMap', |
898
|
|
|
|
|
|
|
Format => 'binary', |
899
|
|
|
|
|
|
|
Binary => 1, |
900
|
|
|
|
|
|
|
}, |
901
|
|
|
|
|
|
|
0x141 => { |
902
|
|
|
|
|
|
|
Name => 'HalftoneHints', |
903
|
|
|
|
|
|
|
Writable => 'int16u', |
904
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
905
|
|
|
|
|
|
|
Count => 2, |
906
|
|
|
|
|
|
|
}, |
907
|
|
|
|
|
|
|
0x142 => { |
908
|
|
|
|
|
|
|
Name => 'TileWidth', |
909
|
|
|
|
|
|
|
Protected => 1, |
910
|
|
|
|
|
|
|
Writable => 'int32u', |
911
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
912
|
|
|
|
|
|
|
}, |
913
|
|
|
|
|
|
|
0x143 => { |
914
|
|
|
|
|
|
|
Name => 'TileLength', |
915
|
|
|
|
|
|
|
Protected => 1, |
916
|
|
|
|
|
|
|
Writable => 'int32u', |
917
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
918
|
|
|
|
|
|
|
}, |
919
|
|
|
|
|
|
|
0x144 => { |
920
|
|
|
|
|
|
|
Name => 'TileOffsets', |
921
|
|
|
|
|
|
|
IsOffset => 1, |
922
|
|
|
|
|
|
|
OffsetPair => 0x145, |
923
|
|
|
|
|
|
|
ValueConv => 'length($val) > 32 ? \$val : $val', |
924
|
|
|
|
|
|
|
}, |
925
|
|
|
|
|
|
|
0x145 => { |
926
|
|
|
|
|
|
|
Name => 'TileByteCounts', |
927
|
|
|
|
|
|
|
OffsetPair => 0x144, |
928
|
|
|
|
|
|
|
ValueConv => 'length($val) > 32 ? \$val : $val', |
929
|
|
|
|
|
|
|
}, |
930
|
|
|
|
|
|
|
0x146 => 'BadFaxLines', #3 |
931
|
|
|
|
|
|
|
0x147 => { #3 |
932
|
|
|
|
|
|
|
Name => 'CleanFaxData', |
933
|
|
|
|
|
|
|
PrintConv => { |
934
|
|
|
|
|
|
|
0 => 'Clean', |
935
|
|
|
|
|
|
|
1 => 'Regenerated', |
936
|
|
|
|
|
|
|
2 => 'Unclean', |
937
|
|
|
|
|
|
|
}, |
938
|
|
|
|
|
|
|
}, |
939
|
|
|
|
|
|
|
0x148 => 'ConsecutiveBadFaxLines', #3 |
940
|
|
|
|
|
|
|
0x14a => [ |
941
|
|
|
|
|
|
|
{ |
942
|
|
|
|
|
|
|
Name => 'SubIFD', |
943
|
|
|
|
|
|
|
# use this opportunity to identify an ARW image, and if so we |
944
|
|
|
|
|
|
|
# must decide if this is a SubIFD or the A100 raw data |
945
|
|
|
|
|
|
|
# (use SubfileType, Compression and FILE_TYPE to identify ARW/SR2, |
946
|
|
|
|
|
|
|
# then call SetARW to finish the job) |
947
|
|
|
|
|
|
|
Condition => q{ |
948
|
|
|
|
|
|
|
$$self{DIR_NAME} ne 'IFD0' or $$self{FILE_TYPE} ne 'TIFF' or |
949
|
|
|
|
|
|
|
$$self{Make} !~ /^SONY/ or |
950
|
|
|
|
|
|
|
not $$self{SubfileType} or $$self{SubfileType} != 1 or |
951
|
|
|
|
|
|
|
not $$self{Compression} or $$self{Compression} != 6 or |
952
|
|
|
|
|
|
|
not require Image::ExifTool::Sony or |
953
|
|
|
|
|
|
|
Image::ExifTool::Sony::SetARW($self, $valPt) |
954
|
|
|
|
|
|
|
}, |
955
|
|
|
|
|
|
|
Groups => { 1 => 'SubIFD' }, |
956
|
|
|
|
|
|
|
Flags => 'SubIFD', |
957
|
|
|
|
|
|
|
SubDirectory => { |
958
|
|
|
|
|
|
|
Start => '$val', |
959
|
|
|
|
|
|
|
MaxSubdirs => 10, # (have seen 5 in a DNG 1.4 image) |
960
|
|
|
|
|
|
|
}, |
961
|
|
|
|
|
|
|
}, |
962
|
|
|
|
|
|
|
{ #16 |
963
|
|
|
|
|
|
|
Name => 'A100DataOffset', |
964
|
|
|
|
|
|
|
Notes => 'the data offset in original Sony DSLR-A100 ARW images', |
965
|
|
|
|
|
|
|
DataMember => 'A100DataOffset', |
966
|
|
|
|
|
|
|
RawConv => '$$self{A100DataOffset} = $val', |
967
|
|
|
|
|
|
|
WriteGroup => 'IFD0', # (only for Validate) |
968
|
|
|
|
|
|
|
IsOffset => 1, |
969
|
|
|
|
|
|
|
Protected => 2, |
970
|
|
|
|
|
|
|
}, |
971
|
|
|
|
|
|
|
], |
972
|
|
|
|
|
|
|
0x14c => { |
973
|
|
|
|
|
|
|
Name => 'InkSet', |
974
|
|
|
|
|
|
|
Writable => 'int16u', |
975
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
976
|
|
|
|
|
|
|
PrintConv => { #3 |
977
|
|
|
|
|
|
|
1 => 'CMYK', |
978
|
|
|
|
|
|
|
2 => 'Not CMYK', |
979
|
|
|
|
|
|
|
}, |
980
|
|
|
|
|
|
|
}, |
981
|
|
|
|
|
|
|
0x14d => 'InkNames', #3 |
982
|
|
|
|
|
|
|
0x14e => 'NumberofInks', #3 |
983
|
|
|
|
|
|
|
0x150 => 'DotRange', |
984
|
|
|
|
|
|
|
0x151 => { |
985
|
|
|
|
|
|
|
Name => 'TargetPrinter', |
986
|
|
|
|
|
|
|
Writable => 'string', |
987
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
988
|
|
|
|
|
|
|
}, |
989
|
|
|
|
|
|
|
0x152 => { |
990
|
|
|
|
|
|
|
Name => 'ExtraSamples', |
991
|
|
|
|
|
|
|
PrintConv => { #20 |
992
|
|
|
|
|
|
|
0 => 'Unspecified', |
993
|
|
|
|
|
|
|
1 => 'Associated Alpha', |
994
|
|
|
|
|
|
|
2 => 'Unassociated Alpha', |
995
|
|
|
|
|
|
|
}, |
996
|
|
|
|
|
|
|
}, |
997
|
|
|
|
|
|
|
0x153 => { |
998
|
|
|
|
|
|
|
Name => 'SampleFormat', |
999
|
|
|
|
|
|
|
Notes => 'SamplesPerPixel values', |
1000
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', # (only for Validate) |
1001
|
|
|
|
|
|
|
PrintConvColumns => 2, |
1002
|
|
|
|
|
|
|
PrintConv => [ \%sampleFormat, \%sampleFormat, \%sampleFormat, \%sampleFormat ], |
1003
|
|
|
|
|
|
|
}, |
1004
|
|
|
|
|
|
|
0x154 => 'SMinSampleValue', |
1005
|
|
|
|
|
|
|
0x155 => 'SMaxSampleValue', |
1006
|
|
|
|
|
|
|
0x156 => 'TransferRange', |
1007
|
|
|
|
|
|
|
0x157 => 'ClipPath', #3 |
1008
|
|
|
|
|
|
|
0x158 => 'XClipPathUnits', #3 |
1009
|
|
|
|
|
|
|
0x159 => 'YClipPathUnits', #3 |
1010
|
|
|
|
|
|
|
0x15a => { #3 |
1011
|
|
|
|
|
|
|
Name => 'Indexed', |
1012
|
|
|
|
|
|
|
PrintConv => { 0 => 'Not indexed', 1 => 'Indexed' }, |
1013
|
|
|
|
|
|
|
}, |
1014
|
|
|
|
|
|
|
0x15b => { |
1015
|
|
|
|
|
|
|
Name => 'JPEGTables', |
1016
|
|
|
|
|
|
|
Binary => 1, |
1017
|
|
|
|
|
|
|
}, |
1018
|
|
|
|
|
|
|
0x15f => { #10 |
1019
|
|
|
|
|
|
|
Name => 'OPIProxy', |
1020
|
|
|
|
|
|
|
PrintConv => { |
1021
|
|
|
|
|
|
|
0 => 'Higher resolution image does not exist', |
1022
|
|
|
|
|
|
|
1 => 'Higher resolution image exists', |
1023
|
|
|
|
|
|
|
}, |
1024
|
|
|
|
|
|
|
}, |
1025
|
|
|
|
|
|
|
# 0x181 => 'Decode', #20 (typo! - should be 0x1b1, ref 21) |
1026
|
|
|
|
|
|
|
# 0x182 => 'DefaultImageColor', #20 (typo! - should be 0x1b2, ref 21) |
1027
|
|
|
|
|
|
|
0x190 => { #3 |
1028
|
|
|
|
|
|
|
Name => 'GlobalParametersIFD', |
1029
|
|
|
|
|
|
|
Groups => { 1 => 'GlobParamIFD' }, |
1030
|
|
|
|
|
|
|
Flags => 'SubIFD', |
1031
|
|
|
|
|
|
|
SubDirectory => { |
1032
|
|
|
|
|
|
|
DirName => 'GlobParamIFD', |
1033
|
|
|
|
|
|
|
Start => '$val', |
1034
|
|
|
|
|
|
|
MaxSubdirs => 1, |
1035
|
|
|
|
|
|
|
}, |
1036
|
|
|
|
|
|
|
}, |
1037
|
|
|
|
|
|
|
0x191 => { #3 |
1038
|
|
|
|
|
|
|
Name => 'ProfileType', |
1039
|
|
|
|
|
|
|
PrintConv => { 0 => 'Unspecified', 1 => 'Group 3 FAX' }, |
1040
|
|
|
|
|
|
|
}, |
1041
|
|
|
|
|
|
|
0x192 => { #3 |
1042
|
|
|
|
|
|
|
Name => 'FaxProfile', |
1043
|
|
|
|
|
|
|
PrintConv => { |
1044
|
|
|
|
|
|
|
0 => 'Unknown', |
1045
|
|
|
|
|
|
|
1 => 'Minimal B&W lossless, S', |
1046
|
|
|
|
|
|
|
2 => 'Extended B&W lossless, F', |
1047
|
|
|
|
|
|
|
3 => 'Lossless JBIG B&W, J', |
1048
|
|
|
|
|
|
|
4 => 'Lossy color and grayscale, C', |
1049
|
|
|
|
|
|
|
5 => 'Lossless color and grayscale, L', |
1050
|
|
|
|
|
|
|
6 => 'Mixed raster content, M', |
1051
|
|
|
|
|
|
|
7 => 'Profile T', #20 |
1052
|
|
|
|
|
|
|
255 => 'Multi Profiles', #20 |
1053
|
|
|
|
|
|
|
}, |
1054
|
|
|
|
|
|
|
}, |
1055
|
|
|
|
|
|
|
0x193 => { #3 |
1056
|
|
|
|
|
|
|
Name => 'CodingMethods', |
1057
|
|
|
|
|
|
|
PrintConv => { BITMASK => { |
1058
|
|
|
|
|
|
|
0 => 'Unspecified compression', |
1059
|
|
|
|
|
|
|
1 => 'Modified Huffman', |
1060
|
|
|
|
|
|
|
2 => 'Modified Read', |
1061
|
|
|
|
|
|
|
3 => 'Modified MR', |
1062
|
|
|
|
|
|
|
4 => 'JBIG', |
1063
|
|
|
|
|
|
|
5 => 'Baseline JPEG', |
1064
|
|
|
|
|
|
|
6 => 'JBIG color', |
1065
|
|
|
|
|
|
|
} }, |
1066
|
|
|
|
|
|
|
}, |
1067
|
|
|
|
|
|
|
0x194 => 'VersionYear', #3 |
1068
|
|
|
|
|
|
|
0x195 => 'ModeNumber', #3 |
1069
|
|
|
|
|
|
|
0x1b1 => 'Decode', #3 |
1070
|
|
|
|
|
|
|
0x1b2 => 'DefaultImageColor', #3 (changed to ImageBaseColor, ref 21) |
1071
|
|
|
|
|
|
|
0x1b3 => 'T82Options', #20 |
1072
|
|
|
|
|
|
|
0x1b5 => { #19 |
1073
|
|
|
|
|
|
|
Name => 'JPEGTables', |
1074
|
|
|
|
|
|
|
Binary => 1, |
1075
|
|
|
|
|
|
|
}, |
1076
|
|
|
|
|
|
|
0x200 => { |
1077
|
|
|
|
|
|
|
Name => 'JPEGProc', |
1078
|
|
|
|
|
|
|
PrintConv => { |
1079
|
|
|
|
|
|
|
1 => 'Baseline', |
1080
|
|
|
|
|
|
|
14 => 'Lossless', |
1081
|
|
|
|
|
|
|
}, |
1082
|
|
|
|
|
|
|
}, |
1083
|
|
|
|
|
|
|
0x201 => [ |
1084
|
|
|
|
|
|
|
{ |
1085
|
|
|
|
|
|
|
Name => 'ThumbnailOffset', |
1086
|
|
|
|
|
|
|
Notes => q{ |
1087
|
|
|
|
|
|
|
ThumbnailOffset in IFD1 of JPEG and some TIFF-based images, IFD0 of MRW |
1088
|
|
|
|
|
|
|
images and AVI and MOV videos, and the SubIFD in IFD1 of SRW images; |
1089
|
|
|
|
|
|
|
PreviewImageStart in MakerNotes and IFD0 of ARW and SR2 images; |
1090
|
|
|
|
|
|
|
JpgFromRawStart in SubIFD of NEF images and IFD2 of PEF images; and |
1091
|
|
|
|
|
|
|
OtherImageStart in everything else |
1092
|
|
|
|
|
|
|
}, |
1093
|
|
|
|
|
|
|
# thumbnail is found in IFD1 of JPEG and TIFF images, and |
1094
|
|
|
|
|
|
|
# IFD0 of EXIF information in FujiFilm AVI (RIFF) and MOV videos |
1095
|
|
|
|
|
|
|
Condition => q{ |
1096
|
|
|
|
|
|
|
# recognize NRW file from a JPEG-compressed thumbnail in IFD0 |
1097
|
|
|
|
|
|
|
if ($$self{TIFF_TYPE} eq 'NEF' and $$self{DIR_NAME} eq 'IFD0' and $$self{Compression} == 6) { |
1098
|
|
|
|
|
|
|
$self->OverrideFileType($$self{TIFF_TYPE} = 'NRW'); |
1099
|
|
|
|
|
|
|
} |
1100
|
|
|
|
|
|
|
$$self{DIR_NAME} eq 'IFD1' or |
1101
|
|
|
|
|
|
|
($$self{DIR_NAME} eq 'IFD0' and $$self{FILE_TYPE} =~ /^(RIFF|MOV)$/) |
1102
|
|
|
|
|
|
|
}, |
1103
|
|
|
|
|
|
|
IsOffset => 1, |
1104
|
|
|
|
|
|
|
OffsetPair => 0x202, |
1105
|
|
|
|
|
|
|
DataTag => 'ThumbnailImage', |
1106
|
|
|
|
|
|
|
Writable => 'int32u', |
1107
|
|
|
|
|
|
|
WriteGroup => 'IFD1', |
1108
|
|
|
|
|
|
|
# according to the EXIF spec. a JPEG-compressed thumbnail image may not |
1109
|
|
|
|
|
|
|
# be stored in a TIFF file, but these TIFF-based RAW image formats |
1110
|
|
|
|
|
|
|
# use IFD1 for a JPEG-compressed thumbnail: CR2, ARW, SR2 and PEF. |
1111
|
|
|
|
|
|
|
# (SRF also stores a JPEG image in IFD1, but it is actually a preview |
1112
|
|
|
|
|
|
|
# and we don't yet write SRF anyway) |
1113
|
|
|
|
|
|
|
WriteCondition => q{ |
1114
|
|
|
|
|
|
|
$$self{FILE_TYPE} ne "TIFF" or |
1115
|
|
|
|
|
|
|
$$self{TIFF_TYPE} =~ /^(CR2|ARW|SR2|PEF)$/ |
1116
|
|
|
|
|
|
|
}, |
1117
|
|
|
|
|
|
|
Protected => 2, |
1118
|
|
|
|
|
|
|
}, |
1119
|
|
|
|
|
|
|
{ |
1120
|
|
|
|
|
|
|
Name => 'ThumbnailOffset', |
1121
|
|
|
|
|
|
|
# thumbnail in IFD0 of MRW images (Minolta A200) |
1122
|
|
|
|
|
|
|
# and IFD0 of NRW images (Nikon Coolpix P6000,P7000,P7100) |
1123
|
|
|
|
|
|
|
Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} =~ /^(MRW|NRW)$/', |
1124
|
|
|
|
|
|
|
IsOffset => 1, |
1125
|
|
|
|
|
|
|
OffsetPair => 0x202, |
1126
|
|
|
|
|
|
|
# A200 uses the wrong base offset for this pointer!! |
1127
|
|
|
|
|
|
|
WrongBase => '$$self{Model} =~ /^DiMAGE A200/ ? $$self{MRW_WrongBase} : undef', |
1128
|
|
|
|
|
|
|
DataTag => 'ThumbnailImage', |
1129
|
|
|
|
|
|
|
Writable => 'int32u', |
1130
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1131
|
|
|
|
|
|
|
Protected => 2, |
1132
|
|
|
|
|
|
|
Permanent => 1, |
1133
|
|
|
|
|
|
|
}, |
1134
|
|
|
|
|
|
|
{ |
1135
|
|
|
|
|
|
|
Name => 'ThumbnailOffset', |
1136
|
|
|
|
|
|
|
# in SubIFD of IFD1 in Samsung SRW images |
1137
|
|
|
|
|
|
|
Condition => q{ |
1138
|
|
|
|
|
|
|
$$self{TIFF_TYPE} eq 'SRW' and $$self{DIR_NAME} eq 'SubIFD' and |
1139
|
|
|
|
|
|
|
$$self{PATH}[-2] eq 'IFD1' |
1140
|
|
|
|
|
|
|
}, |
1141
|
|
|
|
|
|
|
IsOffset => 1, |
1142
|
|
|
|
|
|
|
OffsetPair => 0x202, |
1143
|
|
|
|
|
|
|
DataTag => 'ThumbnailImage', |
1144
|
|
|
|
|
|
|
Writable => 'int32u', |
1145
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
1146
|
|
|
|
|
|
|
Protected => 2, |
1147
|
|
|
|
|
|
|
Permanent => 1, |
1148
|
|
|
|
|
|
|
}, |
1149
|
|
|
|
|
|
|
{ |
1150
|
|
|
|
|
|
|
Name => 'PreviewImageStart', |
1151
|
|
|
|
|
|
|
Condition => '$$self{DIR_NAME} eq "MakerNotes"', |
1152
|
|
|
|
|
|
|
IsOffset => 1, |
1153
|
|
|
|
|
|
|
OffsetPair => 0x202, |
1154
|
|
|
|
|
|
|
DataTag => 'PreviewImage', |
1155
|
|
|
|
|
|
|
Writable => 'int32u', |
1156
|
|
|
|
|
|
|
WriteGroup => 'MakerNotes', |
1157
|
|
|
|
|
|
|
Protected => 2, |
1158
|
|
|
|
|
|
|
Permanent => 1, |
1159
|
|
|
|
|
|
|
}, |
1160
|
|
|
|
|
|
|
{ |
1161
|
|
|
|
|
|
|
Name => 'PreviewImageStart', |
1162
|
|
|
|
|
|
|
# PreviewImage in IFD0 of ARW and SR2 files for all models |
1163
|
|
|
|
|
|
|
Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} =~ /^(ARW|SR2)$/', |
1164
|
|
|
|
|
|
|
IsOffset => 1, |
1165
|
|
|
|
|
|
|
OffsetPair => 0x202, |
1166
|
|
|
|
|
|
|
DataTag => 'PreviewImage', |
1167
|
|
|
|
|
|
|
Writable => 'int32u', |
1168
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1169
|
|
|
|
|
|
|
Protected => 2, |
1170
|
|
|
|
|
|
|
Permanent => 1, |
1171
|
|
|
|
|
|
|
}, |
1172
|
|
|
|
|
|
|
{ |
1173
|
|
|
|
|
|
|
Name => 'JpgFromRawStart', |
1174
|
|
|
|
|
|
|
Condition => '$$self{DIR_NAME} eq "SubIFD"', |
1175
|
|
|
|
|
|
|
IsOffset => 1, |
1176
|
|
|
|
|
|
|
OffsetPair => 0x202, |
1177
|
|
|
|
|
|
|
DataTag => 'JpgFromRaw', |
1178
|
|
|
|
|
|
|
Writable => 'int32u', |
1179
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
1180
|
|
|
|
|
|
|
# JpgFromRaw is in SubIFD of NEF, NRW and SRW files |
1181
|
|
|
|
|
|
|
Protected => 2, |
1182
|
|
|
|
|
|
|
Permanent => 1, |
1183
|
|
|
|
|
|
|
}, |
1184
|
|
|
|
|
|
|
{ |
1185
|
|
|
|
|
|
|
Name => 'JpgFromRawStart', |
1186
|
|
|
|
|
|
|
Condition => '$$self{DIR_NAME} eq "IFD2"', |
1187
|
|
|
|
|
|
|
IsOffset => 1, |
1188
|
|
|
|
|
|
|
OffsetPair => 0x202, |
1189
|
|
|
|
|
|
|
DataTag => 'JpgFromRaw', |
1190
|
|
|
|
|
|
|
Writable => 'int32u', |
1191
|
|
|
|
|
|
|
WriteGroup => 'IFD2', |
1192
|
|
|
|
|
|
|
# JpgFromRaw is in IFD2 of PEF files |
1193
|
|
|
|
|
|
|
Protected => 2, |
1194
|
|
|
|
|
|
|
Permanent => 1, |
1195
|
|
|
|
|
|
|
}, |
1196
|
|
|
|
|
|
|
{ |
1197
|
|
|
|
|
|
|
Name => 'OtherImageStart', |
1198
|
|
|
|
|
|
|
Condition => '$$self{DIR_NAME} eq "SubIFD1"', |
1199
|
|
|
|
|
|
|
IsOffset => 1, |
1200
|
|
|
|
|
|
|
OffsetPair => 0x202, |
1201
|
|
|
|
|
|
|
DataTag => 'OtherImage', |
1202
|
|
|
|
|
|
|
Writable => 'int32u', |
1203
|
|
|
|
|
|
|
WriteGroup => 'SubIFD1', |
1204
|
|
|
|
|
|
|
Protected => 2, |
1205
|
|
|
|
|
|
|
Permanent => 1, |
1206
|
|
|
|
|
|
|
}, |
1207
|
|
|
|
|
|
|
{ |
1208
|
|
|
|
|
|
|
Name => 'OtherImageStart', |
1209
|
|
|
|
|
|
|
Condition => '$$self{DIR_NAME} eq "SubIFD2"', |
1210
|
|
|
|
|
|
|
IsOffset => 1, |
1211
|
|
|
|
|
|
|
OffsetPair => 0x202, |
1212
|
|
|
|
|
|
|
DataTag => 'OtherImage', |
1213
|
|
|
|
|
|
|
Writable => 'int32u', |
1214
|
|
|
|
|
|
|
WriteGroup => 'SubIFD2', |
1215
|
|
|
|
|
|
|
Protected => 2, |
1216
|
|
|
|
|
|
|
Permanent => 1, |
1217
|
|
|
|
|
|
|
}, |
1218
|
|
|
|
|
|
|
{ |
1219
|
|
|
|
|
|
|
Name => 'OtherImageStart', |
1220
|
|
|
|
|
|
|
IsOffset => 1, |
1221
|
|
|
|
|
|
|
OffsetPair => 0x202, |
1222
|
|
|
|
|
|
|
}, |
1223
|
|
|
|
|
|
|
], |
1224
|
|
|
|
|
|
|
0x202 => [ |
1225
|
|
|
|
|
|
|
{ |
1226
|
|
|
|
|
|
|
Name => 'ThumbnailLength', |
1227
|
|
|
|
|
|
|
Notes => q{ |
1228
|
|
|
|
|
|
|
ThumbnailLength in IFD1 of JPEG and some TIFF-based images, IFD0 of MRW |
1229
|
|
|
|
|
|
|
images and AVI and MOV videos, and the SubIFD in IFD1 of SRW images; |
1230
|
|
|
|
|
|
|
PreviewImageLength in MakerNotes and IFD0 of ARW and SR2 images; |
1231
|
|
|
|
|
|
|
JpgFromRawLength in SubIFD of NEF images, and IFD2 of PEF images; and |
1232
|
|
|
|
|
|
|
OtherImageLength in everything else |
1233
|
|
|
|
|
|
|
}, |
1234
|
|
|
|
|
|
|
Condition => q{ |
1235
|
|
|
|
|
|
|
$$self{DIR_NAME} eq 'IFD1' or |
1236
|
|
|
|
|
|
|
($$self{DIR_NAME} eq 'IFD0' and $$self{FILE_TYPE} =~ /^(RIFF|MOV)$/) |
1237
|
|
|
|
|
|
|
}, |
1238
|
|
|
|
|
|
|
OffsetPair => 0x201, |
1239
|
|
|
|
|
|
|
DataTag => 'ThumbnailImage', |
1240
|
|
|
|
|
|
|
Writable => 'int32u', |
1241
|
|
|
|
|
|
|
WriteGroup => 'IFD1', |
1242
|
|
|
|
|
|
|
WriteCondition => q{ |
1243
|
|
|
|
|
|
|
$$self{FILE_TYPE} ne "TIFF" or |
1244
|
|
|
|
|
|
|
$$self{TIFF_TYPE} =~ /^(CR2|ARW|SR2|PEF)$/ |
1245
|
|
|
|
|
|
|
}, |
1246
|
|
|
|
|
|
|
Protected => 2, |
1247
|
|
|
|
|
|
|
}, |
1248
|
|
|
|
|
|
|
{ |
1249
|
|
|
|
|
|
|
Name => 'ThumbnailLength', |
1250
|
|
|
|
|
|
|
# thumbnail in IFD0 of MRW images (Minolta A200) |
1251
|
|
|
|
|
|
|
# and IFD0 of NRW images (Nikon Coolpix P6000,P7000,P7100) |
1252
|
|
|
|
|
|
|
Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} =~ /^(MRW|NRW)$/', |
1253
|
|
|
|
|
|
|
OffsetPair => 0x201, |
1254
|
|
|
|
|
|
|
DataTag => 'ThumbnailImage', |
1255
|
|
|
|
|
|
|
Writable => 'int32u', |
1256
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1257
|
|
|
|
|
|
|
Protected => 2, |
1258
|
|
|
|
|
|
|
Permanent => 1, |
1259
|
|
|
|
|
|
|
}, |
1260
|
|
|
|
|
|
|
{ |
1261
|
|
|
|
|
|
|
Name => 'ThumbnailLength', |
1262
|
|
|
|
|
|
|
# in SubIFD of IFD1 in Samsung SRW images |
1263
|
|
|
|
|
|
|
Condition => q{ |
1264
|
|
|
|
|
|
|
$$self{TIFF_TYPE} eq 'SRW' and $$self{DIR_NAME} eq 'SubIFD' and |
1265
|
|
|
|
|
|
|
$$self{PATH}[-2] eq 'IFD1' |
1266
|
|
|
|
|
|
|
}, |
1267
|
|
|
|
|
|
|
OffsetPair => 0x201, |
1268
|
|
|
|
|
|
|
DataTag => 'ThumbnailImage', |
1269
|
|
|
|
|
|
|
Writable => 'int32u', |
1270
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
1271
|
|
|
|
|
|
|
Protected => 2, |
1272
|
|
|
|
|
|
|
Permanent => 1, |
1273
|
|
|
|
|
|
|
}, |
1274
|
|
|
|
|
|
|
{ |
1275
|
|
|
|
|
|
|
Name => 'PreviewImageLength', |
1276
|
|
|
|
|
|
|
Condition => '$$self{DIR_NAME} eq "MakerNotes"', |
1277
|
|
|
|
|
|
|
OffsetPair => 0x201, |
1278
|
|
|
|
|
|
|
DataTag => 'PreviewImage', |
1279
|
|
|
|
|
|
|
Writable => 'int32u', |
1280
|
|
|
|
|
|
|
WriteGroup => 'MakerNotes', |
1281
|
|
|
|
|
|
|
Protected => 2, |
1282
|
|
|
|
|
|
|
Permanent => 1, |
1283
|
|
|
|
|
|
|
}, |
1284
|
|
|
|
|
|
|
{ |
1285
|
|
|
|
|
|
|
Name => 'PreviewImageLength', |
1286
|
|
|
|
|
|
|
# PreviewImage in IFD0 of ARW and SR2 files for all models |
1287
|
|
|
|
|
|
|
Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} =~ /^(ARW|SR2)$/', |
1288
|
|
|
|
|
|
|
OffsetPair => 0x201, |
1289
|
|
|
|
|
|
|
DataTag => 'PreviewImage', |
1290
|
|
|
|
|
|
|
Writable => 'int32u', |
1291
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1292
|
|
|
|
|
|
|
Protected => 2, |
1293
|
|
|
|
|
|
|
Permanent => 1, |
1294
|
|
|
|
|
|
|
}, |
1295
|
|
|
|
|
|
|
{ |
1296
|
|
|
|
|
|
|
Name => 'JpgFromRawLength', |
1297
|
|
|
|
|
|
|
Condition => '$$self{DIR_NAME} eq "SubIFD"', |
1298
|
|
|
|
|
|
|
OffsetPair => 0x201, |
1299
|
|
|
|
|
|
|
DataTag => 'JpgFromRaw', |
1300
|
|
|
|
|
|
|
Writable => 'int32u', |
1301
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
1302
|
|
|
|
|
|
|
Protected => 2, |
1303
|
|
|
|
|
|
|
Permanent => 1, |
1304
|
|
|
|
|
|
|
}, |
1305
|
|
|
|
|
|
|
{ |
1306
|
|
|
|
|
|
|
Name => 'JpgFromRawLength', |
1307
|
|
|
|
|
|
|
Condition => '$$self{DIR_NAME} eq "IFD2"', |
1308
|
|
|
|
|
|
|
OffsetPair => 0x201, |
1309
|
|
|
|
|
|
|
DataTag => 'JpgFromRaw', |
1310
|
|
|
|
|
|
|
Writable => 'int32u', |
1311
|
|
|
|
|
|
|
WriteGroup => 'IFD2', |
1312
|
|
|
|
|
|
|
Protected => 2, |
1313
|
|
|
|
|
|
|
Permanent => 1, |
1314
|
|
|
|
|
|
|
}, |
1315
|
|
|
|
|
|
|
{ |
1316
|
|
|
|
|
|
|
Name => 'OtherImageLength', |
1317
|
|
|
|
|
|
|
Condition => '$$self{DIR_NAME} eq "SubIFD1"', |
1318
|
|
|
|
|
|
|
OffsetPair => 0x201, |
1319
|
|
|
|
|
|
|
DataTag => 'OtherImage', |
1320
|
|
|
|
|
|
|
Writable => 'int32u', |
1321
|
|
|
|
|
|
|
WriteGroup => 'SubIFD1', |
1322
|
|
|
|
|
|
|
Protected => 2, |
1323
|
|
|
|
|
|
|
Permanent => 1, |
1324
|
|
|
|
|
|
|
}, |
1325
|
|
|
|
|
|
|
{ |
1326
|
|
|
|
|
|
|
Name => 'OtherImageLength', |
1327
|
|
|
|
|
|
|
Condition => '$$self{DIR_NAME} eq "SubIFD2"', |
1328
|
|
|
|
|
|
|
OffsetPair => 0x201, |
1329
|
|
|
|
|
|
|
DataTag => 'OtherImage', |
1330
|
|
|
|
|
|
|
Writable => 'int32u', |
1331
|
|
|
|
|
|
|
WriteGroup => 'SubIFD2', |
1332
|
|
|
|
|
|
|
Protected => 2, |
1333
|
|
|
|
|
|
|
Permanent => 1, |
1334
|
|
|
|
|
|
|
}, |
1335
|
|
|
|
|
|
|
{ |
1336
|
|
|
|
|
|
|
Name => 'OtherImageLength', |
1337
|
|
|
|
|
|
|
OffsetPair => 0x201, |
1338
|
|
|
|
|
|
|
}, |
1339
|
|
|
|
|
|
|
], |
1340
|
|
|
|
|
|
|
0x203 => 'JPEGRestartInterval', |
1341
|
|
|
|
|
|
|
0x205 => 'JPEGLosslessPredictors', |
1342
|
|
|
|
|
|
|
0x206 => 'JPEGPointTransforms', |
1343
|
|
|
|
|
|
|
0x207 => { |
1344
|
|
|
|
|
|
|
Name => 'JPEGQTables', |
1345
|
|
|
|
|
|
|
IsOffset => 1, |
1346
|
|
|
|
|
|
|
# this tag is not supported for writing, so define an |
1347
|
|
|
|
|
|
|
# invalid offset pair to cause a "No size tag" error to be |
1348
|
|
|
|
|
|
|
# generated if we try to write a file containing this tag |
1349
|
|
|
|
|
|
|
OffsetPair => -1, |
1350
|
|
|
|
|
|
|
}, |
1351
|
|
|
|
|
|
|
0x208 => { |
1352
|
|
|
|
|
|
|
Name => 'JPEGDCTables', |
1353
|
|
|
|
|
|
|
IsOffset => 1, |
1354
|
|
|
|
|
|
|
OffsetPair => -1, # (see comment for JPEGQTables) |
1355
|
|
|
|
|
|
|
}, |
1356
|
|
|
|
|
|
|
0x209 => { |
1357
|
|
|
|
|
|
|
Name => 'JPEGACTables', |
1358
|
|
|
|
|
|
|
IsOffset => 1, |
1359
|
|
|
|
|
|
|
OffsetPair => -1, # (see comment for JPEGQTables) |
1360
|
|
|
|
|
|
|
}, |
1361
|
|
|
|
|
|
|
0x211 => { |
1362
|
|
|
|
|
|
|
Name => 'YCbCrCoefficients', |
1363
|
|
|
|
|
|
|
Protected => 1, |
1364
|
|
|
|
|
|
|
Writable => 'rational64u', |
1365
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1366
|
|
|
|
|
|
|
Count => 3, |
1367
|
|
|
|
|
|
|
Priority => 0, |
1368
|
|
|
|
|
|
|
}, |
1369
|
|
|
|
|
|
|
0x212 => { |
1370
|
|
|
|
|
|
|
Name => 'YCbCrSubSampling', |
1371
|
|
|
|
|
|
|
Protected => 1, |
1372
|
|
|
|
|
|
|
Writable => 'int16u', |
1373
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1374
|
|
|
|
|
|
|
Count => 2, |
1375
|
|
|
|
|
|
|
PrintConvColumns => 2, |
1376
|
|
|
|
|
|
|
PrintConv => \%Image::ExifTool::JPEG::yCbCrSubSampling, |
1377
|
|
|
|
|
|
|
Priority => 0, |
1378
|
|
|
|
|
|
|
}, |
1379
|
|
|
|
|
|
|
0x213 => { |
1380
|
|
|
|
|
|
|
Name => 'YCbCrPositioning', |
1381
|
|
|
|
|
|
|
Protected => 1, |
1382
|
|
|
|
|
|
|
Writable => 'int16u', |
1383
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1384
|
|
|
|
|
|
|
Mandatory => 1, |
1385
|
|
|
|
|
|
|
PrintConv => { |
1386
|
|
|
|
|
|
|
1 => 'Centered', |
1387
|
|
|
|
|
|
|
2 => 'Co-sited', |
1388
|
|
|
|
|
|
|
}, |
1389
|
|
|
|
|
|
|
Priority => 0, |
1390
|
|
|
|
|
|
|
}, |
1391
|
|
|
|
|
|
|
0x214 => { |
1392
|
|
|
|
|
|
|
Name => 'ReferenceBlackWhite', |
1393
|
|
|
|
|
|
|
Writable => 'rational64u', |
1394
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1395
|
|
|
|
|
|
|
Count => 6, |
1396
|
|
|
|
|
|
|
Priority => 0, |
1397
|
|
|
|
|
|
|
}, |
1398
|
|
|
|
|
|
|
# 0x220 - int32u: 0 (IFD0, Xaiomi Redmi models) |
1399
|
|
|
|
|
|
|
# 0x221 - int32u: 0 (IFD0, Xaiomi Redmi models) |
1400
|
|
|
|
|
|
|
# 0x222 - int32u: 0 (IFD0, Xaiomi Redmi models) |
1401
|
|
|
|
|
|
|
# 0x223 - int32u: 0 (IFD0, Xaiomi Redmi models) |
1402
|
|
|
|
|
|
|
# 0x224 - int32u: 0,1 (IFD0, Xaiomi Redmi models) |
1403
|
|
|
|
|
|
|
# 0x225 - string: "" (IFD0, Xaiomi Redmi models) |
1404
|
|
|
|
|
|
|
0x22f => 'StripRowCounts', |
1405
|
|
|
|
|
|
|
0x2bc => { |
1406
|
|
|
|
|
|
|
Name => 'ApplicationNotes', # (writable directory!) |
1407
|
|
|
|
|
|
|
Format => 'undef', |
1408
|
|
|
|
|
|
|
Writable => 'int8u', |
1409
|
|
|
|
|
|
|
WriteGroup => 'IFD0', # (only for Validate) |
1410
|
|
|
|
|
|
|
Flags => [ 'Binary', 'Protected' ], |
1411
|
|
|
|
|
|
|
# this could be an XMP block |
1412
|
|
|
|
|
|
|
SubDirectory => { |
1413
|
|
|
|
|
|
|
DirName => 'XMP', |
1414
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::XMP::Main', |
1415
|
|
|
|
|
|
|
}, |
1416
|
|
|
|
|
|
|
}, |
1417
|
|
|
|
|
|
|
0x3e7 => 'USPTOMiscellaneous', #20 |
1418
|
|
|
|
|
|
|
0x1000 => { #5 |
1419
|
|
|
|
|
|
|
Name => 'RelatedImageFileFormat', |
1420
|
|
|
|
|
|
|
Protected => 1, |
1421
|
|
|
|
|
|
|
Writable => 'string', |
1422
|
|
|
|
|
|
|
WriteGroup => 'InteropIFD', |
1423
|
|
|
|
|
|
|
}, |
1424
|
|
|
|
|
|
|
0x1001 => { #5 |
1425
|
|
|
|
|
|
|
Name => 'RelatedImageWidth', |
1426
|
|
|
|
|
|
|
Protected => 1, |
1427
|
|
|
|
|
|
|
Writable => 'int16u', |
1428
|
|
|
|
|
|
|
WriteGroup => 'InteropIFD', |
1429
|
|
|
|
|
|
|
}, |
1430
|
|
|
|
|
|
|
0x1002 => { #5 |
1431
|
|
|
|
|
|
|
Name => 'RelatedImageHeight', |
1432
|
|
|
|
|
|
|
Notes => 'called RelatedImageLength by the DCF spec.', |
1433
|
|
|
|
|
|
|
Protected => 1, |
1434
|
|
|
|
|
|
|
Writable => 'int16u', |
1435
|
|
|
|
|
|
|
WriteGroup => 'InteropIFD', |
1436
|
|
|
|
|
|
|
}, |
1437
|
|
|
|
|
|
|
# (0x474x tags written by MicrosoftPhoto) |
1438
|
|
|
|
|
|
|
0x4746 => { #PH |
1439
|
|
|
|
|
|
|
Name => 'Rating', |
1440
|
|
|
|
|
|
|
Writable => 'int16u', |
1441
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1442
|
|
|
|
|
|
|
Avoid => 1, |
1443
|
|
|
|
|
|
|
}, |
1444
|
|
|
|
|
|
|
0x4747 => { # (written by Digital Image Pro) |
1445
|
|
|
|
|
|
|
Name => 'XP_DIP_XML', |
1446
|
|
|
|
|
|
|
Format => 'undef', |
1447
|
|
|
|
|
|
|
# the following reference indicates this is Unicode: |
1448
|
|
|
|
|
|
|
# http://social.msdn.microsoft.com/Forums/en-US/isvvba/thread/ce6edcbb-8fc2-40c6-ad98-85f5d835ddfb |
1449
|
|
|
|
|
|
|
ValueConv => '$self->Decode($val,"UCS2","II")', |
1450
|
|
|
|
|
|
|
}, |
1451
|
|
|
|
|
|
|
0x4748 => { |
1452
|
|
|
|
|
|
|
Name => 'StitchInfo', |
1453
|
|
|
|
|
|
|
SubDirectory => { |
1454
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Microsoft::Stitch', |
1455
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', #PH (NC) |
1456
|
|
|
|
|
|
|
}, |
1457
|
|
|
|
|
|
|
}, |
1458
|
|
|
|
|
|
|
0x4749 => { #PH |
1459
|
|
|
|
|
|
|
Name => 'RatingPercent', |
1460
|
|
|
|
|
|
|
Writable => 'int16u', |
1461
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1462
|
|
|
|
|
|
|
Avoid => 1, |
1463
|
|
|
|
|
|
|
}, |
1464
|
|
|
|
|
|
|
0x7000 => { #JR |
1465
|
|
|
|
|
|
|
Name => 'SonyRawFileType', |
1466
|
|
|
|
|
|
|
# (only valid if Sony:FileFormat >= ARW 2.0, ref IB) |
1467
|
|
|
|
|
|
|
# Writable => 'int16u', (don't allow writes for now) |
1468
|
|
|
|
|
|
|
PrintConv => { |
1469
|
|
|
|
|
|
|
0 => 'Sony Uncompressed 14-bit RAW', |
1470
|
|
|
|
|
|
|
1 => 'Sony Uncompressed 12-bit RAW', #IB |
1471
|
|
|
|
|
|
|
2 => 'Sony Compressed RAW', # (lossy, ref IB) |
1472
|
|
|
|
|
|
|
3 => 'Sony Lossless Compressed RAW', #IB |
1473
|
|
|
|
|
|
|
4 => 'Sony Lossless Compressed RAW 2', #JR (ILCE-1) |
1474
|
|
|
|
|
|
|
}, |
1475
|
|
|
|
|
|
|
}, |
1476
|
|
|
|
|
|
|
# 0x7001 - int16u[1] (in SubIFD of Sony ARW images) - values: 0,1 |
1477
|
|
|
|
|
|
|
0x7010 => { #IB |
1478
|
|
|
|
|
|
|
Name => 'SonyToneCurve', |
1479
|
|
|
|
|
|
|
# int16u[4] (in SubIFD of Sony ARW images -- don't allow writes for now) |
1480
|
|
|
|
|
|
|
# - only the middle 4 points are stored (lower comes from black level, |
1481
|
|
|
|
|
|
|
# and upper from data maximum) |
1482
|
|
|
|
|
|
|
}, |
1483
|
|
|
|
|
|
|
# 0x7011 - int16u[4] (in SubIFD of Sony ARW images) - values: "0 4912 8212 12287","4000 7200 10050 12075" |
1484
|
|
|
|
|
|
|
# 0x7020 - int32u[1] (in SubIFD of Sony ARW images) - values: 0,3 |
1485
|
|
|
|
|
|
|
0x7031 => { |
1486
|
|
|
|
|
|
|
Name => 'VignettingCorrection', |
1487
|
|
|
|
|
|
|
Notes => 'found in Sony ARW images', |
1488
|
|
|
|
|
|
|
Protected => 1, |
1489
|
|
|
|
|
|
|
Writable => 'int16s', |
1490
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
1491
|
|
|
|
|
|
|
PrintConv => { |
1492
|
|
|
|
|
|
|
256 => 'Off', |
1493
|
|
|
|
|
|
|
257 => 'Auto', |
1494
|
|
|
|
|
|
|
272 => 'Auto (ILCE-1)', #JR |
1495
|
|
|
|
|
|
|
511 => 'No correction params available', |
1496
|
|
|
|
|
|
|
}, |
1497
|
|
|
|
|
|
|
}, |
1498
|
|
|
|
|
|
|
0x7032 => { |
1499
|
|
|
|
|
|
|
Name => 'VignettingCorrParams', #forum7640 |
1500
|
|
|
|
|
|
|
Notes => 'found in Sony ARW images', |
1501
|
|
|
|
|
|
|
Protected => 1, |
1502
|
|
|
|
|
|
|
Writable => 'int16s', |
1503
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
1504
|
|
|
|
|
|
|
Count => 17, |
1505
|
|
|
|
|
|
|
}, |
1506
|
|
|
|
|
|
|
0x7034 => { |
1507
|
|
|
|
|
|
|
Name => 'ChromaticAberrationCorrection', |
1508
|
|
|
|
|
|
|
Notes => 'found in Sony ARW images', |
1509
|
|
|
|
|
|
|
Protected => 1, |
1510
|
|
|
|
|
|
|
Writable => 'int16s', |
1511
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
1512
|
|
|
|
|
|
|
PrintConv => { |
1513
|
|
|
|
|
|
|
0 => 'Off', |
1514
|
|
|
|
|
|
|
1 => 'Auto', |
1515
|
|
|
|
|
|
|
255 => 'No correction params available', |
1516
|
|
|
|
|
|
|
}, |
1517
|
|
|
|
|
|
|
}, |
1518
|
|
|
|
|
|
|
0x7035 => { |
1519
|
|
|
|
|
|
|
Name => 'ChromaticAberrationCorrParams', #forum6509 |
1520
|
|
|
|
|
|
|
Notes => 'found in Sony ARW images', |
1521
|
|
|
|
|
|
|
Protected => 1, |
1522
|
|
|
|
|
|
|
Writable => 'int16s', |
1523
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
1524
|
|
|
|
|
|
|
Count => 33, |
1525
|
|
|
|
|
|
|
}, |
1526
|
|
|
|
|
|
|
0x7036 => { |
1527
|
|
|
|
|
|
|
Name => 'DistortionCorrection', |
1528
|
|
|
|
|
|
|
Notes => 'found in Sony ARW images', |
1529
|
|
|
|
|
|
|
Protected => 1, |
1530
|
|
|
|
|
|
|
Writable => 'int16s', |
1531
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
1532
|
|
|
|
|
|
|
PrintConv => { |
1533
|
|
|
|
|
|
|
0 => 'Off', |
1534
|
|
|
|
|
|
|
1 => 'Auto', |
1535
|
|
|
|
|
|
|
17 => 'Auto fixed by lens', |
1536
|
|
|
|
|
|
|
255 => 'No correction params available', |
1537
|
|
|
|
|
|
|
}, |
1538
|
|
|
|
|
|
|
}, |
1539
|
|
|
|
|
|
|
0x7037 => { |
1540
|
|
|
|
|
|
|
Name => 'DistortionCorrParams', #forum6509 |
1541
|
|
|
|
|
|
|
Notes => 'found in Sony ARW images', |
1542
|
|
|
|
|
|
|
Protected => 1, |
1543
|
|
|
|
|
|
|
Writable => 'int16s', |
1544
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
1545
|
|
|
|
|
|
|
Count => 17, |
1546
|
|
|
|
|
|
|
}, |
1547
|
|
|
|
|
|
|
0x74c7 => { #IB (in ARW images from some Sony cameras) |
1548
|
|
|
|
|
|
|
Name => 'SonyCropTopLeft', |
1549
|
|
|
|
|
|
|
Writable => 'int32u', |
1550
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
1551
|
|
|
|
|
|
|
Count => 2, |
1552
|
|
|
|
|
|
|
Permanent => 1, |
1553
|
|
|
|
|
|
|
Protected => 1, |
1554
|
|
|
|
|
|
|
}, |
1555
|
|
|
|
|
|
|
0x74c8 => { #IB (in ARW images from some Sony cameras) |
1556
|
|
|
|
|
|
|
Name => 'SonyCropSize', |
1557
|
|
|
|
|
|
|
Writable => 'int32u', |
1558
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
1559
|
|
|
|
|
|
|
Count => 2, |
1560
|
|
|
|
|
|
|
Permanent => 1, |
1561
|
|
|
|
|
|
|
Protected => 1, |
1562
|
|
|
|
|
|
|
}, |
1563
|
|
|
|
|
|
|
0x800d => 'ImageID', #10 |
1564
|
|
|
|
|
|
|
0x80a3 => { Name => 'WangTag1', Binary => 1 }, #20 |
1565
|
|
|
|
|
|
|
0x80a4 => { Name => 'WangAnnotation', Binary => 1 }, |
1566
|
|
|
|
|
|
|
0x80a5 => { Name => 'WangTag3', Binary => 1 }, #20 |
1567
|
|
|
|
|
|
|
0x80a6 => { #20 |
1568
|
|
|
|
|
|
|
Name => 'WangTag4', |
1569
|
|
|
|
|
|
|
PrintConv => 'length($val) <= 64 ? $val : \$val', |
1570
|
|
|
|
|
|
|
}, |
1571
|
|
|
|
|
|
|
# tags 0x80b8-0x80bc are registered to Island Graphics |
1572
|
|
|
|
|
|
|
0x80b9 => 'ImageReferencePoints', #29 |
1573
|
|
|
|
|
|
|
0x80ba => 'RegionXformTackPoint', #29 |
1574
|
|
|
|
|
|
|
0x80bb => 'WarpQuadrilateral', #29 |
1575
|
|
|
|
|
|
|
0x80bc => 'AffineTransformMat', #29 |
1576
|
|
|
|
|
|
|
0x80e3 => 'Matteing', #9 |
1577
|
|
|
|
|
|
|
0x80e4 => 'DataType', #9 |
1578
|
|
|
|
|
|
|
0x80e5 => 'ImageDepth', #9 |
1579
|
|
|
|
|
|
|
0x80e6 => 'TileDepth', #9 |
1580
|
|
|
|
|
|
|
# tags 0x8214-0x8219 are registered to Pixar |
1581
|
|
|
|
|
|
|
0x8214 => 'ImageFullWidth', #29 |
1582
|
|
|
|
|
|
|
0x8215 => 'ImageFullHeight', #29 |
1583
|
|
|
|
|
|
|
0x8216 => 'TextureFormat', #29 |
1584
|
|
|
|
|
|
|
0x8217 => 'WrapModes', #29 |
1585
|
|
|
|
|
|
|
0x8218 => 'FovCot', #29 |
1586
|
|
|
|
|
|
|
0x8219 => 'MatrixWorldToScreen', #29 |
1587
|
|
|
|
|
|
|
0x821a => 'MatrixWorldToCamera', #29 |
1588
|
|
|
|
|
|
|
0x827d => 'Model2', #29 (Eastman Kodak) |
1589
|
|
|
|
|
|
|
0x828d => { #12 |
1590
|
|
|
|
|
|
|
Name => 'CFARepeatPatternDim', |
1591
|
|
|
|
|
|
|
Protected => 1, |
1592
|
|
|
|
|
|
|
Writable => 'int16u', |
1593
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
1594
|
|
|
|
|
|
|
Count => 2, |
1595
|
|
|
|
|
|
|
}, |
1596
|
|
|
|
|
|
|
0x828e => { |
1597
|
|
|
|
|
|
|
Name => 'CFAPattern2', #12 |
1598
|
|
|
|
|
|
|
Format => 'int8u', # (written incorrectly as 'undef' in Nikon NRW images) |
1599
|
|
|
|
|
|
|
Protected => 1, |
1600
|
|
|
|
|
|
|
Writable => 'int8u', |
1601
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
1602
|
|
|
|
|
|
|
Count => -1, |
1603
|
|
|
|
|
|
|
}, |
1604
|
|
|
|
|
|
|
0x828f => { #12 |
1605
|
|
|
|
|
|
|
Name => 'BatteryLevel', |
1606
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
1607
|
|
|
|
|
|
|
}, |
1608
|
|
|
|
|
|
|
0x8290 => { |
1609
|
|
|
|
|
|
|
Name => 'KodakIFD', |
1610
|
|
|
|
|
|
|
Groups => { 1 => 'KodakIFD' }, |
1611
|
|
|
|
|
|
|
Flags => 'SubIFD', |
1612
|
|
|
|
|
|
|
Notes => 'used in various types of Kodak images', |
1613
|
|
|
|
|
|
|
SubDirectory => { |
1614
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Kodak::IFD', |
1615
|
|
|
|
|
|
|
DirName => 'KodakIFD', |
1616
|
|
|
|
|
|
|
Start => '$val', |
1617
|
|
|
|
|
|
|
MaxSubdirs => 1, |
1618
|
|
|
|
|
|
|
}, |
1619
|
|
|
|
|
|
|
}, |
1620
|
|
|
|
|
|
|
0x8298 => { |
1621
|
|
|
|
|
|
|
Name => 'Copyright', |
1622
|
|
|
|
|
|
|
Groups => { 2 => 'Author' }, |
1623
|
|
|
|
|
|
|
Format => 'undef', |
1624
|
|
|
|
|
|
|
Writable => 'string', |
1625
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1626
|
|
|
|
|
|
|
Notes => q{ |
1627
|
|
|
|
|
|
|
may contain copyright notices for photographer and editor, separated by a |
1628
|
|
|
|
|
|
|
newline. As per the EXIF specification, the newline is replaced by a null |
1629
|
|
|
|
|
|
|
byte when writing to file, but this may be avoided by disabling the print |
1630
|
|
|
|
|
|
|
conversion |
1631
|
|
|
|
|
|
|
}, |
1632
|
|
|
|
|
|
|
# internally the strings are separated by a null character in this format: |
1633
|
|
|
|
|
|
|
# Photographer only: photographer + NULL |
1634
|
|
|
|
|
|
|
# Both: photographer + NULL + editor + NULL |
1635
|
|
|
|
|
|
|
# Editor only: SPACE + NULL + editor + NULL |
1636
|
|
|
|
|
|
|
# (this is done as a RawConv so conditional replaces will work properly) |
1637
|
|
|
|
|
|
|
RawConv => sub { |
1638
|
|
|
|
|
|
|
my ($val, $self) = @_; |
1639
|
|
|
|
|
|
|
$val =~ s/ *\0/\n/; # translate first NULL to a newline, removing trailing blanks |
1640
|
|
|
|
|
|
|
$val =~ s/ *\0.*//s; # truncate at second NULL and remove trailing blanks |
1641
|
|
|
|
|
|
|
$val =~ s/\n$//; # remove trailing newline if it exists |
1642
|
|
|
|
|
|
|
# decode if necessary (note: this is the only non-'string' EXIF value like this) |
1643
|
|
|
|
|
|
|
my $enc = $self->Options('CharsetEXIF'); |
1644
|
|
|
|
|
|
|
$val = $self->Decode($val,$enc) if $enc; |
1645
|
|
|
|
|
|
|
return $val; |
1646
|
|
|
|
|
|
|
}, |
1647
|
|
|
|
|
|
|
RawConvInv => '$val . "\0"', |
1648
|
|
|
|
|
|
|
PrintConvInv => sub { |
1649
|
|
|
|
|
|
|
my ($val, $self) = @_; |
1650
|
|
|
|
|
|
|
# encode if necessary (not automatic because Format is 'undef') |
1651
|
|
|
|
|
|
|
my $enc = $self->Options('CharsetEXIF'); |
1652
|
|
|
|
|
|
|
$val = $self->Encode($val,$enc) if $enc and $val !~ /\0/; |
1653
|
|
|
|
|
|
|
if ($val =~ /(.*?)\s*[\n\r]+\s*(.*)/s) { |
1654
|
|
|
|
|
|
|
return $1 unless length $2; |
1655
|
|
|
|
|
|
|
# photographer copyright set to ' ' if it doesn't exist, according to spec. |
1656
|
|
|
|
|
|
|
return((length($1) ? $1 : ' ') . "\0" . $2); |
1657
|
|
|
|
|
|
|
} |
1658
|
|
|
|
|
|
|
return $val; |
1659
|
|
|
|
|
|
|
}, |
1660
|
|
|
|
|
|
|
}, |
1661
|
|
|
|
|
|
|
0x829a => { |
1662
|
|
|
|
|
|
|
Name => 'ExposureTime', |
1663
|
|
|
|
|
|
|
Writable => 'rational64u', |
1664
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', |
1665
|
|
|
|
|
|
|
PrintConvInv => '$val', |
1666
|
|
|
|
|
|
|
}, |
1667
|
|
|
|
|
|
|
0x829d => { |
1668
|
|
|
|
|
|
|
Name => 'FNumber', |
1669
|
|
|
|
|
|
|
Writable => 'rational64u', |
1670
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', |
1671
|
|
|
|
|
|
|
PrintConvInv => '$val', |
1672
|
|
|
|
|
|
|
}, |
1673
|
|
|
|
|
|
|
0x82a5 => { #3 |
1674
|
|
|
|
|
|
|
Name => 'MDFileTag', |
1675
|
|
|
|
|
|
|
Notes => 'tags 0x82a5-0x82ac are used in Molecular Dynamics GEL files', |
1676
|
|
|
|
|
|
|
}, |
1677
|
|
|
|
|
|
|
0x82a6 => 'MDScalePixel', #3 |
1678
|
|
|
|
|
|
|
0x82a7 => 'MDColorTable', #3 |
1679
|
|
|
|
|
|
|
0x82a8 => 'MDLabName', #3 |
1680
|
|
|
|
|
|
|
0x82a9 => 'MDSampleInfo', #3 |
1681
|
|
|
|
|
|
|
0x82aa => 'MDPrepDate', #3 |
1682
|
|
|
|
|
|
|
0x82ab => 'MDPrepTime', #3 |
1683
|
|
|
|
|
|
|
0x82ac => 'MDFileUnits', #3 |
1684
|
|
|
|
|
|
|
0x830e => { #30 (GeoTiff) |
1685
|
|
|
|
|
|
|
Name => 'PixelScale', |
1686
|
|
|
|
|
|
|
Writable => 'double', |
1687
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1688
|
|
|
|
|
|
|
Count => 3, |
1689
|
|
|
|
|
|
|
}, |
1690
|
|
|
|
|
|
|
0x8335 => 'AdventScale', #20 |
1691
|
|
|
|
|
|
|
0x8336 => 'AdventRevision', #20 |
1692
|
|
|
|
|
|
|
0x835c => 'UIC1Tag', #23 |
1693
|
|
|
|
|
|
|
0x835d => 'UIC2Tag', #23 |
1694
|
|
|
|
|
|
|
0x835e => 'UIC3Tag', #23 |
1695
|
|
|
|
|
|
|
0x835f => 'UIC4Tag', #23 |
1696
|
|
|
|
|
|
|
0x83bb => { #12 |
1697
|
|
|
|
|
|
|
Name => 'IPTC-NAA', # (writable directory! -- but see note below) |
1698
|
|
|
|
|
|
|
# this should actually be written as 'undef' (see |
1699
|
|
|
|
|
|
|
# http://www.awaresystems.be/imaging/tiff/tifftags/iptc.html), |
1700
|
|
|
|
|
|
|
# but Photoshop writes it as int32u and Nikon Capture won't read |
1701
|
|
|
|
|
|
|
# anything else, so we do the same thing here... Doh! |
1702
|
|
|
|
|
|
|
Format => 'undef', # convert binary values as undef |
1703
|
|
|
|
|
|
|
Writable => 'int32u', # but write int32u format code in IFD |
1704
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1705
|
|
|
|
|
|
|
Flags => [ 'Binary', 'Protected' ], |
1706
|
|
|
|
|
|
|
SubDirectory => { |
1707
|
|
|
|
|
|
|
DirName => 'IPTC', |
1708
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::IPTC::Main', |
1709
|
|
|
|
|
|
|
}, |
1710
|
|
|
|
|
|
|
# Note: This directory may be written as a block via the IPTC-NAA tag, |
1711
|
|
|
|
|
|
|
# but this technique is not recommended. Instead, it is better to |
1712
|
|
|
|
|
|
|
# write the Extra IPTC tag and let ExifTool decide where it should go. |
1713
|
|
|
|
|
|
|
}, |
1714
|
|
|
|
|
|
|
0x847e => 'IntergraphPacketData', #3 |
1715
|
|
|
|
|
|
|
0x847f => 'IntergraphFlagRegisters', #3 |
1716
|
|
|
|
|
|
|
0x8480 => { #30 (GeoTiff, obsolete) |
1717
|
|
|
|
|
|
|
Name => 'IntergraphMatrix', |
1718
|
|
|
|
|
|
|
Writable => 'double', |
1719
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1720
|
|
|
|
|
|
|
Count => -1, |
1721
|
|
|
|
|
|
|
}, |
1722
|
|
|
|
|
|
|
0x8481 => 'INGRReserved', #20 |
1723
|
|
|
|
|
|
|
0x8482 => { #30 (GeoTiff) |
1724
|
|
|
|
|
|
|
Name => 'ModelTiePoint', |
1725
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
1726
|
|
|
|
|
|
|
Writable => 'double', |
1727
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1728
|
|
|
|
|
|
|
Count => -1, |
1729
|
|
|
|
|
|
|
}, |
1730
|
|
|
|
|
|
|
0x84e0 => 'Site', #9 |
1731
|
|
|
|
|
|
|
0x84e1 => 'ColorSequence', #9 |
1732
|
|
|
|
|
|
|
0x84e2 => 'IT8Header', #9 |
1733
|
|
|
|
|
|
|
0x84e3 => { #9 |
1734
|
|
|
|
|
|
|
Name => 'RasterPadding', |
1735
|
|
|
|
|
|
|
PrintConv => { #20 |
1736
|
|
|
|
|
|
|
0 => 'Byte', |
1737
|
|
|
|
|
|
|
1 => 'Word', |
1738
|
|
|
|
|
|
|
2 => 'Long Word', |
1739
|
|
|
|
|
|
|
9 => 'Sector', |
1740
|
|
|
|
|
|
|
10 => 'Long Sector', |
1741
|
|
|
|
|
|
|
}, |
1742
|
|
|
|
|
|
|
}, |
1743
|
|
|
|
|
|
|
0x84e4 => 'BitsPerRunLength', #9 |
1744
|
|
|
|
|
|
|
0x84e5 => 'BitsPerExtendedRunLength', #9 |
1745
|
|
|
|
|
|
|
0x84e6 => 'ColorTable', #9 |
1746
|
|
|
|
|
|
|
0x84e7 => { #9 |
1747
|
|
|
|
|
|
|
Name => 'ImageColorIndicator', |
1748
|
|
|
|
|
|
|
PrintConv => { #20 |
1749
|
|
|
|
|
|
|
0 => 'Unspecified Image Color', |
1750
|
|
|
|
|
|
|
1 => 'Specified Image Color', |
1751
|
|
|
|
|
|
|
}, |
1752
|
|
|
|
|
|
|
}, |
1753
|
|
|
|
|
|
|
0x84e8 => { #9 |
1754
|
|
|
|
|
|
|
Name => 'BackgroundColorIndicator', |
1755
|
|
|
|
|
|
|
PrintConv => { #20 |
1756
|
|
|
|
|
|
|
0 => 'Unspecified Background Color', |
1757
|
|
|
|
|
|
|
1 => 'Specified Background Color', |
1758
|
|
|
|
|
|
|
}, |
1759
|
|
|
|
|
|
|
}, |
1760
|
|
|
|
|
|
|
0x84e9 => 'ImageColorValue', #9 |
1761
|
|
|
|
|
|
|
0x84ea => 'BackgroundColorValue', #9 |
1762
|
|
|
|
|
|
|
0x84eb => 'PixelIntensityRange', #9 |
1763
|
|
|
|
|
|
|
0x84ec => 'TransparencyIndicator', #9 |
1764
|
|
|
|
|
|
|
0x84ed => 'ColorCharacterization', #9 |
1765
|
|
|
|
|
|
|
0x84ee => { #9 |
1766
|
|
|
|
|
|
|
Name => 'HCUsage', |
1767
|
|
|
|
|
|
|
PrintConv => { #20 |
1768
|
|
|
|
|
|
|
0 => 'CT', |
1769
|
|
|
|
|
|
|
1 => 'Line Art', |
1770
|
|
|
|
|
|
|
2 => 'Trap', |
1771
|
|
|
|
|
|
|
}, |
1772
|
|
|
|
|
|
|
}, |
1773
|
|
|
|
|
|
|
0x84ef => 'TrapIndicator', #17 |
1774
|
|
|
|
|
|
|
0x84f0 => 'CMYKEquivalent', #17 |
1775
|
|
|
|
|
|
|
0x8546 => { #11 |
1776
|
|
|
|
|
|
|
Name => 'SEMInfo', |
1777
|
|
|
|
|
|
|
Notes => 'found in some scanning electron microscope images', |
1778
|
|
|
|
|
|
|
Writable => 'string', |
1779
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1780
|
|
|
|
|
|
|
}, |
1781
|
|
|
|
|
|
|
0x8568 => { |
1782
|
|
|
|
|
|
|
Name => 'AFCP_IPTC', |
1783
|
|
|
|
|
|
|
SubDirectory => { |
1784
|
|
|
|
|
|
|
# must change directory name so we don't create this directory |
1785
|
|
|
|
|
|
|
DirName => 'AFCP_IPTC', |
1786
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::IPTC::Main', |
1787
|
|
|
|
|
|
|
}, |
1788
|
|
|
|
|
|
|
}, |
1789
|
|
|
|
|
|
|
0x85b8 => 'PixelMagicJBIGOptions', #20 |
1790
|
|
|
|
|
|
|
0x85d7 => 'JPLCartoIFD', #exifprobe (NC) |
1791
|
|
|
|
|
|
|
0x85d8 => { #30 (GeoTiff) |
1792
|
|
|
|
|
|
|
Name => 'ModelTransform', |
1793
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
1794
|
|
|
|
|
|
|
Writable => 'double', |
1795
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1796
|
|
|
|
|
|
|
Count => 16, |
1797
|
|
|
|
|
|
|
}, |
1798
|
|
|
|
|
|
|
0x8602 => { #16 |
1799
|
|
|
|
|
|
|
Name => 'WB_GRGBLevels', |
1800
|
|
|
|
|
|
|
Notes => 'found in IFD0 of Leaf MOS images', |
1801
|
|
|
|
|
|
|
}, |
1802
|
|
|
|
|
|
|
# 0x8603 - Leaf CatchLight color matrix (ref 16) |
1803
|
|
|
|
|
|
|
0x8606 => { |
1804
|
|
|
|
|
|
|
Name => 'LeafData', |
1805
|
|
|
|
|
|
|
Format => 'undef', # avoid converting huge block to string of int8u's! |
1806
|
|
|
|
|
|
|
SubDirectory => { |
1807
|
|
|
|
|
|
|
DirName => 'LeafIFD', |
1808
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Leaf::Main', |
1809
|
|
|
|
|
|
|
}, |
1810
|
|
|
|
|
|
|
}, |
1811
|
|
|
|
|
|
|
0x8649 => { #19 |
1812
|
|
|
|
|
|
|
Name => 'PhotoshopSettings', |
1813
|
|
|
|
|
|
|
Format => 'binary', |
1814
|
|
|
|
|
|
|
WriteGroup => 'IFD0', # (only for Validate) |
1815
|
|
|
|
|
|
|
SubDirectory => { |
1816
|
|
|
|
|
|
|
DirName => 'Photoshop', |
1817
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Photoshop::Main', |
1818
|
|
|
|
|
|
|
}, |
1819
|
|
|
|
|
|
|
}, |
1820
|
|
|
|
|
|
|
0x8769 => { |
1821
|
|
|
|
|
|
|
Name => 'ExifOffset', |
1822
|
|
|
|
|
|
|
Groups => { 1 => 'ExifIFD' }, |
1823
|
|
|
|
|
|
|
WriteGroup => 'IFD0', # (only for Validate) |
1824
|
|
|
|
|
|
|
SubIFD => 2, |
1825
|
|
|
|
|
|
|
SubDirectory => { |
1826
|
|
|
|
|
|
|
DirName => 'ExifIFD', |
1827
|
|
|
|
|
|
|
Start => '$val', |
1828
|
|
|
|
|
|
|
}, |
1829
|
|
|
|
|
|
|
}, |
1830
|
|
|
|
|
|
|
0x8773 => { |
1831
|
|
|
|
|
|
|
Name => 'ICC_Profile', |
1832
|
|
|
|
|
|
|
WriteGroup => 'IFD0', # (only for Validate) |
1833
|
|
|
|
|
|
|
SubDirectory => { |
1834
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::ICC_Profile::Main', |
1835
|
|
|
|
|
|
|
}, |
1836
|
|
|
|
|
|
|
}, |
1837
|
|
|
|
|
|
|
0x877f => { #20 |
1838
|
|
|
|
|
|
|
Name => 'TIFF_FXExtensions', |
1839
|
|
|
|
|
|
|
PrintConv => { BITMASK => { |
1840
|
|
|
|
|
|
|
0 => 'Resolution/Image Width', |
1841
|
|
|
|
|
|
|
1 => 'N Layer Profile M', |
1842
|
|
|
|
|
|
|
2 => 'Shared Data', |
1843
|
|
|
|
|
|
|
3 => 'B&W JBIG2', |
1844
|
|
|
|
|
|
|
4 => 'JBIG2 Profile M', |
1845
|
|
|
|
|
|
|
}}, |
1846
|
|
|
|
|
|
|
}, |
1847
|
|
|
|
|
|
|
0x8780 => { #20 |
1848
|
|
|
|
|
|
|
Name => 'MultiProfiles', |
1849
|
|
|
|
|
|
|
PrintConv => { BITMASK => { |
1850
|
|
|
|
|
|
|
0 => 'Profile S', |
1851
|
|
|
|
|
|
|
1 => 'Profile F', |
1852
|
|
|
|
|
|
|
2 => 'Profile J', |
1853
|
|
|
|
|
|
|
3 => 'Profile C', |
1854
|
|
|
|
|
|
|
4 => 'Profile L', |
1855
|
|
|
|
|
|
|
5 => 'Profile M', |
1856
|
|
|
|
|
|
|
6 => 'Profile T', |
1857
|
|
|
|
|
|
|
7 => 'Resolution/Image Width', |
1858
|
|
|
|
|
|
|
8 => 'N Layer Profile M', |
1859
|
|
|
|
|
|
|
9 => 'Shared Data', |
1860
|
|
|
|
|
|
|
10 => 'JBIG2 Profile M', |
1861
|
|
|
|
|
|
|
}}, |
1862
|
|
|
|
|
|
|
}, |
1863
|
|
|
|
|
|
|
0x8781 => { #22 |
1864
|
|
|
|
|
|
|
Name => 'SharedData', |
1865
|
|
|
|
|
|
|
IsOffset => 1, |
1866
|
|
|
|
|
|
|
# this tag is not supported for writing, so define an |
1867
|
|
|
|
|
|
|
# invalid offset pair to cause a "No size tag" error to be |
1868
|
|
|
|
|
|
|
# generated if we try to write a file containing this tag |
1869
|
|
|
|
|
|
|
OffsetPair => -1, |
1870
|
|
|
|
|
|
|
}, |
1871
|
|
|
|
|
|
|
0x8782 => 'T88Options', #20 |
1872
|
|
|
|
|
|
|
0x87ac => 'ImageLayer', |
1873
|
|
|
|
|
|
|
0x87af => { #30 |
1874
|
|
|
|
|
|
|
Name => 'GeoTiffDirectory', |
1875
|
|
|
|
|
|
|
Format => 'undef', |
1876
|
|
|
|
|
|
|
Writable => 'int16u', |
1877
|
|
|
|
|
|
|
Notes => q{ |
1878
|
|
|
|
|
|
|
these "GeoTiff" tags may read and written as a block, but they aren't |
1879
|
|
|
|
|
|
|
extracted unless specifically requested. Byte order changes are handled |
1880
|
|
|
|
|
|
|
automatically when copying between TIFF images with different byte order |
1881
|
|
|
|
|
|
|
}, |
1882
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1883
|
|
|
|
|
|
|
Binary => 1, |
1884
|
|
|
|
|
|
|
RawConv => '$val . GetByteOrder()', # save byte order |
1885
|
|
|
|
|
|
|
# swap byte order if necessary |
1886
|
|
|
|
|
|
|
RawConvInv => q{ |
1887
|
|
|
|
|
|
|
return $val if length $val < 2; |
1888
|
|
|
|
|
|
|
my $order = substr($val, -2); |
1889
|
|
|
|
|
|
|
return $val unless $order eq 'II' or $order eq 'MM'; |
1890
|
|
|
|
|
|
|
$val = substr($val, 0, -2); |
1891
|
|
|
|
|
|
|
return $val if $order eq GetByteOrder(); |
1892
|
|
|
|
|
|
|
return pack('v*',unpack('n*',$val)); |
1893
|
|
|
|
|
|
|
}, |
1894
|
|
|
|
|
|
|
}, |
1895
|
|
|
|
|
|
|
0x87b0 => { #30 |
1896
|
|
|
|
|
|
|
Name => 'GeoTiffDoubleParams', |
1897
|
|
|
|
|
|
|
Format => 'undef', |
1898
|
|
|
|
|
|
|
Writable => 'double', |
1899
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1900
|
|
|
|
|
|
|
Binary => 1, |
1901
|
|
|
|
|
|
|
RawConv => '$val . GetByteOrder()', # save byte order |
1902
|
|
|
|
|
|
|
# swap byte order if necessary |
1903
|
|
|
|
|
|
|
RawConvInv => q{ |
1904
|
|
|
|
|
|
|
return $val if length $val < 2; |
1905
|
|
|
|
|
|
|
my $order = substr($val, -2); |
1906
|
|
|
|
|
|
|
return $val unless $order eq 'II' or $order eq 'MM'; |
1907
|
|
|
|
|
|
|
$val = substr($val, 0, -2); |
1908
|
|
|
|
|
|
|
return $val if $order eq GetByteOrder(); |
1909
|
|
|
|
|
|
|
$val =~ s/(.{4})(.{4})/$2$1/sg; # swap words |
1910
|
|
|
|
|
|
|
return pack('V*',unpack('N*',$val)); |
1911
|
|
|
|
|
|
|
}, |
1912
|
|
|
|
|
|
|
}, |
1913
|
|
|
|
|
|
|
0x87b1 => { #30 |
1914
|
|
|
|
|
|
|
Name => 'GeoTiffAsciiParams', |
1915
|
|
|
|
|
|
|
Format => 'undef', |
1916
|
|
|
|
|
|
|
Writable => 'string', |
1917
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
1918
|
|
|
|
|
|
|
Binary => 1, |
1919
|
|
|
|
|
|
|
}, |
1920
|
|
|
|
|
|
|
0x87be => 'JBIGOptions', #29 |
1921
|
|
|
|
|
|
|
0x8822 => { |
1922
|
|
|
|
|
|
|
Name => 'ExposureProgram', |
1923
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
1924
|
|
|
|
|
|
|
Notes => 'the value of 9 is not standard EXIF, but is used by the Canon EOS 7D', |
1925
|
|
|
|
|
|
|
Writable => 'int16u', |
1926
|
|
|
|
|
|
|
PrintConv => { |
1927
|
|
|
|
|
|
|
0 => 'Not Defined', |
1928
|
|
|
|
|
|
|
1 => 'Manual', |
1929
|
|
|
|
|
|
|
2 => 'Program AE', |
1930
|
|
|
|
|
|
|
3 => 'Aperture-priority AE', |
1931
|
|
|
|
|
|
|
4 => 'Shutter speed priority AE', |
1932
|
|
|
|
|
|
|
5 => 'Creative (Slow speed)', |
1933
|
|
|
|
|
|
|
6 => 'Action (High speed)', |
1934
|
|
|
|
|
|
|
7 => 'Portrait', |
1935
|
|
|
|
|
|
|
8 => 'Landscape', |
1936
|
|
|
|
|
|
|
9 => 'Bulb', #25 |
1937
|
|
|
|
|
|
|
}, |
1938
|
|
|
|
|
|
|
}, |
1939
|
|
|
|
|
|
|
0x8824 => { |
1940
|
|
|
|
|
|
|
Name => 'SpectralSensitivity', |
1941
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
1942
|
|
|
|
|
|
|
Writable => 'string', |
1943
|
|
|
|
|
|
|
}, |
1944
|
|
|
|
|
|
|
0x8825 => { |
1945
|
|
|
|
|
|
|
Name => 'GPSInfo', |
1946
|
|
|
|
|
|
|
Groups => { 1 => 'GPS' }, |
1947
|
|
|
|
|
|
|
WriteGroup => 'IFD0', # (only for Validate) |
1948
|
|
|
|
|
|
|
Flags => 'SubIFD', |
1949
|
|
|
|
|
|
|
SubDirectory => { |
1950
|
|
|
|
|
|
|
DirName => 'GPS', |
1951
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::GPS::Main', |
1952
|
|
|
|
|
|
|
Start => '$val', |
1953
|
|
|
|
|
|
|
MaxSubdirs => 1, |
1954
|
|
|
|
|
|
|
}, |
1955
|
|
|
|
|
|
|
}, |
1956
|
|
|
|
|
|
|
0x8827 => { |
1957
|
|
|
|
|
|
|
Name => 'ISO', |
1958
|
|
|
|
|
|
|
Notes => q{ |
1959
|
|
|
|
|
|
|
called ISOSpeedRatings by EXIF 2.2, then PhotographicSensitivity by the EXIF |
1960
|
|
|
|
|
|
|
2.3 spec. |
1961
|
|
|
|
|
|
|
}, |
1962
|
|
|
|
|
|
|
Writable => 'int16u', |
1963
|
|
|
|
|
|
|
Count => -1, |
1964
|
|
|
|
|
|
|
PrintConv => '$val=~s/\s+/, /g; $val', |
1965
|
|
|
|
|
|
|
PrintConvInv => '$val=~tr/,//d; $val', |
1966
|
|
|
|
|
|
|
}, |
1967
|
|
|
|
|
|
|
0x8828 => { |
1968
|
|
|
|
|
|
|
Name => 'Opto-ElectricConvFactor', |
1969
|
|
|
|
|
|
|
Notes => 'called OECF by the EXIF spec.', |
1970
|
|
|
|
|
|
|
Binary => 1, |
1971
|
|
|
|
|
|
|
}, |
1972
|
|
|
|
|
|
|
0x8829 => 'Interlace', #12 |
1973
|
|
|
|
|
|
|
0x882a => { #12 |
1974
|
|
|
|
|
|
|
Name => 'TimeZoneOffset', |
1975
|
|
|
|
|
|
|
Writable => 'int16s', |
1976
|
|
|
|
|
|
|
Count => -1, # can be 1 or 2 |
1977
|
|
|
|
|
|
|
Notes => q{ |
1978
|
|
|
|
|
|
|
1 or 2 values: 1. The time zone offset of DateTimeOriginal from GMT in |
1979
|
|
|
|
|
|
|
hours, 2. If present, the time zone offset of ModifyDate |
1980
|
|
|
|
|
|
|
}, |
1981
|
|
|
|
|
|
|
}, |
1982
|
|
|
|
|
|
|
0x882b => { #12 |
1983
|
|
|
|
|
|
|
Name => 'SelfTimerMode', |
1984
|
|
|
|
|
|
|
Writable => 'int16u', |
1985
|
|
|
|
|
|
|
}, |
1986
|
|
|
|
|
|
|
0x8830 => { #24 |
1987
|
|
|
|
|
|
|
Name => 'SensitivityType', |
1988
|
|
|
|
|
|
|
Notes => 'applies to EXIF:ISO tag', |
1989
|
|
|
|
|
|
|
Writable => 'int16u', |
1990
|
|
|
|
|
|
|
PrintConv => { |
1991
|
|
|
|
|
|
|
0 => 'Unknown', |
1992
|
|
|
|
|
|
|
1 => 'Standard Output Sensitivity', |
1993
|
|
|
|
|
|
|
2 => 'Recommended Exposure Index', |
1994
|
|
|
|
|
|
|
3 => 'ISO Speed', |
1995
|
|
|
|
|
|
|
4 => 'Standard Output Sensitivity and Recommended Exposure Index', |
1996
|
|
|
|
|
|
|
5 => 'Standard Output Sensitivity and ISO Speed', |
1997
|
|
|
|
|
|
|
6 => 'Recommended Exposure Index and ISO Speed', |
1998
|
|
|
|
|
|
|
7 => 'Standard Output Sensitivity, Recommended Exposure Index and ISO Speed', |
1999
|
|
|
|
|
|
|
}, |
2000
|
|
|
|
|
|
|
}, |
2001
|
|
|
|
|
|
|
0x8831 => { #24 |
2002
|
|
|
|
|
|
|
Name => 'StandardOutputSensitivity', |
2003
|
|
|
|
|
|
|
Writable => 'int32u', |
2004
|
|
|
|
|
|
|
}, |
2005
|
|
|
|
|
|
|
0x8832 => { #24 |
2006
|
|
|
|
|
|
|
Name => 'RecommendedExposureIndex', |
2007
|
|
|
|
|
|
|
Writable => 'int32u', |
2008
|
|
|
|
|
|
|
}, |
2009
|
|
|
|
|
|
|
0x8833 => { #24 |
2010
|
|
|
|
|
|
|
Name => 'ISOSpeed', |
2011
|
|
|
|
|
|
|
Writable => 'int32u', |
2012
|
|
|
|
|
|
|
}, |
2013
|
|
|
|
|
|
|
0x8834 => { #24 |
2014
|
|
|
|
|
|
|
Name => 'ISOSpeedLatitudeyyy', |
2015
|
|
|
|
|
|
|
Description => 'ISO Speed Latitude yyy', |
2016
|
|
|
|
|
|
|
Writable => 'int32u', |
2017
|
|
|
|
|
|
|
}, |
2018
|
|
|
|
|
|
|
0x8835 => { #24 |
2019
|
|
|
|
|
|
|
Name => 'ISOSpeedLatitudezzz', |
2020
|
|
|
|
|
|
|
Description => 'ISO Speed Latitude zzz', |
2021
|
|
|
|
|
|
|
Writable => 'int32u', |
2022
|
|
|
|
|
|
|
}, |
2023
|
|
|
|
|
|
|
0x885c => 'FaxRecvParams', #9 |
2024
|
|
|
|
|
|
|
0x885d => 'FaxSubAddress', #9 |
2025
|
|
|
|
|
|
|
0x885e => 'FaxRecvTime', #9 |
2026
|
|
|
|
|
|
|
0x8871 => 'FedexEDR', #exifprobe (NC) |
2027
|
|
|
|
|
|
|
# 0x8889 - string: "portrait" (ExifIFD, Xiaomi POCO F1) |
2028
|
|
|
|
|
|
|
0x888a => { #PH |
2029
|
|
|
|
|
|
|
Name => 'LeafSubIFD', |
2030
|
|
|
|
|
|
|
Format => 'int32u', # Leaf incorrectly uses 'undef' format! |
2031
|
|
|
|
|
|
|
Groups => { 1 => 'LeafSubIFD' }, |
2032
|
|
|
|
|
|
|
Flags => 'SubIFD', |
2033
|
|
|
|
|
|
|
SubDirectory => { |
2034
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Leaf::SubIFD', |
2035
|
|
|
|
|
|
|
Start => '$val', |
2036
|
|
|
|
|
|
|
}, |
2037
|
|
|
|
|
|
|
}, |
2038
|
|
|
|
|
|
|
# 0x8891 - int16u: 35 (ExifIFD, Xiaomi POCO F1) |
2039
|
|
|
|
|
|
|
# 0x8894 - int16u: 0 (ExifIFD, Xiaomi POCO F1) |
2040
|
|
|
|
|
|
|
# 0x8895 - int16u: 0 (ExifIFD, Xiaomi POCO F1) |
2041
|
|
|
|
|
|
|
# 0x889a - int16u: 0 (ExifIFD, Xiaomi POCO F1) |
2042
|
|
|
|
|
|
|
# 0x89ab - seen "11 100 130 16 0 0 0 0" in IFD0 of TIFF image from IR scanner (forum8470) |
2043
|
|
|
|
|
|
|
0x9000 => { |
2044
|
|
|
|
|
|
|
Name => 'ExifVersion', |
2045
|
|
|
|
|
|
|
Writable => 'undef', |
2046
|
|
|
|
|
|
|
Mandatory => 1, |
2047
|
|
|
|
|
|
|
RawConv => '$val=~s/\0+$//; $val', # (some idiots add null terminators) |
2048
|
|
|
|
|
|
|
# (allow strings like "2.31" when writing) |
2049
|
|
|
|
|
|
|
PrintConvInv => '$val=~tr/.//d; $val=~/^\d{4}$/ ? $val : $val =~ /^\d{3}$/ ? "0$val" : undef', |
2050
|
|
|
|
|
|
|
}, |
2051
|
|
|
|
|
|
|
0x9003 => { |
2052
|
|
|
|
|
|
|
Name => 'DateTimeOriginal', |
2053
|
|
|
|
|
|
|
Description => 'Date/Time Original', |
2054
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
2055
|
|
|
|
|
|
|
Notes => 'date/time when original image was taken', |
2056
|
|
|
|
|
|
|
Writable => 'string', |
2057
|
|
|
|
|
|
|
Shift => 'Time', |
2058
|
|
|
|
|
|
|
Validate => 'ValidateExifDate($val)', |
2059
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
2060
|
|
|
|
|
|
|
PrintConvInv => '$self->InverseDateTime($val,0)', |
2061
|
|
|
|
|
|
|
}, |
2062
|
|
|
|
|
|
|
0x9004 => { |
2063
|
|
|
|
|
|
|
Name => 'CreateDate', |
2064
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
2065
|
|
|
|
|
|
|
Notes => 'called DateTimeDigitized by the EXIF spec.', |
2066
|
|
|
|
|
|
|
Writable => 'string', |
2067
|
|
|
|
|
|
|
Shift => 'Time', |
2068
|
|
|
|
|
|
|
Validate => 'ValidateExifDate($val)', |
2069
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
2070
|
|
|
|
|
|
|
PrintConvInv => '$self->InverseDateTime($val,0)', |
2071
|
|
|
|
|
|
|
}, |
2072
|
|
|
|
|
|
|
0x9009 => { # undef[44] (or undef[11]) written by Google Plus uploader - PH |
2073
|
|
|
|
|
|
|
Name => 'GooglePlusUploadCode', |
2074
|
|
|
|
|
|
|
Format => 'int8u', |
2075
|
|
|
|
|
|
|
Writable => 'undef', |
2076
|
|
|
|
|
|
|
Count => -1, |
2077
|
|
|
|
|
|
|
}, |
2078
|
|
|
|
|
|
|
0x9010 => { |
2079
|
|
|
|
|
|
|
Name => 'OffsetTime', |
2080
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
2081
|
|
|
|
|
|
|
Notes => 'time zone for ModifyDate', |
2082
|
|
|
|
|
|
|
Writable => 'string', |
2083
|
|
|
|
|
|
|
PrintConvInv => q{ |
2084
|
|
|
|
|
|
|
return "+00:00" if $val =~ /\d{2}Z$/; |
2085
|
|
|
|
|
|
|
return sprintf("%s%.2d:%.2d",$1,$2,$3) if $val =~ /([-+])(\d{1,2}):(\d{2})/; |
2086
|
|
|
|
|
|
|
return undef; |
2087
|
|
|
|
|
|
|
}, |
2088
|
|
|
|
|
|
|
}, |
2089
|
|
|
|
|
|
|
0x9011 => { |
2090
|
|
|
|
|
|
|
Name => 'OffsetTimeOriginal', |
2091
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
2092
|
|
|
|
|
|
|
Notes => 'time zone for DateTimeOriginal', |
2093
|
|
|
|
|
|
|
Writable => 'string', |
2094
|
|
|
|
|
|
|
PrintConvInv => q{ |
2095
|
|
|
|
|
|
|
return "+00:00" if $val =~ /\d{2}Z$/; |
2096
|
|
|
|
|
|
|
return sprintf("%s%.2d:%.2d",$1,$2,$3) if $val =~ /([-+])(\d{1,2}):(\d{2})/; |
2097
|
|
|
|
|
|
|
return undef; |
2098
|
|
|
|
|
|
|
}, |
2099
|
|
|
|
|
|
|
}, |
2100
|
|
|
|
|
|
|
0x9012 => { |
2101
|
|
|
|
|
|
|
Name => 'OffsetTimeDigitized', |
2102
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
2103
|
|
|
|
|
|
|
Notes => 'time zone for CreateDate', |
2104
|
|
|
|
|
|
|
Writable => 'string', |
2105
|
|
|
|
|
|
|
PrintConvInv => q{ |
2106
|
|
|
|
|
|
|
return "+00:00" if $val =~ /\d{2}Z$/; |
2107
|
|
|
|
|
|
|
return sprintf("%s%.2d:%.2d",$1,$2,$3) if $val =~ /([-+])(\d{1,2}):(\d{2})/; |
2108
|
|
|
|
|
|
|
return undef; |
2109
|
|
|
|
|
|
|
}, |
2110
|
|
|
|
|
|
|
}, |
2111
|
|
|
|
|
|
|
0x9101 => { |
2112
|
|
|
|
|
|
|
Name => 'ComponentsConfiguration', |
2113
|
|
|
|
|
|
|
Format => 'int8u', |
2114
|
|
|
|
|
|
|
Protected => 1, |
2115
|
|
|
|
|
|
|
Writable => 'undef', |
2116
|
|
|
|
|
|
|
Count => 4, |
2117
|
|
|
|
|
|
|
Mandatory => 1, |
2118
|
|
|
|
|
|
|
ValueConvInv => '$val=~tr/,//d; $val', # (so we can copy from XMP with -n) |
2119
|
|
|
|
|
|
|
PrintConvColumns => 2, |
2120
|
|
|
|
|
|
|
PrintConv => { |
2121
|
|
|
|
|
|
|
0 => '-', |
2122
|
|
|
|
|
|
|
1 => 'Y', |
2123
|
|
|
|
|
|
|
2 => 'Cb', |
2124
|
|
|
|
|
|
|
3 => 'Cr', |
2125
|
|
|
|
|
|
|
4 => 'R', |
2126
|
|
|
|
|
|
|
5 => 'G', |
2127
|
|
|
|
|
|
|
6 => 'B', |
2128
|
|
|
|
|
|
|
OTHER => sub { |
2129
|
|
|
|
|
|
|
my ($val, $inv, $conv) = @_; |
2130
|
|
|
|
|
|
|
my @a = split /,?\s+/, $val; |
2131
|
|
|
|
|
|
|
if ($inv) { |
2132
|
|
|
|
|
|
|
my %invConv; |
2133
|
|
|
|
|
|
|
$invConv{lc $$conv{$_}} = $_ foreach keys %$conv; |
2134
|
|
|
|
|
|
|
# strings like "YCbCr" and "RGB" still work for writing |
2135
|
|
|
|
|
|
|
@a = $a[0] =~ /(Y|Cb|Cr|R|G|B)/g if @a == 1; |
2136
|
|
|
|
|
|
|
foreach (@a) { |
2137
|
|
|
|
|
|
|
$_ = $invConv{lc $_}; |
2138
|
|
|
|
|
|
|
return undef unless defined $_; |
2139
|
|
|
|
|
|
|
} |
2140
|
|
|
|
|
|
|
push @a, 0 while @a < 4; |
2141
|
|
|
|
|
|
|
} else { |
2142
|
|
|
|
|
|
|
foreach (@a) { |
2143
|
|
|
|
|
|
|
$_ = $$conv{$_} || "Err ($_)"; |
2144
|
|
|
|
|
|
|
} |
2145
|
|
|
|
|
|
|
} |
2146
|
|
|
|
|
|
|
return join ', ', @a; |
2147
|
|
|
|
|
|
|
}, |
2148
|
|
|
|
|
|
|
}, |
2149
|
|
|
|
|
|
|
}, |
2150
|
|
|
|
|
|
|
0x9102 => { |
2151
|
|
|
|
|
|
|
Name => 'CompressedBitsPerPixel', |
2152
|
|
|
|
|
|
|
Protected => 1, |
2153
|
|
|
|
|
|
|
Writable => 'rational64u', |
2154
|
|
|
|
|
|
|
}, |
2155
|
|
|
|
|
|
|
# 0x9103 - int16u: 1 (found in Pentax XG-1 samples) |
2156
|
|
|
|
|
|
|
0x9201 => { |
2157
|
|
|
|
|
|
|
Name => 'ShutterSpeedValue', |
2158
|
|
|
|
|
|
|
Notes => 'displayed in seconds, but stored as an APEX value', |
2159
|
|
|
|
|
|
|
Format => 'rational64s', # Leica M8 patch (incorrectly written as rational64u) |
2160
|
|
|
|
|
|
|
Writable => 'rational64s', |
2161
|
|
|
|
|
|
|
ValueConv => 'IsFloat($val) && abs($val)<100 ? 2**(-$val) : 0', |
2162
|
|
|
|
|
|
|
ValueConvInv => '$val>0 ? -log($val)/log(2) : -100', |
2163
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', |
2164
|
|
|
|
|
|
|
PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', |
2165
|
|
|
|
|
|
|
}, |
2166
|
|
|
|
|
|
|
0x9202 => { |
2167
|
|
|
|
|
|
|
Name => 'ApertureValue', |
2168
|
|
|
|
|
|
|
Notes => 'displayed as an F number, but stored as an APEX value', |
2169
|
|
|
|
|
|
|
Writable => 'rational64u', |
2170
|
|
|
|
|
|
|
ValueConv => '2 ** ($val / 2)', |
2171
|
|
|
|
|
|
|
ValueConvInv => '$val>0 ? 2*log($val)/log(2) : 0', |
2172
|
|
|
|
|
|
|
PrintConv => 'sprintf("%.1f",$val)', |
2173
|
|
|
|
|
|
|
PrintConvInv => '$val', |
2174
|
|
|
|
|
|
|
}, |
2175
|
|
|
|
|
|
|
# Wikipedia: BrightnessValue = Bv = Av + Tv - Sv |
2176
|
|
|
|
|
|
|
# ExifTool: LightValue = LV = Av + Tv - Sv + 5 (5 is the Sv for ISO 100 in Exif usage) |
2177
|
|
|
|
|
|
|
0x9203 => { |
2178
|
|
|
|
|
|
|
Name => 'BrightnessValue', |
2179
|
|
|
|
|
|
|
Writable => 'rational64s', |
2180
|
|
|
|
|
|
|
}, |
2181
|
|
|
|
|
|
|
0x9204 => { |
2182
|
|
|
|
|
|
|
Name => 'ExposureCompensation', |
2183
|
|
|
|
|
|
|
Format => 'rational64s', # Leica M8 patch (incorrectly written as rational64u) |
2184
|
|
|
|
|
|
|
Notes => 'called ExposureBiasValue by the EXIF spec.', |
2185
|
|
|
|
|
|
|
Writable => 'rational64s', |
2186
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', |
2187
|
|
|
|
|
|
|
PrintConvInv => '$val', |
2188
|
|
|
|
|
|
|
}, |
2189
|
|
|
|
|
|
|
0x9205 => { |
2190
|
|
|
|
|
|
|
Name => 'MaxApertureValue', |
2191
|
|
|
|
|
|
|
Notes => 'displayed as an F number, but stored as an APEX value', |
2192
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2193
|
|
|
|
|
|
|
Writable => 'rational64u', |
2194
|
|
|
|
|
|
|
ValueConv => '2 ** ($val / 2)', |
2195
|
|
|
|
|
|
|
ValueConvInv => '$val>0 ? 2*log($val)/log(2) : 0', |
2196
|
|
|
|
|
|
|
PrintConv => 'sprintf("%.1f",$val)', |
2197
|
|
|
|
|
|
|
PrintConvInv => '$val', |
2198
|
|
|
|
|
|
|
}, |
2199
|
|
|
|
|
|
|
0x9206 => { |
2200
|
|
|
|
|
|
|
Name => 'SubjectDistance', |
2201
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2202
|
|
|
|
|
|
|
Writable => 'rational64u', |
2203
|
|
|
|
|
|
|
PrintConv => '$val =~ /^(inf|undef)$/ ? $val : "${val} m"', |
2204
|
|
|
|
|
|
|
PrintConvInv => '$val=~s/\s*m$//;$val', |
2205
|
|
|
|
|
|
|
}, |
2206
|
|
|
|
|
|
|
0x9207 => { |
2207
|
|
|
|
|
|
|
Name => 'MeteringMode', |
2208
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2209
|
|
|
|
|
|
|
Writable => 'int16u', |
2210
|
|
|
|
|
|
|
PrintConv => { |
2211
|
|
|
|
|
|
|
0 => 'Unknown', |
2212
|
|
|
|
|
|
|
1 => 'Average', |
2213
|
|
|
|
|
|
|
2 => 'Center-weighted average', |
2214
|
|
|
|
|
|
|
3 => 'Spot', |
2215
|
|
|
|
|
|
|
4 => 'Multi-spot', |
2216
|
|
|
|
|
|
|
5 => 'Multi-segment', |
2217
|
|
|
|
|
|
|
6 => 'Partial', |
2218
|
|
|
|
|
|
|
255 => 'Other', |
2219
|
|
|
|
|
|
|
}, |
2220
|
|
|
|
|
|
|
}, |
2221
|
|
|
|
|
|
|
0x9208 => { |
2222
|
|
|
|
|
|
|
Name => 'LightSource', |
2223
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2224
|
|
|
|
|
|
|
Writable => 'int16u', |
2225
|
|
|
|
|
|
|
SeparateTable => 'LightSource', |
2226
|
|
|
|
|
|
|
PrintConv => \%lightSource, |
2227
|
|
|
|
|
|
|
}, |
2228
|
|
|
|
|
|
|
0x9209 => { |
2229
|
|
|
|
|
|
|
Name => 'Flash', |
2230
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2231
|
|
|
|
|
|
|
Writable => 'int16u', |
2232
|
|
|
|
|
|
|
Flags => 'PrintHex', |
2233
|
|
|
|
|
|
|
SeparateTable => 'Flash', |
2234
|
|
|
|
|
|
|
PrintConv => \%flash, |
2235
|
|
|
|
|
|
|
}, |
2236
|
|
|
|
|
|
|
0x920a => { |
2237
|
|
|
|
|
|
|
Name => 'FocalLength', |
2238
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2239
|
|
|
|
|
|
|
Writable => 'rational64u', |
2240
|
|
|
|
|
|
|
PrintConv => 'sprintf("%.1f mm",$val)', |
2241
|
|
|
|
|
|
|
PrintConvInv => '$val=~s/\s*mm$//;$val', |
2242
|
|
|
|
|
|
|
}, |
2243
|
|
|
|
|
|
|
# Note: tags 0x920b-0x9217 are duplicates of 0xa20b-0xa217 |
2244
|
|
|
|
|
|
|
# (The EXIF standard uses 0xa2xx, but you'll find both in images) |
2245
|
|
|
|
|
|
|
0x920b => { #12 |
2246
|
|
|
|
|
|
|
Name => 'FlashEnergy', |
2247
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2248
|
|
|
|
|
|
|
}, |
2249
|
|
|
|
|
|
|
0x920c => 'SpatialFrequencyResponse', #12 (not in Fuji images - PH) |
2250
|
|
|
|
|
|
|
0x920d => 'Noise', #12 |
2251
|
|
|
|
|
|
|
0x920e => 'FocalPlaneXResolution', #12 |
2252
|
|
|
|
|
|
|
0x920f => 'FocalPlaneYResolution', #12 |
2253
|
|
|
|
|
|
|
0x9210 => { #12 |
2254
|
|
|
|
|
|
|
Name => 'FocalPlaneResolutionUnit', |
2255
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2256
|
|
|
|
|
|
|
PrintConv => { |
2257
|
|
|
|
|
|
|
1 => 'None', |
2258
|
|
|
|
|
|
|
2 => 'inches', |
2259
|
|
|
|
|
|
|
3 => 'cm', |
2260
|
|
|
|
|
|
|
4 => 'mm', |
2261
|
|
|
|
|
|
|
5 => 'um', |
2262
|
|
|
|
|
|
|
}, |
2263
|
|
|
|
|
|
|
}, |
2264
|
|
|
|
|
|
|
0x9211 => { #12 |
2265
|
|
|
|
|
|
|
Name => 'ImageNumber', |
2266
|
|
|
|
|
|
|
Writable => 'int32u', |
2267
|
|
|
|
|
|
|
}, |
2268
|
|
|
|
|
|
|
0x9212 => { #12 |
2269
|
|
|
|
|
|
|
Name => 'SecurityClassification', |
2270
|
|
|
|
|
|
|
Writable => 'string', |
2271
|
|
|
|
|
|
|
PrintConv => { |
2272
|
|
|
|
|
|
|
T => 'Top Secret', |
2273
|
|
|
|
|
|
|
S => 'Secret', |
2274
|
|
|
|
|
|
|
C => 'Confidential', |
2275
|
|
|
|
|
|
|
R => 'Restricted', |
2276
|
|
|
|
|
|
|
U => 'Unclassified', |
2277
|
|
|
|
|
|
|
}, |
2278
|
|
|
|
|
|
|
}, |
2279
|
|
|
|
|
|
|
0x9213 => { #12 |
2280
|
|
|
|
|
|
|
Name => 'ImageHistory', |
2281
|
|
|
|
|
|
|
Writable => 'string', |
2282
|
|
|
|
|
|
|
}, |
2283
|
|
|
|
|
|
|
0x9214 => { |
2284
|
|
|
|
|
|
|
Name => 'SubjectArea', |
2285
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2286
|
|
|
|
|
|
|
Writable => 'int16u', |
2287
|
|
|
|
|
|
|
Count => -1, # 2, 3 or 4 values |
2288
|
|
|
|
|
|
|
}, |
2289
|
|
|
|
|
|
|
0x9215 => 'ExposureIndex', #12 |
2290
|
|
|
|
|
|
|
0x9216 => 'TIFF-EPStandardID', #12 |
2291
|
|
|
|
|
|
|
0x9217 => { #12 |
2292
|
|
|
|
|
|
|
Name => 'SensingMethod', |
2293
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2294
|
|
|
|
|
|
|
PrintConv => { |
2295
|
|
|
|
|
|
|
# (values 1 and 6 are not used by corresponding EXIF tag 0xa217) |
2296
|
|
|
|
|
|
|
1 => 'Monochrome area', |
2297
|
|
|
|
|
|
|
2 => 'One-chip color area', |
2298
|
|
|
|
|
|
|
3 => 'Two-chip color area', |
2299
|
|
|
|
|
|
|
4 => 'Three-chip color area', |
2300
|
|
|
|
|
|
|
5 => 'Color sequential area', |
2301
|
|
|
|
|
|
|
6 => 'Monochrome linear', |
2302
|
|
|
|
|
|
|
7 => 'Trilinear', |
2303
|
|
|
|
|
|
|
8 => 'Color sequential linear', |
2304
|
|
|
|
|
|
|
}, |
2305
|
|
|
|
|
|
|
}, |
2306
|
|
|
|
|
|
|
0x923a => 'CIP3DataFile', #20 |
2307
|
|
|
|
|
|
|
0x923b => 'CIP3Sheet', #20 |
2308
|
|
|
|
|
|
|
0x923c => 'CIP3Side', #20 |
2309
|
|
|
|
|
|
|
0x923f => 'StoNits', #9 |
2310
|
|
|
|
|
|
|
# handle maker notes as a conditional list |
2311
|
|
|
|
|
|
|
0x927c => \@Image::ExifTool::MakerNotes::Main, |
2312
|
|
|
|
|
|
|
0x9286 => { |
2313
|
|
|
|
|
|
|
Name => 'UserComment', |
2314
|
|
|
|
|
|
|
# I have seen other applications write it incorrectly as 'string' or 'int8u' |
2315
|
|
|
|
|
|
|
Format => 'undef', |
2316
|
|
|
|
|
|
|
Writable => 'undef', |
2317
|
|
|
|
|
|
|
RawConv => 'Image::ExifTool::Exif::ConvertExifText($self,$val,1,$tag)', |
2318
|
|
|
|
|
|
|
# (starts with "ASCII\0\0\0", "UNICODE\0", "JIS\0\0\0\0\0" or "\0\0\0\0\0\0\0\0") |
2319
|
|
|
|
|
|
|
RawConvInv => 'Image::ExifTool::Exif::EncodeExifText($self,$val)', |
2320
|
|
|
|
|
|
|
# SHOULD ADD SPECIAL LOGIC TO ALLOW CONDITIONAL OVERWRITE OF |
2321
|
|
|
|
|
|
|
# "UNKNOWN" VALUES FILLED WITH SPACES |
2322
|
|
|
|
|
|
|
}, |
2323
|
|
|
|
|
|
|
0x9290 => { |
2324
|
|
|
|
|
|
|
Name => 'SubSecTime', |
2325
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
2326
|
|
|
|
|
|
|
Notes => 'fractional seconds for ModifyDate', |
2327
|
|
|
|
|
|
|
Writable => 'string', |
2328
|
|
|
|
|
|
|
ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks |
2329
|
|
|
|
|
|
|
# extract fractional seconds from a full date/time value |
2330
|
|
|
|
|
|
|
ValueConvInv => '$val=~/^(\d+)\s*$/ ? $1 : ($val=~/\.(\d+)/ ? $1 : undef)', |
2331
|
|
|
|
|
|
|
}, |
2332
|
|
|
|
|
|
|
0x9291 => { |
2333
|
|
|
|
|
|
|
Name => 'SubSecTimeOriginal', |
2334
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
2335
|
|
|
|
|
|
|
Notes => 'fractional seconds for DateTimeOriginal', |
2336
|
|
|
|
|
|
|
Writable => 'string', |
2337
|
|
|
|
|
|
|
ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks |
2338
|
|
|
|
|
|
|
ValueConvInv => '$val=~/^(\d+)\s*$/ ? $1 : ($val=~/\.(\d+)/ ? $1 : undef)', |
2339
|
|
|
|
|
|
|
}, |
2340
|
|
|
|
|
|
|
0x9292 => { |
2341
|
|
|
|
|
|
|
Name => 'SubSecTimeDigitized', |
2342
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
2343
|
|
|
|
|
|
|
Notes => 'fractional seconds for CreateDate', |
2344
|
|
|
|
|
|
|
Writable => 'string', |
2345
|
|
|
|
|
|
|
ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks |
2346
|
|
|
|
|
|
|
ValueConvInv => '$val=~/^(\d+)\s*$/ ? $1 : ($val=~/\.(\d+)/ ? $1 : undef)', |
2347
|
|
|
|
|
|
|
}, |
2348
|
|
|
|
|
|
|
# The following 3 tags are found in MSOffice TIFF images |
2349
|
|
|
|
|
|
|
# References: |
2350
|
|
|
|
|
|
|
# http://social.msdn.microsoft.com/Forums/en-US/os_standocs/thread/03086d55-294a-49d5-967a-5303d34c40f8/ |
2351
|
|
|
|
|
|
|
# http://blogs.msdn.com/openspecification/archive/2009/12/08/details-of-three-tiff-tag-extensions-that-microsoft-office-document-imaging-modi-software-may-write-into-the-tiff-files-it-generates.aspx |
2352
|
|
|
|
|
|
|
# http://www.microsoft.com/downloads/details.aspx?FamilyID=0dbc435d-3544-4f4b-9092-2f2643d64a39&displaylang=en#filelist |
2353
|
|
|
|
|
|
|
0x932f => 'MSDocumentText', |
2354
|
|
|
|
|
|
|
0x9330 => { |
2355
|
|
|
|
|
|
|
Name => 'MSPropertySetStorage', |
2356
|
|
|
|
|
|
|
Binary => 1, |
2357
|
|
|
|
|
|
|
}, |
2358
|
|
|
|
|
|
|
0x9331 => { |
2359
|
|
|
|
|
|
|
Name => 'MSDocumentTextPosition', |
2360
|
|
|
|
|
|
|
Binary => 1, # (just in case -- don't know what format this is) |
2361
|
|
|
|
|
|
|
}, |
2362
|
|
|
|
|
|
|
0x935c => { #3/19 |
2363
|
|
|
|
|
|
|
Name => 'ImageSourceData', # (writable directory!) |
2364
|
|
|
|
|
|
|
Writable => 'undef', |
2365
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
2366
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Photoshop::DocumentData' }, |
2367
|
|
|
|
|
|
|
Binary => 1, |
2368
|
|
|
|
|
|
|
Protected => 1, # (because this can be hundreds of megabytes) |
2369
|
|
|
|
|
|
|
ReadFromRAF => 1, # don't load into memory when reading |
2370
|
|
|
|
|
|
|
}, |
2371
|
|
|
|
|
|
|
0x9400 => { |
2372
|
|
|
|
|
|
|
Name => 'AmbientTemperature', |
2373
|
|
|
|
|
|
|
Notes => 'ambient temperature in degrees C, called Temperature by the EXIF spec.', |
2374
|
|
|
|
|
|
|
Writable => 'rational64s', |
2375
|
|
|
|
|
|
|
PrintConv => '"$val C"', |
2376
|
|
|
|
|
|
|
PrintConvInv => '$val=~s/ ?C//; $val', |
2377
|
|
|
|
|
|
|
}, |
2378
|
|
|
|
|
|
|
0x9401 => { |
2379
|
|
|
|
|
|
|
Name => 'Humidity', |
2380
|
|
|
|
|
|
|
Notes => 'ambient relative humidity in percent', |
2381
|
|
|
|
|
|
|
Writable => 'rational64u', |
2382
|
|
|
|
|
|
|
}, |
2383
|
|
|
|
|
|
|
0x9402 => { |
2384
|
|
|
|
|
|
|
Name => 'Pressure', |
2385
|
|
|
|
|
|
|
Notes => 'air pressure in hPa or mbar', |
2386
|
|
|
|
|
|
|
Writable => 'rational64u', |
2387
|
|
|
|
|
|
|
}, |
2388
|
|
|
|
|
|
|
0x9403 => { |
2389
|
|
|
|
|
|
|
Name => 'WaterDepth', |
2390
|
|
|
|
|
|
|
Notes => 'depth under water in metres, negative for above water', |
2391
|
|
|
|
|
|
|
Writable => 'rational64s', |
2392
|
|
|
|
|
|
|
}, |
2393
|
|
|
|
|
|
|
0x9404 => { |
2394
|
|
|
|
|
|
|
Name => 'Acceleration', |
2395
|
|
|
|
|
|
|
Notes => 'directionless camera acceleration in units of mGal, or 10-5 m/s2', |
2396
|
|
|
|
|
|
|
Writable => 'rational64u', |
2397
|
|
|
|
|
|
|
}, |
2398
|
|
|
|
|
|
|
0x9405 => { |
2399
|
|
|
|
|
|
|
Name => 'CameraElevationAngle', |
2400
|
|
|
|
|
|
|
Writable => 'rational64s', |
2401
|
|
|
|
|
|
|
}, |
2402
|
|
|
|
|
|
|
# 0x9999 - string: camera settings (ExifIFD, Xiaomi POCO F1) |
2403
|
|
|
|
|
|
|
# 0x9aaa - int8u[2176]: ? (ExifIFD, Xiaomi POCO F1) |
2404
|
|
|
|
|
|
|
0x9c9b => { |
2405
|
|
|
|
|
|
|
Name => 'XPTitle', |
2406
|
|
|
|
|
|
|
Format => 'undef', |
2407
|
|
|
|
|
|
|
Writable => 'int8u', |
2408
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
2409
|
|
|
|
|
|
|
Notes => q{ |
2410
|
|
|
|
|
|
|
tags 0x9c9b-0x9c9f are used by Windows Explorer; special characters |
2411
|
|
|
|
|
|
|
in these values are converted to UTF-8 by default, or Windows Latin1 |
2412
|
|
|
|
|
|
|
with the -L option. XPTitle is ignored by Windows Explorer if |
2413
|
|
|
|
|
|
|
ImageDescription exists |
2414
|
|
|
|
|
|
|
}, |
2415
|
|
|
|
|
|
|
ValueConv => '$self->Decode($val,"UCS2","II")', |
2416
|
|
|
|
|
|
|
ValueConvInv => '$self->Encode($val,"UCS2","II") . "\0\0"', |
2417
|
|
|
|
|
|
|
}, |
2418
|
|
|
|
|
|
|
0x9c9c => { |
2419
|
|
|
|
|
|
|
Name => 'XPComment', |
2420
|
|
|
|
|
|
|
Format => 'undef', |
2421
|
|
|
|
|
|
|
Writable => 'int8u', |
2422
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
2423
|
|
|
|
|
|
|
ValueConv => '$self->Decode($val,"UCS2","II")', |
2424
|
|
|
|
|
|
|
ValueConvInv => '$self->Encode($val,"UCS2","II") . "\0\0"', |
2425
|
|
|
|
|
|
|
}, |
2426
|
|
|
|
|
|
|
0x9c9d => { |
2427
|
|
|
|
|
|
|
Name => 'XPAuthor', |
2428
|
|
|
|
|
|
|
Groups => { 2 => 'Author' }, |
2429
|
|
|
|
|
|
|
Format => 'undef', |
2430
|
|
|
|
|
|
|
Writable => 'int8u', |
2431
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
2432
|
|
|
|
|
|
|
Notes => 'ignored by Windows Explorer if Artist exists', |
2433
|
|
|
|
|
|
|
ValueConv => '$self->Decode($val,"UCS2","II")', |
2434
|
|
|
|
|
|
|
ValueConvInv => '$self->Encode($val,"UCS2","II") . "\0\0"', |
2435
|
|
|
|
|
|
|
}, |
2436
|
|
|
|
|
|
|
0x9c9e => { |
2437
|
|
|
|
|
|
|
Name => 'XPKeywords', |
2438
|
|
|
|
|
|
|
Format => 'undef', |
2439
|
|
|
|
|
|
|
Writable => 'int8u', |
2440
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
2441
|
|
|
|
|
|
|
ValueConv => '$self->Decode($val,"UCS2","II")', |
2442
|
|
|
|
|
|
|
ValueConvInv => '$self->Encode($val,"UCS2","II") . "\0\0"', |
2443
|
|
|
|
|
|
|
}, |
2444
|
|
|
|
|
|
|
0x9c9f => { |
2445
|
|
|
|
|
|
|
Name => 'XPSubject', |
2446
|
|
|
|
|
|
|
Format => 'undef', |
2447
|
|
|
|
|
|
|
Writable => 'int8u', |
2448
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
2449
|
|
|
|
|
|
|
ValueConv => '$self->Decode($val,"UCS2","II")', |
2450
|
|
|
|
|
|
|
ValueConvInv => '$self->Encode($val,"UCS2","II") . "\0\0"', |
2451
|
|
|
|
|
|
|
}, |
2452
|
|
|
|
|
|
|
0xa000 => { |
2453
|
|
|
|
|
|
|
Name => 'FlashpixVersion', |
2454
|
|
|
|
|
|
|
Writable => 'undef', |
2455
|
|
|
|
|
|
|
Mandatory => 1, |
2456
|
|
|
|
|
|
|
RawConv => '$val=~s/\0+$//; $val', # (some idiots add null terminators) |
2457
|
|
|
|
|
|
|
PrintConvInv => '$val=~tr/.//d; $val=~/^\d{4}$/ ? $val : undef', |
2458
|
|
|
|
|
|
|
}, |
2459
|
|
|
|
|
|
|
0xa001 => { |
2460
|
|
|
|
|
|
|
Name => 'ColorSpace', |
2461
|
|
|
|
|
|
|
Notes => q{ |
2462
|
|
|
|
|
|
|
the value of 0x2 is not standard EXIF. Instead, an Adobe RGB image is |
2463
|
|
|
|
|
|
|
indicated by "Uncalibrated" with an InteropIndex of "R03". The values |
2464
|
|
|
|
|
|
|
0xfffd and 0xfffe are also non-standard, and are used by some Sony cameras |
2465
|
|
|
|
|
|
|
}, |
2466
|
|
|
|
|
|
|
Writable => 'int16u', |
2467
|
|
|
|
|
|
|
Mandatory => 1, |
2468
|
|
|
|
|
|
|
PrintHex => 1, |
2469
|
|
|
|
|
|
|
PrintConv => { |
2470
|
|
|
|
|
|
|
1 => 'sRGB', |
2471
|
|
|
|
|
|
|
2 => 'Adobe RGB', |
2472
|
|
|
|
|
|
|
0xffff => 'Uncalibrated', |
2473
|
|
|
|
|
|
|
# Sony uses these definitions: (ref JD) |
2474
|
|
|
|
|
|
|
# 0xffff => 'Adobe RGB', (conflicts with Uncalibrated) |
2475
|
|
|
|
|
|
|
0xfffe => 'ICC Profile', |
2476
|
|
|
|
|
|
|
0xfffd => 'Wide Gamut RGB', |
2477
|
|
|
|
|
|
|
}, |
2478
|
|
|
|
|
|
|
}, |
2479
|
|
|
|
|
|
|
0xa002 => { |
2480
|
|
|
|
|
|
|
Name => 'ExifImageWidth', |
2481
|
|
|
|
|
|
|
Notes => 'called PixelXDimension by the EXIF spec.', |
2482
|
|
|
|
|
|
|
Writable => 'int16u', |
2483
|
|
|
|
|
|
|
Mandatory => 1, |
2484
|
|
|
|
|
|
|
}, |
2485
|
|
|
|
|
|
|
0xa003 => { |
2486
|
|
|
|
|
|
|
Name => 'ExifImageHeight', |
2487
|
|
|
|
|
|
|
Notes => 'called PixelYDimension by the EXIF spec.', |
2488
|
|
|
|
|
|
|
Writable => 'int16u', |
2489
|
|
|
|
|
|
|
Mandatory => 1, |
2490
|
|
|
|
|
|
|
}, |
2491
|
|
|
|
|
|
|
0xa004 => { |
2492
|
|
|
|
|
|
|
Name => 'RelatedSoundFile', |
2493
|
|
|
|
|
|
|
Writable => 'string', |
2494
|
|
|
|
|
|
|
}, |
2495
|
|
|
|
|
|
|
0xa005 => { |
2496
|
|
|
|
|
|
|
Name => 'InteropOffset', |
2497
|
|
|
|
|
|
|
Groups => { 1 => 'InteropIFD' }, |
2498
|
|
|
|
|
|
|
Flags => 'SubIFD', |
2499
|
|
|
|
|
|
|
Description => 'Interoperability Offset', |
2500
|
|
|
|
|
|
|
SubDirectory => { |
2501
|
|
|
|
|
|
|
DirName => 'InteropIFD', |
2502
|
|
|
|
|
|
|
Start => '$val', |
2503
|
|
|
|
|
|
|
MaxSubdirs => 1, |
2504
|
|
|
|
|
|
|
}, |
2505
|
|
|
|
|
|
|
}, |
2506
|
|
|
|
|
|
|
# the following 4 tags found in SubIFD1 of some Samsung SRW images |
2507
|
|
|
|
|
|
|
0xa010 => { |
2508
|
|
|
|
|
|
|
Name => 'SamsungRawPointersOffset', |
2509
|
|
|
|
|
|
|
IsOffset => 1, |
2510
|
|
|
|
|
|
|
OffsetPair => 0xa011, # point to associated byte count |
2511
|
|
|
|
|
|
|
}, |
2512
|
|
|
|
|
|
|
0xa011 => { |
2513
|
|
|
|
|
|
|
Name => 'SamsungRawPointersLength', |
2514
|
|
|
|
|
|
|
OffsetPair => 0xa010, # point to associated offset |
2515
|
|
|
|
|
|
|
}, |
2516
|
|
|
|
|
|
|
0xa101 => { |
2517
|
|
|
|
|
|
|
Name => 'SamsungRawByteOrder', |
2518
|
|
|
|
|
|
|
Format => 'undef', |
2519
|
|
|
|
|
|
|
# this is written incorrectly as string[1], but is "\0\0MM" or "II\0\0" |
2520
|
|
|
|
|
|
|
FixedSize => 4, |
2521
|
|
|
|
|
|
|
Count => 1, |
2522
|
|
|
|
|
|
|
}, |
2523
|
|
|
|
|
|
|
0xa102 => { |
2524
|
|
|
|
|
|
|
Name => 'SamsungRawUnknown', |
2525
|
|
|
|
|
|
|
Unknown => 1, |
2526
|
|
|
|
|
|
|
}, |
2527
|
|
|
|
|
|
|
0xa20b => { |
2528
|
|
|
|
|
|
|
Name => 'FlashEnergy', |
2529
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2530
|
|
|
|
|
|
|
Writable => 'rational64u', |
2531
|
|
|
|
|
|
|
}, |
2532
|
|
|
|
|
|
|
0xa20c => { |
2533
|
|
|
|
|
|
|
Name => 'SpatialFrequencyResponse', |
2534
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::Exif::PrintSFR($val)', |
2535
|
|
|
|
|
|
|
}, |
2536
|
|
|
|
|
|
|
0xa20d => 'Noise', |
2537
|
|
|
|
|
|
|
0xa20e => { |
2538
|
|
|
|
|
|
|
Name => 'FocalPlaneXResolution', |
2539
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2540
|
|
|
|
|
|
|
Writable => 'rational64u', |
2541
|
|
|
|
|
|
|
}, |
2542
|
|
|
|
|
|
|
0xa20f => { |
2543
|
|
|
|
|
|
|
Name => 'FocalPlaneYResolution', |
2544
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2545
|
|
|
|
|
|
|
Writable => 'rational64u', |
2546
|
|
|
|
|
|
|
}, |
2547
|
|
|
|
|
|
|
0xa210 => { |
2548
|
|
|
|
|
|
|
Name => 'FocalPlaneResolutionUnit', |
2549
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2550
|
|
|
|
|
|
|
Notes => 'values 1, 4 and 5 are not standard EXIF', |
2551
|
|
|
|
|
|
|
Writable => 'int16u', |
2552
|
|
|
|
|
|
|
PrintConv => { |
2553
|
|
|
|
|
|
|
1 => 'None', # (not standard EXIF) |
2554
|
|
|
|
|
|
|
2 => 'inches', |
2555
|
|
|
|
|
|
|
3 => 'cm', |
2556
|
|
|
|
|
|
|
4 => 'mm', # (not standard EXIF) |
2557
|
|
|
|
|
|
|
5 => 'um', # (not standard EXIF) |
2558
|
|
|
|
|
|
|
}, |
2559
|
|
|
|
|
|
|
}, |
2560
|
|
|
|
|
|
|
0xa211 => 'ImageNumber', |
2561
|
|
|
|
|
|
|
0xa212 => 'SecurityClassification', |
2562
|
|
|
|
|
|
|
0xa213 => 'ImageHistory', |
2563
|
|
|
|
|
|
|
0xa214 => { |
2564
|
|
|
|
|
|
|
Name => 'SubjectLocation', |
2565
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2566
|
|
|
|
|
|
|
Writable => 'int16u', |
2567
|
|
|
|
|
|
|
Count => 2, |
2568
|
|
|
|
|
|
|
}, |
2569
|
|
|
|
|
|
|
0xa215 => { Name => 'ExposureIndex', Writable => 'rational64u' }, |
2570
|
|
|
|
|
|
|
0xa216 => 'TIFF-EPStandardID', |
2571
|
|
|
|
|
|
|
0xa217 => { |
2572
|
|
|
|
|
|
|
Name => 'SensingMethod', |
2573
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2574
|
|
|
|
|
|
|
Writable => 'int16u', |
2575
|
|
|
|
|
|
|
PrintConv => { |
2576
|
|
|
|
|
|
|
1 => 'Not defined', |
2577
|
|
|
|
|
|
|
2 => 'One-chip color area', |
2578
|
|
|
|
|
|
|
3 => 'Two-chip color area', |
2579
|
|
|
|
|
|
|
4 => 'Three-chip color area', |
2580
|
|
|
|
|
|
|
5 => 'Color sequential area', |
2581
|
|
|
|
|
|
|
7 => 'Trilinear', |
2582
|
|
|
|
|
|
|
8 => 'Color sequential linear', |
2583
|
|
|
|
|
|
|
# 15 - used by DJI XT2 |
2584
|
|
|
|
|
|
|
}, |
2585
|
|
|
|
|
|
|
}, |
2586
|
|
|
|
|
|
|
0xa300 => { |
2587
|
|
|
|
|
|
|
Name => 'FileSource', |
2588
|
|
|
|
|
|
|
Writable => 'undef', |
2589
|
|
|
|
|
|
|
ValueConvInv => '($val=~/^\d+$/ and $val < 256) ? chr($val) : $val', |
2590
|
|
|
|
|
|
|
PrintConv => { |
2591
|
|
|
|
|
|
|
1 => 'Film Scanner', |
2592
|
|
|
|
|
|
|
2 => 'Reflection Print Scanner', |
2593
|
|
|
|
|
|
|
3 => 'Digital Camera', |
2594
|
|
|
|
|
|
|
# handle the case where Sigma incorrectly gives this tag a count of 4 |
2595
|
|
|
|
|
|
|
"\3\0\0\0" => 'Sigma Digital Camera', |
2596
|
|
|
|
|
|
|
}, |
2597
|
|
|
|
|
|
|
}, |
2598
|
|
|
|
|
|
|
0xa301 => { |
2599
|
|
|
|
|
|
|
Name => 'SceneType', |
2600
|
|
|
|
|
|
|
Writable => 'undef', |
2601
|
|
|
|
|
|
|
ValueConvInv => 'chr($val & 0xff)', |
2602
|
|
|
|
|
|
|
PrintConv => { |
2603
|
|
|
|
|
|
|
1 => 'Directly photographed', |
2604
|
|
|
|
|
|
|
}, |
2605
|
|
|
|
|
|
|
}, |
2606
|
|
|
|
|
|
|
0xa302 => { |
2607
|
|
|
|
|
|
|
Name => 'CFAPattern', |
2608
|
|
|
|
|
|
|
Writable => 'undef', |
2609
|
|
|
|
|
|
|
RawConv => 'Image::ExifTool::Exif::DecodeCFAPattern($self, $val)', |
2610
|
|
|
|
|
|
|
RawConvInv => q{ |
2611
|
|
|
|
|
|
|
my @a = split ' ', $val; |
2612
|
|
|
|
|
|
|
return $val if @a <= 2; # also accept binary data for backward compatibility |
2613
|
|
|
|
|
|
|
return pack(GetByteOrder() eq 'II' ? 'v2C*' : 'n2C*', @a); |
2614
|
|
|
|
|
|
|
}, |
2615
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::Exif::PrintCFAPattern($val)', |
2616
|
|
|
|
|
|
|
PrintConvInv => 'Image::ExifTool::Exif::GetCFAPattern($val)', |
2617
|
|
|
|
|
|
|
}, |
2618
|
|
|
|
|
|
|
0xa401 => { |
2619
|
|
|
|
|
|
|
Name => 'CustomRendered', |
2620
|
|
|
|
|
|
|
Writable => 'int16u', |
2621
|
|
|
|
|
|
|
Notes => q{ |
2622
|
|
|
|
|
|
|
only 0 and 1 are standard EXIF, but other values are used by Apple iOS |
2623
|
|
|
|
|
|
|
devices |
2624
|
|
|
|
|
|
|
}, |
2625
|
|
|
|
|
|
|
PrintConv => { |
2626
|
|
|
|
|
|
|
0 => 'Normal', |
2627
|
|
|
|
|
|
|
1 => 'Custom', |
2628
|
|
|
|
|
|
|
2 => 'HDR (no original saved)', #32 non-standard (Apple iOS) |
2629
|
|
|
|
|
|
|
3 => 'HDR (original saved)', #32 non-standard (Apple iOS) |
2630
|
|
|
|
|
|
|
4 => 'Original (for HDR)', #32 non-standard (Apple iOS) |
2631
|
|
|
|
|
|
|
6 => 'Panorama', # non-standard (Apple iOS, horizontal or vertical) |
2632
|
|
|
|
|
|
|
7 => 'Portrait HDR', #32 non-standard (Apple iOS) |
2633
|
|
|
|
|
|
|
8 => 'Portrait', # non-standard (Apple iOS, blurred background) |
2634
|
|
|
|
|
|
|
# 9 - also seen (Apple iOS) (HDR Portrait?) |
2635
|
|
|
|
|
|
|
}, |
2636
|
|
|
|
|
|
|
}, |
2637
|
|
|
|
|
|
|
0xa402 => { |
2638
|
|
|
|
|
|
|
Name => 'ExposureMode', |
2639
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2640
|
|
|
|
|
|
|
Writable => 'int16u', |
2641
|
|
|
|
|
|
|
PrintConv => { |
2642
|
|
|
|
|
|
|
0 => 'Auto', |
2643
|
|
|
|
|
|
|
1 => 'Manual', |
2644
|
|
|
|
|
|
|
2 => 'Auto bracket', |
2645
|
|
|
|
|
|
|
# have seen 3 from Samsung EX1, NX30, NX200 - PH |
2646
|
|
|
|
|
|
|
}, |
2647
|
|
|
|
|
|
|
}, |
2648
|
|
|
|
|
|
|
0xa403 => { |
2649
|
|
|
|
|
|
|
Name => 'WhiteBalance', |
2650
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2651
|
|
|
|
|
|
|
Writable => 'int16u', |
2652
|
|
|
|
|
|
|
# set Priority to zero to keep this WhiteBalance from overriding the |
2653
|
|
|
|
|
|
|
# MakerNotes WhiteBalance, since the MakerNotes WhiteBalance and is more |
2654
|
|
|
|
|
|
|
# accurate and contains more information (if it exists) |
2655
|
|
|
|
|
|
|
Priority => 0, |
2656
|
|
|
|
|
|
|
PrintConv => { |
2657
|
|
|
|
|
|
|
0 => 'Auto', |
2658
|
|
|
|
|
|
|
1 => 'Manual', |
2659
|
|
|
|
|
|
|
}, |
2660
|
|
|
|
|
|
|
}, |
2661
|
|
|
|
|
|
|
0xa404 => { |
2662
|
|
|
|
|
|
|
Name => 'DigitalZoomRatio', |
2663
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2664
|
|
|
|
|
|
|
Writable => 'rational64u', |
2665
|
|
|
|
|
|
|
}, |
2666
|
|
|
|
|
|
|
0xa405 => { |
2667
|
|
|
|
|
|
|
Name => 'FocalLengthIn35mmFormat', |
2668
|
|
|
|
|
|
|
Notes => 'called FocalLengthIn35mmFilm by the EXIF spec.', |
2669
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2670
|
|
|
|
|
|
|
Writable => 'int16u', |
2671
|
|
|
|
|
|
|
PrintConv => '"$val mm"', |
2672
|
|
|
|
|
|
|
PrintConvInv => '$val=~s/\s*mm$//;$val', |
2673
|
|
|
|
|
|
|
}, |
2674
|
|
|
|
|
|
|
0xa406 => { |
2675
|
|
|
|
|
|
|
Name => 'SceneCaptureType', |
2676
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2677
|
|
|
|
|
|
|
Writable => 'int16u', |
2678
|
|
|
|
|
|
|
Notes => 'the value of 4 is non-standard, and used by some Samsung models', |
2679
|
|
|
|
|
|
|
PrintConv => { |
2680
|
|
|
|
|
|
|
0 => 'Standard', |
2681
|
|
|
|
|
|
|
1 => 'Landscape', |
2682
|
|
|
|
|
|
|
2 => 'Portrait', |
2683
|
|
|
|
|
|
|
3 => 'Night', |
2684
|
|
|
|
|
|
|
4 => 'Other', # (non-standard Samsung, ref forum 5724) |
2685
|
|
|
|
|
|
|
}, |
2686
|
|
|
|
|
|
|
}, |
2687
|
|
|
|
|
|
|
0xa407 => { |
2688
|
|
|
|
|
|
|
Name => 'GainControl', |
2689
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2690
|
|
|
|
|
|
|
Writable => 'int16u', |
2691
|
|
|
|
|
|
|
PrintConv => { |
2692
|
|
|
|
|
|
|
0 => 'None', |
2693
|
|
|
|
|
|
|
1 => 'Low gain up', |
2694
|
|
|
|
|
|
|
2 => 'High gain up', |
2695
|
|
|
|
|
|
|
3 => 'Low gain down', |
2696
|
|
|
|
|
|
|
4 => 'High gain down', |
2697
|
|
|
|
|
|
|
}, |
2698
|
|
|
|
|
|
|
}, |
2699
|
|
|
|
|
|
|
0xa408 => { |
2700
|
|
|
|
|
|
|
Name => 'Contrast', |
2701
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2702
|
|
|
|
|
|
|
Writable => 'int16u', |
2703
|
|
|
|
|
|
|
PrintConv => { |
2704
|
|
|
|
|
|
|
0 => 'Normal', |
2705
|
|
|
|
|
|
|
1 => 'Low', |
2706
|
|
|
|
|
|
|
2 => 'High', |
2707
|
|
|
|
|
|
|
}, |
2708
|
|
|
|
|
|
|
PrintConvInv => 'Image::ExifTool::Exif::ConvertParameter($val)', |
2709
|
|
|
|
|
|
|
}, |
2710
|
|
|
|
|
|
|
0xa409 => { |
2711
|
|
|
|
|
|
|
Name => 'Saturation', |
2712
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2713
|
|
|
|
|
|
|
Writable => 'int16u', |
2714
|
|
|
|
|
|
|
PrintConv => { |
2715
|
|
|
|
|
|
|
0 => 'Normal', |
2716
|
|
|
|
|
|
|
1 => 'Low', |
2717
|
|
|
|
|
|
|
2 => 'High', |
2718
|
|
|
|
|
|
|
}, |
2719
|
|
|
|
|
|
|
PrintConvInv => 'Image::ExifTool::Exif::ConvertParameter($val)', |
2720
|
|
|
|
|
|
|
}, |
2721
|
|
|
|
|
|
|
0xa40a => { |
2722
|
|
|
|
|
|
|
Name => 'Sharpness', |
2723
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2724
|
|
|
|
|
|
|
Writable => 'int16u', |
2725
|
|
|
|
|
|
|
PrintConv => { |
2726
|
|
|
|
|
|
|
0 => 'Normal', |
2727
|
|
|
|
|
|
|
1 => 'Soft', |
2728
|
|
|
|
|
|
|
2 => 'Hard', |
2729
|
|
|
|
|
|
|
}, |
2730
|
|
|
|
|
|
|
PrintConvInv => 'Image::ExifTool::Exif::ConvertParameter($val)', |
2731
|
|
|
|
|
|
|
}, |
2732
|
|
|
|
|
|
|
0xa40b => { |
2733
|
|
|
|
|
|
|
Name => 'DeviceSettingDescription', |
2734
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2735
|
|
|
|
|
|
|
Binary => 1, |
2736
|
|
|
|
|
|
|
}, |
2737
|
|
|
|
|
|
|
0xa40c => { |
2738
|
|
|
|
|
|
|
Name => 'SubjectDistanceRange', |
2739
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
2740
|
|
|
|
|
|
|
Writable => 'int16u', |
2741
|
|
|
|
|
|
|
PrintConv => { |
2742
|
|
|
|
|
|
|
0 => 'Unknown', |
2743
|
|
|
|
|
|
|
1 => 'Macro', |
2744
|
|
|
|
|
|
|
2 => 'Close', |
2745
|
|
|
|
|
|
|
3 => 'Distant', |
2746
|
|
|
|
|
|
|
}, |
2747
|
|
|
|
|
|
|
}, |
2748
|
|
|
|
|
|
|
# 0xa40d - int16u: 0 (GE E1486 TW) |
2749
|
|
|
|
|
|
|
# 0xa40e - int16u: 1 (GE E1486 TW) |
2750
|
|
|
|
|
|
|
0xa420 => { Name => 'ImageUniqueID', Writable => 'string' }, |
2751
|
|
|
|
|
|
|
0xa430 => { #24 |
2752
|
|
|
|
|
|
|
Name => 'OwnerName', |
2753
|
|
|
|
|
|
|
Notes => 'called CameraOwnerName by the EXIF spec.', |
2754
|
|
|
|
|
|
|
Writable => 'string', |
2755
|
|
|
|
|
|
|
}, |
2756
|
|
|
|
|
|
|
0xa431 => { #24 |
2757
|
|
|
|
|
|
|
Name => 'SerialNumber', |
2758
|
|
|
|
|
|
|
Notes => 'called BodySerialNumber by the EXIF spec.', |
2759
|
|
|
|
|
|
|
Writable => 'string', |
2760
|
|
|
|
|
|
|
}, |
2761
|
|
|
|
|
|
|
0xa432 => { #24 |
2762
|
|
|
|
|
|
|
Name => 'LensInfo', |
2763
|
|
|
|
|
|
|
Notes => q{ |
2764
|
|
|
|
|
|
|
4 rational values giving focal and aperture ranges, called LensSpecification |
2765
|
|
|
|
|
|
|
by the EXIF spec. |
2766
|
|
|
|
|
|
|
}, |
2767
|
|
|
|
|
|
|
Writable => 'rational64u', |
2768
|
|
|
|
|
|
|
Count => 4, |
2769
|
|
|
|
|
|
|
# convert to the form "12-20mm f/3.8-4.5" or "50mm f/1.4" |
2770
|
|
|
|
|
|
|
PrintConv => \&PrintLensInfo, |
2771
|
|
|
|
|
|
|
PrintConvInv => \&ConvertLensInfo, |
2772
|
|
|
|
|
|
|
}, |
2773
|
|
|
|
|
|
|
0xa433 => { Name => 'LensMake', Writable => 'string' }, #24 |
2774
|
|
|
|
|
|
|
0xa434 => { Name => 'LensModel', Writable => 'string' }, #24 |
2775
|
|
|
|
|
|
|
0xa435 => { Name => 'LensSerialNumber', Writable => 'string' }, #24 |
2776
|
|
|
|
|
|
|
0xa460 => { #Exif2.32 |
2777
|
|
|
|
|
|
|
Name => 'CompositeImage', |
2778
|
|
|
|
|
|
|
Writable => 'int16u', |
2779
|
|
|
|
|
|
|
PrintConv => { |
2780
|
|
|
|
|
|
|
0 => 'Unknown', |
2781
|
|
|
|
|
|
|
1 => 'Not a Composite Image', |
2782
|
|
|
|
|
|
|
2 => 'General Composite Image', |
2783
|
|
|
|
|
|
|
3 => 'Composite Image Captured While Shooting', |
2784
|
|
|
|
|
|
|
}, |
2785
|
|
|
|
|
|
|
}, |
2786
|
|
|
|
|
|
|
0xa461 => { #Exif2.32 |
2787
|
|
|
|
|
|
|
Name => 'CompositeImageCount', |
2788
|
|
|
|
|
|
|
Notes => q{ |
2789
|
|
|
|
|
|
|
2 values: 1. Number of source images, 2. Number of images used. Called |
2790
|
|
|
|
|
|
|
SourceImageNumberOfCompositeImage by the EXIF spec. |
2791
|
|
|
|
|
|
|
}, |
2792
|
|
|
|
|
|
|
Writable => 'int16u', |
2793
|
|
|
|
|
|
|
Count => 2, |
2794
|
|
|
|
|
|
|
}, |
2795
|
|
|
|
|
|
|
0xa462 => { #Exif2.32 |
2796
|
|
|
|
|
|
|
Name => 'CompositeImageExposureTimes', |
2797
|
|
|
|
|
|
|
Notes => q{ |
2798
|
|
|
|
|
|
|
11 or more values: 1. Total exposure time period, 2. Total exposure of all |
2799
|
|
|
|
|
|
|
source images, 3. Total exposure of all used images, 4. Max exposure time of |
2800
|
|
|
|
|
|
|
source images, 5. Max exposure time of used images, 6. Min exposure time of |
2801
|
|
|
|
|
|
|
source images, 7. Min exposure of used images, 8. Number of sequences, 9. |
2802
|
|
|
|
|
|
|
Number of source images in sequence. 10-N. Exposure times of each source |
2803
|
|
|
|
|
|
|
image. Called SourceExposureTimesOfCompositeImage by the EXIF spec. |
2804
|
|
|
|
|
|
|
}, |
2805
|
|
|
|
|
|
|
Writable => 'undef', |
2806
|
|
|
|
|
|
|
RawConv => sub { |
2807
|
|
|
|
|
|
|
my $val = shift; |
2808
|
|
|
|
|
|
|
my @v; |
2809
|
|
|
|
|
|
|
my $i = 0; |
2810
|
|
|
|
|
|
|
for (;;) { |
2811
|
|
|
|
|
|
|
if ($i == 56 or $i == 58) { |
2812
|
|
|
|
|
|
|
last if $i + 2 > length $val; |
2813
|
|
|
|
|
|
|
push @v, Get16u(\$val, $i); |
2814
|
|
|
|
|
|
|
$i += 2; |
2815
|
|
|
|
|
|
|
} else { |
2816
|
|
|
|
|
|
|
last if $i + 8 > length $val; |
2817
|
|
|
|
|
|
|
push @v, Image::ExifTool::GetRational64u(\$val, $i); |
2818
|
|
|
|
|
|
|
$i += 8; |
2819
|
|
|
|
|
|
|
} |
2820
|
|
|
|
|
|
|
} |
2821
|
|
|
|
|
|
|
return join ' ', @v; |
2822
|
|
|
|
|
|
|
}, |
2823
|
|
|
|
|
|
|
RawConvInv => sub { |
2824
|
|
|
|
|
|
|
my $val = shift; |
2825
|
|
|
|
|
|
|
my @v = split ' ', $val; |
2826
|
|
|
|
|
|
|
my $i; |
2827
|
|
|
|
|
|
|
for ($i=0; ; ++$i) { |
2828
|
|
|
|
|
|
|
last unless defined $v[$i]; |
2829
|
|
|
|
|
|
|
$v[$i] = ($i == 7 or $i == 8) ? Set16u($v[$i]) : Image::ExifTool::SetRational64u($v[$i]); |
2830
|
|
|
|
|
|
|
} |
2831
|
|
|
|
|
|
|
return join '', @v; |
2832
|
|
|
|
|
|
|
}, |
2833
|
|
|
|
|
|
|
PrintConv => sub { |
2834
|
|
|
|
|
|
|
my $val = shift; |
2835
|
|
|
|
|
|
|
my @v = split ' ', $val; |
2836
|
|
|
|
|
|
|
my $i; |
2837
|
|
|
|
|
|
|
for ($i=0; ; ++$i) { |
2838
|
|
|
|
|
|
|
last unless defined $v[$i]; |
2839
|
|
|
|
|
|
|
$v[$i] = PrintExposureTime($v[$i]) unless $i == 7 or $i == 8; |
2840
|
|
|
|
|
|
|
} |
2841
|
|
|
|
|
|
|
return join ' ', @v; |
2842
|
|
|
|
|
|
|
}, |
2843
|
|
|
|
|
|
|
PrintConvInv => '$val', |
2844
|
|
|
|
|
|
|
}, |
2845
|
|
|
|
|
|
|
0xa480 => { Name => 'GDALMetadata', Writable => 'string', WriteGroup => 'IFD0' }, #3 |
2846
|
|
|
|
|
|
|
0xa481 => { Name => 'GDALNoData', Writable => 'string', WriteGroup => 'IFD0' }, #3 |
2847
|
|
|
|
|
|
|
0xa500 => { Name => 'Gamma', Writable => 'rational64u' }, |
2848
|
|
|
|
|
|
|
0xafc0 => 'ExpandSoftware', #JD (Opanda) |
2849
|
|
|
|
|
|
|
0xafc1 => 'ExpandLens', #JD (Opanda) |
2850
|
|
|
|
|
|
|
0xafc2 => 'ExpandFilm', #JD (Opanda) |
2851
|
|
|
|
|
|
|
0xafc3 => 'ExpandFilterLens', #JD (Opanda) |
2852
|
|
|
|
|
|
|
0xafc4 => 'ExpandScanner', #JD (Opanda) |
2853
|
|
|
|
|
|
|
0xafc5 => 'ExpandFlashLamp', #JD (Opanda) |
2854
|
|
|
|
|
|
|
0xb4c3 => { Name => 'HasselbladRawImage', Format => 'undef', Binary => 1 }, #IB |
2855
|
|
|
|
|
|
|
# |
2856
|
|
|
|
|
|
|
# Windows Media Photo / HD Photo (WDP/HDP) tags |
2857
|
|
|
|
|
|
|
# |
2858
|
|
|
|
|
|
|
0xbc01 => { #13 |
2859
|
|
|
|
|
|
|
Name => 'PixelFormat', |
2860
|
|
|
|
|
|
|
PrintHex => 1, |
2861
|
|
|
|
|
|
|
Format => 'undef', |
2862
|
|
|
|
|
|
|
Notes => q{ |
2863
|
|
|
|
|
|
|
tags 0xbc** are used in Windows HD Photo (HDP and WDP) images. The actual |
2864
|
|
|
|
|
|
|
PixelFormat values are 16-byte GUID's but the leading 15 bytes, |
2865
|
|
|
|
|
|
|
'6fddc324-4e03-4bfe-b1853-d77768dc9', have been removed below to avoid |
2866
|
|
|
|
|
|
|
unnecessary clutter |
2867
|
|
|
|
|
|
|
}, |
2868
|
|
|
|
|
|
|
ValueConv => q{ |
2869
|
|
|
|
|
|
|
require Image::ExifTool::ASF; |
2870
|
|
|
|
|
|
|
$val = Image::ExifTool::ASF::GetGUID($val); |
2871
|
|
|
|
|
|
|
# GUID's are too long, so remove redundant information |
2872
|
|
|
|
|
|
|
$val =~ s/^6fddc324-4e03-4bfe-b185-3d77768dc9//i and $val = hex($val); |
2873
|
|
|
|
|
|
|
return $val; |
2874
|
|
|
|
|
|
|
}, |
2875
|
|
|
|
|
|
|
PrintConv => { |
2876
|
|
|
|
|
|
|
0x0d => '24-bit RGB', |
2877
|
|
|
|
|
|
|
0x0c => '24-bit BGR', |
2878
|
|
|
|
|
|
|
0x0e => '32-bit BGR', |
2879
|
|
|
|
|
|
|
0x15 => '48-bit RGB', |
2880
|
|
|
|
|
|
|
0x12 => '48-bit RGB Fixed Point', |
2881
|
|
|
|
|
|
|
0x3b => '48-bit RGB Half', |
2882
|
|
|
|
|
|
|
0x18 => '96-bit RGB Fixed Point', |
2883
|
|
|
|
|
|
|
0x1b => '128-bit RGB Float', |
2884
|
|
|
|
|
|
|
0x0f => '32-bit BGRA', |
2885
|
|
|
|
|
|
|
0x16 => '64-bit RGBA', |
2886
|
|
|
|
|
|
|
0x1d => '64-bit RGBA Fixed Point', |
2887
|
|
|
|
|
|
|
0x3a => '64-bit RGBA Half', |
2888
|
|
|
|
|
|
|
0x1e => '128-bit RGBA Fixed Point', |
2889
|
|
|
|
|
|
|
0x19 => '128-bit RGBA Float', |
2890
|
|
|
|
|
|
|
0x10 => '32-bit PBGRA', |
2891
|
|
|
|
|
|
|
0x17 => '64-bit PRGBA', |
2892
|
|
|
|
|
|
|
0x1a => '128-bit PRGBA Float', |
2893
|
|
|
|
|
|
|
0x1c => '32-bit CMYK', |
2894
|
|
|
|
|
|
|
0x2c => '40-bit CMYK Alpha', |
2895
|
|
|
|
|
|
|
0x1f => '64-bit CMYK', |
2896
|
|
|
|
|
|
|
0x2d => '80-bit CMYK Alpha', |
2897
|
|
|
|
|
|
|
0x20 => '24-bit 3 Channels', |
2898
|
|
|
|
|
|
|
0x21 => '32-bit 4 Channels', |
2899
|
|
|
|
|
|
|
0x22 => '40-bit 5 Channels', |
2900
|
|
|
|
|
|
|
0x23 => '48-bit 6 Channels', |
2901
|
|
|
|
|
|
|
0x24 => '56-bit 7 Channels', |
2902
|
|
|
|
|
|
|
0x25 => '64-bit 8 Channels', |
2903
|
|
|
|
|
|
|
0x2e => '32-bit 3 Channels Alpha', |
2904
|
|
|
|
|
|
|
0x2f => '40-bit 4 Channels Alpha', |
2905
|
|
|
|
|
|
|
0x30 => '48-bit 5 Channels Alpha', |
2906
|
|
|
|
|
|
|
0x31 => '56-bit 6 Channels Alpha', |
2907
|
|
|
|
|
|
|
0x32 => '64-bit 7 Channels Alpha', |
2908
|
|
|
|
|
|
|
0x33 => '72-bit 8 Channels Alpha', |
2909
|
|
|
|
|
|
|
0x26 => '48-bit 3 Channels', |
2910
|
|
|
|
|
|
|
0x27 => '64-bit 4 Channels', |
2911
|
|
|
|
|
|
|
0x28 => '80-bit 5 Channels', |
2912
|
|
|
|
|
|
|
0x29 => '96-bit 6 Channels', |
2913
|
|
|
|
|
|
|
0x2a => '112-bit 7 Channels', |
2914
|
|
|
|
|
|
|
0x2b => '128-bit 8 Channels', |
2915
|
|
|
|
|
|
|
0x34 => '64-bit 3 Channels Alpha', |
2916
|
|
|
|
|
|
|
0x35 => '80-bit 4 Channels Alpha', |
2917
|
|
|
|
|
|
|
0x36 => '96-bit 5 Channels Alpha', |
2918
|
|
|
|
|
|
|
0x37 => '112-bit 6 Channels Alpha', |
2919
|
|
|
|
|
|
|
0x38 => '128-bit 7 Channels Alpha', |
2920
|
|
|
|
|
|
|
0x39 => '144-bit 8 Channels Alpha', |
2921
|
|
|
|
|
|
|
0x08 => '8-bit Gray', |
2922
|
|
|
|
|
|
|
0x0b => '16-bit Gray', |
2923
|
|
|
|
|
|
|
0x13 => '16-bit Gray Fixed Point', |
2924
|
|
|
|
|
|
|
0x3e => '16-bit Gray Half', |
2925
|
|
|
|
|
|
|
0x3f => '32-bit Gray Fixed Point', |
2926
|
|
|
|
|
|
|
0x11 => '32-bit Gray Float', |
2927
|
|
|
|
|
|
|
0x05 => 'Black & White', |
2928
|
|
|
|
|
|
|
0x09 => '16-bit BGR555', |
2929
|
|
|
|
|
|
|
0x0a => '16-bit BGR565', |
2930
|
|
|
|
|
|
|
0x13 => '32-bit BGR101010', |
2931
|
|
|
|
|
|
|
0x3d => '32-bit RGBE', |
2932
|
|
|
|
|
|
|
}, |
2933
|
|
|
|
|
|
|
}, |
2934
|
|
|
|
|
|
|
0xbc02 => { #13 |
2935
|
|
|
|
|
|
|
Name => 'Transformation', |
2936
|
|
|
|
|
|
|
PrintConv => { |
2937
|
|
|
|
|
|
|
0 => 'Horizontal (normal)', |
2938
|
|
|
|
|
|
|
1 => 'Mirror vertical', |
2939
|
|
|
|
|
|
|
2 => 'Mirror horizontal', |
2940
|
|
|
|
|
|
|
3 => 'Rotate 180', |
2941
|
|
|
|
|
|
|
4 => 'Rotate 90 CW', |
2942
|
|
|
|
|
|
|
5 => 'Mirror horizontal and rotate 90 CW', |
2943
|
|
|
|
|
|
|
6 => 'Mirror horizontal and rotate 270 CW', |
2944
|
|
|
|
|
|
|
7 => 'Rotate 270 CW', |
2945
|
|
|
|
|
|
|
}, |
2946
|
|
|
|
|
|
|
}, |
2947
|
|
|
|
|
|
|
0xbc03 => { #13 |
2948
|
|
|
|
|
|
|
Name => 'Uncompressed', |
2949
|
|
|
|
|
|
|
PrintConv => { 0 => 'No', 1 => 'Yes' }, |
2950
|
|
|
|
|
|
|
}, |
2951
|
|
|
|
|
|
|
0xbc04 => { #13 |
2952
|
|
|
|
|
|
|
Name => 'ImageType', |
2953
|
|
|
|
|
|
|
PrintConv => { BITMASK => { |
2954
|
|
|
|
|
|
|
0 => 'Preview', |
2955
|
|
|
|
|
|
|
1 => 'Page', |
2956
|
|
|
|
|
|
|
} }, |
2957
|
|
|
|
|
|
|
}, |
2958
|
|
|
|
|
|
|
0xbc80 => 'ImageWidth', #13 |
2959
|
|
|
|
|
|
|
0xbc81 => 'ImageHeight', #13 |
2960
|
|
|
|
|
|
|
0xbc82 => 'WidthResolution', #13 |
2961
|
|
|
|
|
|
|
0xbc83 => 'HeightResolution', #13 |
2962
|
|
|
|
|
|
|
0xbcc0 => { #13 |
2963
|
|
|
|
|
|
|
Name => 'ImageOffset', |
2964
|
|
|
|
|
|
|
IsOffset => 1, |
2965
|
|
|
|
|
|
|
OffsetPair => 0xbcc1, # point to associated byte count |
2966
|
|
|
|
|
|
|
}, |
2967
|
|
|
|
|
|
|
0xbcc1 => { #13 |
2968
|
|
|
|
|
|
|
Name => 'ImageByteCount', |
2969
|
|
|
|
|
|
|
OffsetPair => 0xbcc0, # point to associated offset |
2970
|
|
|
|
|
|
|
}, |
2971
|
|
|
|
|
|
|
0xbcc2 => { #13 |
2972
|
|
|
|
|
|
|
Name => 'AlphaOffset', |
2973
|
|
|
|
|
|
|
IsOffset => 1, |
2974
|
|
|
|
|
|
|
OffsetPair => 0xbcc3, # point to associated byte count |
2975
|
|
|
|
|
|
|
}, |
2976
|
|
|
|
|
|
|
0xbcc3 => { #13 |
2977
|
|
|
|
|
|
|
Name => 'AlphaByteCount', |
2978
|
|
|
|
|
|
|
OffsetPair => 0xbcc2, # point to associated offset |
2979
|
|
|
|
|
|
|
}, |
2980
|
|
|
|
|
|
|
0xbcc4 => { #13 |
2981
|
|
|
|
|
|
|
Name => 'ImageDataDiscard', |
2982
|
|
|
|
|
|
|
PrintConv => { |
2983
|
|
|
|
|
|
|
0 => 'Full Resolution', |
2984
|
|
|
|
|
|
|
1 => 'Flexbits Discarded', |
2985
|
|
|
|
|
|
|
2 => 'HighPass Frequency Data Discarded', |
2986
|
|
|
|
|
|
|
3 => 'Highpass and LowPass Frequency Data Discarded', |
2987
|
|
|
|
|
|
|
}, |
2988
|
|
|
|
|
|
|
}, |
2989
|
|
|
|
|
|
|
0xbcc5 => { #13 |
2990
|
|
|
|
|
|
|
Name => 'AlphaDataDiscard', |
2991
|
|
|
|
|
|
|
PrintConv => { |
2992
|
|
|
|
|
|
|
0 => 'Full Resolution', |
2993
|
|
|
|
|
|
|
1 => 'Flexbits Discarded', |
2994
|
|
|
|
|
|
|
2 => 'HighPass Frequency Data Discarded', |
2995
|
|
|
|
|
|
|
3 => 'Highpass and LowPass Frequency Data Discarded', |
2996
|
|
|
|
|
|
|
}, |
2997
|
|
|
|
|
|
|
}, |
2998
|
|
|
|
|
|
|
# |
2999
|
|
|
|
|
|
|
0xc427 => 'OceScanjobDesc', #3 |
3000
|
|
|
|
|
|
|
0xc428 => 'OceApplicationSelector', #3 |
3001
|
|
|
|
|
|
|
0xc429 => 'OceIDNumber', #3 |
3002
|
|
|
|
|
|
|
0xc42a => 'OceImageLogic', #3 |
3003
|
|
|
|
|
|
|
0xc44f => { Name => 'Annotations', Binary => 1 }, #7/19 |
3004
|
|
|
|
|
|
|
0xc4a5 => { |
3005
|
|
|
|
|
|
|
Name => 'PrintIM', # (writable directory!) |
3006
|
|
|
|
|
|
|
# must set Writable here so this tag will be saved with MakerNotes option |
3007
|
|
|
|
|
|
|
Writable => 'undef', |
3008
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3009
|
|
|
|
|
|
|
Binary => 1, |
3010
|
|
|
|
|
|
|
# (don't make Binary/Protected because we can't copy individual PrintIM tags anyway) |
3011
|
|
|
|
|
|
|
Description => 'Print Image Matching', |
3012
|
|
|
|
|
|
|
SubDirectory => { |
3013
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::PrintIM::Main', |
3014
|
|
|
|
|
|
|
}, |
3015
|
|
|
|
|
|
|
PrintConvInv => '$val =~ /^PrintIM/ ? $val : undef', # quick validation |
3016
|
|
|
|
|
|
|
}, |
3017
|
|
|
|
|
|
|
0xc51b => { # (Hasselblad H3D) |
3018
|
|
|
|
|
|
|
Name => 'HasselbladExif', |
3019
|
|
|
|
|
|
|
Format => 'undef', |
3020
|
|
|
|
|
|
|
RawConv => q{ |
3021
|
|
|
|
|
|
|
$$self{DOC_NUM} = ++$$self{DOC_COUNT}; |
3022
|
|
|
|
|
|
|
$self->ExtractInfo(\$val, { ReEntry => 1 }); |
3023
|
|
|
|
|
|
|
$$self{DOC_NUM} = 0; |
3024
|
|
|
|
|
|
|
return undef; |
3025
|
|
|
|
|
|
|
}, |
3026
|
|
|
|
|
|
|
}, |
3027
|
|
|
|
|
|
|
0xc573 => { #PH |
3028
|
|
|
|
|
|
|
Name => 'OriginalFileName', |
3029
|
|
|
|
|
|
|
Notes => 'used by some obscure software', # (possibly Swizzy Photosmacker?) |
3030
|
|
|
|
|
|
|
# (it is a 'string', but obscure, so don't make it writable) |
3031
|
|
|
|
|
|
|
}, |
3032
|
|
|
|
|
|
|
0xc580 => { #20 |
3033
|
|
|
|
|
|
|
Name => 'USPTOOriginalContentType', |
3034
|
|
|
|
|
|
|
PrintConv => { |
3035
|
|
|
|
|
|
|
0 => 'Text or Drawing', |
3036
|
|
|
|
|
|
|
1 => 'Grayscale', |
3037
|
|
|
|
|
|
|
2 => 'Color', |
3038
|
|
|
|
|
|
|
}, |
3039
|
|
|
|
|
|
|
}, |
3040
|
|
|
|
|
|
|
# 0xc5d8 - found in CR2 images |
3041
|
|
|
|
|
|
|
# 0xc5d9 - found in CR2 images |
3042
|
|
|
|
|
|
|
0xc5e0 => { #forum8153 (CR2 images) |
3043
|
|
|
|
|
|
|
Name => 'CR2CFAPattern', |
3044
|
|
|
|
|
|
|
ValueConv => { |
3045
|
|
|
|
|
|
|
1 => '0 1 1 2', |
3046
|
|
|
|
|
|
|
2 => '2 1 1 0', |
3047
|
|
|
|
|
|
|
3 => '1 2 0 1', |
3048
|
|
|
|
|
|
|
4 => '1 0 2 1', |
3049
|
|
|
|
|
|
|
}, |
3050
|
|
|
|
|
|
|
PrintConv => { |
3051
|
|
|
|
|
|
|
'0 1 1 2' => '[Red,Green][Green,Blue]', |
3052
|
|
|
|
|
|
|
'2 1 1 0' => '[Blue,Green][Green,Red]', |
3053
|
|
|
|
|
|
|
'1 2 0 1' => '[Green,Blue][Red,Green]', |
3054
|
|
|
|
|
|
|
'1 0 2 1' => '[Green,Red][Blue,Green]', |
3055
|
|
|
|
|
|
|
}, |
3056
|
|
|
|
|
|
|
}, |
3057
|
|
|
|
|
|
|
# |
3058
|
|
|
|
|
|
|
# DNG tags 0xc6XX, 0xc7XX and 0xcdXX (ref 2 unless otherwise stated) |
3059
|
|
|
|
|
|
|
# |
3060
|
|
|
|
|
|
|
0xc612 => { |
3061
|
|
|
|
|
|
|
Name => 'DNGVersion', |
3062
|
|
|
|
|
|
|
Notes => q{ |
3063
|
|
|
|
|
|
|
tags 0xc612-0xcd3b are defined by the DNG specification unless otherwise |
3064
|
|
|
|
|
|
|
noted. See L for |
3065
|
|
|
|
|
|
|
the specification |
3066
|
|
|
|
|
|
|
}, |
3067
|
|
|
|
|
|
|
Writable => 'int8u', |
3068
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3069
|
|
|
|
|
|
|
Count => 4, |
3070
|
|
|
|
|
|
|
Protected => 1, # (confuses Apple Preview if written to a TIFF image) |
3071
|
|
|
|
|
|
|
DataMember => 'DNGVersion', |
3072
|
|
|
|
|
|
|
RawConv => '$$self{DNGVersion} = $val', |
3073
|
|
|
|
|
|
|
PrintConv => '$val =~ tr/ /./; $val', |
3074
|
|
|
|
|
|
|
PrintConvInv => '$val =~ tr/./ /; $val', |
3075
|
|
|
|
|
|
|
}, |
3076
|
|
|
|
|
|
|
0xc613 => { |
3077
|
|
|
|
|
|
|
Name => 'DNGBackwardVersion', |
3078
|
|
|
|
|
|
|
Writable => 'int8u', |
3079
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3080
|
|
|
|
|
|
|
Count => 4, |
3081
|
|
|
|
|
|
|
Protected => 1, |
3082
|
|
|
|
|
|
|
PrintConv => '$val =~ tr/ /./; $val', |
3083
|
|
|
|
|
|
|
PrintConvInv => '$val =~ tr/./ /; $val', |
3084
|
|
|
|
|
|
|
}, |
3085
|
|
|
|
|
|
|
0xc614 => { |
3086
|
|
|
|
|
|
|
Name => 'UniqueCameraModel', |
3087
|
|
|
|
|
|
|
Writable => 'string', |
3088
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3089
|
|
|
|
|
|
|
}, |
3090
|
|
|
|
|
|
|
0xc615 => { |
3091
|
|
|
|
|
|
|
Name => 'LocalizedCameraModel', |
3092
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3093
|
|
|
|
|
|
|
%utf8StringConv, |
3094
|
|
|
|
|
|
|
PrintConv => '$self->Printable($val, 0)', |
3095
|
|
|
|
|
|
|
PrintConvInv => '$val', |
3096
|
|
|
|
|
|
|
}, |
3097
|
|
|
|
|
|
|
0xc616 => { |
3098
|
|
|
|
|
|
|
Name => 'CFAPlaneColor', |
3099
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', # (only for Validate) |
3100
|
|
|
|
|
|
|
PrintConv => q{ |
3101
|
|
|
|
|
|
|
my @cols = qw(Red Green Blue Cyan Magenta Yellow White); |
3102
|
|
|
|
|
|
|
my @vals = map { $cols[$_] || "Unknown($_)" } split(' ', $val); |
3103
|
|
|
|
|
|
|
return join(',', @vals); |
3104
|
|
|
|
|
|
|
}, |
3105
|
|
|
|
|
|
|
}, |
3106
|
|
|
|
|
|
|
0xc617 => { |
3107
|
|
|
|
|
|
|
Name => 'CFALayout', |
3108
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', # (only for Validate) |
3109
|
|
|
|
|
|
|
PrintConv => { |
3110
|
|
|
|
|
|
|
1 => 'Rectangular', |
3111
|
|
|
|
|
|
|
2 => 'Even columns offset down 1/2 row', |
3112
|
|
|
|
|
|
|
3 => 'Even columns offset up 1/2 row', |
3113
|
|
|
|
|
|
|
4 => 'Even rows offset right 1/2 column', |
3114
|
|
|
|
|
|
|
5 => 'Even rows offset left 1/2 column', |
3115
|
|
|
|
|
|
|
# the following are new for DNG 1.3: |
3116
|
|
|
|
|
|
|
6 => 'Even rows offset up by 1/2 row, even columns offset left by 1/2 column', |
3117
|
|
|
|
|
|
|
7 => 'Even rows offset up by 1/2 row, even columns offset right by 1/2 column', |
3118
|
|
|
|
|
|
|
8 => 'Even rows offset down by 1/2 row, even columns offset left by 1/2 column', |
3119
|
|
|
|
|
|
|
9 => 'Even rows offset down by 1/2 row, even columns offset right by 1/2 column', |
3120
|
|
|
|
|
|
|
}, |
3121
|
|
|
|
|
|
|
}, |
3122
|
|
|
|
|
|
|
0xc618 => { |
3123
|
|
|
|
|
|
|
Name => 'LinearizationTable', |
3124
|
|
|
|
|
|
|
Writable => 'int16u', |
3125
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3126
|
|
|
|
|
|
|
Count => -1, |
3127
|
|
|
|
|
|
|
Protected => 1, |
3128
|
|
|
|
|
|
|
Binary => 1, |
3129
|
|
|
|
|
|
|
}, |
3130
|
|
|
|
|
|
|
0xc619 => { |
3131
|
|
|
|
|
|
|
Name => 'BlackLevelRepeatDim', |
3132
|
|
|
|
|
|
|
Writable => 'int16u', |
3133
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3134
|
|
|
|
|
|
|
Count => 2, |
3135
|
|
|
|
|
|
|
Protected => 1, |
3136
|
|
|
|
|
|
|
}, |
3137
|
|
|
|
|
|
|
0xc61a => { |
3138
|
|
|
|
|
|
|
Name => 'BlackLevel', |
3139
|
|
|
|
|
|
|
Writable => 'rational64u', |
3140
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3141
|
|
|
|
|
|
|
Count => -1, |
3142
|
|
|
|
|
|
|
Protected => 1, |
3143
|
|
|
|
|
|
|
}, |
3144
|
|
|
|
|
|
|
0xc61b => { |
3145
|
|
|
|
|
|
|
Name => 'BlackLevelDeltaH', |
3146
|
|
|
|
|
|
|
%longBin, |
3147
|
|
|
|
|
|
|
Writable => 'rational64s', |
3148
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3149
|
|
|
|
|
|
|
Count => -1, |
3150
|
|
|
|
|
|
|
Protected => 1, |
3151
|
|
|
|
|
|
|
}, |
3152
|
|
|
|
|
|
|
0xc61c => { |
3153
|
|
|
|
|
|
|
Name => 'BlackLevelDeltaV', |
3154
|
|
|
|
|
|
|
%longBin, |
3155
|
|
|
|
|
|
|
Writable => 'rational64s', |
3156
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3157
|
|
|
|
|
|
|
Count => -1, |
3158
|
|
|
|
|
|
|
Protected => 1, |
3159
|
|
|
|
|
|
|
}, |
3160
|
|
|
|
|
|
|
0xc61d => { |
3161
|
|
|
|
|
|
|
Name => 'WhiteLevel', |
3162
|
|
|
|
|
|
|
Writable => 'int32u', |
3163
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3164
|
|
|
|
|
|
|
Count => -1, |
3165
|
|
|
|
|
|
|
Protected => 1, |
3166
|
|
|
|
|
|
|
}, |
3167
|
|
|
|
|
|
|
0xc61e => { |
3168
|
|
|
|
|
|
|
Name => 'DefaultScale', |
3169
|
|
|
|
|
|
|
Writable => 'rational64u', |
3170
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3171
|
|
|
|
|
|
|
Count => 2, |
3172
|
|
|
|
|
|
|
Protected => 1, |
3173
|
|
|
|
|
|
|
}, |
3174
|
|
|
|
|
|
|
0xc61f => { |
3175
|
|
|
|
|
|
|
Name => 'DefaultCropOrigin', |
3176
|
|
|
|
|
|
|
Writable => 'int32u', |
3177
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3178
|
|
|
|
|
|
|
Count => 2, |
3179
|
|
|
|
|
|
|
Protected => 1, |
3180
|
|
|
|
|
|
|
}, |
3181
|
|
|
|
|
|
|
0xc620 => { |
3182
|
|
|
|
|
|
|
Name => 'DefaultCropSize', |
3183
|
|
|
|
|
|
|
Writable => 'int32u', |
3184
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3185
|
|
|
|
|
|
|
Count => 2, |
3186
|
|
|
|
|
|
|
Protected => 1, |
3187
|
|
|
|
|
|
|
}, |
3188
|
|
|
|
|
|
|
0xc621 => { |
3189
|
|
|
|
|
|
|
Name => 'ColorMatrix1', |
3190
|
|
|
|
|
|
|
Writable => 'rational64s', |
3191
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3192
|
|
|
|
|
|
|
Count => -1, |
3193
|
|
|
|
|
|
|
Protected => 1, |
3194
|
|
|
|
|
|
|
}, |
3195
|
|
|
|
|
|
|
0xc622 => { |
3196
|
|
|
|
|
|
|
Name => 'ColorMatrix2', |
3197
|
|
|
|
|
|
|
Writable => 'rational64s', |
3198
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3199
|
|
|
|
|
|
|
Count => -1, |
3200
|
|
|
|
|
|
|
Protected => 1, |
3201
|
|
|
|
|
|
|
}, |
3202
|
|
|
|
|
|
|
0xc623 => { |
3203
|
|
|
|
|
|
|
Name => 'CameraCalibration1', |
3204
|
|
|
|
|
|
|
Writable => 'rational64s', |
3205
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3206
|
|
|
|
|
|
|
Count => -1, |
3207
|
|
|
|
|
|
|
Protected => 1, |
3208
|
|
|
|
|
|
|
}, |
3209
|
|
|
|
|
|
|
0xc624 => { |
3210
|
|
|
|
|
|
|
Name => 'CameraCalibration2', |
3211
|
|
|
|
|
|
|
Writable => 'rational64s', |
3212
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3213
|
|
|
|
|
|
|
Count => -1, |
3214
|
|
|
|
|
|
|
Protected => 1, |
3215
|
|
|
|
|
|
|
}, |
3216
|
|
|
|
|
|
|
0xc625 => { |
3217
|
|
|
|
|
|
|
Name => 'ReductionMatrix1', |
3218
|
|
|
|
|
|
|
Writable => 'rational64s', |
3219
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3220
|
|
|
|
|
|
|
Count => -1, |
3221
|
|
|
|
|
|
|
Protected => 1, |
3222
|
|
|
|
|
|
|
}, |
3223
|
|
|
|
|
|
|
0xc626 => { |
3224
|
|
|
|
|
|
|
Name => 'ReductionMatrix2', |
3225
|
|
|
|
|
|
|
Writable => 'rational64s', |
3226
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3227
|
|
|
|
|
|
|
Count => -1, |
3228
|
|
|
|
|
|
|
Protected => 1, |
3229
|
|
|
|
|
|
|
}, |
3230
|
|
|
|
|
|
|
0xc627 => { |
3231
|
|
|
|
|
|
|
Name => 'AnalogBalance', |
3232
|
|
|
|
|
|
|
Writable => 'rational64u', |
3233
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3234
|
|
|
|
|
|
|
Count => -1, |
3235
|
|
|
|
|
|
|
Protected => 1, |
3236
|
|
|
|
|
|
|
}, |
3237
|
|
|
|
|
|
|
0xc628 => { |
3238
|
|
|
|
|
|
|
Name => 'AsShotNeutral', |
3239
|
|
|
|
|
|
|
Writable => 'rational64u', |
3240
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3241
|
|
|
|
|
|
|
Count => -1, |
3242
|
|
|
|
|
|
|
Protected => 1, |
3243
|
|
|
|
|
|
|
}, |
3244
|
|
|
|
|
|
|
0xc629 => { |
3245
|
|
|
|
|
|
|
Name => 'AsShotWhiteXY', |
3246
|
|
|
|
|
|
|
Writable => 'rational64u', |
3247
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3248
|
|
|
|
|
|
|
Count => 2, |
3249
|
|
|
|
|
|
|
Protected => 1, |
3250
|
|
|
|
|
|
|
}, |
3251
|
|
|
|
|
|
|
0xc62a => { |
3252
|
|
|
|
|
|
|
Name => 'BaselineExposure', |
3253
|
|
|
|
|
|
|
Writable => 'rational64s', |
3254
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3255
|
|
|
|
|
|
|
Protected => 1, |
3256
|
|
|
|
|
|
|
}, |
3257
|
|
|
|
|
|
|
0xc62b => { |
3258
|
|
|
|
|
|
|
Name => 'BaselineNoise', |
3259
|
|
|
|
|
|
|
Writable => 'rational64u', |
3260
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3261
|
|
|
|
|
|
|
Protected => 1, |
3262
|
|
|
|
|
|
|
}, |
3263
|
|
|
|
|
|
|
0xc62c => { |
3264
|
|
|
|
|
|
|
Name => 'BaselineSharpness', |
3265
|
|
|
|
|
|
|
Writable => 'rational64u', |
3266
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3267
|
|
|
|
|
|
|
Protected => 1, |
3268
|
|
|
|
|
|
|
}, |
3269
|
|
|
|
|
|
|
0xc62d => { |
3270
|
|
|
|
|
|
|
Name => 'BayerGreenSplit', |
3271
|
|
|
|
|
|
|
Writable => 'int32u', |
3272
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3273
|
|
|
|
|
|
|
Protected => 1, |
3274
|
|
|
|
|
|
|
}, |
3275
|
|
|
|
|
|
|
0xc62e => { |
3276
|
|
|
|
|
|
|
Name => 'LinearResponseLimit', |
3277
|
|
|
|
|
|
|
Writable => 'rational64u', |
3278
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3279
|
|
|
|
|
|
|
Protected => 1, |
3280
|
|
|
|
|
|
|
}, |
3281
|
|
|
|
|
|
|
0xc62f => { |
3282
|
|
|
|
|
|
|
Name => 'CameraSerialNumber', |
3283
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
3284
|
|
|
|
|
|
|
Writable => 'string', |
3285
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3286
|
|
|
|
|
|
|
}, |
3287
|
|
|
|
|
|
|
0xc630 => { |
3288
|
|
|
|
|
|
|
Name => 'DNGLensInfo', |
3289
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
3290
|
|
|
|
|
|
|
Writable => 'rational64u', |
3291
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3292
|
|
|
|
|
|
|
Count => 4, |
3293
|
|
|
|
|
|
|
PrintConv =>\&PrintLensInfo, |
3294
|
|
|
|
|
|
|
PrintConvInv => \&ConvertLensInfo, |
3295
|
|
|
|
|
|
|
}, |
3296
|
|
|
|
|
|
|
0xc631 => { |
3297
|
|
|
|
|
|
|
Name => 'ChromaBlurRadius', |
3298
|
|
|
|
|
|
|
Writable => 'rational64u', |
3299
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3300
|
|
|
|
|
|
|
Protected => 1, |
3301
|
|
|
|
|
|
|
}, |
3302
|
|
|
|
|
|
|
0xc632 => { |
3303
|
|
|
|
|
|
|
Name => 'AntiAliasStrength', |
3304
|
|
|
|
|
|
|
Writable => 'rational64u', |
3305
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3306
|
|
|
|
|
|
|
Protected => 1, |
3307
|
|
|
|
|
|
|
}, |
3308
|
|
|
|
|
|
|
0xc633 => { |
3309
|
|
|
|
|
|
|
Name => 'ShadowScale', |
3310
|
|
|
|
|
|
|
Writable => 'rational64u', |
3311
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3312
|
|
|
|
|
|
|
Protected => 1, |
3313
|
|
|
|
|
|
|
}, |
3314
|
|
|
|
|
|
|
0xc634 => [ |
3315
|
|
|
|
|
|
|
{ |
3316
|
|
|
|
|
|
|
Condition => '$$self{TIFF_TYPE} =~ /^(ARW|SR2)$/', |
3317
|
|
|
|
|
|
|
Name => 'SR2Private', |
3318
|
|
|
|
|
|
|
Groups => { 1 => 'SR2' }, |
3319
|
|
|
|
|
|
|
Flags => 'SubIFD', |
3320
|
|
|
|
|
|
|
Format => 'int32u', |
3321
|
|
|
|
|
|
|
# some utilities have problems unless this is int8u format: |
3322
|
|
|
|
|
|
|
# - Adobe Camera Raw 5.3 gives an error |
3323
|
|
|
|
|
|
|
# - Apple Preview 10.5.8 gets the wrong white balance |
3324
|
|
|
|
|
|
|
FixFormat => 'int8u', # (stupid Sony) |
3325
|
|
|
|
|
|
|
WriteGroup => 'IFD0', # (for Validate) |
3326
|
|
|
|
|
|
|
SubDirectory => { |
3327
|
|
|
|
|
|
|
DirName => 'SR2Private', |
3328
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Sony::SR2Private', |
3329
|
|
|
|
|
|
|
Start => '$val', |
3330
|
|
|
|
|
|
|
}, |
3331
|
|
|
|
|
|
|
}, |
3332
|
|
|
|
|
|
|
{ |
3333
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^Adobe\0/', |
3334
|
|
|
|
|
|
|
Name => 'DNGAdobeData', |
3335
|
|
|
|
|
|
|
Flags => [ 'Binary', 'Protected' ], |
3336
|
|
|
|
|
|
|
Writable => 'undef', # (writable directory!) (to make it possible to delete this mess) |
3337
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3338
|
|
|
|
|
|
|
NestedHtmlDump => 1, |
3339
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::DNG::AdobeData' }, |
3340
|
|
|
|
|
|
|
Format => 'undef', # but written as int8u (change to undef for speed) |
3341
|
|
|
|
|
|
|
}, |
3342
|
|
|
|
|
|
|
{ |
3343
|
|
|
|
|
|
|
# Pentax/Samsung models that write AOC maker notes in JPG images: |
3344
|
|
|
|
|
|
|
# K-5,K-7,K-m,K-x,K-r,K10D,K20D,K100D,K110D,K200D,K2000,GX10,GX20 |
3345
|
|
|
|
|
|
|
# (Note: the following expression also appears in WriteExif.pl) |
3346
|
|
|
|
|
|
|
Condition => q{ |
3347
|
|
|
|
|
|
|
$$valPt =~ /^(PENTAX |SAMSUNG)\0/ and |
3348
|
|
|
|
|
|
|
$$self{Model} =~ /\b(K(-[57mrx]|(10|20|100|110|200)D|2000)|GX(10|20))\b/ |
3349
|
|
|
|
|
|
|
}, |
3350
|
|
|
|
|
|
|
Name => 'MakerNotePentax', |
3351
|
|
|
|
|
|
|
MakerNotes => 1, # (causes "MakerNotes header" to be identified in HtmlDump output) |
3352
|
|
|
|
|
|
|
Binary => 1, |
3353
|
|
|
|
|
|
|
WriteGroup => 'IFD0', # (for Validate) |
3354
|
|
|
|
|
|
|
# Note: Don't make this block-writable for a few reasons: |
3355
|
|
|
|
|
|
|
# 1) It would be dangerous (possibly confusing Pentax software) |
3356
|
|
|
|
|
|
|
# 2) It is a different format from the JPEG version of MakerNotePentax |
3357
|
|
|
|
|
|
|
# 3) It is converted to JPEG format by RebuildMakerNotes() when copying |
3358
|
|
|
|
|
|
|
SubDirectory => { |
3359
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Pentax::Main', |
3360
|
|
|
|
|
|
|
Start => '$valuePtr + 10', |
3361
|
|
|
|
|
|
|
Base => '$start - 10', |
3362
|
|
|
|
|
|
|
ByteOrder => 'Unknown', # easier to do this than read byteorder word |
3363
|
|
|
|
|
|
|
}, |
3364
|
|
|
|
|
|
|
Format => 'undef', # but written as int8u (change to undef for speed) |
3365
|
|
|
|
|
|
|
}, |
3366
|
|
|
|
|
|
|
{ |
3367
|
|
|
|
|
|
|
# must duplicate the above tag with a different name for more recent |
3368
|
|
|
|
|
|
|
# Pentax models which use the "PENTAX" instead of the "AOC" maker notes |
3369
|
|
|
|
|
|
|
# in JPG images (needed when copying maker notes from DNG to JPG) |
3370
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^(PENTAX |SAMSUNG)\0/', |
3371
|
|
|
|
|
|
|
Name => 'MakerNotePentax5', |
3372
|
|
|
|
|
|
|
MakerNotes => 1, |
3373
|
|
|
|
|
|
|
Binary => 1, |
3374
|
|
|
|
|
|
|
WriteGroup => 'IFD0', # (for Validate) |
3375
|
|
|
|
|
|
|
SubDirectory => { |
3376
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Pentax::Main', |
3377
|
|
|
|
|
|
|
Start => '$valuePtr + 10', |
3378
|
|
|
|
|
|
|
Base => '$start - 10', |
3379
|
|
|
|
|
|
|
ByteOrder => 'Unknown', |
3380
|
|
|
|
|
|
|
}, |
3381
|
|
|
|
|
|
|
Format => 'undef', |
3382
|
|
|
|
|
|
|
}, |
3383
|
|
|
|
|
|
|
{ |
3384
|
|
|
|
|
|
|
# Ricoh models such as the GR III |
3385
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^RICOH\0(II|MM)/', |
3386
|
|
|
|
|
|
|
Name => 'MakerNoteRicohPentax', |
3387
|
|
|
|
|
|
|
MakerNotes => 1, |
3388
|
|
|
|
|
|
|
Binary => 1, |
3389
|
|
|
|
|
|
|
WriteGroup => 'IFD0', # (for Validate) |
3390
|
|
|
|
|
|
|
SubDirectory => { |
3391
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Pentax::Main', |
3392
|
|
|
|
|
|
|
Start => '$valuePtr + 8', |
3393
|
|
|
|
|
|
|
Base => '$start - 8', |
3394
|
|
|
|
|
|
|
ByteOrder => 'Unknown', |
3395
|
|
|
|
|
|
|
}, |
3396
|
|
|
|
|
|
|
Format => 'undef', |
3397
|
|
|
|
|
|
|
}, |
3398
|
|
|
|
|
|
|
# the DJI FC2103 writes some interesting stuff here (with sections labelled |
3399
|
|
|
|
|
|
|
# awb_dbg_info, ae_dbg_info, ae_histogram_info, af_dbg_info, hiso, xidiri) - PH |
3400
|
|
|
|
|
|
|
{ |
3401
|
|
|
|
|
|
|
Name => 'MakerNoteDJIInfo', |
3402
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^\[ae_dbg_info:/', |
3403
|
|
|
|
|
|
|
MakerNotes => 1, |
3404
|
|
|
|
|
|
|
Binary => 1, |
3405
|
|
|
|
|
|
|
WriteGroup => 'IFD0', # (for Validate) |
3406
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::DJI::Info' }, |
3407
|
|
|
|
|
|
|
Format => 'undef', |
3408
|
|
|
|
|
|
|
}, |
3409
|
|
|
|
|
|
|
{ |
3410
|
|
|
|
|
|
|
Name => 'DNGPrivateData', |
3411
|
|
|
|
|
|
|
Flags => [ 'Binary', 'Protected' ], |
3412
|
|
|
|
|
|
|
Format => 'undef', |
3413
|
|
|
|
|
|
|
Writable => 'int8u', |
3414
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3415
|
|
|
|
|
|
|
}, |
3416
|
|
|
|
|
|
|
], |
3417
|
|
|
|
|
|
|
0xc635 => { |
3418
|
|
|
|
|
|
|
Name => 'MakerNoteSafety', |
3419
|
|
|
|
|
|
|
Writable => 'int16u', |
3420
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3421
|
|
|
|
|
|
|
PrintConv => { |
3422
|
|
|
|
|
|
|
0 => 'Unsafe', |
3423
|
|
|
|
|
|
|
1 => 'Safe', |
3424
|
|
|
|
|
|
|
}, |
3425
|
|
|
|
|
|
|
}, |
3426
|
|
|
|
|
|
|
0xc640 => { #15 |
3427
|
|
|
|
|
|
|
Name => 'RawImageSegmentation', |
3428
|
|
|
|
|
|
|
# (int16u[3], not writable) |
3429
|
|
|
|
|
|
|
Notes => q{ |
3430
|
|
|
|
|
|
|
used in segmented Canon CR2 images. 3 numbers: 1. Number of segments minus |
3431
|
|
|
|
|
|
|
one; 2. Pixel width of segments except last; 3. Pixel width of last segment |
3432
|
|
|
|
|
|
|
}, |
3433
|
|
|
|
|
|
|
}, |
3434
|
|
|
|
|
|
|
0xc65a => { |
3435
|
|
|
|
|
|
|
Name => 'CalibrationIlluminant1', |
3436
|
|
|
|
|
|
|
Writable => 'int16u', |
3437
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3438
|
|
|
|
|
|
|
Protected => 1, |
3439
|
|
|
|
|
|
|
SeparateTable => 'LightSource', |
3440
|
|
|
|
|
|
|
PrintConv => \%lightSource, |
3441
|
|
|
|
|
|
|
}, |
3442
|
|
|
|
|
|
|
0xc65b => { |
3443
|
|
|
|
|
|
|
Name => 'CalibrationIlluminant2', |
3444
|
|
|
|
|
|
|
Writable => 'int16u', |
3445
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3446
|
|
|
|
|
|
|
Protected => 1, |
3447
|
|
|
|
|
|
|
SeparateTable => 'LightSource', |
3448
|
|
|
|
|
|
|
PrintConv => \%lightSource, |
3449
|
|
|
|
|
|
|
}, |
3450
|
|
|
|
|
|
|
0xc65c => { |
3451
|
|
|
|
|
|
|
Name => 'BestQualityScale', |
3452
|
|
|
|
|
|
|
Writable => 'rational64u', |
3453
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3454
|
|
|
|
|
|
|
Protected => 1, |
3455
|
|
|
|
|
|
|
}, |
3456
|
|
|
|
|
|
|
0xc65d => { |
3457
|
|
|
|
|
|
|
Name => 'RawDataUniqueID', |
3458
|
|
|
|
|
|
|
Format => 'undef', |
3459
|
|
|
|
|
|
|
Writable => 'int8u', |
3460
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3461
|
|
|
|
|
|
|
Count => 16, |
3462
|
|
|
|
|
|
|
Protected => 1, |
3463
|
|
|
|
|
|
|
ValueConv => 'uc(unpack("H*",$val))', |
3464
|
|
|
|
|
|
|
ValueConvInv => 'pack("H*", $val)', |
3465
|
|
|
|
|
|
|
}, |
3466
|
|
|
|
|
|
|
0xc660 => { #3 |
3467
|
|
|
|
|
|
|
Name => 'AliasLayerMetadata', |
3468
|
|
|
|
|
|
|
Notes => 'used by Alias Sketchbook Pro', |
3469
|
|
|
|
|
|
|
}, |
3470
|
|
|
|
|
|
|
0xc68b => { |
3471
|
|
|
|
|
|
|
Name => 'OriginalRawFileName', |
3472
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3473
|
|
|
|
|
|
|
Protected => 1, |
3474
|
|
|
|
|
|
|
%utf8StringConv, |
3475
|
|
|
|
|
|
|
}, |
3476
|
|
|
|
|
|
|
0xc68c => { |
3477
|
|
|
|
|
|
|
Name => 'OriginalRawFileData', # (writable directory!) |
3478
|
|
|
|
|
|
|
Writable => 'undef', # must be defined here so tag will be extracted if specified |
3479
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3480
|
|
|
|
|
|
|
Flags => [ 'Binary', 'Protected' ], |
3481
|
|
|
|
|
|
|
SubDirectory => { |
3482
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::DNG::OriginalRaw', |
3483
|
|
|
|
|
|
|
}, |
3484
|
|
|
|
|
|
|
}, |
3485
|
|
|
|
|
|
|
0xc68d => { |
3486
|
|
|
|
|
|
|
Name => 'ActiveArea', |
3487
|
|
|
|
|
|
|
Writable => 'int32u', |
3488
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3489
|
|
|
|
|
|
|
Count => 4, |
3490
|
|
|
|
|
|
|
Protected => 1, |
3491
|
|
|
|
|
|
|
}, |
3492
|
|
|
|
|
|
|
0xc68e => { |
3493
|
|
|
|
|
|
|
Name => 'MaskedAreas', |
3494
|
|
|
|
|
|
|
Writable => 'int32u', |
3495
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3496
|
|
|
|
|
|
|
Count => -1, |
3497
|
|
|
|
|
|
|
Protected => 1, |
3498
|
|
|
|
|
|
|
}, |
3499
|
|
|
|
|
|
|
0xc68f => { |
3500
|
|
|
|
|
|
|
Name => 'AsShotICCProfile', # (writable directory) |
3501
|
|
|
|
|
|
|
Binary => 1, |
3502
|
|
|
|
|
|
|
Writable => 'undef', # must be defined here so tag will be extracted if specified |
3503
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3504
|
|
|
|
|
|
|
Protected => 1, |
3505
|
|
|
|
|
|
|
WriteCheck => q{ |
3506
|
|
|
|
|
|
|
require Image::ExifTool::ICC_Profile; |
3507
|
|
|
|
|
|
|
return Image::ExifTool::ICC_Profile::ValidateICC(\$val); |
3508
|
|
|
|
|
|
|
}, |
3509
|
|
|
|
|
|
|
SubDirectory => { |
3510
|
|
|
|
|
|
|
DirName => 'AsShotICCProfile', |
3511
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::ICC_Profile::Main', |
3512
|
|
|
|
|
|
|
}, |
3513
|
|
|
|
|
|
|
}, |
3514
|
|
|
|
|
|
|
0xc690 => { |
3515
|
|
|
|
|
|
|
Name => 'AsShotPreProfileMatrix', |
3516
|
|
|
|
|
|
|
Writable => 'rational64s', |
3517
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3518
|
|
|
|
|
|
|
Count => -1, |
3519
|
|
|
|
|
|
|
Protected => 1, |
3520
|
|
|
|
|
|
|
}, |
3521
|
|
|
|
|
|
|
0xc691 => { |
3522
|
|
|
|
|
|
|
Name => 'CurrentICCProfile', # (writable directory) |
3523
|
|
|
|
|
|
|
Binary => 1, |
3524
|
|
|
|
|
|
|
Writable => 'undef', # must be defined here so tag will be extracted if specified |
3525
|
|
|
|
|
|
|
SubDirectory => { |
3526
|
|
|
|
|
|
|
DirName => 'CurrentICCProfile', |
3527
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::ICC_Profile::Main', |
3528
|
|
|
|
|
|
|
}, |
3529
|
|
|
|
|
|
|
Writable => 'undef', |
3530
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3531
|
|
|
|
|
|
|
Protected => 1, |
3532
|
|
|
|
|
|
|
WriteCheck => q{ |
3533
|
|
|
|
|
|
|
require Image::ExifTool::ICC_Profile; |
3534
|
|
|
|
|
|
|
return Image::ExifTool::ICC_Profile::ValidateICC(\$val); |
3535
|
|
|
|
|
|
|
}, |
3536
|
|
|
|
|
|
|
}, |
3537
|
|
|
|
|
|
|
0xc692 => { |
3538
|
|
|
|
|
|
|
Name => 'CurrentPreProfileMatrix', |
3539
|
|
|
|
|
|
|
Writable => 'rational64s', |
3540
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3541
|
|
|
|
|
|
|
Count => -1, |
3542
|
|
|
|
|
|
|
Protected => 1, |
3543
|
|
|
|
|
|
|
}, |
3544
|
|
|
|
|
|
|
0xc6bf => { |
3545
|
|
|
|
|
|
|
Name => 'ColorimetricReference', |
3546
|
|
|
|
|
|
|
Writable => 'int16u', |
3547
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3548
|
|
|
|
|
|
|
Protected => 1, |
3549
|
|
|
|
|
|
|
}, |
3550
|
|
|
|
|
|
|
0xc6c5 => { Name => 'SRawType', Description => 'SRaw Type', WriteGroup => 'IFD0' }, #exifprobe (CR2 proprietary) |
3551
|
|
|
|
|
|
|
0xc6d2 => { #JD (Panasonic DMC-TZ5) |
3552
|
|
|
|
|
|
|
# this text is UTF-8 encoded (hooray!) - PH (TZ5) |
3553
|
|
|
|
|
|
|
Name => 'PanasonicTitle', |
3554
|
|
|
|
|
|
|
Format => 'string', # written incorrectly as 'undef' |
3555
|
|
|
|
|
|
|
Notes => 'proprietary Panasonic tag used for baby/pet name, etc', |
3556
|
|
|
|
|
|
|
Writable => 'undef', |
3557
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3558
|
|
|
|
|
|
|
# panasonic always records this tag (64 zero bytes), |
3559
|
|
|
|
|
|
|
# so ignore it unless it contains valid information |
3560
|
|
|
|
|
|
|
RawConv => 'length($val) ? $val : undef', |
3561
|
|
|
|
|
|
|
ValueConv => '$self->Decode($val, "UTF8")', |
3562
|
|
|
|
|
|
|
ValueConvInv => '$self->Encode($val,"UTF8")', |
3563
|
|
|
|
|
|
|
}, |
3564
|
|
|
|
|
|
|
0xc6d3 => { #PH (Panasonic DMC-FS7) |
3565
|
|
|
|
|
|
|
Name => 'PanasonicTitle2', |
3566
|
|
|
|
|
|
|
Format => 'string', # written incorrectly as 'undef' |
3567
|
|
|
|
|
|
|
Notes => 'proprietary Panasonic tag used for baby/pet name with age', |
3568
|
|
|
|
|
|
|
Writable => 'undef', |
3569
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3570
|
|
|
|
|
|
|
# panasonic always records this tag (128 zero bytes), |
3571
|
|
|
|
|
|
|
# so ignore it unless it contains valid information |
3572
|
|
|
|
|
|
|
RawConv => 'length($val) ? $val : undef', |
3573
|
|
|
|
|
|
|
ValueConv => '$self->Decode($val, "UTF8")', |
3574
|
|
|
|
|
|
|
ValueConvInv => '$self->Encode($val,"UTF8")', |
3575
|
|
|
|
|
|
|
}, |
3576
|
|
|
|
|
|
|
# 0xc6dc - int32u[4]: found in CR2 images (PH, 7DmkIII) |
3577
|
|
|
|
|
|
|
# 0xc6dd - int16u[256]: found in CR2 images (PH, 5DmkIV) |
3578
|
|
|
|
|
|
|
0xc6f3 => { |
3579
|
|
|
|
|
|
|
Name => 'CameraCalibrationSig', |
3580
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3581
|
|
|
|
|
|
|
Protected => 1, |
3582
|
|
|
|
|
|
|
%utf8StringConv, |
3583
|
|
|
|
|
|
|
}, |
3584
|
|
|
|
|
|
|
0xc6f4 => { |
3585
|
|
|
|
|
|
|
Name => 'ProfileCalibrationSig', |
3586
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3587
|
|
|
|
|
|
|
Protected => 1, |
3588
|
|
|
|
|
|
|
%utf8StringConv, |
3589
|
|
|
|
|
|
|
}, |
3590
|
|
|
|
|
|
|
0xc6f5 => { |
3591
|
|
|
|
|
|
|
Name => 'ProfileIFD', # (ExtraCameraProfiles) |
3592
|
|
|
|
|
|
|
Groups => { 1 => 'ProfileIFD' }, |
3593
|
|
|
|
|
|
|
Flags => 'SubIFD', |
3594
|
|
|
|
|
|
|
WriteGroup => 'IFD0', # (only for Validate) |
3595
|
|
|
|
|
|
|
SubDirectory => { |
3596
|
|
|
|
|
|
|
ProcessProc => \&ProcessTiffIFD, |
3597
|
|
|
|
|
|
|
WriteProc => \&ProcessTiffIFD, |
3598
|
|
|
|
|
|
|
DirName => 'ProfileIFD', |
3599
|
|
|
|
|
|
|
Start => '$val', |
3600
|
|
|
|
|
|
|
Base => '$start', # offsets relative to start of TIFF-like header |
3601
|
|
|
|
|
|
|
MaxSubdirs => 10, |
3602
|
|
|
|
|
|
|
Magic => 0x4352, # magic number for TIFF-like header |
3603
|
|
|
|
|
|
|
}, |
3604
|
|
|
|
|
|
|
}, |
3605
|
|
|
|
|
|
|
0xc6f6 => { |
3606
|
|
|
|
|
|
|
Name => 'AsShotProfileName', |
3607
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3608
|
|
|
|
|
|
|
Protected => 1, |
3609
|
|
|
|
|
|
|
%utf8StringConv, |
3610
|
|
|
|
|
|
|
}, |
3611
|
|
|
|
|
|
|
0xc6f7 => { |
3612
|
|
|
|
|
|
|
Name => 'NoiseReductionApplied', |
3613
|
|
|
|
|
|
|
Writable => 'rational64u', |
3614
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3615
|
|
|
|
|
|
|
Protected => 1, |
3616
|
|
|
|
|
|
|
}, |
3617
|
|
|
|
|
|
|
0xc6f8 => { |
3618
|
|
|
|
|
|
|
Name => 'ProfileName', |
3619
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3620
|
|
|
|
|
|
|
Protected => 1, |
3621
|
|
|
|
|
|
|
%utf8StringConv, |
3622
|
|
|
|
|
|
|
}, |
3623
|
|
|
|
|
|
|
0xc6f9 => { |
3624
|
|
|
|
|
|
|
Name => 'ProfileHueSatMapDims', |
3625
|
|
|
|
|
|
|
Writable => 'int32u', |
3626
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3627
|
|
|
|
|
|
|
Count => 3, |
3628
|
|
|
|
|
|
|
Protected => 1, |
3629
|
|
|
|
|
|
|
}, |
3630
|
|
|
|
|
|
|
0xc6fa => { |
3631
|
|
|
|
|
|
|
Name => 'ProfileHueSatMapData1', |
3632
|
|
|
|
|
|
|
%longBin, |
3633
|
|
|
|
|
|
|
Writable => 'float', |
3634
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3635
|
|
|
|
|
|
|
Count => -1, |
3636
|
|
|
|
|
|
|
Protected => 1, |
3637
|
|
|
|
|
|
|
}, |
3638
|
|
|
|
|
|
|
0xc6fb => { |
3639
|
|
|
|
|
|
|
Name => 'ProfileHueSatMapData2', |
3640
|
|
|
|
|
|
|
%longBin, |
3641
|
|
|
|
|
|
|
Writable => 'float', |
3642
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3643
|
|
|
|
|
|
|
Count => -1, |
3644
|
|
|
|
|
|
|
Protected => 1, |
3645
|
|
|
|
|
|
|
}, |
3646
|
|
|
|
|
|
|
0xc6fc => { |
3647
|
|
|
|
|
|
|
Name => 'ProfileToneCurve', |
3648
|
|
|
|
|
|
|
%longBin, |
3649
|
|
|
|
|
|
|
Writable => 'float', |
3650
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3651
|
|
|
|
|
|
|
Count => -1, |
3652
|
|
|
|
|
|
|
Protected => 1, |
3653
|
|
|
|
|
|
|
}, |
3654
|
|
|
|
|
|
|
0xc6fd => { |
3655
|
|
|
|
|
|
|
Name => 'ProfileEmbedPolicy', |
3656
|
|
|
|
|
|
|
Writable => 'int32u', |
3657
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3658
|
|
|
|
|
|
|
Protected => 1, |
3659
|
|
|
|
|
|
|
PrintConv => { |
3660
|
|
|
|
|
|
|
0 => 'Allow Copying', |
3661
|
|
|
|
|
|
|
1 => 'Embed if Used', |
3662
|
|
|
|
|
|
|
2 => 'Never Embed', |
3663
|
|
|
|
|
|
|
3 => 'No Restrictions', |
3664
|
|
|
|
|
|
|
}, |
3665
|
|
|
|
|
|
|
}, |
3666
|
|
|
|
|
|
|
0xc6fe => { |
3667
|
|
|
|
|
|
|
Name => 'ProfileCopyright', |
3668
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3669
|
|
|
|
|
|
|
Protected => 1, |
3670
|
|
|
|
|
|
|
%utf8StringConv, |
3671
|
|
|
|
|
|
|
}, |
3672
|
|
|
|
|
|
|
0xc714 => { |
3673
|
|
|
|
|
|
|
Name => 'ForwardMatrix1', |
3674
|
|
|
|
|
|
|
Writable => 'rational64s', |
3675
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3676
|
|
|
|
|
|
|
Count => -1, |
3677
|
|
|
|
|
|
|
Protected => 1, |
3678
|
|
|
|
|
|
|
}, |
3679
|
|
|
|
|
|
|
0xc715 => { |
3680
|
|
|
|
|
|
|
Name => 'ForwardMatrix2', |
3681
|
|
|
|
|
|
|
Writable => 'rational64s', |
3682
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3683
|
|
|
|
|
|
|
Count => -1, |
3684
|
|
|
|
|
|
|
Protected => 1, |
3685
|
|
|
|
|
|
|
}, |
3686
|
|
|
|
|
|
|
0xc716 => { |
3687
|
|
|
|
|
|
|
Name => 'PreviewApplicationName', |
3688
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3689
|
|
|
|
|
|
|
Protected => 1, |
3690
|
|
|
|
|
|
|
%utf8StringConv, |
3691
|
|
|
|
|
|
|
}, |
3692
|
|
|
|
|
|
|
0xc717 => { |
3693
|
|
|
|
|
|
|
Name => 'PreviewApplicationVersion', |
3694
|
|
|
|
|
|
|
Writable => 'string', |
3695
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3696
|
|
|
|
|
|
|
Protected => 1, |
3697
|
|
|
|
|
|
|
%utf8StringConv, |
3698
|
|
|
|
|
|
|
}, |
3699
|
|
|
|
|
|
|
0xc718 => { |
3700
|
|
|
|
|
|
|
Name => 'PreviewSettingsName', |
3701
|
|
|
|
|
|
|
Writable => 'string', |
3702
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3703
|
|
|
|
|
|
|
Protected => 1, |
3704
|
|
|
|
|
|
|
%utf8StringConv, |
3705
|
|
|
|
|
|
|
}, |
3706
|
|
|
|
|
|
|
0xc719 => { |
3707
|
|
|
|
|
|
|
Name => 'PreviewSettingsDigest', |
3708
|
|
|
|
|
|
|
Format => 'undef', |
3709
|
|
|
|
|
|
|
Writable => 'int8u', |
3710
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3711
|
|
|
|
|
|
|
Protected => 1, |
3712
|
|
|
|
|
|
|
ValueConv => 'unpack("H*", $val)', |
3713
|
|
|
|
|
|
|
ValueConvInv => 'pack("H*", $val)', |
3714
|
|
|
|
|
|
|
}, |
3715
|
|
|
|
|
|
|
0xc71a => { |
3716
|
|
|
|
|
|
|
Name => 'PreviewColorSpace', |
3717
|
|
|
|
|
|
|
Writable => 'int32u', |
3718
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3719
|
|
|
|
|
|
|
Protected => 1, |
3720
|
|
|
|
|
|
|
PrintConv => { |
3721
|
|
|
|
|
|
|
0 => 'Unknown', |
3722
|
|
|
|
|
|
|
1 => 'Gray Gamma 2.2', |
3723
|
|
|
|
|
|
|
2 => 'sRGB', |
3724
|
|
|
|
|
|
|
3 => 'Adobe RGB', |
3725
|
|
|
|
|
|
|
4 => 'ProPhoto RGB', |
3726
|
|
|
|
|
|
|
}, |
3727
|
|
|
|
|
|
|
}, |
3728
|
|
|
|
|
|
|
0xc71b => { |
3729
|
|
|
|
|
|
|
Name => 'PreviewDateTime', |
3730
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
3731
|
|
|
|
|
|
|
Writable => 'string', |
3732
|
|
|
|
|
|
|
Shift => 'Time', |
3733
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3734
|
|
|
|
|
|
|
Protected => 1, |
3735
|
|
|
|
|
|
|
ValueConv => q{ |
3736
|
|
|
|
|
|
|
require Image::ExifTool::XMP; |
3737
|
|
|
|
|
|
|
return Image::ExifTool::XMP::ConvertXMPDate($val); |
3738
|
|
|
|
|
|
|
}, |
3739
|
|
|
|
|
|
|
ValueConvInv => q{ |
3740
|
|
|
|
|
|
|
require Image::ExifTool::XMP; |
3741
|
|
|
|
|
|
|
return Image::ExifTool::XMP::FormatXMPDate($val); |
3742
|
|
|
|
|
|
|
}, |
3743
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
3744
|
|
|
|
|
|
|
PrintConvInv => '$self->InverseDateTime($val,1,1)', |
3745
|
|
|
|
|
|
|
}, |
3746
|
|
|
|
|
|
|
0xc71c => { |
3747
|
|
|
|
|
|
|
Name => 'RawImageDigest', |
3748
|
|
|
|
|
|
|
Format => 'undef', |
3749
|
|
|
|
|
|
|
Writable => 'int8u', |
3750
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3751
|
|
|
|
|
|
|
Count => 16, |
3752
|
|
|
|
|
|
|
Protected => 1, |
3753
|
|
|
|
|
|
|
ValueConv => 'unpack("H*", $val)', |
3754
|
|
|
|
|
|
|
ValueConvInv => 'pack("H*", $val)', |
3755
|
|
|
|
|
|
|
}, |
3756
|
|
|
|
|
|
|
0xc71d => { |
3757
|
|
|
|
|
|
|
Name => 'OriginalRawFileDigest', |
3758
|
|
|
|
|
|
|
Format => 'undef', |
3759
|
|
|
|
|
|
|
Writable => 'int8u', |
3760
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3761
|
|
|
|
|
|
|
Count => 16, |
3762
|
|
|
|
|
|
|
Protected => 1, |
3763
|
|
|
|
|
|
|
ValueConv => 'unpack("H*", $val)', |
3764
|
|
|
|
|
|
|
ValueConvInv => 'pack("H*", $val)', |
3765
|
|
|
|
|
|
|
}, |
3766
|
|
|
|
|
|
|
0xc71e => 'SubTileBlockSize', |
3767
|
|
|
|
|
|
|
0xc71f => 'RowInterleaveFactor', |
3768
|
|
|
|
|
|
|
0xc725 => { |
3769
|
|
|
|
|
|
|
Name => 'ProfileLookTableDims', |
3770
|
|
|
|
|
|
|
Writable => 'int32u', |
3771
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3772
|
|
|
|
|
|
|
Count => 3, |
3773
|
|
|
|
|
|
|
Protected => 1, |
3774
|
|
|
|
|
|
|
}, |
3775
|
|
|
|
|
|
|
0xc726 => { |
3776
|
|
|
|
|
|
|
Name => 'ProfileLookTableData', |
3777
|
|
|
|
|
|
|
%longBin, |
3778
|
|
|
|
|
|
|
Writable => 'float', |
3779
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3780
|
|
|
|
|
|
|
Count => -1, |
3781
|
|
|
|
|
|
|
Protected => 1, |
3782
|
|
|
|
|
|
|
}, |
3783
|
|
|
|
|
|
|
0xc740 => { Name => 'OpcodeList1', %opcodeInfo }, # DNG 1.3 |
3784
|
|
|
|
|
|
|
0xc741 => { Name => 'OpcodeList2', %opcodeInfo }, # DNG 1.3 |
3785
|
|
|
|
|
|
|
0xc74e => { Name => 'OpcodeList3', %opcodeInfo }, # DNG 1.3 |
3786
|
|
|
|
|
|
|
0xc761 => { # DNG 1.3 |
3787
|
|
|
|
|
|
|
Name => 'NoiseProfile', |
3788
|
|
|
|
|
|
|
Writable => 'double', |
3789
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
3790
|
|
|
|
|
|
|
Count => -1, |
3791
|
|
|
|
|
|
|
Protected => 1, |
3792
|
|
|
|
|
|
|
}, |
3793
|
|
|
|
|
|
|
0xc763 => { #28 |
3794
|
|
|
|
|
|
|
Name => 'TimeCodes', |
3795
|
|
|
|
|
|
|
Writable => 'int8u', |
3796
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3797
|
|
|
|
|
|
|
Count => -1, # (8 * number of time codes, max 10) |
3798
|
|
|
|
|
|
|
ValueConv => q{ |
3799
|
|
|
|
|
|
|
my @a = split ' ', $val; |
3800
|
|
|
|
|
|
|
my @v; |
3801
|
|
|
|
|
|
|
push @v, join('.', map { sprintf('%.2x',$_) } splice(@a,0,8)) while @a >= 8; |
3802
|
|
|
|
|
|
|
join ' ', @v; |
3803
|
|
|
|
|
|
|
}, |
3804
|
|
|
|
|
|
|
ValueConvInv => q{ |
3805
|
|
|
|
|
|
|
my @a = map hex, split /[. ]+/, $val; |
3806
|
|
|
|
|
|
|
join ' ', @a; |
3807
|
|
|
|
|
|
|
}, |
3808
|
|
|
|
|
|
|
# Note: Currently ignore the flags: |
3809
|
|
|
|
|
|
|
# byte 0 0x80 - color frame |
3810
|
|
|
|
|
|
|
# byte 0 0x40 - drop frame |
3811
|
|
|
|
|
|
|
# byte 1 0x80 - field phase |
3812
|
|
|
|
|
|
|
PrintConv => q{ |
3813
|
|
|
|
|
|
|
my @a = map hex, split /[. ]+/, $val; |
3814
|
|
|
|
|
|
|
my @v; |
3815
|
|
|
|
|
|
|
while (@a >= 8) { |
3816
|
|
|
|
|
|
|
my $str = sprintf("%.2x:%.2x:%.2x.%.2x", $a[3]&0x3f, |
3817
|
|
|
|
|
|
|
$a[2]&0x7f, $a[1]&0x7f, $a[0]&0x3f); |
3818
|
|
|
|
|
|
|
if ($a[3] & 0x80) { # date+timezone exist if BGF2 is set |
3819
|
|
|
|
|
|
|
my $tz = $a[7] & 0x3f; |
3820
|
|
|
|
|
|
|
my $bz = sprintf('%.2x', $tz); |
3821
|
|
|
|
|
|
|
$bz = 100 if $bz =~ /[a-f]/i; # not BCD |
3822
|
|
|
|
|
|
|
if ($bz < 26) { |
3823
|
|
|
|
|
|
|
$tz = ($bz < 13 ? 0 : 26) - $bz; |
3824
|
|
|
|
|
|
|
} elsif ($bz == 32) { |
3825
|
|
|
|
|
|
|
$tz = 12.75; |
3826
|
|
|
|
|
|
|
} elsif ($bz >= 28 and $bz <= 31) { |
3827
|
|
|
|
|
|
|
$tz = 0; # UTC |
3828
|
|
|
|
|
|
|
} elsif ($bz < 100) { |
3829
|
|
|
|
|
|
|
undef $tz; # undefined or user-defined |
3830
|
|
|
|
|
|
|
} elsif ($tz < 0x20) { |
3831
|
|
|
|
|
|
|
$tz = (($tz < 0x10 ? 10 : 20) - $tz) - 0.5; |
3832
|
|
|
|
|
|
|
} else { |
3833
|
|
|
|
|
|
|
$tz = (($tz < 0x30 ? 53 : 63) - $tz) + 0.5; |
3834
|
|
|
|
|
|
|
} |
3835
|
|
|
|
|
|
|
if ($a[7] & 0x80) { # MJD format (/w UTC time) |
3836
|
|
|
|
|
|
|
my ($h,$m,$s,$f) = split /[:.]/, $str; |
3837
|
|
|
|
|
|
|
my $jday = sprintf('%x%.2x%.2x', reverse @a[4..6]); |
3838
|
|
|
|
|
|
|
$str = ConvertUnixTime(($jday - 40587) * 24 * 3600 |
3839
|
|
|
|
|
|
|
+ ((($h+$tz) * 60) + $m) * 60 + $s) . ".$f"; |
3840
|
|
|
|
|
|
|
$str =~ s/^(\d+):(\d+):(\d+) /$1-$2-${3}T/; |
3841
|
|
|
|
|
|
|
} else { # YYMMDD (Note: CinemaDNG 1.1 example seems wrong) |
3842
|
|
|
|
|
|
|
my $yr = sprintf('%.2x',$a[6]) + 1900; |
3843
|
|
|
|
|
|
|
$yr += 100 if $yr < 1970; |
3844
|
|
|
|
|
|
|
$str = sprintf('%d-%.2x-%.2xT%s',$yr,$a[5],$a[4],$str); |
3845
|
|
|
|
|
|
|
} |
3846
|
|
|
|
|
|
|
$str .= TimeZoneString($tz*60) if defined $tz; |
3847
|
|
|
|
|
|
|
} |
3848
|
|
|
|
|
|
|
push @v, $str; |
3849
|
|
|
|
|
|
|
splice @a, 0, 8; |
3850
|
|
|
|
|
|
|
} |
3851
|
|
|
|
|
|
|
join ' ', @v; |
3852
|
|
|
|
|
|
|
}, |
3853
|
|
|
|
|
|
|
PrintConvInv => q{ |
3854
|
|
|
|
|
|
|
my @a = split ' ', $val; |
3855
|
|
|
|
|
|
|
my @v; |
3856
|
|
|
|
|
|
|
foreach (@a) { |
3857
|
|
|
|
|
|
|
my @td = reverse split /T/; |
3858
|
|
|
|
|
|
|
my $tz = 0x39; # default to unknown timezone |
3859
|
|
|
|
|
|
|
if ($td[0] =~ s/([-+])(\d+):(\d+)$//) { |
3860
|
|
|
|
|
|
|
if ($3 == 0) { |
3861
|
|
|
|
|
|
|
$tz = hex(($1 eq '-') ? $2 : 0x26 - $2); |
3862
|
|
|
|
|
|
|
} elsif ($3 == 30) { |
3863
|
|
|
|
|
|
|
if ($1 eq '-') { |
3864
|
|
|
|
|
|
|
$tz = $2 + 0x0a; |
3865
|
|
|
|
|
|
|
$tz += 0x0a if $tz > 0x0f; |
3866
|
|
|
|
|
|
|
} else { |
3867
|
|
|
|
|
|
|
$tz = 0x3f - $2; |
3868
|
|
|
|
|
|
|
$tz -= 0x0a if $tz < 0x3a; |
3869
|
|
|
|
|
|
|
} |
3870
|
|
|
|
|
|
|
} elsif ($3 == 45) { |
3871
|
|
|
|
|
|
|
$tz = 0x32 if $1 eq '+' and $2 == 12; |
3872
|
|
|
|
|
|
|
} |
3873
|
|
|
|
|
|
|
} |
3874
|
|
|
|
|
|
|
my @t = split /[:.]/, $td[0]; |
3875
|
|
|
|
|
|
|
push @t, '00' while @t < 4; |
3876
|
|
|
|
|
|
|
my $bg; |
3877
|
|
|
|
|
|
|
if ($td[1]) { |
3878
|
|
|
|
|
|
|
# date was specified: fill in date & timezone |
3879
|
|
|
|
|
|
|
my @d = split /[-]/, $td[1]; |
3880
|
|
|
|
|
|
|
next if @d < 3; |
3881
|
|
|
|
|
|
|
$bg = sprintf('.%.2d.%.2d.%.2d.%.2x', $d[2], $d[1], $d[0]%100, $tz); |
3882
|
|
|
|
|
|
|
$t[0] = sprintf('%.2x', hex($t[0]) + 0xc0); # set BGF1+BGF2 |
3883
|
|
|
|
|
|
|
} else { # time only |
3884
|
|
|
|
|
|
|
$bg = '.00.00.00.00'; |
3885
|
|
|
|
|
|
|
} |
3886
|
|
|
|
|
|
|
push @v, join('.', reverse(@t[0..3])) . $bg; |
3887
|
|
|
|
|
|
|
} |
3888
|
|
|
|
|
|
|
join ' ', @v; |
3889
|
|
|
|
|
|
|
}, |
3890
|
|
|
|
|
|
|
}, |
3891
|
|
|
|
|
|
|
0xc764 => { #28 |
3892
|
|
|
|
|
|
|
Name => 'FrameRate', |
3893
|
|
|
|
|
|
|
Writable => 'rational64s', |
3894
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3895
|
|
|
|
|
|
|
PrintConv => 'int($val * 1000 + 0.5) / 1000', |
3896
|
|
|
|
|
|
|
PrintConvInv => '$val', |
3897
|
|
|
|
|
|
|
}, |
3898
|
|
|
|
|
|
|
0xc772 => { #28 |
3899
|
|
|
|
|
|
|
Name => 'TStop', |
3900
|
|
|
|
|
|
|
Writable => 'rational64u', |
3901
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3902
|
|
|
|
|
|
|
Count => -1, # (1 or 2) |
3903
|
|
|
|
|
|
|
PrintConv => 'join("-", map { sprintf("%.2f",$_) } split " ", $val)', |
3904
|
|
|
|
|
|
|
PrintConvInv => '$val=~tr/-/ /; $val', |
3905
|
|
|
|
|
|
|
}, |
3906
|
|
|
|
|
|
|
0xc789 => { #28 |
3907
|
|
|
|
|
|
|
Name => 'ReelName', |
3908
|
|
|
|
|
|
|
Writable => 'string', |
3909
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3910
|
|
|
|
|
|
|
}, |
3911
|
|
|
|
|
|
|
0xc791 => { # DNG 1.4 |
3912
|
|
|
|
|
|
|
Name => 'OriginalDefaultFinalSize', |
3913
|
|
|
|
|
|
|
Writable => 'int32u', |
3914
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3915
|
|
|
|
|
|
|
Count => 2, |
3916
|
|
|
|
|
|
|
Protected => 1, |
3917
|
|
|
|
|
|
|
}, |
3918
|
|
|
|
|
|
|
0xc792 => { # DNG 1.4 |
3919
|
|
|
|
|
|
|
Name => 'OriginalBestQualitySize', |
3920
|
|
|
|
|
|
|
Notes => 'called OriginalBestQualityFinalSize by the DNG spec', |
3921
|
|
|
|
|
|
|
Writable => 'int32u', |
3922
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3923
|
|
|
|
|
|
|
Count => 2, |
3924
|
|
|
|
|
|
|
Protected => 1, |
3925
|
|
|
|
|
|
|
}, |
3926
|
|
|
|
|
|
|
0xc793 => { # DNG 1.4 |
3927
|
|
|
|
|
|
|
Name => 'OriginalDefaultCropSize', |
3928
|
|
|
|
|
|
|
Writable => 'rational64u', |
3929
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3930
|
|
|
|
|
|
|
Count => 2, |
3931
|
|
|
|
|
|
|
Protected => 1, |
3932
|
|
|
|
|
|
|
}, |
3933
|
|
|
|
|
|
|
0xc7a1 => { #28 |
3934
|
|
|
|
|
|
|
Name => 'CameraLabel', |
3935
|
|
|
|
|
|
|
Writable => 'string', |
3936
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3937
|
|
|
|
|
|
|
}, |
3938
|
|
|
|
|
|
|
0xc7a3 => { # DNG 1.4 |
3939
|
|
|
|
|
|
|
Name => 'ProfileHueSatMapEncoding', |
3940
|
|
|
|
|
|
|
Writable => 'int32u', |
3941
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3942
|
|
|
|
|
|
|
Protected => 1, |
3943
|
|
|
|
|
|
|
PrintConv => { |
3944
|
|
|
|
|
|
|
0 => 'Linear', |
3945
|
|
|
|
|
|
|
1 => 'sRGB', |
3946
|
|
|
|
|
|
|
}, |
3947
|
|
|
|
|
|
|
}, |
3948
|
|
|
|
|
|
|
0xc7a4 => { # DNG 1.4 |
3949
|
|
|
|
|
|
|
Name => 'ProfileLookTableEncoding', |
3950
|
|
|
|
|
|
|
Writable => 'int32u', |
3951
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3952
|
|
|
|
|
|
|
Protected => 1, |
3953
|
|
|
|
|
|
|
PrintConv => { |
3954
|
|
|
|
|
|
|
0 => 'Linear', |
3955
|
|
|
|
|
|
|
1 => 'sRGB', |
3956
|
|
|
|
|
|
|
}, |
3957
|
|
|
|
|
|
|
}, |
3958
|
|
|
|
|
|
|
0xc7a5 => { # DNG 1.4 |
3959
|
|
|
|
|
|
|
Name => 'BaselineExposureOffset', |
3960
|
|
|
|
|
|
|
Writable => 'rational64s', # (incorrectly "RATIONAL" in DNG 1.4 spec) |
3961
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3962
|
|
|
|
|
|
|
Protected => 1, |
3963
|
|
|
|
|
|
|
}, |
3964
|
|
|
|
|
|
|
0xc7a6 => { # DNG 1.4 |
3965
|
|
|
|
|
|
|
Name => 'DefaultBlackRender', |
3966
|
|
|
|
|
|
|
Writable => 'int32u', |
3967
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3968
|
|
|
|
|
|
|
Protected => 1, |
3969
|
|
|
|
|
|
|
PrintConv => { |
3970
|
|
|
|
|
|
|
0 => 'Auto', |
3971
|
|
|
|
|
|
|
1 => 'None', |
3972
|
|
|
|
|
|
|
}, |
3973
|
|
|
|
|
|
|
}, |
3974
|
|
|
|
|
|
|
0xc7a7 => { # DNG 1.4 |
3975
|
|
|
|
|
|
|
Name => 'NewRawImageDigest', |
3976
|
|
|
|
|
|
|
Format => 'undef', |
3977
|
|
|
|
|
|
|
Writable => 'int8u', |
3978
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3979
|
|
|
|
|
|
|
Count => 16, |
3980
|
|
|
|
|
|
|
Protected => 1, |
3981
|
|
|
|
|
|
|
ValueConv => 'unpack("H*", $val)', |
3982
|
|
|
|
|
|
|
ValueConvInv => 'pack("H*", $val)', |
3983
|
|
|
|
|
|
|
}, |
3984
|
|
|
|
|
|
|
0xc7a8 => { # DNG 1.4 |
3985
|
|
|
|
|
|
|
Name => 'RawToPreviewGain', |
3986
|
|
|
|
|
|
|
Writable => 'double', |
3987
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
3988
|
|
|
|
|
|
|
Protected => 1, |
3989
|
|
|
|
|
|
|
}, |
3990
|
|
|
|
|
|
|
# 0xc7a9 - CacheBlob (ref 31) |
3991
|
|
|
|
|
|
|
0xc7aa => { #31 undocumented DNG tag written by LR4 (val=256, related to fast load data?) |
3992
|
|
|
|
|
|
|
Name => 'CacheVersion', |
3993
|
|
|
|
|
|
|
Writable => 'int32u', |
3994
|
|
|
|
|
|
|
WriteGroup => 'SubIFD2', |
3995
|
|
|
|
|
|
|
Format => 'int8u', |
3996
|
|
|
|
|
|
|
Count => 4, |
3997
|
|
|
|
|
|
|
Protected => 1, |
3998
|
|
|
|
|
|
|
PrintConv => '$val =~ tr/ /./; $val', |
3999
|
|
|
|
|
|
|
PrintConvInv => '$val =~ tr/./ /; $val', |
4000
|
|
|
|
|
|
|
}, |
4001
|
|
|
|
|
|
|
0xc7b5 => { # DNG 1.4 |
4002
|
|
|
|
|
|
|
Name => 'DefaultUserCrop', |
4003
|
|
|
|
|
|
|
Writable => 'rational64u', |
4004
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
4005
|
|
|
|
|
|
|
Count => 4, |
4006
|
|
|
|
|
|
|
Protected => 1, |
4007
|
|
|
|
|
|
|
}, |
4008
|
|
|
|
|
|
|
0xc7d5 => { #PH (in SubIFD1 of Nikon Z6/Z7 NEF images) |
4009
|
|
|
|
|
|
|
Name => 'NikonNEFInfo', |
4010
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^Nikon\0/', |
4011
|
|
|
|
|
|
|
SubDirectory => { |
4012
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Nikon::NEFInfo', |
4013
|
|
|
|
|
|
|
Start => '$valuePtr + 18', |
4014
|
|
|
|
|
|
|
Base => '$start - 8', |
4015
|
|
|
|
|
|
|
ByteOrder => 'Unknown', |
4016
|
|
|
|
|
|
|
}, |
4017
|
|
|
|
|
|
|
}, |
4018
|
|
|
|
|
|
|
# 0xc7d6 - int8u: 1 (SubIFD1 of Nikon Z6/Z7 NEF) |
4019
|
|
|
|
|
|
|
0xc7e9 => { # DNG 1.5 |
4020
|
|
|
|
|
|
|
Name => 'DepthFormat', |
4021
|
|
|
|
|
|
|
Writable => 'int16u', |
4022
|
|
|
|
|
|
|
Notes => 'tags 0xc7e9-0xc7ee added by DNG 1.5.0.0', |
4023
|
|
|
|
|
|
|
Protected => 1, |
4024
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
4025
|
|
|
|
|
|
|
PrintConv => { |
4026
|
|
|
|
|
|
|
0 => 'Unknown', |
4027
|
|
|
|
|
|
|
1 => 'Linear', |
4028
|
|
|
|
|
|
|
2 => 'Inverse', |
4029
|
|
|
|
|
|
|
}, |
4030
|
|
|
|
|
|
|
}, |
4031
|
|
|
|
|
|
|
0xc7ea => { # DNG 1.5 |
4032
|
|
|
|
|
|
|
Name => 'DepthNear', |
4033
|
|
|
|
|
|
|
Writable => 'rational64u', |
4034
|
|
|
|
|
|
|
Protected => 1, |
4035
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
4036
|
|
|
|
|
|
|
}, |
4037
|
|
|
|
|
|
|
0xc7eb => { # DNG 1.5 |
4038
|
|
|
|
|
|
|
Name => 'DepthFar', |
4039
|
|
|
|
|
|
|
Writable => 'rational64u', |
4040
|
|
|
|
|
|
|
Protected => 1, |
4041
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
4042
|
|
|
|
|
|
|
}, |
4043
|
|
|
|
|
|
|
0xc7ec => { # DNG 1.5 |
4044
|
|
|
|
|
|
|
Name => 'DepthUnits', |
4045
|
|
|
|
|
|
|
Writable => 'int16u', |
4046
|
|
|
|
|
|
|
Protected => 1, |
4047
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
4048
|
|
|
|
|
|
|
PrintConv => { |
4049
|
|
|
|
|
|
|
0 => 'Unknown', |
4050
|
|
|
|
|
|
|
1 => 'Meters', |
4051
|
|
|
|
|
|
|
}, |
4052
|
|
|
|
|
|
|
}, |
4053
|
|
|
|
|
|
|
0xc7ed => { # DNG 1.5 |
4054
|
|
|
|
|
|
|
Name => 'DepthMeasureType', |
4055
|
|
|
|
|
|
|
Writable => 'int16u', |
4056
|
|
|
|
|
|
|
Protected => 1, |
4057
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
4058
|
|
|
|
|
|
|
PrintConv => { |
4059
|
|
|
|
|
|
|
0 => 'Unknown', |
4060
|
|
|
|
|
|
|
1 => 'Optical Axis', |
4061
|
|
|
|
|
|
|
2 => 'Optical Ray', |
4062
|
|
|
|
|
|
|
}, |
4063
|
|
|
|
|
|
|
}, |
4064
|
|
|
|
|
|
|
0xc7ee => { # DNG 1.5 |
4065
|
|
|
|
|
|
|
Name => 'EnhanceParams', |
4066
|
|
|
|
|
|
|
Writable => 'string', |
4067
|
|
|
|
|
|
|
Protected => 1, |
4068
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
4069
|
|
|
|
|
|
|
}, |
4070
|
|
|
|
|
|
|
0xcd2d => { # DNG 1.6 |
4071
|
|
|
|
|
|
|
Name => 'ProfileGainTableMap', |
4072
|
|
|
|
|
|
|
Writable => 'undef', |
4073
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', |
4074
|
|
|
|
|
|
|
Protected => 1, |
4075
|
|
|
|
|
|
|
Binary => 1, |
4076
|
|
|
|
|
|
|
}, |
4077
|
|
|
|
|
|
|
0xcd2e => { # DNG 1.6 |
4078
|
|
|
|
|
|
|
Name => 'SemanticName', |
4079
|
|
|
|
|
|
|
# Writable => 'string', |
4080
|
|
|
|
|
|
|
WriteGroup => 'SubIFD' #? (NC) Semantic Mask IFD (only for Validate) |
4081
|
|
|
|
|
|
|
}, |
4082
|
|
|
|
|
|
|
0xcd30 => { # DNG 1.6 |
4083
|
|
|
|
|
|
|
Name => 'SemanticInstanceIFD', |
4084
|
|
|
|
|
|
|
# Writable => 'string', |
4085
|
|
|
|
|
|
|
WriteGroup => 'SubIFD' #? (NC) Semantic Mask IFD (only for Validate) |
4086
|
|
|
|
|
|
|
}, |
4087
|
|
|
|
|
|
|
0xcd31 => { # DNG 1.6 |
4088
|
|
|
|
|
|
|
Name => 'CalibrationIlluminant3', |
4089
|
|
|
|
|
|
|
Writable => 'int16u', |
4090
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
4091
|
|
|
|
|
|
|
Protected => 1, |
4092
|
|
|
|
|
|
|
SeparateTable => 'LightSource', |
4093
|
|
|
|
|
|
|
PrintConv => \%lightSource, |
4094
|
|
|
|
|
|
|
}, |
4095
|
|
|
|
|
|
|
0xcd32 => { # DNG 1.6 |
4096
|
|
|
|
|
|
|
Name => 'CameraCalibration3', |
4097
|
|
|
|
|
|
|
Writable => 'rational64s', |
4098
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
4099
|
|
|
|
|
|
|
Count => -1, |
4100
|
|
|
|
|
|
|
Protected => 1, |
4101
|
|
|
|
|
|
|
}, |
4102
|
|
|
|
|
|
|
0xcd33 => { # DNG 1.6 |
4103
|
|
|
|
|
|
|
Name => 'ColorMatrix3', |
4104
|
|
|
|
|
|
|
Writable => 'rational64s', |
4105
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
4106
|
|
|
|
|
|
|
Count => -1, |
4107
|
|
|
|
|
|
|
Protected => 1, |
4108
|
|
|
|
|
|
|
}, |
4109
|
|
|
|
|
|
|
0xcd34 => { # DNG 1.6 |
4110
|
|
|
|
|
|
|
Name => 'ForwardMatrix3', |
4111
|
|
|
|
|
|
|
Writable => 'rational64s', |
4112
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
4113
|
|
|
|
|
|
|
Count => -1, |
4114
|
|
|
|
|
|
|
Protected => 1, |
4115
|
|
|
|
|
|
|
}, |
4116
|
|
|
|
|
|
|
0xcd35 => { # DNG 1.6 |
4117
|
|
|
|
|
|
|
Name => 'IlluminantData1', |
4118
|
|
|
|
|
|
|
Writable => 'undef', |
4119
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
4120
|
|
|
|
|
|
|
Protected => 1, |
4121
|
|
|
|
|
|
|
}, |
4122
|
|
|
|
|
|
|
0xcd36 => { # DNG 1.6 |
4123
|
|
|
|
|
|
|
Name => 'IlluminantData2', |
4124
|
|
|
|
|
|
|
Writable => 'undef', |
4125
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
4126
|
|
|
|
|
|
|
Protected => 1, |
4127
|
|
|
|
|
|
|
}, |
4128
|
|
|
|
|
|
|
0xcd37 => { # DNG 1.6 |
4129
|
|
|
|
|
|
|
Name => 'IlluminantData3', |
4130
|
|
|
|
|
|
|
Writable => 'undef', |
4131
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
4132
|
|
|
|
|
|
|
Protected => 1, |
4133
|
|
|
|
|
|
|
}, |
4134
|
|
|
|
|
|
|
0xcd38 => { # DNG 1.6 |
4135
|
|
|
|
|
|
|
Name => 'MaskSubArea', |
4136
|
|
|
|
|
|
|
# Writable => 'int32u', |
4137
|
|
|
|
|
|
|
WriteGroup => 'SubIFD', #? (NC) Semantic Mask IFD (only for Validate) |
4138
|
|
|
|
|
|
|
Count => 4, |
4139
|
|
|
|
|
|
|
}, |
4140
|
|
|
|
|
|
|
0xcd39 => { # DNG 1.6 |
4141
|
|
|
|
|
|
|
Name => 'ProfileHueSatMapData3', |
4142
|
|
|
|
|
|
|
%longBin, |
4143
|
|
|
|
|
|
|
Writable => 'float', |
4144
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
4145
|
|
|
|
|
|
|
Count => -1, |
4146
|
|
|
|
|
|
|
Protected => 1, |
4147
|
|
|
|
|
|
|
}, |
4148
|
|
|
|
|
|
|
0xcd3a => { # DNG 1.6 |
4149
|
|
|
|
|
|
|
Name => 'ReductionMatrix3', |
4150
|
|
|
|
|
|
|
Writable => 'rational64s', |
4151
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
4152
|
|
|
|
|
|
|
Count => -1, |
4153
|
|
|
|
|
|
|
Protected => 1, |
4154
|
|
|
|
|
|
|
}, |
4155
|
|
|
|
|
|
|
0xcd3b => { # DNG 1.6 |
4156
|
|
|
|
|
|
|
Name => 'RGBTables', |
4157
|
|
|
|
|
|
|
Writable => 'undef', |
4158
|
|
|
|
|
|
|
WriteGroup => 'IFD0', |
4159
|
|
|
|
|
|
|
Protected => 1, |
4160
|
|
|
|
|
|
|
}, |
4161
|
|
|
|
|
|
|
0xea1c => { #13 |
4162
|
|
|
|
|
|
|
Name => 'Padding', |
4163
|
|
|
|
|
|
|
Binary => 1, |
4164
|
|
|
|
|
|
|
Protected => 1, |
4165
|
|
|
|
|
|
|
Writable => 'undef', |
4166
|
|
|
|
|
|
|
# must start with 0x1c 0xea by the WM Photo specification |
4167
|
|
|
|
|
|
|
# (not sure what should happen if padding is only 1 byte) |
4168
|
|
|
|
|
|
|
# (why does MicrosoftPhoto write "1c ea 00 00 00 08"?) |
4169
|
|
|
|
|
|
|
RawConvInv => '$val=~s/^../\x1c\xea/s; $val', |
4170
|
|
|
|
|
|
|
}, |
4171
|
|
|
|
|
|
|
0xea1d => { |
4172
|
|
|
|
|
|
|
Name => 'OffsetSchema', |
4173
|
|
|
|
|
|
|
Notes => "Microsoft's ill-conceived maker note offset difference", |
4174
|
|
|
|
|
|
|
Protected => 1, |
4175
|
|
|
|
|
|
|
Writable => 'int32s', |
4176
|
|
|
|
|
|
|
# From the Microsoft documentation: |
4177
|
|
|
|
|
|
|
# |
4178
|
|
|
|
|
|
|
# Any time the "Maker Note" is relocated by Windows, the Exif MakerNote |
4179
|
|
|
|
|
|
|
# tag (37500) is updated automatically to reference the new location. In |
4180
|
|
|
|
|
|
|
# addition, Windows records the offset (or difference) between the old and |
4181
|
|
|
|
|
|
|
# new locations in the Exif OffsetSchema tag (59933). If the "Maker Note" |
4182
|
|
|
|
|
|
|
# contains relative references, the developer can add the value in |
4183
|
|
|
|
|
|
|
# OffsetSchema to the original references to find the correct information. |
4184
|
|
|
|
|
|
|
# |
4185
|
|
|
|
|
|
|
# My recommendation is for other developers to ignore this tag because the |
4186
|
|
|
|
|
|
|
# information it contains is unreliable. It will be wrong if the image has |
4187
|
|
|
|
|
|
|
# been subsequently edited by another application that doesn't recognize the |
4188
|
|
|
|
|
|
|
# new Microsoft tag. |
4189
|
|
|
|
|
|
|
# |
4190
|
|
|
|
|
|
|
# The new tag unfortunately only gives the difference between the new maker |
4191
|
|
|
|
|
|
|
# note offset and the original offset. Instead, it should have been designed |
4192
|
|
|
|
|
|
|
# to store the original offset. The new offset may change if the image is |
4193
|
|
|
|
|
|
|
# edited, which will invalidate the tag as currently written. If instead the |
4194
|
|
|
|
|
|
|
# original offset had been stored, the new difference could be easily |
4195
|
|
|
|
|
|
|
# calculated because the new maker note offset is known. |
4196
|
|
|
|
|
|
|
# |
4197
|
|
|
|
|
|
|
# I exchanged emails with a Microsoft technical representative, pointing out |
4198
|
|
|
|
|
|
|
# this problem shortly after they released the update (Feb 2007), but so far |
4199
|
|
|
|
|
|
|
# they have taken no steps to address this. |
4200
|
|
|
|
|
|
|
}, |
4201
|
|
|
|
|
|
|
# 0xefee - int16u: 0 - seen this from a WIC-scanned image |
4202
|
|
|
|
|
|
|
|
4203
|
|
|
|
|
|
|
# tags in the range 0xfde8-0xfe58 have been observed in PS7 files |
4204
|
|
|
|
|
|
|
# generated from RAW images. They are all strings with the |
4205
|
|
|
|
|
|
|
# tag name at the start of the string. To accommodate these types |
4206
|
|
|
|
|
|
|
# of tags, all tags with values above 0xf000 are handled specially |
4207
|
|
|
|
|
|
|
# by ProcessExif(). |
4208
|
|
|
|
|
|
|
0xfde8 => { |
4209
|
|
|
|
|
|
|
Name => 'OwnerName', |
4210
|
|
|
|
|
|
|
Condition => '$$self{TIFF_TYPE} ne "DCR"', # (used for another purpose in Kodak DCR images) |
4211
|
|
|
|
|
|
|
Avoid => 1, |
4212
|
|
|
|
|
|
|
PSRaw => 1, |
4213
|
|
|
|
|
|
|
Writable => 'string', |
4214
|
|
|
|
|
|
|
ValueConv => '$val=~s/^.*: //;$val', |
4215
|
|
|
|
|
|
|
ValueConvInv => q{"Owner's Name: $val"}, |
4216
|
|
|
|
|
|
|
Notes => q{ |
4217
|
|
|
|
|
|
|
tags 0xfde8-0xfdea and 0xfe4c-0xfe58 are generated by Photoshop Camera RAW. |
4218
|
|
|
|
|
|
|
Some names are the same as other EXIF tags, but ExifTool will avoid writing |
4219
|
|
|
|
|
|
|
these unless they already exist in the file |
4220
|
|
|
|
|
|
|
}, |
4221
|
|
|
|
|
|
|
}, |
4222
|
|
|
|
|
|
|
0xfde9 => { |
4223
|
|
|
|
|
|
|
Name => 'SerialNumber', |
4224
|
|
|
|
|
|
|
Condition => '$$self{TIFF_TYPE} ne "DCR"', # (used for another purpose in Kodak DCR SubIFD) |
4225
|
|
|
|
|
|
|
Avoid => 1, |
4226
|
|
|
|
|
|
|
PSRaw => 1, |
4227
|
|
|
|
|
|
|
Writable => 'string', |
4228
|
|
|
|
|
|
|
ValueConv => '$val=~s/^.*: //;$val', |
4229
|
|
|
|
|
|
|
ValueConvInv => q{"Serial Number: $val"}, |
4230
|
|
|
|
|
|
|
}, |
4231
|
|
|
|
|
|
|
0xfdea => { |
4232
|
|
|
|
|
|
|
Name => 'Lens', |
4233
|
|
|
|
|
|
|
Condition => '$$self{TIFF_TYPE} ne "DCR"', # (used for another purpose in Kodak DCR SubIFD) |
4234
|
|
|
|
|
|
|
Avoid => 1, |
4235
|
|
|
|
|
|
|
PSRaw => 1, |
4236
|
|
|
|
|
|
|
Writable => 'string', |
4237
|
|
|
|
|
|
|
ValueConv => '$val=~s/^.*: //;$val', |
4238
|
|
|
|
|
|
|
ValueConvInv => q{"Lens: $val"}, |
4239
|
|
|
|
|
|
|
}, |
4240
|
|
|
|
|
|
|
0xfe4c => { |
4241
|
|
|
|
|
|
|
Name => 'RawFile', |
4242
|
|
|
|
|
|
|
Avoid => 1, |
4243
|
|
|
|
|
|
|
PSRaw => 1, |
4244
|
|
|
|
|
|
|
Writable => 'string', |
4245
|
|
|
|
|
|
|
ValueConv => '$val=~s/^.*: //;$val', |
4246
|
|
|
|
|
|
|
ValueConvInv => q{"Raw File: $val"}, |
4247
|
|
|
|
|
|
|
}, |
4248
|
|
|
|
|
|
|
0xfe4d => { |
4249
|
|
|
|
|
|
|
Name => 'Converter', |
4250
|
|
|
|
|
|
|
Avoid => 1, |
4251
|
|
|
|
|
|
|
PSRaw => 1, |
4252
|
|
|
|
|
|
|
Writable => 'string', |
4253
|
|
|
|
|
|
|
ValueConv => '$val=~s/^.*: //;$val', |
4254
|
|
|
|
|
|
|
ValueConvInv => q{"Converter: $val"}, |
4255
|
|
|
|
|
|
|
}, |
4256
|
|
|
|
|
|
|
0xfe4e => { |
4257
|
|
|
|
|
|
|
Name => 'WhiteBalance', |
4258
|
|
|
|
|
|
|
Avoid => 1, |
4259
|
|
|
|
|
|
|
PSRaw => 1, |
4260
|
|
|
|
|
|
|
Writable => 'string', |
4261
|
|
|
|
|
|
|
ValueConv => '$val=~s/^.*: //;$val', |
4262
|
|
|
|
|
|
|
ValueConvInv => q{"White Balance: $val"}, |
4263
|
|
|
|
|
|
|
}, |
4264
|
|
|
|
|
|
|
0xfe51 => { |
4265
|
|
|
|
|
|
|
Name => 'Exposure', |
4266
|
|
|
|
|
|
|
Avoid => 1, |
4267
|
|
|
|
|
|
|
PSRaw => 1, |
4268
|
|
|
|
|
|
|
Writable => 'string', |
4269
|
|
|
|
|
|
|
ValueConv => '$val=~s/^.*: //;$val', |
4270
|
|
|
|
|
|
|
ValueConvInv => q{"Exposure: $val"}, |
4271
|
|
|
|
|
|
|
}, |
4272
|
|
|
|
|
|
|
0xfe52 => { |
4273
|
|
|
|
|
|
|
Name => 'Shadows', |
4274
|
|
|
|
|
|
|
Avoid => 1, |
4275
|
|
|
|
|
|
|
PSRaw => 1, |
4276
|
|
|
|
|
|
|
Writable => 'string', |
4277
|
|
|
|
|
|
|
ValueConv => '$val=~s/^.*: //;$val', |
4278
|
|
|
|
|
|
|
ValueConvInv => q{"Shadows: $val"}, |
4279
|
|
|
|
|
|
|
}, |
4280
|
|
|
|
|
|
|
0xfe53 => { |
4281
|
|
|
|
|
|
|
Name => 'Brightness', |
4282
|
|
|
|
|
|
|
Avoid => 1, |
4283
|
|
|
|
|
|
|
PSRaw => 1, |
4284
|
|
|
|
|
|
|
Writable => 'string', |
4285
|
|
|
|
|
|
|
ValueConv => '$val=~s/^.*: //;$val', |
4286
|
|
|
|
|
|
|
ValueConvInv => q{"Brightness: $val"}, |
4287
|
|
|
|
|
|
|
}, |
4288
|
|
|
|
|
|
|
0xfe54 => { |
4289
|
|
|
|
|
|
|
Name => 'Contrast', |
4290
|
|
|
|
|
|
|
Avoid => 1, |
4291
|
|
|
|
|
|
|
PSRaw => 1, |
4292
|
|
|
|
|
|
|
Writable => 'string', |
4293
|
|
|
|
|
|
|
ValueConv => '$val=~s/^.*: //;$val', |
4294
|
|
|
|
|
|
|
ValueConvInv => q{"Contrast: $val"}, |
4295
|
|
|
|
|
|
|
}, |
4296
|
|
|
|
|
|
|
0xfe55 => { |
4297
|
|
|
|
|
|
|
Name => 'Saturation', |
4298
|
|
|
|
|
|
|
Avoid => 1, |
4299
|
|
|
|
|
|
|
PSRaw => 1, |
4300
|
|
|
|
|
|
|
Writable => 'string', |
4301
|
|
|
|
|
|
|
ValueConv => '$val=~s/^.*: //;$val', |
4302
|
|
|
|
|
|
|
ValueConvInv => q{"Saturation: $val"}, |
4303
|
|
|
|
|
|
|
}, |
4304
|
|
|
|
|
|
|
0xfe56 => { |
4305
|
|
|
|
|
|
|
Name => 'Sharpness', |
4306
|
|
|
|
|
|
|
Avoid => 1, |
4307
|
|
|
|
|
|
|
PSRaw => 1, |
4308
|
|
|
|
|
|
|
Writable => 'string', |
4309
|
|
|
|
|
|
|
ValueConv => '$val=~s/^.*: //;$val', |
4310
|
|
|
|
|
|
|
ValueConvInv => q{"Sharpness: $val"}, |
4311
|
|
|
|
|
|
|
}, |
4312
|
|
|
|
|
|
|
0xfe57 => { |
4313
|
|
|
|
|
|
|
Name => 'Smoothness', |
4314
|
|
|
|
|
|
|
Avoid => 1, |
4315
|
|
|
|
|
|
|
PSRaw => 1, |
4316
|
|
|
|
|
|
|
Writable => 'string', |
4317
|
|
|
|
|
|
|
ValueConv => '$val=~s/^.*: //;$val', |
4318
|
|
|
|
|
|
|
ValueConvInv => q{"Smoothness: $val"}, |
4319
|
|
|
|
|
|
|
}, |
4320
|
|
|
|
|
|
|
0xfe58 => { |
4321
|
|
|
|
|
|
|
Name => 'MoireFilter', |
4322
|
|
|
|
|
|
|
Avoid => 1, |
4323
|
|
|
|
|
|
|
PSRaw => 1, |
4324
|
|
|
|
|
|
|
Writable => 'string', |
4325
|
|
|
|
|
|
|
ValueConv => '$val=~s/^.*: //;$val', |
4326
|
|
|
|
|
|
|
ValueConvInv => q{"Moire Filter: $val"}, |
4327
|
|
|
|
|
|
|
}, |
4328
|
|
|
|
|
|
|
|
4329
|
|
|
|
|
|
|
#------------- |
4330
|
|
|
|
|
|
|
0xfe00 => { |
4331
|
|
|
|
|
|
|
Name => 'KDC_IFD', |
4332
|
|
|
|
|
|
|
Groups => { 1 => 'KDC_IFD' }, |
4333
|
|
|
|
|
|
|
Flags => 'SubIFD', |
4334
|
|
|
|
|
|
|
Notes => 'used in some Kodak KDC images', |
4335
|
|
|
|
|
|
|
SubDirectory => { |
4336
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Kodak::KDC_IFD', |
4337
|
|
|
|
|
|
|
DirName => 'KDC_IFD', |
4338
|
|
|
|
|
|
|
Start => '$val', |
4339
|
|
|
|
|
|
|
}, |
4340
|
|
|
|
|
|
|
}, |
4341
|
|
|
|
|
|
|
); |
4342
|
|
|
|
|
|
|
|
4343
|
|
|
|
|
|
|
# conversions for Composite SubSec date/time tags |
4344
|
|
|
|
|
|
|
my %subSecConv = ( |
4345
|
|
|
|
|
|
|
# @val array: 0) date/time, 1) sub-seconds, 2) time zone offset |
4346
|
|
|
|
|
|
|
RawConv => q{ |
4347
|
|
|
|
|
|
|
my $v; |
4348
|
|
|
|
|
|
|
if (defined $val[1] and $val[1]=~/^(\d+)/) { |
4349
|
|
|
|
|
|
|
my $subSec = $1; |
4350
|
|
|
|
|
|
|
# be careful here just in case the time already contains sub-seconds or a timezone (contrary to spec) |
4351
|
|
|
|
|
|
|
undef $v unless ($v = $val[0]) =~ s/( \d{2}:\d{2}:\d{2})(?!\.\d+)/$1\.$subSec/; |
4352
|
|
|
|
|
|
|
} |
4353
|
|
|
|
|
|
|
if (defined $val[2] and $val[0]!~/[-+]/ and $val[2]=~/^([-+])(\d{1,2}):(\d{2})/) { |
4354
|
|
|
|
|
|
|
$v = ($v || $val[0]) . sprintf('%s%.2d:%.2d', $1, $2, $3); |
4355
|
|
|
|
|
|
|
} |
4356
|
|
|
|
|
|
|
return $v; |
4357
|
|
|
|
|
|
|
}, |
4358
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
4359
|
|
|
|
|
|
|
PrintConvInv => '$self->InverseDateTime($val)', |
4360
|
|
|
|
|
|
|
); |
4361
|
|
|
|
|
|
|
|
4362
|
|
|
|
|
|
|
# EXIF Composite tags (plus other more general Composite tags) |
4363
|
|
|
|
|
|
|
%Image::ExifTool::Exif::Composite = ( |
4364
|
|
|
|
|
|
|
GROUPS => { 2 => 'Image' }, |
4365
|
|
|
|
|
|
|
ImageSize => { |
4366
|
|
|
|
|
|
|
Require => { |
4367
|
|
|
|
|
|
|
0 => 'ImageWidth', |
4368
|
|
|
|
|
|
|
1 => 'ImageHeight', |
4369
|
|
|
|
|
|
|
}, |
4370
|
|
|
|
|
|
|
Desire => { |
4371
|
|
|
|
|
|
|
2 => 'ExifImageWidth', |
4372
|
|
|
|
|
|
|
3 => 'ExifImageHeight', |
4373
|
|
|
|
|
|
|
4 => 'RawImageCroppedSize', # (FujiFilm RAF images) |
4374
|
|
|
|
|
|
|
}, |
4375
|
|
|
|
|
|
|
# use ExifImageWidth/Height only for Canon and Phase One TIFF-base RAW images |
4376
|
|
|
|
|
|
|
ValueConv => q{ |
4377
|
|
|
|
|
|
|
return $val[4] if $val[4]; |
4378
|
|
|
|
|
|
|
return "$val[2] $val[3]" if $val[2] and $val[3] and |
4379
|
|
|
|
|
|
|
$$self{TIFF_TYPE} =~ /^(CR2|Canon 1D RAW|IIQ|EIP)$/; |
4380
|
|
|
|
|
|
|
return "$val[0] $val[1]" if IsFloat($val[0]) and IsFloat($val[1]); |
4381
|
|
|
|
|
|
|
return undef; |
4382
|
|
|
|
|
|
|
}, |
4383
|
|
|
|
|
|
|
PrintConv => '$val =~ tr/ /x/; $val', |
4384
|
|
|
|
|
|
|
}, |
4385
|
|
|
|
|
|
|
Megapixels => { |
4386
|
|
|
|
|
|
|
Require => 'ImageSize', |
4387
|
|
|
|
|
|
|
ValueConv => 'my @d = ($val =~ /\d+/g); $d[0] * $d[1] / 1000000', |
4388
|
|
|
|
|
|
|
PrintConv => 'sprintf("%.*f", ($val >= 1 ? 1 : ($val >= 0.001 ? 3 : 6)), $val)', |
4389
|
|
|
|
|
|
|
}, |
4390
|
|
|
|
|
|
|
# pick the best shutter speed value |
4391
|
|
|
|
|
|
|
ShutterSpeed => { |
4392
|
|
|
|
|
|
|
Desire => { |
4393
|
|
|
|
|
|
|
0 => 'ExposureTime', |
4394
|
|
|
|
|
|
|
1 => 'ShutterSpeedValue', |
4395
|
|
|
|
|
|
|
2 => 'BulbDuration', |
4396
|
|
|
|
|
|
|
}, |
4397
|
|
|
|
|
|
|
ValueConv => '($val[2] and $val[2]>0) ? $val[2] : (defined($val[0]) ? $val[0] : $val[1])', |
4398
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', |
4399
|
|
|
|
|
|
|
}, |
4400
|
|
|
|
|
|
|
Aperture => { |
4401
|
|
|
|
|
|
|
Desire => { |
4402
|
|
|
|
|
|
|
0 => 'FNumber', |
4403
|
|
|
|
|
|
|
1 => 'ApertureValue', |
4404
|
|
|
|
|
|
|
}, |
4405
|
|
|
|
|
|
|
RawConv => '($val[0] || $val[1]) ? $val : undef', |
4406
|
|
|
|
|
|
|
ValueConv => '$val[0] || $val[1]', |
4407
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)', |
4408
|
|
|
|
|
|
|
}, |
4409
|
|
|
|
|
|
|
LightValue => { |
4410
|
|
|
|
|
|
|
Notes => q{ |
4411
|
|
|
|
|
|
|
calculated LV = 2 * log2(Aperture) - log2(ShutterSpeed) - log2(ISO/100); |
4412
|
|
|
|
|
|
|
similar to exposure value but normalized to ISO 100 |
4413
|
|
|
|
|
|
|
}, |
4414
|
|
|
|
|
|
|
Require => { |
4415
|
|
|
|
|
|
|
0 => 'Aperture', |
4416
|
|
|
|
|
|
|
1 => 'ShutterSpeed', |
4417
|
|
|
|
|
|
|
2 => 'ISO', |
4418
|
|
|
|
|
|
|
}, |
4419
|
|
|
|
|
|
|
ValueConv => 'Image::ExifTool::Exif::CalculateLV($val[0],$val[1],$prt[2])', |
4420
|
|
|
|
|
|
|
PrintConv => 'sprintf("%.1f",$val)', |
4421
|
|
|
|
|
|
|
}, |
4422
|
|
|
|
|
|
|
FocalLength35efl => { #26/PH |
4423
|
|
|
|
|
|
|
Description => 'Focal Length', |
4424
|
|
|
|
|
|
|
Notes => 'this value may be incorrect if the image has been resized', |
4425
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
4426
|
|
|
|
|
|
|
Require => { |
4427
|
|
|
|
|
|
|
0 => 'FocalLength', |
4428
|
|
|
|
|
|
|
}, |
4429
|
|
|
|
|
|
|
Desire => { |
4430
|
|
|
|
|
|
|
1 => 'ScaleFactor35efl', |
4431
|
|
|
|
|
|
|
}, |
4432
|
|
|
|
|
|
|
ValueConv => 'ToFloat(@val); ($val[0] || 0) * ($val[1] || 1)', |
4433
|
|
|
|
|
|
|
PrintConv => '$val[1] ? sprintf("%.1f mm (35 mm equivalent: %.1f mm)", $val[0], $val) : sprintf("%.1f mm", $val)', |
4434
|
|
|
|
|
|
|
}, |
4435
|
|
|
|
|
|
|
ScaleFactor35efl => { #26/PH |
4436
|
|
|
|
|
|
|
Description => 'Scale Factor To 35 mm Equivalent', |
4437
|
|
|
|
|
|
|
Notes => q{ |
4438
|
|
|
|
|
|
|
this value and any derived values may be incorrect if the image has been |
4439
|
|
|
|
|
|
|
resized |
4440
|
|
|
|
|
|
|
}, |
4441
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
4442
|
|
|
|
|
|
|
Desire => { |
4443
|
|
|
|
|
|
|
0 => 'FocalLength', |
4444
|
|
|
|
|
|
|
1 => 'FocalLengthIn35mmFormat', |
4445
|
|
|
|
|
|
|
2 => 'Composite:DigitalZoom', |
4446
|
|
|
|
|
|
|
3 => 'FocalPlaneDiagonal', |
4447
|
|
|
|
|
|
|
4 => 'SensorSize', |
4448
|
|
|
|
|
|
|
5 => 'FocalPlaneXSize', |
4449
|
|
|
|
|
|
|
6 => 'FocalPlaneYSize', |
4450
|
|
|
|
|
|
|
7 => 'FocalPlaneResolutionUnit', |
4451
|
|
|
|
|
|
|
8 => 'FocalPlaneXResolution', |
4452
|
|
|
|
|
|
|
9 => 'FocalPlaneYResolution', |
4453
|
|
|
|
|
|
|
10 => 'ExifImageWidth', |
4454
|
|
|
|
|
|
|
11 => 'ExifImageHeight', |
4455
|
|
|
|
|
|
|
12 => 'CanonImageWidth', |
4456
|
|
|
|
|
|
|
13 => 'CanonImageHeight', |
4457
|
|
|
|
|
|
|
14 => 'ImageWidth', |
4458
|
|
|
|
|
|
|
15 => 'ImageHeight', |
4459
|
|
|
|
|
|
|
}, |
4460
|
|
|
|
|
|
|
ValueConv => 'Image::ExifTool::Exif::CalcScaleFactor35efl($self, @val)', |
4461
|
|
|
|
|
|
|
PrintConv => 'sprintf("%.1f", $val)', |
4462
|
|
|
|
|
|
|
}, |
4463
|
|
|
|
|
|
|
CircleOfConfusion => { |
4464
|
|
|
|
|
|
|
Notes => q{ |
4465
|
|
|
|
|
|
|
calculated as D/1440, where D is the focal plane diagonal in mm. This value |
4466
|
|
|
|
|
|
|
may be incorrect if the image has been resized |
4467
|
|
|
|
|
|
|
}, |
4468
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
4469
|
|
|
|
|
|
|
Require => 'ScaleFactor35efl', |
4470
|
|
|
|
|
|
|
ValueConv => 'sqrt(24*24+36*36) / ($val * 1440)', |
4471
|
|
|
|
|
|
|
PrintConv => 'sprintf("%.3f mm",$val)', |
4472
|
|
|
|
|
|
|
}, |
4473
|
|
|
|
|
|
|
HyperfocalDistance => { |
4474
|
|
|
|
|
|
|
Notes => 'this value may be incorrect if the image has been resized', |
4475
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
4476
|
|
|
|
|
|
|
Require => { |
4477
|
|
|
|
|
|
|
0 => 'FocalLength', |
4478
|
|
|
|
|
|
|
1 => 'Aperture', |
4479
|
|
|
|
|
|
|
2 => 'CircleOfConfusion', |
4480
|
|
|
|
|
|
|
}, |
4481
|
|
|
|
|
|
|
ValueConv => q{ |
4482
|
|
|
|
|
|
|
ToFloat(@val); |
4483
|
|
|
|
|
|
|
return 'inf' unless $val[1] and $val[2]; |
4484
|
|
|
|
|
|
|
return $val[0] * $val[0] / ($val[1] * $val[2] * 1000); |
4485
|
|
|
|
|
|
|
}, |
4486
|
|
|
|
|
|
|
PrintConv => 'sprintf("%.2f m", $val)', |
4487
|
|
|
|
|
|
|
}, |
4488
|
|
|
|
|
|
|
DOF => { |
4489
|
|
|
|
|
|
|
Description => 'Depth Of Field', |
4490
|
|
|
|
|
|
|
Notes => 'this value may be incorrect if the image has been resized', |
4491
|
|
|
|
|
|
|
Require => { |
4492
|
|
|
|
|
|
|
0 => 'FocalLength', |
4493
|
|
|
|
|
|
|
1 => 'Aperture', |
4494
|
|
|
|
|
|
|
2 => 'CircleOfConfusion', |
4495
|
|
|
|
|
|
|
}, |
4496
|
|
|
|
|
|
|
Desire => { |
4497
|
|
|
|
|
|
|
3 => 'FocusDistance', # focus distance in metres (0 is infinity) |
4498
|
|
|
|
|
|
|
4 => 'SubjectDistance', |
4499
|
|
|
|
|
|
|
5 => 'ObjectDistance', |
4500
|
|
|
|
|
|
|
6 => 'ApproximateFocusDistance', |
4501
|
|
|
|
|
|
|
7 => 'FocusDistanceLower', |
4502
|
|
|
|
|
|
|
8 => 'FocusDistanceUpper', |
4503
|
|
|
|
|
|
|
}, |
4504
|
|
|
|
|
|
|
ValueConv => q{ |
4505
|
|
|
|
|
|
|
ToFloat(@val); |
4506
|
|
|
|
|
|
|
my ($d, $f) = ($val[3], $val[0]); |
4507
|
|
|
|
|
|
|
if (defined $d) { |
4508
|
|
|
|
|
|
|
$d or $d = 1e10; # (use large number for infinity) |
4509
|
|
|
|
|
|
|
} else { |
4510
|
|
|
|
|
|
|
$d = $val[4] || $val[5] || $val[6]; |
4511
|
|
|
|
|
|
|
unless (defined $d) { |
4512
|
|
|
|
|
|
|
return undef unless defined $val[7] and defined $val[8]; |
4513
|
|
|
|
|
|
|
$d = ($val[7] + $val[8]) / 2; |
4514
|
|
|
|
|
|
|
} |
4515
|
|
|
|
|
|
|
} |
4516
|
|
|
|
|
|
|
return 0 unless $f and $val[2]; |
4517
|
|
|
|
|
|
|
my $t = $val[1] * $val[2] * ($d * 1000 - $f) / ($f * $f); |
4518
|
|
|
|
|
|
|
my @v = ($d / (1 + $t), $d / (1 - $t)); |
4519
|
|
|
|
|
|
|
$v[1] < 0 and $v[1] = 0; # 0 means 'inf' |
4520
|
|
|
|
|
|
|
return join(' ',@v); |
4521
|
|
|
|
|
|
|
}, |
4522
|
|
|
|
|
|
|
PrintConv => q{ |
4523
|
|
|
|
|
|
|
$val =~ tr/,/./; # in case locale is whacky |
4524
|
|
|
|
|
|
|
my @v = split ' ', $val; |
4525
|
|
|
|
|
|
|
$v[1] or return sprintf("inf (%.2f m - inf)", $v[0]); |
4526
|
|
|
|
|
|
|
my $dof = $v[1] - $v[0]; |
4527
|
|
|
|
|
|
|
my $fmt = ($dof>0 and $dof<0.02) ? "%.3f" : "%.2f"; |
4528
|
|
|
|
|
|
|
return sprintf("$fmt m ($fmt - $fmt m)",$dof,$v[0],$v[1]); |
4529
|
|
|
|
|
|
|
}, |
4530
|
|
|
|
|
|
|
}, |
4531
|
|
|
|
|
|
|
FOV => { |
4532
|
|
|
|
|
|
|
Description => 'Field Of View', |
4533
|
|
|
|
|
|
|
Notes => q{ |
4534
|
|
|
|
|
|
|
calculated for the long image dimension. This value may be incorrect for |
4535
|
|
|
|
|
|
|
fisheye lenses, or if the image has been resized |
4536
|
|
|
|
|
|
|
}, |
4537
|
|
|
|
|
|
|
Require => { |
4538
|
|
|
|
|
|
|
0 => 'FocalLength', |
4539
|
|
|
|
|
|
|
1 => 'ScaleFactor35efl', |
4540
|
|
|
|
|
|
|
}, |
4541
|
|
|
|
|
|
|
Desire => { |
4542
|
|
|
|
|
|
|
2 => 'FocusDistance', # (multiply by 1000 to convert to mm) |
4543
|
|
|
|
|
|
|
}, |
4544
|
|
|
|
|
|
|
# ref http://www.bobatkins.com/photography/technical/field_of_view.html |
4545
|
|
|
|
|
|
|
# (calculations below apply to rectilinear lenses only, not fisheye) |
4546
|
|
|
|
|
|
|
ValueConv => q{ |
4547
|
|
|
|
|
|
|
ToFloat(@val); |
4548
|
|
|
|
|
|
|
return undef unless $val[0] and $val[1]; |
4549
|
|
|
|
|
|
|
my $corr = 1; |
4550
|
|
|
|
|
|
|
if ($val[2]) { |
4551
|
|
|
|
|
|
|
my $d = 1000 * $val[2] - $val[0]; |
4552
|
|
|
|
|
|
|
$corr += $val[0]/$d if $d > 0; |
4553
|
|
|
|
|
|
|
} |
4554
|
|
|
|
|
|
|
my $fd2 = atan2(36, 2*$val[0]*$val[1]*$corr); |
4555
|
|
|
|
|
|
|
my @fov = ( $fd2 * 360 / 3.14159 ); |
4556
|
|
|
|
|
|
|
if ($val[2] and $val[2] > 0 and $val[2] < 10000) { |
4557
|
|
|
|
|
|
|
push @fov, 2 * $val[2] * sin($fd2) / cos($fd2); |
4558
|
|
|
|
|
|
|
} |
4559
|
|
|
|
|
|
|
return join(' ', @fov); |
4560
|
|
|
|
|
|
|
}, |
4561
|
|
|
|
|
|
|
PrintConv => q{ |
4562
|
|
|
|
|
|
|
my @v = split(' ',$val); |
4563
|
|
|
|
|
|
|
my $str = sprintf("%.1f deg", $v[0]); |
4564
|
|
|
|
|
|
|
$str .= sprintf(" (%.2f m)", $v[1]) if $v[1]; |
4565
|
|
|
|
|
|
|
return $str; |
4566
|
|
|
|
|
|
|
}, |
4567
|
|
|
|
|
|
|
}, |
4568
|
|
|
|
|
|
|
# generate DateTimeOriginal from Date and Time Created if not extracted already |
4569
|
|
|
|
|
|
|
DateTimeOriginal => { |
4570
|
|
|
|
|
|
|
Condition => 'not defined $$self{VALUE}{DateTimeOriginal}', |
4571
|
|
|
|
|
|
|
Description => 'Date/Time Original', |
4572
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
4573
|
|
|
|
|
|
|
Desire => { |
4574
|
|
|
|
|
|
|
0 => 'DateTimeCreated', |
4575
|
|
|
|
|
|
|
1 => 'DateCreated', |
4576
|
|
|
|
|
|
|
2 => 'TimeCreated', |
4577
|
|
|
|
|
|
|
}, |
4578
|
|
|
|
|
|
|
RawConv => '($val[1] and $val[2]) ? $val : undef', |
4579
|
|
|
|
|
|
|
ValueConv => q{ |
4580
|
|
|
|
|
|
|
return $val[0] if $val[0] and $val[0]=~/ /; |
4581
|
|
|
|
|
|
|
return "$val[1] $val[2]"; |
4582
|
|
|
|
|
|
|
}, |
4583
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
4584
|
|
|
|
|
|
|
}, |
4585
|
|
|
|
|
|
|
ThumbnailImage => { |
4586
|
|
|
|
|
|
|
Groups => { 0 => 'EXIF', 1 => 'IFD1', 2 => 'Preview' }, |
4587
|
|
|
|
|
|
|
Writable => 1, |
4588
|
|
|
|
|
|
|
WriteGroup => 'All', |
4589
|
|
|
|
|
|
|
WriteCheck => '$self->CheckImage(\$val)', |
4590
|
|
|
|
|
|
|
WriteAlso => { |
4591
|
|
|
|
|
|
|
# (the 0xfeedfeed values are translated in the Exif write routine) |
4592
|
|
|
|
|
|
|
ThumbnailOffset => 'defined $val ? 0xfeedfeed : undef', |
4593
|
|
|
|
|
|
|
ThumbnailLength => 'defined $val ? 0xfeedfeed : undef', |
4594
|
|
|
|
|
|
|
}, |
4595
|
|
|
|
|
|
|
Require => { |
4596
|
|
|
|
|
|
|
0 => 'ThumbnailOffset', |
4597
|
|
|
|
|
|
|
1 => 'ThumbnailLength', |
4598
|
|
|
|
|
|
|
}, |
4599
|
|
|
|
|
|
|
Notes => q{ |
4600
|
|
|
|
|
|
|
this tag is writable, and may be used to update existing thumbnails, but may |
4601
|
|
|
|
|
|
|
only create a thumbnail in IFD1 of certain types of files. Note that for |
4602
|
|
|
|
|
|
|
this and other Composite embedded-image tags the family 0 and 1 groups match |
4603
|
|
|
|
|
|
|
those of the originating tags |
4604
|
|
|
|
|
|
|
}, |
4605
|
|
|
|
|
|
|
# retrieve the thumbnail from our EXIF data |
4606
|
|
|
|
|
|
|
RawConv => q{ |
4607
|
|
|
|
|
|
|
@grps = $self->GetGroup($$val{0}); # set groups from ThumbnailOffsets |
4608
|
|
|
|
|
|
|
Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],"ThumbnailImage"); |
4609
|
|
|
|
|
|
|
}, |
4610
|
|
|
|
|
|
|
}, |
4611
|
|
|
|
|
|
|
ThumbnailTIFF => { |
4612
|
|
|
|
|
|
|
Groups => { 2 => 'Preview' }, |
4613
|
|
|
|
|
|
|
Require => { |
4614
|
|
|
|
|
|
|
0 => 'SubfileType', |
4615
|
|
|
|
|
|
|
1 => 'Compression', |
4616
|
|
|
|
|
|
|
2 => 'ImageWidth', |
4617
|
|
|
|
|
|
|
3 => 'ImageHeight', |
4618
|
|
|
|
|
|
|
4 => 'BitsPerSample', |
4619
|
|
|
|
|
|
|
5 => 'PhotometricInterpretation', |
4620
|
|
|
|
|
|
|
6 => 'StripOffsets', |
4621
|
|
|
|
|
|
|
7 => 'SamplesPerPixel', |
4622
|
|
|
|
|
|
|
8 => 'RowsPerStrip', |
4623
|
|
|
|
|
|
|
9 => 'StripByteCounts', |
4624
|
|
|
|
|
|
|
}, |
4625
|
|
|
|
|
|
|
Desire => { |
4626
|
|
|
|
|
|
|
10 => 'PlanarConfiguration', |
4627
|
|
|
|
|
|
|
11 => 'Orientation', |
4628
|
|
|
|
|
|
|
}, |
4629
|
|
|
|
|
|
|
# rebuild the TIFF thumbnail from our EXIF data |
4630
|
|
|
|
|
|
|
RawConv => q{ |
4631
|
|
|
|
|
|
|
my $tiff; |
4632
|
|
|
|
|
|
|
($tiff, @grps) = Image::ExifTool::Exif::RebuildTIFF($self, @val); |
4633
|
|
|
|
|
|
|
return $tiff; |
4634
|
|
|
|
|
|
|
}, |
4635
|
|
|
|
|
|
|
}, |
4636
|
|
|
|
|
|
|
PreviewImage => { |
4637
|
|
|
|
|
|
|
Groups => { 0 => 'EXIF', 1 => 'SubIFD', 2 => 'Preview' }, |
4638
|
|
|
|
|
|
|
Writable => 1, |
4639
|
|
|
|
|
|
|
WriteGroup => 'All', |
4640
|
|
|
|
|
|
|
WriteCheck => '$self->CheckImage(\$val)', |
4641
|
|
|
|
|
|
|
DelCheck => '$val = ""; return undef', # can't delete, so set to empty string |
4642
|
|
|
|
|
|
|
WriteAlso => { |
4643
|
|
|
|
|
|
|
PreviewImageStart => 'defined $val ? 0xfeedfeed : undef', |
4644
|
|
|
|
|
|
|
PreviewImageLength => 'defined $val ? 0xfeedfeed : undef', |
4645
|
|
|
|
|
|
|
PreviewImageValid => 'defined $val and length $val ? 1 : 0', # (for Olympus) |
4646
|
|
|
|
|
|
|
}, |
4647
|
|
|
|
|
|
|
Require => { |
4648
|
|
|
|
|
|
|
0 => 'PreviewImageStart', |
4649
|
|
|
|
|
|
|
1 => 'PreviewImageLength', |
4650
|
|
|
|
|
|
|
}, |
4651
|
|
|
|
|
|
|
Desire => { |
4652
|
|
|
|
|
|
|
2 => 'PreviewImageValid', |
4653
|
|
|
|
|
|
|
# (DNG and A100 ARW may be have 2 preview images) |
4654
|
|
|
|
|
|
|
3 => 'PreviewImageStart (1)', |
4655
|
|
|
|
|
|
|
4 => 'PreviewImageLength (1)', |
4656
|
|
|
|
|
|
|
}, |
4657
|
|
|
|
|
|
|
Notes => q{ |
4658
|
|
|
|
|
|
|
this tag is writable, and may be used to update existing embedded images, |
4659
|
|
|
|
|
|
|
but not create or delete them |
4660
|
|
|
|
|
|
|
}, |
4661
|
|
|
|
|
|
|
# note: extract 2nd preview, but ignore double-referenced preview |
4662
|
|
|
|
|
|
|
# (in A100 ARW images, the 2nd PreviewImageLength from IFD0 may be wrong anyway) |
4663
|
|
|
|
|
|
|
RawConv => q{ |
4664
|
|
|
|
|
|
|
if ($val[3] and $val[4] and $val[0] ne $val[3]) { |
4665
|
|
|
|
|
|
|
my %val = ( |
4666
|
|
|
|
|
|
|
0 => 'PreviewImageStart (1)', |
4667
|
|
|
|
|
|
|
1 => 'PreviewImageLength (1)', |
4668
|
|
|
|
|
|
|
2 => 'PreviewImageValid', |
4669
|
|
|
|
|
|
|
); |
4670
|
|
|
|
|
|
|
$self->FoundTag($tagInfo, \%val); |
4671
|
|
|
|
|
|
|
} |
4672
|
|
|
|
|
|
|
return undef if defined $val[2] and not $val[2]; |
4673
|
|
|
|
|
|
|
@grps = $self->GetGroup($$val{0}); |
4674
|
|
|
|
|
|
|
return Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],'PreviewImage'); |
4675
|
|
|
|
|
|
|
}, |
4676
|
|
|
|
|
|
|
}, |
4677
|
|
|
|
|
|
|
JpgFromRaw => { |
4678
|
|
|
|
|
|
|
Groups => { 0 => 'EXIF', 1 => 'SubIFD', 2 => 'Preview' }, |
4679
|
|
|
|
|
|
|
Writable => 1, |
4680
|
|
|
|
|
|
|
WriteGroup => 'All', |
4681
|
|
|
|
|
|
|
WriteCheck => '$self->CheckImage(\$val)', |
4682
|
|
|
|
|
|
|
# Note: ExifTool 10.38 had disabled the ability to delete this -- why? |
4683
|
|
|
|
|
|
|
# --> added the DelCheck in 10.61 to re-enable this |
4684
|
|
|
|
|
|
|
DelCheck => '$val = ""; return undef', # can't delete, so set to empty string |
4685
|
|
|
|
|
|
|
WriteAlso => { |
4686
|
|
|
|
|
|
|
JpgFromRawStart => 'defined $val ? 0xfeedfeed : undef', |
4687
|
|
|
|
|
|
|
JpgFromRawLength => 'defined $val ? 0xfeedfeed : undef', |
4688
|
|
|
|
|
|
|
}, |
4689
|
|
|
|
|
|
|
Require => { |
4690
|
|
|
|
|
|
|
0 => 'JpgFromRawStart', |
4691
|
|
|
|
|
|
|
1 => 'JpgFromRawLength', |
4692
|
|
|
|
|
|
|
}, |
4693
|
|
|
|
|
|
|
Notes => q{ |
4694
|
|
|
|
|
|
|
this tag is writable, and may be used to update existing embedded images, |
4695
|
|
|
|
|
|
|
but not create or delete them |
4696
|
|
|
|
|
|
|
}, |
4697
|
|
|
|
|
|
|
RawConv => q{ |
4698
|
|
|
|
|
|
|
@grps = $self->GetGroup($$val{0}); |
4699
|
|
|
|
|
|
|
return Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],"JpgFromRaw"); |
4700
|
|
|
|
|
|
|
}, |
4701
|
|
|
|
|
|
|
}, |
4702
|
|
|
|
|
|
|
OtherImage => { |
4703
|
|
|
|
|
|
|
Groups => { 0 => 'EXIF', 1 => 'SubIFD', 2 => 'Preview' }, |
4704
|
|
|
|
|
|
|
Writable => 1, |
4705
|
|
|
|
|
|
|
WriteGroup => 'All', |
4706
|
|
|
|
|
|
|
WriteCheck => '$self->CheckImage(\$val)', |
4707
|
|
|
|
|
|
|
DelCheck => '$val = ""; return undef', # can't delete, so set to empty string |
4708
|
|
|
|
|
|
|
WriteAlso => { |
4709
|
|
|
|
|
|
|
OtherImageStart => 'defined $val ? 0xfeedfeed : undef', |
4710
|
|
|
|
|
|
|
OtherImageLength => 'defined $val ? 0xfeedfeed : undef', |
4711
|
|
|
|
|
|
|
}, |
4712
|
|
|
|
|
|
|
Require => { |
4713
|
|
|
|
|
|
|
0 => 'OtherImageStart', |
4714
|
|
|
|
|
|
|
1 => 'OtherImageLength', |
4715
|
|
|
|
|
|
|
}, |
4716
|
|
|
|
|
|
|
Notes => q{ |
4717
|
|
|
|
|
|
|
this tag is writable, and may be used to update existing embedded images, |
4718
|
|
|
|
|
|
|
but not create or delete them |
4719
|
|
|
|
|
|
|
}, |
4720
|
|
|
|
|
|
|
# retrieve the thumbnail from our EXIF data |
4721
|
|
|
|
|
|
|
RawConv => q{ |
4722
|
|
|
|
|
|
|
@grps = $self->GetGroup($$val{0}); |
4723
|
|
|
|
|
|
|
Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],"OtherImage"); |
4724
|
|
|
|
|
|
|
}, |
4725
|
|
|
|
|
|
|
}, |
4726
|
|
|
|
|
|
|
PreviewImageSize => { |
4727
|
|
|
|
|
|
|
Require => { |
4728
|
|
|
|
|
|
|
0 => 'PreviewImageWidth', |
4729
|
|
|
|
|
|
|
1 => 'PreviewImageHeight', |
4730
|
|
|
|
|
|
|
}, |
4731
|
|
|
|
|
|
|
ValueConv => '"$val[0]x$val[1]"', |
4732
|
|
|
|
|
|
|
}, |
4733
|
|
|
|
|
|
|
SubSecDateTimeOriginal => { |
4734
|
|
|
|
|
|
|
Description => 'Date/Time Original', |
4735
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
4736
|
|
|
|
|
|
|
Writable => 1, |
4737
|
|
|
|
|
|
|
Shift => 0, # don't shift this tag |
4738
|
|
|
|
|
|
|
Require => { |
4739
|
|
|
|
|
|
|
0 => 'EXIF:DateTimeOriginal', |
4740
|
|
|
|
|
|
|
}, |
4741
|
|
|
|
|
|
|
Desire => { |
4742
|
|
|
|
|
|
|
1 => 'SubSecTimeOriginal', |
4743
|
|
|
|
|
|
|
2 => 'OffsetTimeOriginal', |
4744
|
|
|
|
|
|
|
}, |
4745
|
|
|
|
|
|
|
WriteAlso => { |
4746
|
|
|
|
|
|
|
'EXIF:DateTimeOriginal' => '($val and $val=~/^(\d{4}:\d{2}:\d{2} \d{2}:\d{2}:\d{2})/) ? $1 : undef', |
4747
|
|
|
|
|
|
|
'EXIF:SubSecTimeOriginal' => '($val and $val=~/\.(\d+)/) ? $1 : undef', |
4748
|
|
|
|
|
|
|
'EXIF:OffsetTimeOriginal' => '($val and $val=~/([-+]\d{2}:\d{2}|Z)$/) ? ($1 eq "Z" ? "+00:00" : $1) : undef', |
4749
|
|
|
|
|
|
|
}, |
4750
|
|
|
|
|
|
|
%subSecConv, |
4751
|
|
|
|
|
|
|
}, |
4752
|
|
|
|
|
|
|
SubSecCreateDate => { |
4753
|
|
|
|
|
|
|
Description => 'Create Date', |
4754
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
4755
|
|
|
|
|
|
|
Writable => 1, |
4756
|
|
|
|
|
|
|
Shift => 0, # don't shift this tag |
4757
|
|
|
|
|
|
|
Require => { |
4758
|
|
|
|
|
|
|
0 => 'EXIF:CreateDate', |
4759
|
|
|
|
|
|
|
}, |
4760
|
|
|
|
|
|
|
Desire => { |
4761
|
|
|
|
|
|
|
1 => 'SubSecTimeDigitized', |
4762
|
|
|
|
|
|
|
2 => 'OffsetTimeDigitized', |
4763
|
|
|
|
|
|
|
}, |
4764
|
|
|
|
|
|
|
WriteAlso => { |
4765
|
|
|
|
|
|
|
'EXIF:CreateDate' => '($val and $val=~/^(\d{4}:\d{2}:\d{2} \d{2}:\d{2}:\d{2})/) ? $1 : undef', |
4766
|
|
|
|
|
|
|
'EXIF:SubSecTimeDigitized' => '($val and $val=~/\.(\d+)/) ? $1 : undef', |
4767
|
|
|
|
|
|
|
'EXIF:OffsetTimeDigitized' => '($val and $val=~/([-+]\d{2}:\d{2}|Z)$/) ? ($1 eq "Z" ? "+00:00" : $1) : undef', |
4768
|
|
|
|
|
|
|
}, |
4769
|
|
|
|
|
|
|
%subSecConv, |
4770
|
|
|
|
|
|
|
}, |
4771
|
|
|
|
|
|
|
SubSecModifyDate => { |
4772
|
|
|
|
|
|
|
Description => 'Modify Date', |
4773
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
4774
|
|
|
|
|
|
|
Writable => 1, |
4775
|
|
|
|
|
|
|
Shift => 0, # don't shift this tag |
4776
|
|
|
|
|
|
|
Require => { |
4777
|
|
|
|
|
|
|
0 => 'EXIF:ModifyDate', |
4778
|
|
|
|
|
|
|
}, |
4779
|
|
|
|
|
|
|
Desire => { |
4780
|
|
|
|
|
|
|
1 => 'SubSecTime', |
4781
|
|
|
|
|
|
|
2 => 'OffsetTime', |
4782
|
|
|
|
|
|
|
}, |
4783
|
|
|
|
|
|
|
WriteAlso => { |
4784
|
|
|
|
|
|
|
'EXIF:ModifyDate' => '($val and $val=~/^(\d{4}:\d{2}:\d{2} \d{2}:\d{2}:\d{2})/) ? $1 : undef', |
4785
|
|
|
|
|
|
|
'EXIF:SubSecTime' => '($val and $val=~/\.(\d+)/) ? $1 : undef', |
4786
|
|
|
|
|
|
|
'EXIF:OffsetTime' => '($val and $val=~/([-+]\d{2}:\d{2}|Z)$/) ? ($1 eq "Z" ? "+00:00" : $1) : undef', |
4787
|
|
|
|
|
|
|
}, |
4788
|
|
|
|
|
|
|
%subSecConv, |
4789
|
|
|
|
|
|
|
}, |
4790
|
|
|
|
|
|
|
CFAPattern => { |
4791
|
|
|
|
|
|
|
Require => { |
4792
|
|
|
|
|
|
|
0 => 'CFARepeatPatternDim', |
4793
|
|
|
|
|
|
|
1 => 'CFAPattern2', |
4794
|
|
|
|
|
|
|
}, |
4795
|
|
|
|
|
|
|
# generate CFAPattern |
4796
|
|
|
|
|
|
|
ValueConv => q{ |
4797
|
|
|
|
|
|
|
my @a = split / /, $val[0]; |
4798
|
|
|
|
|
|
|
my @b = split / /, $val[1]; |
4799
|
|
|
|
|
|
|
return '?' unless @a==2 and @b==$a[0]*$a[1]; |
4800
|
|
|
|
|
|
|
return "$a[0] $a[1] @b"; |
4801
|
|
|
|
|
|
|
}, |
4802
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::Exif::PrintCFAPattern($val)', |
4803
|
|
|
|
|
|
|
}, |
4804
|
|
|
|
|
|
|
RedBalance => { |
4805
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
4806
|
|
|
|
|
|
|
Desire => { |
4807
|
|
|
|
|
|
|
0 => 'WB_RGGBLevels', |
4808
|
|
|
|
|
|
|
1 => 'WB_RGBGLevels', |
4809
|
|
|
|
|
|
|
2 => 'WB_RBGGLevels', |
4810
|
|
|
|
|
|
|
3 => 'WB_GRBGLevels', |
4811
|
|
|
|
|
|
|
4 => 'WB_GRGBLevels', |
4812
|
|
|
|
|
|
|
5 => 'WB_GBRGLevels', |
4813
|
|
|
|
|
|
|
6 => 'WB_RGBLevels', |
4814
|
|
|
|
|
|
|
7 => 'WB_GRBLevels', |
4815
|
|
|
|
|
|
|
8 => 'WB_RBLevels', |
4816
|
|
|
|
|
|
|
9 => 'WBRedLevel', # red |
4817
|
|
|
|
|
|
|
10 => 'WBGreenLevel', |
4818
|
|
|
|
|
|
|
}, |
4819
|
|
|
|
|
|
|
ValueConv => 'Image::ExifTool::Exif::RedBlueBalance(0,@val)', |
4820
|
|
|
|
|
|
|
PrintConv => 'int($val * 1e6 + 0.5) * 1e-6', |
4821
|
|
|
|
|
|
|
}, |
4822
|
|
|
|
|
|
|
BlueBalance => { |
4823
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
4824
|
|
|
|
|
|
|
Desire => { |
4825
|
|
|
|
|
|
|
0 => 'WB_RGGBLevels', |
4826
|
|
|
|
|
|
|
1 => 'WB_RGBGLevels', |
4827
|
|
|
|
|
|
|
2 => 'WB_RBGGLevels', |
4828
|
|
|
|
|
|
|
3 => 'WB_GRBGLevels', |
4829
|
|
|
|
|
|
|
4 => 'WB_GRGBLevels', |
4830
|
|
|
|
|
|
|
5 => 'WB_GBRGLevels', |
4831
|
|
|
|
|
|
|
6 => 'WB_RGBLevels', |
4832
|
|
|
|
|
|
|
7 => 'WB_GRBLevels', |
4833
|
|
|
|
|
|
|
8 => 'WB_RBLevels', |
4834
|
|
|
|
|
|
|
9 => 'WBBlueLevel', # blue |
4835
|
|
|
|
|
|
|
10 => 'WBGreenLevel', |
4836
|
|
|
|
|
|
|
}, |
4837
|
|
|
|
|
|
|
ValueConv => 'Image::ExifTool::Exif::RedBlueBalance(1,@val)', |
4838
|
|
|
|
|
|
|
PrintConv => 'int($val * 1e6 + 0.5) * 1e-6', |
4839
|
|
|
|
|
|
|
}, |
4840
|
|
|
|
|
|
|
GPSPosition => { |
4841
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
4842
|
|
|
|
|
|
|
Writable => 1, |
4843
|
|
|
|
|
|
|
Protected => 1, |
4844
|
|
|
|
|
|
|
WriteAlso => { |
4845
|
|
|
|
|
|
|
GPSLatitude => '$val =~ /(.*?)( ?[NS])?,/ ? $1 : undef', |
4846
|
|
|
|
|
|
|
GPSLatitudeRef => '$val =~ /(-?)(.*?) ?([NS]?),/ ? ($3 || ($1 ? "S" : "N")) : undef', |
4847
|
|
|
|
|
|
|
GPSLongitude => '$val =~ /, ?(.*?)( ?[EW]?)$/ ? $1 : undef', |
4848
|
|
|
|
|
|
|
GPSLongitudeRef => '$val =~ /, ?(-?)(.*?) ?([EW]?)$/ ? ($3 || ($1 ? "W" : "E")) : undef', |
4849
|
|
|
|
|
|
|
}, |
4850
|
|
|
|
|
|
|
PrintConvInv => q{ |
4851
|
|
|
|
|
|
|
return undef unless $val =~ /(.*? ?[NS]?), ?(.*? ?[EW]?)$/; |
4852
|
|
|
|
|
|
|
my ($lat, $lon) = ($1, $2); |
4853
|
|
|
|
|
|
|
require Image::ExifTool::GPS; |
4854
|
|
|
|
|
|
|
$lat = Image::ExifTool::GPS::ToDegrees($lat, 1, "lat"); |
4855
|
|
|
|
|
|
|
$lon = Image::ExifTool::GPS::ToDegrees($lon, 1, "lon"); |
4856
|
|
|
|
|
|
|
return "$lat, $lon"; |
4857
|
|
|
|
|
|
|
}, |
4858
|
|
|
|
|
|
|
Require => { |
4859
|
|
|
|
|
|
|
0 => 'GPSLatitude', |
4860
|
|
|
|
|
|
|
1 => 'GPSLongitude', |
4861
|
|
|
|
|
|
|
}, |
4862
|
|
|
|
|
|
|
Priority => 0, |
4863
|
|
|
|
|
|
|
Notes => q{ |
4864
|
|
|
|
|
|
|
when written, writes GPSLatitude, GPSLatitudeRef, GPSLongitude and |
4865
|
|
|
|
|
|
|
GPSLongitudeRef. This tag may be written using the same coordinate |
4866
|
|
|
|
|
|
|
format as provided by Google Maps when right-clicking on a location |
4867
|
|
|
|
|
|
|
}, |
4868
|
|
|
|
|
|
|
ValueConv => '(length($val[0]) or length($val[1])) ? "$val[0] $val[1]" : undef', |
4869
|
|
|
|
|
|
|
PrintConv => '"$prt[0], $prt[1]"', |
4870
|
|
|
|
|
|
|
}, |
4871
|
|
|
|
|
|
|
LensID => { |
4872
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
4873
|
|
|
|
|
|
|
Require => 'LensType', |
4874
|
|
|
|
|
|
|
Desire => { |
4875
|
|
|
|
|
|
|
1 => 'FocalLength', |
4876
|
|
|
|
|
|
|
2 => 'MaxAperture', |
4877
|
|
|
|
|
|
|
3 => 'MaxApertureValue', |
4878
|
|
|
|
|
|
|
4 => 'MinFocalLength', |
4879
|
|
|
|
|
|
|
5 => 'MaxFocalLength', |
4880
|
|
|
|
|
|
|
6 => 'LensModel', |
4881
|
|
|
|
|
|
|
7 => 'LensFocalRange', |
4882
|
|
|
|
|
|
|
8 => 'LensSpec', |
4883
|
|
|
|
|
|
|
9 => 'LensType2', |
4884
|
|
|
|
|
|
|
10 => 'LensType3', |
4885
|
|
|
|
|
|
|
11 => 'LensFocalLength', # (for Pentax to check for converter) |
4886
|
|
|
|
|
|
|
12 => 'RFLensType', |
4887
|
|
|
|
|
|
|
}, |
4888
|
|
|
|
|
|
|
Notes => q{ |
4889
|
|
|
|
|
|
|
attempt to identify the actual lens from all lenses with a given LensType. |
4890
|
|
|
|
|
|
|
Applies only to LensType values with a lookup table. May be configured |
4891
|
|
|
|
|
|
|
by adding user-defined lenses |
4892
|
|
|
|
|
|
|
}, |
4893
|
|
|
|
|
|
|
# this LensID is only valid if the LensType has a PrintConv or is a model name |
4894
|
|
|
|
|
|
|
RawConv => q{ |
4895
|
|
|
|
|
|
|
my $printConv = $$self{TAG_INFO}{LensType}{PrintConv}; |
4896
|
|
|
|
|
|
|
return $val if ref $printConv eq 'HASH' or (ref $printConv eq 'ARRAY' and |
4897
|
|
|
|
|
|
|
ref $$printConv[0] eq 'HASH') or $val[0] =~ /(mm|\d\/F)/; |
4898
|
|
|
|
|
|
|
return undef; |
4899
|
|
|
|
|
|
|
}, |
4900
|
|
|
|
|
|
|
ValueConv => '$val', |
4901
|
|
|
|
|
|
|
PrintConv => q{ |
4902
|
|
|
|
|
|
|
my $pcv; |
4903
|
|
|
|
|
|
|
# use LensType2 instead of LensType if available and valid (Sony E-mount lenses) |
4904
|
|
|
|
|
|
|
# (0x8000 or greater; 0 for several older/3rd-party E-mount lenses) |
4905
|
|
|
|
|
|
|
if (defined $val[9] and ($val[9] & 0x8000 or $val[9] == 0)) { |
4906
|
|
|
|
|
|
|
$val[0] = $val[9]; |
4907
|
|
|
|
|
|
|
$prt[0] = $prt[9]; |
4908
|
|
|
|
|
|
|
# Particularly GM lenses: often LensType2=0 but LensType3 is available and valid: use LensType3. |
4909
|
|
|
|
|
|
|
if ($val[9] == 0 and $val[10] & 0x8000) { |
4910
|
|
|
|
|
|
|
$val[0] = $val[10]; |
4911
|
|
|
|
|
|
|
$prt[0] = $prt[10]; |
4912
|
|
|
|
|
|
|
} |
4913
|
|
|
|
|
|
|
$pcv = $$self{TAG_INFO}{LensType2}{PrintConv}; |
4914
|
|
|
|
|
|
|
} |
4915
|
|
|
|
|
|
|
# use Canon RFLensType if available |
4916
|
|
|
|
|
|
|
if ($val[12]) { |
4917
|
|
|
|
|
|
|
$val[0] = $val[12]; |
4918
|
|
|
|
|
|
|
$prt[0] = $prt[12]; |
4919
|
|
|
|
|
|
|
$pcv = $$self{TAG_INFO}{RFLensType}{PrintConv}; |
4920
|
|
|
|
|
|
|
} |
4921
|
|
|
|
|
|
|
my $lens = Image::ExifTool::Exif::PrintLensID($self, $prt[0], $pcv, $prt[8], @val); |
4922
|
|
|
|
|
|
|
# check for use of lens converter (Pentax K-3) |
4923
|
|
|
|
|
|
|
if ($val[11] and $val[1] and $lens) { |
4924
|
|
|
|
|
|
|
my $conv = $val[1] / $val[11]; |
4925
|
|
|
|
|
|
|
$lens .= sprintf(' + %.1fx converter', $conv) if $conv > 1.1; |
4926
|
|
|
|
|
|
|
} |
4927
|
|
|
|
|
|
|
return $lens; |
4928
|
|
|
|
|
|
|
}, |
4929
|
|
|
|
|
|
|
}, |
4930
|
|
|
|
|
|
|
'LensID-2' => { |
4931
|
|
|
|
|
|
|
Name => 'LensID', |
4932
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
4933
|
|
|
|
|
|
|
Desire => { |
4934
|
|
|
|
|
|
|
0 => 'LensModel', |
4935
|
|
|
|
|
|
|
1 => 'Lens', |
4936
|
|
|
|
|
|
|
2 => 'XMP-aux:LensID', |
4937
|
|
|
|
|
|
|
3 => 'Make', |
4938
|
|
|
|
|
|
|
}, |
4939
|
|
|
|
|
|
|
Inhibit => { |
4940
|
|
|
|
|
|
|
4 => 'Composite:LensID', |
4941
|
|
|
|
|
|
|
}, |
4942
|
|
|
|
|
|
|
RawConv => q{ |
4943
|
|
|
|
|
|
|
return undef if defined $val[2] and defined $val[3]; |
4944
|
|
|
|
|
|
|
return $val if defined $val[0] and $val[0] =~ /(mm|\d\/F)/; |
4945
|
|
|
|
|
|
|
return $val if defined $val[1] and $val[1] =~ /(mm|\d\/F)/; |
4946
|
|
|
|
|
|
|
return undef; |
4947
|
|
|
|
|
|
|
}, |
4948
|
|
|
|
|
|
|
ValueConv => q{ |
4949
|
|
|
|
|
|
|
return $val[0] if defined $val[0] and $val[0] =~ /(mm|\d\/F)/; |
4950
|
|
|
|
|
|
|
return $val[1]; |
4951
|
|
|
|
|
|
|
}, |
4952
|
|
|
|
|
|
|
PrintConv => '$_=$val; s/(\d)\/F/$1mm F/; s/mmF/mm F/; s/(\d) mm/${1}mm/; s/ - /-/; $_', |
4953
|
|
|
|
|
|
|
}, |
4954
|
|
|
|
|
|
|
); |
4955
|
|
|
|
|
|
|
|
4956
|
|
|
|
|
|
|
# table for unknown IFD entries |
4957
|
|
|
|
|
|
|
%Image::ExifTool::Exif::Unknown = ( |
4958
|
|
|
|
|
|
|
GROUPS => { 0 => 'EXIF', 1 => 'UnknownIFD', 2 => 'Image'}, |
4959
|
|
|
|
|
|
|
WRITE_PROC => \&WriteExif, |
4960
|
|
|
|
|
|
|
); |
4961
|
|
|
|
|
|
|
|
4962
|
|
|
|
|
|
|
# add our composite tags |
4963
|
|
|
|
|
|
|
Image::ExifTool::AddCompositeTags('Image::ExifTool::Exif'); |
4964
|
|
|
|
|
|
|
|
4965
|
|
|
|
|
|
|
|
4966
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
4967
|
|
|
|
|
|
|
# AutoLoad our writer routines when necessary |
4968
|
|
|
|
|
|
|
# |
4969
|
|
|
|
|
|
|
sub AUTOLOAD |
4970
|
|
|
|
|
|
|
{ |
4971
|
40
|
|
|
40
|
|
255
|
return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_); |
4972
|
|
|
|
|
|
|
} |
4973
|
|
|
|
|
|
|
|
4974
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
4975
|
|
|
|
|
|
|
# Identify RAW file type for some TIFF-based formats using Compression value |
4976
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object reference, 1) Compression value |
4977
|
|
|
|
|
|
|
# - sets TIFF_TYPE and FileType if identified |
4978
|
|
|
|
|
|
|
sub IdentifyRawFile($$) |
4979
|
|
|
|
|
|
|
{ |
4980
|
270
|
|
|
270
|
0
|
919
|
my ($et, $comp) = @_; |
4981
|
270
|
100
|
66
|
|
|
4481
|
if ($$et{FILE_TYPE} eq 'TIFF' and not $$et{IdentifiedRawFile}) { |
4982
|
71
|
100
|
66
|
|
|
1604
|
if ($compression{$comp} and $compression{$comp} =~ /^\w+ ([A-Z]{3}) Compressed$/) { |
4983
|
3
|
|
|
|
|
23
|
$et->OverrideFileType($$et{TIFF_TYPE} = $1); |
4984
|
3
|
|
|
|
|
56
|
$$et{IdentifiedRawFile} = 1; |
4985
|
|
|
|
|
|
|
} |
4986
|
|
|
|
|
|
|
} |
4987
|
|
|
|
|
|
|
} |
4988
|
|
|
|
|
|
|
|
4989
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
4990
|
|
|
|
|
|
|
# Calculate LV (Light Value) |
4991
|
|
|
|
|
|
|
# Inputs: 0) Aperture, 1) ShutterSpeed, 2) ISO |
4992
|
|
|
|
|
|
|
# Returns: LV value (and converts input values to floating point if necessary) |
4993
|
|
|
|
|
|
|
sub CalculateLV($$$) |
4994
|
|
|
|
|
|
|
{ |
4995
|
126
|
|
|
126
|
0
|
341
|
local $_; |
4996
|
|
|
|
|
|
|
# do validity checks on arguments |
4997
|
126
|
50
|
|
|
|
487
|
return undef unless @_ >= 3; |
4998
|
126
|
|
|
|
|
395
|
foreach (@_) { |
4999
|
378
|
50
|
66
|
|
|
3112
|
return undef unless $_ and /([+-]?(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?)/ and $1 > 0; |
|
|
|
66
|
|
|
|
|
5000
|
373
|
|
|
|
|
874
|
$_ = $1; # extract float from any other garbage |
5001
|
|
|
|
|
|
|
} |
5002
|
|
|
|
|
|
|
# (A light value of 0 is defined as f/1.0 at 1 second with ISO 100) |
5003
|
121
|
|
|
|
|
1497
|
return log($_[0] * $_[0] * 100 / ($_[1] * $_[2])) / log(2); |
5004
|
|
|
|
|
|
|
} |
5005
|
|
|
|
|
|
|
|
5006
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5007
|
|
|
|
|
|
|
# Calculate scale factor for 35mm effective focal length (ref 26/PH) |
5008
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object ref |
5009
|
|
|
|
|
|
|
# 1) Focal length |
5010
|
|
|
|
|
|
|
# 2) Focal length in 35mm format |
5011
|
|
|
|
|
|
|
# 3) Canon digital zoom factor |
5012
|
|
|
|
|
|
|
# 4) Focal plane diagonal size (in mm) |
5013
|
|
|
|
|
|
|
# 5) Sensor size (X and Y in mm) |
5014
|
|
|
|
|
|
|
# 6/7) Focal plane X/Y size (in mm) |
5015
|
|
|
|
|
|
|
# 8) focal plane resolution units (1=None,2=inches,3=cm,4=mm,5=um) |
5016
|
|
|
|
|
|
|
# 9/10) Focal plane X/Y resolution |
5017
|
|
|
|
|
|
|
# 11/12,13/14...) Image width/height in order of precedence (first valid pair is used) |
5018
|
|
|
|
|
|
|
# Returns: 35mm conversion factor (or undefined if it can't be calculated) |
5019
|
|
|
|
|
|
|
sub CalcScaleFactor35efl |
5020
|
|
|
|
|
|
|
{ |
5021
|
548
|
|
|
548
|
0
|
1163
|
my $et = shift; |
5022
|
548
|
|
|
|
|
899
|
my $res = $_[7]; # save resolution units (in case they have been converted to string) |
5023
|
548
|
|
|
|
|
772
|
my $sensXY = $_[4]; |
5024
|
548
|
|
|
|
|
1915
|
Image::ExifTool::ToFloat(@_); |
5025
|
548
|
|
|
|
|
857
|
my $focal = shift; |
5026
|
548
|
|
|
|
|
810
|
my $foc35 = shift; |
5027
|
|
|
|
|
|
|
|
5028
|
548
|
100
|
100
|
|
|
2180
|
return $foc35 / $focal if $focal and $foc35; |
5029
|
|
|
|
|
|
|
|
5030
|
517
|
|
50
|
|
|
1712
|
my $digz = shift || 1; |
5031
|
517
|
|
|
|
|
751
|
my $diag = shift; |
5032
|
517
|
|
|
|
|
831
|
my $sens = shift; |
5033
|
|
|
|
|
|
|
# calculate Canon sensor size using a dedicated algorithm |
5034
|
517
|
100
|
|
|
|
1455
|
if ($$et{Make} eq 'Canon') { |
5035
|
51
|
|
|
|
|
3341
|
require Image::ExifTool::Canon; |
5036
|
|
|
|
|
|
|
my $canonDiag = Image::ExifTool::Canon::CalcSensorDiag( |
5037
|
|
|
|
|
|
|
$$et{RATIONAL}{FocalPlaneXResolution}, |
5038
|
|
|
|
|
|
|
$$et{RATIONAL}{FocalPlaneYResolution}, |
5039
|
51
|
|
|
|
|
454
|
); |
5040
|
51
|
100
|
|
|
|
175
|
$diag = $canonDiag if $canonDiag; |
5041
|
|
|
|
|
|
|
} |
5042
|
517
|
100
|
66
|
|
|
1671
|
unless ($diag and Image::ExifTool::IsFloat($diag)) { |
5043
|
483
|
50
|
33
|
|
|
1329
|
if ($sens and $sensXY =~ / (\d+(\.?\d*)?)$/) { |
5044
|
0
|
|
|
|
|
0
|
$diag = sqrt($sens * $sens + $1 * $1); |
5045
|
|
|
|
|
|
|
} else { |
5046
|
483
|
|
|
|
|
736
|
undef $diag; |
5047
|
483
|
|
|
|
|
2026
|
my $xsize = shift; |
5048
|
483
|
|
|
|
|
642
|
my $ysize = shift; |
5049
|
483
|
100
|
66
|
|
|
1306
|
if ($xsize and $ysize) { |
5050
|
|
|
|
|
|
|
# validate by checking aspect ratio because FocalPlaneX/YSize is not reliable |
5051
|
16
|
|
|
|
|
43
|
my $a = $xsize / $ysize; |
5052
|
16
|
50
|
66
|
|
|
95
|
if (abs($a-1.3333) < .1 or abs($a-1.5) < .1) { |
5053
|
16
|
|
|
|
|
100
|
$diag = sqrt($xsize * $xsize + $ysize * $ysize); |
5054
|
|
|
|
|
|
|
} |
5055
|
|
|
|
|
|
|
} |
5056
|
|
|
|
|
|
|
} |
5057
|
483
|
100
|
|
|
|
1018
|
unless ($diag) { |
5058
|
|
|
|
|
|
|
# get number of mm in units (assume inches unless otherwise specified) |
5059
|
467
|
|
|
|
|
2421
|
my %lkup = ( 3=>10, 4=>1, 5=>0.001 , cm=>10, mm=>1, um=>0.001 ); |
5060
|
467
|
|
100
|
|
|
2801
|
my $units = $lkup{ shift() || $res || '' } || 25.4; |
5061
|
467
|
|
100
|
|
|
3825
|
my $x_res = shift || return undef; |
5062
|
123
|
|
66
|
|
|
270
|
my $y_res = shift || $x_res; |
5063
|
123
|
50
|
33
|
|
|
336
|
Image::ExifTool::IsFloat($x_res) and $x_res != 0 or return undef; |
5064
|
123
|
50
|
33
|
|
|
293
|
Image::ExifTool::IsFloat($y_res) and $y_res != 0 or return undef; |
5065
|
123
|
|
|
|
|
245
|
my ($w, $h); |
5066
|
123
|
|
|
|
|
180
|
for (;;) { |
5067
|
125
|
50
|
|
|
|
294
|
@_ < 2 and return undef; |
5068
|
125
|
|
|
|
|
211
|
$w = shift; |
5069
|
125
|
|
|
|
|
190
|
$h = shift; |
5070
|
125
|
100
|
66
|
|
|
439
|
next unless $w and $h; |
5071
|
123
|
|
|
|
|
244
|
my $a = $w / $h; |
5072
|
123
|
50
|
33
|
|
|
454
|
last if $a > 0.5 and $a < 2; # stop if we get a reasonable value |
5073
|
|
|
|
|
|
|
} |
5074
|
|
|
|
|
|
|
# calculate focal plane size in mm |
5075
|
123
|
|
|
|
|
223
|
$w *= $units / $x_res; |
5076
|
123
|
|
|
|
|
191
|
$h *= $units / $y_res; |
5077
|
123
|
|
|
|
|
242
|
$diag = sqrt($w*$w+$h*$h); |
5078
|
|
|
|
|
|
|
# make sure size is reasonable |
5079
|
123
|
100
|
100
|
|
|
1231
|
return undef unless $diag > 1 and $diag < 100; |
5080
|
|
|
|
|
|
|
} |
5081
|
|
|
|
|
|
|
} |
5082
|
57
|
|
|
|
|
512
|
return sqrt(36*36+24*24) * $digz / $diag; |
5083
|
|
|
|
|
|
|
} |
5084
|
|
|
|
|
|
|
|
5085
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5086
|
|
|
|
|
|
|
# Print exposure compensation fraction |
5087
|
|
|
|
|
|
|
sub PrintFraction($) |
5088
|
|
|
|
|
|
|
{ |
5089
|
286
|
|
|
286
|
0
|
753
|
my $val = shift; |
5090
|
286
|
|
|
|
|
573
|
my $str; |
5091
|
286
|
50
|
|
|
|
802
|
if (defined $val) { |
5092
|
286
|
|
|
|
|
734
|
$val *= 1.00001; # avoid round-off errors |
5093
|
286
|
100
|
|
|
|
925
|
if (not $val) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
5094
|
258
|
|
|
|
|
522
|
$str = '0'; |
5095
|
|
|
|
|
|
|
} elsif (int($val)/$val > 0.999) { |
5096
|
5
|
|
|
|
|
22
|
$str = sprintf("%+d", int($val)); |
5097
|
|
|
|
|
|
|
} elsif ((int($val*2))/($val*2) > 0.999) { |
5098
|
0
|
|
|
|
|
0
|
$str = sprintf("%+d/2", int($val * 2)); |
5099
|
|
|
|
|
|
|
} elsif ((int($val*3))/($val*3) > 0.999) { |
5100
|
10
|
|
|
|
|
41
|
$str = sprintf("%+d/3", int($val * 3)); |
5101
|
|
|
|
|
|
|
} else { |
5102
|
13
|
|
|
|
|
92
|
$str = sprintf("%+.3g", $val); |
5103
|
|
|
|
|
|
|
} |
5104
|
|
|
|
|
|
|
} |
5105
|
286
|
|
|
|
|
1738
|
return $str; |
5106
|
|
|
|
|
|
|
} |
5107
|
|
|
|
|
|
|
|
5108
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5109
|
|
|
|
|
|
|
# Convert fraction or number to floating point value (or 'undef' or 'inf') |
5110
|
|
|
|
|
|
|
sub ConvertFraction($) |
5111
|
|
|
|
|
|
|
{ |
5112
|
1167
|
|
|
1167
|
0
|
2366
|
my $val = shift; |
5113
|
1167
|
100
|
|
|
|
3440
|
if ($val =~ m{([-+]?\d+)/(\d+)}) { |
5114
|
436
|
0
|
|
|
|
1742
|
$val = $2 ? $1 / $2 : ($1 ? 'inf' : 'undef'); |
|
|
50
|
|
|
|
|
|
5115
|
|
|
|
|
|
|
} |
5116
|
1167
|
|
|
|
|
7077
|
return $val; |
5117
|
|
|
|
|
|
|
} |
5118
|
|
|
|
|
|
|
|
5119
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5120
|
|
|
|
|
|
|
# Convert EXIF text to something readable |
5121
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object reference, 1) EXIF text, |
5122
|
|
|
|
|
|
|
# 2) [optional] 1 to apply CharsetEXIF to ASCII text, |
5123
|
|
|
|
|
|
|
# 3) tag name for warning message (may be argument 2) |
5124
|
|
|
|
|
|
|
# Returns: text encoded according to Charset option (with trailing spaces removed) |
5125
|
|
|
|
|
|
|
sub ConvertExifText($$;$$) |
5126
|
|
|
|
|
|
|
{ |
5127
|
85
|
|
|
85
|
0
|
382
|
my ($et, $val, $asciiFlex, $tag) = @_; |
5128
|
85
|
50
|
|
|
|
329
|
return $val if length($val) < 8; |
5129
|
85
|
|
|
|
|
250
|
my $id = substr($val, 0, 8); |
5130
|
85
|
|
|
|
|
237
|
my $str = substr($val, 8); |
5131
|
85
|
|
|
|
|
147
|
my $type; |
5132
|
|
|
|
|
|
|
|
5133
|
85
|
|
|
|
|
202
|
delete $$et{WrongByteOrder}; |
5134
|
85
|
50
|
66
|
|
|
436
|
if ($$et{OPTIONS}{Validate} and $id =~ /^(ASCII|UNICODE|JIS)?\0* \0*$/) { |
5135
|
0
|
0
|
0
|
|
|
0
|
$et->Warn(($1 || 'Undefined') . ' text header' . ($tag ? " for $tag" : '') . ' has spaces instead of nulls'); |
5136
|
|
|
|
|
|
|
} |
5137
|
|
|
|
|
|
|
# Note: allow spaces instead of nulls in the ID codes because |
5138
|
|
|
|
|
|
|
# it is fairly common for camera manufacturers to get this wrong |
5139
|
|
|
|
|
|
|
# (also handle Canon ZoomBrowser EX 4.5 null followed by 7 bytes of garbage) |
5140
|
85
|
50
|
|
|
|
491
|
if ($id =~ /^(ASCII)?(\0|[\0 ]+$)/) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
5141
|
|
|
|
|
|
|
# truncate at null terminator (shouldn't have a null based on the |
5142
|
|
|
|
|
|
|
# EXIF spec, but it seems that few people actually read the spec) |
5143
|
85
|
|
|
|
|
367
|
$str =~ s/\0.*//s; |
5144
|
|
|
|
|
|
|
# allow ASCII text to contain any other specified encoding |
5145
|
85
|
100
|
66
|
|
|
529
|
if ($asciiFlex and $asciiFlex eq '1') { |
5146
|
84
|
|
|
|
|
329
|
my $enc = $et->Options('CharsetEXIF'); |
5147
|
84
|
50
|
|
|
|
306
|
$str = $et->Decode($str, $enc) if $enc; |
5148
|
|
|
|
|
|
|
} |
5149
|
|
|
|
|
|
|
# by the EXIF spec, the following string should be "UNICODE\0", but |
5150
|
|
|
|
|
|
|
# apparently Kodak sometimes uses "Unicode\0" in the APP3 "Meta" information. |
5151
|
|
|
|
|
|
|
# However, unfortunately Ricoh uses "Unicode\0" in the RR30 EXIF UserComment |
5152
|
|
|
|
|
|
|
# when the text is actually ASCII, so only recognize uppercase "UNICODE\0". |
5153
|
|
|
|
|
|
|
} elsif ($id =~ /^(UNICODE)[\0 ]$/) { |
5154
|
0
|
|
|
|
|
0
|
$type = $1; |
5155
|
|
|
|
|
|
|
# MicrosoftPhoto writes as little-endian even in big-endian EXIF, |
5156
|
|
|
|
|
|
|
# so we must guess at the true byte ordering |
5157
|
0
|
|
|
|
|
0
|
$str = $et->Decode($str, 'UTF16', 'Unknown'); |
5158
|
|
|
|
|
|
|
} elsif ($id =~ /^(JIS)[\0 ]{5}$/) { |
5159
|
0
|
|
|
|
|
0
|
$type = $1; |
5160
|
0
|
|
|
|
|
0
|
$str = $et->Decode($str, 'JIS', 'Unknown'); |
5161
|
|
|
|
|
|
|
} else { |
5162
|
0
|
0
|
0
|
|
|
0
|
$tag = $asciiFlex if $asciiFlex and $asciiFlex ne '1'; |
5163
|
0
|
0
|
|
|
|
0
|
$et->Warn('Invalid EXIF text encoding' . ($tag ? " for $tag" : '')); |
5164
|
0
|
|
|
|
|
0
|
$str = $id . $str; |
5165
|
|
|
|
|
|
|
} |
5166
|
85
|
0
|
33
|
|
|
295
|
if ($$et{WrongByteOrder} and $$et{OPTIONS}{Validate}) { |
5167
|
0
|
0
|
|
|
|
0
|
$et->Warn('Wrong byte order for EXIF' . ($tag ? " $tag" : '') . |
|
|
0
|
|
|
|
|
|
5168
|
|
|
|
|
|
|
($type ? " $type" : '') . ' text'); |
5169
|
|
|
|
|
|
|
} |
5170
|
85
|
|
|
|
|
220
|
$str =~ s/ +$//; # trim trailing blanks |
5171
|
85
|
|
|
|
|
688
|
return $str; |
5172
|
|
|
|
|
|
|
} |
5173
|
|
|
|
|
|
|
|
5174
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5175
|
|
|
|
|
|
|
# Print conversion for SpatialFrequencyResponse |
5176
|
|
|
|
|
|
|
sub PrintSFR($) |
5177
|
|
|
|
|
|
|
{ |
5178
|
0
|
|
|
0
|
0
|
0
|
my $val = shift; |
5179
|
0
|
0
|
|
|
|
0
|
return $val unless length $val > 4; |
5180
|
0
|
|
|
|
|
0
|
my ($n, $m) = (Get16u(\$val, 0), Get16u(\$val, 2)); |
5181
|
0
|
|
|
|
|
0
|
my @cols = split /\0/, substr($val, 4), $n+1; |
5182
|
0
|
|
|
|
|
0
|
my $pos = length($val) - 8 * $n * $m; |
5183
|
0
|
0
|
0
|
|
|
0
|
return $val unless @cols == $n+1 and $pos >= 4; |
5184
|
0
|
|
|
|
|
0
|
pop @cols; |
5185
|
0
|
|
|
|
|
0
|
my ($i, $j); |
5186
|
0
|
|
|
|
|
0
|
for ($i=0; $i<$n; ++$i) { |
5187
|
0
|
|
|
|
|
0
|
my @rows; |
5188
|
0
|
|
|
|
|
0
|
for ($j=0; $j<$m; ++$j) { |
5189
|
0
|
|
|
|
|
0
|
push @rows, Image::ExifTool::GetRational64u(\$val, $pos + 8*($i+$j*$n)); |
5190
|
|
|
|
|
|
|
} |
5191
|
0
|
|
|
|
|
0
|
$cols[$i] .= '=' . join(',',@rows) . ''; |
5192
|
|
|
|
|
|
|
} |
5193
|
0
|
|
|
|
|
0
|
return join '; ', @cols; |
5194
|
|
|
|
|
|
|
} |
5195
|
|
|
|
|
|
|
|
5196
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5197
|
|
|
|
|
|
|
# Print numerical parameter value (with sign, or 'Normal' for zero) |
5198
|
|
|
|
|
|
|
# Inputs: 0) value, 1) flag for inverse conversion, 2) conversion hash reference |
5199
|
|
|
|
|
|
|
sub PrintParameter($$$) |
5200
|
|
|
|
|
|
|
{ |
5201
|
195
|
|
|
195
|
0
|
469
|
my ($val, $inv, $conv) = @_; |
5202
|
195
|
100
|
|
|
|
710
|
return $val if $inv; |
5203
|
48
|
50
|
|
|
|
116
|
if ($val > 0) { |
5204
|
48
|
50
|
|
|
|
109
|
if ($val > 0xfff0) { # a negative value in disguise? |
5205
|
0
|
|
|
|
|
0
|
$val = $val - 0x10000; |
5206
|
|
|
|
|
|
|
} else { |
5207
|
48
|
|
|
|
|
109
|
$val = "+$val"; |
5208
|
|
|
|
|
|
|
} |
5209
|
|
|
|
|
|
|
} |
5210
|
48
|
|
|
|
|
135
|
return $val; |
5211
|
|
|
|
|
|
|
} |
5212
|
|
|
|
|
|
|
|
5213
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5214
|
|
|
|
|
|
|
# Convert parameter back to standard EXIF value |
5215
|
|
|
|
|
|
|
# 0,0.00,etc or "Normal" => 0 |
5216
|
|
|
|
|
|
|
# -1,-2,etc or "Soft" or "Low" => 1 |
5217
|
|
|
|
|
|
|
# +1,+2,1,2,etc or "Hard" or "High" => 2 |
5218
|
|
|
|
|
|
|
sub ConvertParameter($) |
5219
|
|
|
|
|
|
|
{ |
5220
|
67
|
|
|
67
|
0
|
156
|
my $val = shift; |
5221
|
67
|
|
|
|
|
185
|
my $isFloat = Image::ExifTool::IsFloat($val); |
5222
|
|
|
|
|
|
|
# normal is a value of zero |
5223
|
67
|
100
|
100
|
|
|
608
|
return 0 if $val =~ /\bn/i or ($isFloat and $val == 0); |
|
|
|
100
|
|
|
|
|
5224
|
|
|
|
|
|
|
# "soft", "low" or any negative number is a value of 1 |
5225
|
39
|
50
|
66
|
|
|
256
|
return 1 if $val =~ /\b(s|l)/i or ($isFloat and $val < 0); |
|
|
|
33
|
|
|
|
|
5226
|
|
|
|
|
|
|
# "hard", "high" or any positive number is a value of 2 |
5227
|
39
|
100
|
100
|
|
|
384
|
return 2 if $val =~ /\bh/i or $isFloat; |
5228
|
2
|
|
|
|
|
14
|
return undef; |
5229
|
|
|
|
|
|
|
} |
5230
|
|
|
|
|
|
|
|
5231
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5232
|
|
|
|
|
|
|
# Calculate Red/BlueBalance |
5233
|
|
|
|
|
|
|
# Inputs: 0) 0=red, 1=blue, 1-8) WB_RGGB/RGBG/RBGG/GRBG/GRGB/RGB/GRB/RBLevels, |
5234
|
|
|
|
|
|
|
# 8) red or blue level, 9) green level |
5235
|
|
|
|
|
|
|
my @rggbLookup = ( |
5236
|
|
|
|
|
|
|
# indices for R, G, G and B components in input value |
5237
|
|
|
|
|
|
|
[ 0, 1, 2, 3 ], # 0 RGGB |
5238
|
|
|
|
|
|
|
[ 0, 1, 3, 2 ], # 1 RGBG |
5239
|
|
|
|
|
|
|
[ 0, 2, 3, 1 ], # 2 RBGG |
5240
|
|
|
|
|
|
|
[ 1, 0, 3, 2 ], # 3 GRBG |
5241
|
|
|
|
|
|
|
[ 1, 0, 2, 3 ], # 4 GRGB |
5242
|
|
|
|
|
|
|
[ 2, 3, 0, 1 ], # 5 GBRG |
5243
|
|
|
|
|
|
|
[ 0, 1, 1, 2 ], # 6 RGB |
5244
|
|
|
|
|
|
|
[ 1, 0, 0, 2 ], # 7 GRB |
5245
|
|
|
|
|
|
|
[ 0, 256, 256, 1 ], # 8 RB (green level is 256) |
5246
|
|
|
|
|
|
|
); |
5247
|
|
|
|
|
|
|
sub RedBlueBalance($@) |
5248
|
|
|
|
|
|
|
{ |
5249
|
86
|
|
|
86
|
0
|
218
|
my $blue = shift; |
5250
|
86
|
|
|
|
|
168
|
my ($i, $val, $levels); |
5251
|
86
|
|
|
|
|
362
|
for ($i=0; $i<@rggbLookup; ++$i) { |
5252
|
228
|
100
|
|
|
|
498
|
$levels = shift or next; |
5253
|
82
|
|
|
|
|
307
|
my @levels = split ' ', $levels; |
5254
|
82
|
50
|
|
|
|
221
|
next if @levels < 2; |
5255
|
82
|
|
|
|
|
167
|
my $lookup = $rggbLookup[$i]; |
5256
|
82
|
|
|
|
|
156
|
my $g = $$lookup[1]; # get green level or index |
5257
|
82
|
100
|
|
|
|
296
|
if ($g < 4) { |
|
|
50
|
|
|
|
|
|
5258
|
74
|
50
|
|
|
|
187
|
next if @levels < 3; |
5259
|
74
|
50
|
|
|
|
325
|
$g = ($levels[$g] + $levels[$$lookup[2]]) / 2 or next; |
5260
|
|
|
|
|
|
|
} elsif ($levels[$$lookup[$blue * 3]] < 4) { |
5261
|
0
|
|
|
|
|
0
|
$g = 1; # Some Nikon cameras use a scaling factor of 1 (E5700) |
5262
|
|
|
|
|
|
|
} |
5263
|
82
|
|
|
|
|
279
|
$val = $levels[$$lookup[$blue * 3]] / $g; |
5264
|
82
|
|
|
|
|
212
|
last; |
5265
|
|
|
|
|
|
|
} |
5266
|
86
|
50
|
33
|
|
|
258
|
$val = $_[0] / $_[1] if not defined $val and ($_[0] and $_[1]); |
|
|
|
66
|
|
|
|
|
5267
|
86
|
|
|
|
|
572
|
return $val; |
5268
|
|
|
|
|
|
|
} |
5269
|
|
|
|
|
|
|
|
5270
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5271
|
|
|
|
|
|
|
# Print exposure time as a fraction |
5272
|
|
|
|
|
|
|
sub PrintExposureTime($) |
5273
|
|
|
|
|
|
|
{ |
5274
|
559
|
|
|
559
|
0
|
1247
|
my $secs = shift; |
5275
|
559
|
50
|
|
|
|
1433
|
return $secs unless Image::ExifTool::IsFloat($secs); |
5276
|
559
|
100
|
100
|
|
|
3011
|
if ($secs < 0.25001 and $secs > 0) { |
5277
|
432
|
|
|
|
|
4049
|
return sprintf("1/%d",int(0.5 + 1/$secs)); |
5278
|
|
|
|
|
|
|
} |
5279
|
127
|
|
|
|
|
728
|
$_ = sprintf("%.1f",$secs); |
5280
|
127
|
|
|
|
|
483
|
s/\.0$//; |
5281
|
127
|
|
|
|
|
808
|
return $_; |
5282
|
|
|
|
|
|
|
} |
5283
|
|
|
|
|
|
|
|
5284
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5285
|
|
|
|
|
|
|
# Print FNumber |
5286
|
|
|
|
|
|
|
sub PrintFNumber($) |
5287
|
|
|
|
|
|
|
{ |
5288
|
342
|
|
|
342
|
0
|
870
|
my $val = shift; |
5289
|
342
|
50
|
33
|
|
|
966
|
if (Image::ExifTool::IsFloat($val) and $val > 0) { |
5290
|
|
|
|
|
|
|
# round to 1 decimal place, or 2 for values < 1.0 |
5291
|
342
|
100
|
|
|
|
2686
|
$val = sprintf(($val<1 ? "%.2f" : "%.1f"), $val); |
5292
|
|
|
|
|
|
|
} |
5293
|
342
|
|
|
|
|
2266
|
return $val; |
5294
|
|
|
|
|
|
|
} |
5295
|
|
|
|
|
|
|
|
5296
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5297
|
|
|
|
|
|
|
# Decode raw CFAPattern value |
5298
|
|
|
|
|
|
|
# Inputs: 0) ExifTool ref, 1) binary value |
5299
|
|
|
|
|
|
|
# Returns: string of numbers |
5300
|
|
|
|
|
|
|
sub DecodeCFAPattern($$) |
5301
|
|
|
|
|
|
|
{ |
5302
|
5
|
|
|
5
|
0
|
21
|
my ($self, $val) = @_; |
5303
|
|
|
|
|
|
|
# some panasonic cameras (SV-AS3, SV-AS30) write this in ascii (very odd) |
5304
|
5
|
50
|
|
|
|
28
|
if ($val =~ /^[0-6]+$/) { |
5305
|
0
|
|
|
|
|
0
|
$self->Warn('Incorrectly formatted CFAPattern', 1); |
5306
|
0
|
|
|
|
|
0
|
$val =~ tr/0-6/\x00-\x06/; |
5307
|
|
|
|
|
|
|
} |
5308
|
5
|
50
|
|
|
|
23
|
return $val unless length($val) >= 4; |
5309
|
5
|
100
|
|
|
|
20
|
my @a = unpack(GetByteOrder() eq 'II' ? 'v2C*' : 'n2C*', $val); |
5310
|
5
|
|
|
|
|
18
|
my $end = 2 + $a[0] * $a[1]; |
5311
|
5
|
100
|
|
|
|
19
|
if ($end > @a) { |
5312
|
|
|
|
|
|
|
# try swapping byte order (I have seen this order different than in EXIF) |
5313
|
2
|
|
|
|
|
13
|
my ($x, $y) = unpack('n2',pack('v2',$a[0],$a[1])); |
5314
|
2
|
50
|
|
|
|
8
|
if (@a < 2 + $x * $y) { |
5315
|
0
|
|
|
|
|
0
|
$self->Warn('Invalid CFAPattern', 1); |
5316
|
|
|
|
|
|
|
} else { |
5317
|
2
|
|
|
|
|
8
|
($a[0], $a[1]) = ($x, $y); |
5318
|
|
|
|
|
|
|
# (can't technically be wrong because the order isn't well defined by the EXIF spec) |
5319
|
|
|
|
|
|
|
# $self->Warn('Wrong byte order for CFAPattern'); |
5320
|
|
|
|
|
|
|
} |
5321
|
|
|
|
|
|
|
} |
5322
|
5
|
|
|
|
|
57
|
return "@a"; |
5323
|
|
|
|
|
|
|
} |
5324
|
|
|
|
|
|
|
|
5325
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5326
|
|
|
|
|
|
|
# Print CFA Pattern |
5327
|
|
|
|
|
|
|
sub PrintCFAPattern($) |
5328
|
|
|
|
|
|
|
{ |
5329
|
6
|
|
|
6
|
0
|
18
|
my $val = shift; |
5330
|
6
|
|
|
|
|
30
|
my @a = split ' ', $val; |
5331
|
6
|
50
|
|
|
|
23
|
return '' unless @a >= 2; |
5332
|
6
|
50
|
33
|
|
|
37
|
return '' unless $a[0] and $a[1]; |
5333
|
6
|
|
|
|
|
16
|
my $end = 2 + $a[0] * $a[1]; |
5334
|
6
|
50
|
|
|
|
22
|
return '' if $end > @a; |
5335
|
6
|
|
|
|
|
26
|
my @cfaColor = qw(Red Green Blue Cyan Magenta Yellow White); |
5336
|
6
|
|
|
|
|
19
|
my ($pos, $rtnVal) = (2, '['); |
5337
|
6
|
|
|
|
|
10
|
for (;;) { |
5338
|
24
|
|
50
|
|
|
58
|
$rtnVal .= $cfaColor[$a[$pos]] || 'Unknown'; |
5339
|
24
|
100
|
|
|
|
47
|
last if ++$pos >= $end; |
5340
|
18
|
100
|
|
|
|
43
|
($pos - 2) % $a[1] and $rtnVal .= ',', next; |
5341
|
6
|
|
|
|
|
14
|
$rtnVal .= ']['; |
5342
|
|
|
|
|
|
|
} |
5343
|
6
|
|
|
|
|
70
|
return $rtnVal . ']'; |
5344
|
|
|
|
|
|
|
} |
5345
|
|
|
|
|
|
|
|
5346
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5347
|
|
|
|
|
|
|
# Print Opcode List |
5348
|
|
|
|
|
|
|
# Inputs: 0) value, 1) flag for inverse conversion, 2) conversion hash reference |
5349
|
|
|
|
|
|
|
# Returns: converted value |
5350
|
|
|
|
|
|
|
sub PrintOpcode($$$) |
5351
|
|
|
|
|
|
|
{ |
5352
|
0
|
|
|
0
|
0
|
0
|
my ($val, $inv, $conv) = @_; |
5353
|
0
|
0
|
|
|
|
0
|
return undef if $inv; # (can't do inverse conversion) |
5354
|
0
|
0
|
|
|
|
0
|
return '' unless length $$val > 4; |
5355
|
0
|
|
|
|
|
0
|
my $num = unpack('N', $$val); |
5356
|
0
|
|
|
|
|
0
|
my $pos = 4; |
5357
|
0
|
|
|
|
|
0
|
my ($i, @ops); |
5358
|
0
|
|
|
|
|
0
|
for ($i=0; $i<$num; ++$i) { |
5359
|
0
|
0
|
|
|
|
0
|
$pos + 16 <= length $$val or push(@ops, ''), last; |
5360
|
0
|
|
|
|
|
0
|
my ($op, $ver, $flags, $len) = unpack("x${pos}N4", $$val); |
5361
|
0
|
|
0
|
|
|
0
|
push @ops, $$conv{$op} || "[opcode $op]"; |
5362
|
0
|
|
|
|
|
0
|
$pos += 16 + $len; |
5363
|
|
|
|
|
|
|
} |
5364
|
0
|
|
|
|
|
0
|
return join ', ', @ops; |
5365
|
|
|
|
|
|
|
} |
5366
|
|
|
|
|
|
|
|
5367
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5368
|
|
|
|
|
|
|
# Print conversion for lens info |
5369
|
|
|
|
|
|
|
# Inputs: 0) string of values (min focal, max focal, min F, max F) |
5370
|
|
|
|
|
|
|
# Returns: string in the form "12-20mm f/3.8-4.5" or "50mm f/1.4" |
5371
|
|
|
|
|
|
|
sub PrintLensInfo($) |
5372
|
|
|
|
|
|
|
{ |
5373
|
13
|
|
|
13
|
0
|
29
|
my $val = shift; |
5374
|
13
|
|
|
|
|
51
|
my @vals = split ' ', $val; |
5375
|
13
|
50
|
|
|
|
47
|
return $val unless @vals == 4; |
5376
|
13
|
|
|
|
|
28
|
my $c = 0; |
5377
|
13
|
|
|
|
|
34
|
foreach (@vals) { |
5378
|
52
|
100
|
|
|
|
107
|
Image::ExifTool::IsFloat($_) and ++$c, next; |
5379
|
4
|
50
|
|
|
|
12
|
$_ eq 'inf' and $_ = '?', ++$c, next; |
5380
|
4
|
50
|
|
|
|
14
|
$_ eq 'undef' and $_ = '?', ++$c, next; |
5381
|
|
|
|
|
|
|
} |
5382
|
13
|
50
|
|
|
|
44
|
return $val unless $c == 4; |
5383
|
13
|
|
|
|
|
24
|
$val = $vals[0]; |
5384
|
|
|
|
|
|
|
# (the Pentax Q writes zero for upper value of fixed-focal-length lenses) |
5385
|
13
|
100
|
66
|
|
|
78
|
$val .= "-$vals[1]" if $vals[1] and $vals[1] ne $vals[0]; |
5386
|
13
|
|
|
|
|
33
|
$val .= "mm f/$vals[2]"; |
5387
|
13
|
100
|
100
|
|
|
87
|
$val .= "-$vals[3]" if $vals[3] and $vals[3] ne $vals[2]; |
5388
|
13
|
|
|
|
|
43
|
return $val; |
5389
|
|
|
|
|
|
|
} |
5390
|
|
|
|
|
|
|
|
5391
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5392
|
|
|
|
|
|
|
# Get lens info from lens model string |
5393
|
|
|
|
|
|
|
# Inputs: 0) lens string, 1) flag to allow unknown "?" values |
5394
|
|
|
|
|
|
|
# Returns: 0) min focal, 1) max focal, 2) min aperture, 3) max aperture |
5395
|
|
|
|
|
|
|
# Notes: returns empty list if lens string could not be parsed |
5396
|
|
|
|
|
|
|
sub GetLensInfo($;$) |
5397
|
|
|
|
|
|
|
{ |
5398
|
53
|
|
|
53
|
0
|
107
|
my ($lens, $unk) = @_; |
5399
|
|
|
|
|
|
|
# extract focal length and aperture ranges for this lens |
5400
|
53
|
|
|
|
|
74
|
my $pat = '\\d+(?:\\.\\d+)?'; |
5401
|
53
|
100
|
|
|
|
299
|
$pat .= '|\\?' if $unk; |
5402
|
53
|
100
|
|
|
|
819
|
return () unless $lens =~ /($pat)(?:-($pat))?\s*mm.*?(?:[fF]\/?\s*)($pat)(?:-($pat))?/; |
5403
|
|
|
|
|
|
|
# ($1=short focal, $2=long focal, $3=max aperture wide, $4=max aperture tele) |
5404
|
33
|
|
|
|
|
110
|
my @a = ($1, $2, $3, $4); |
5405
|
33
|
50
|
|
|
|
64
|
$a[1] or $a[1] = $a[0]; |
5406
|
33
|
50
|
|
|
|
52
|
$a[3] or $a[3] = $a[2]; |
5407
|
33
|
100
|
|
|
|
65
|
if ($unk) { |
5408
|
1
|
|
|
|
|
2
|
local $_; |
5409
|
1
|
|
50
|
|
|
7
|
$_ eq '?' and $_ = 'undef' foreach @a; |
5410
|
|
|
|
|
|
|
} |
5411
|
33
|
|
|
|
|
109
|
return @a; |
5412
|
|
|
|
|
|
|
} |
5413
|
|
|
|
|
|
|
|
5414
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5415
|
|
|
|
|
|
|
# Match lens in list of possbilities based on value of LensModel |
5416
|
|
|
|
|
|
|
# Inputs: 0) reference to list of possible models, 1) LensModel string |
5417
|
|
|
|
|
|
|
# - updates list on return; guaranteed not to remove all list entries |
5418
|
|
|
|
|
|
|
sub MatchLensModel($$) |
5419
|
|
|
|
|
|
|
{ |
5420
|
4
|
|
|
4
|
0
|
11
|
my ($try, $lensModel) = @_; |
5421
|
4
|
50
|
33
|
|
|
24
|
if (@$try > 1 and $lensModel) { |
5422
|
0
|
|
|
|
|
0
|
my (@filt, $pat); |
5423
|
|
|
|
|
|
|
# filter by focal length |
5424
|
0
|
0
|
|
|
|
0
|
if ($lensModel =~ /((\d+-)?\d+mm)/) { |
5425
|
0
|
|
|
|
|
0
|
my $focal = $1; |
5426
|
0
|
|
|
|
|
0
|
@filt = grep /$focal/, @$try; |
5427
|
0
|
0
|
0
|
|
|
0
|
@$try = @filt if @filt and @filt < @$try; |
5428
|
|
|
|
|
|
|
} |
5429
|
|
|
|
|
|
|
# filter by aperture |
5430
|
0
|
0
|
0
|
|
|
0
|
if (@$try > 1 and $lensModel =~ m{(?:F/?|1:)(\d+(\.\d+)?)}i) { |
5431
|
0
|
|
|
|
|
0
|
my $fnum = $1; |
5432
|
0
|
|
|
|
|
0
|
@filt = grep m{(F/?|1:)$fnum(\b|[A-Z])}i, @$try; |
5433
|
0
|
0
|
0
|
|
|
0
|
@$try = @filt if @filt and @filt < @$try; |
5434
|
|
|
|
|
|
|
} |
5435
|
|
|
|
|
|
|
# filter by model version, and other lens parameters |
5436
|
0
|
|
|
|
|
0
|
foreach $pat ('I+', 'USM') { |
5437
|
0
|
0
|
0
|
|
|
0
|
next unless @$try > 1 and $lensModel =~ /\b($pat)\b/; |
5438
|
0
|
|
|
|
|
0
|
my $val = $1; |
5439
|
0
|
|
|
|
|
0
|
@filt = grep /\b$val\b/, @$try; |
5440
|
0
|
0
|
0
|
|
|
0
|
@$try = @filt if @filt and @filt < @$try; |
5441
|
|
|
|
|
|
|
} |
5442
|
|
|
|
|
|
|
} |
5443
|
|
|
|
|
|
|
} |
5444
|
|
|
|
|
|
|
|
5445
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5446
|
|
|
|
|
|
|
# Attempt to identify the specific lens if multiple lenses have the same LensType |
5447
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object ref, 1) LensType print value, 2) PrintConv hash ref, |
5448
|
|
|
|
|
|
|
# 3) LensSpec print value, 4) LensType numerical value, 5) FocalLength, |
5449
|
|
|
|
|
|
|
# 6) MaxAperture, 7) MaxApertureValue, 8) MinFocalLength, 9) MaxFocalLength, |
5450
|
|
|
|
|
|
|
# 10) LensModel, 11) LensFocalRange, 12) LensSpec |
5451
|
|
|
|
|
|
|
my %sonyEtype; |
5452
|
|
|
|
|
|
|
sub PrintLensID($$@) |
5453
|
|
|
|
|
|
|
{ |
5454
|
34
|
|
|
34
|
0
|
177
|
my ($et, $lensTypePrt, $printConv, $lensSpecPrt, $lensType, $focalLength, |
5455
|
|
|
|
|
|
|
$maxAperture, $maxApertureValue, $shortFocal, $longFocal, $lensModel, |
5456
|
|
|
|
|
|
|
$lensFocalRange, $lensSpec) = @_; |
5457
|
|
|
|
|
|
|
# this logic relies on the LensType lookup: |
5458
|
34
|
50
|
|
|
|
116
|
return undef unless defined $lensType; |
5459
|
|
|
|
|
|
|
# get print conversion hash if necessary |
5460
|
34
|
50
|
|
|
|
153
|
$printConv or $printConv = $$et{TAG_INFO}{LensType}{PrintConv}; |
5461
|
|
|
|
|
|
|
# just copy LensType PrintConv value if it was a lens name |
5462
|
|
|
|
|
|
|
# (Olympus or Panasonic -- just exclude things like Nikon and Leaf LensType) |
5463
|
34
|
50
|
|
|
|
118
|
unless (ref $printConv eq 'HASH') { |
5464
|
0
|
0
|
0
|
|
|
0
|
if (ref $printConv eq 'ARRAY' and ref $$printConv[0] eq 'HASH') { |
5465
|
0
|
|
|
|
|
0
|
$printConv = $$printConv[0]; |
5466
|
0
|
|
|
|
|
0
|
$lensTypePrt =~ s/;.*//; |
5467
|
0
|
|
|
|
|
0
|
$lensType =~ s/ .*//; |
5468
|
|
|
|
|
|
|
} else { |
5469
|
0
|
0
|
|
|
|
0
|
return $lensTypePrt if $lensTypePrt =~ /mm/; |
5470
|
0
|
0
|
|
|
|
0
|
return $lensTypePrt if $lensTypePrt =~ s/(\d)\/F/$1mm F/; |
5471
|
0
|
|
|
|
|
0
|
return undef; |
5472
|
|
|
|
|
|
|
} |
5473
|
|
|
|
|
|
|
} |
5474
|
|
|
|
|
|
|
# get LensSpec information if available (Sony) |
5475
|
34
|
|
|
|
|
86
|
my ($sf0, $lf0, $sa0, $la0); |
5476
|
34
|
50
|
|
|
|
115
|
if ($lensSpecPrt) { |
5477
|
0
|
|
|
|
|
0
|
($sf0, $lf0, $sa0, $la0) = GetLensInfo($lensSpecPrt); |
5478
|
0
|
0
|
|
|
|
0
|
undef $sf0 unless $sa0; # (make sure aperture isn't zero) |
5479
|
|
|
|
|
|
|
} |
5480
|
|
|
|
|
|
|
# use MaxApertureValue if MaxAperture is not available |
5481
|
34
|
100
|
|
|
|
106
|
$maxAperture = $maxApertureValue unless $maxAperture; |
5482
|
34
|
100
|
100
|
|
|
137
|
if ($lensFocalRange and $lensFocalRange =~ /^(\d+)(?: (?:to )?(\d+))?$/) { |
5483
|
1
|
|
33
|
|
|
6
|
($shortFocal, $longFocal) = ($1, $2 || $1); |
5484
|
|
|
|
|
|
|
} |
5485
|
34
|
50
|
66
|
|
|
327
|
if ($$et{Make} eq 'SONY') { |
|
|
100
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
5486
|
0
|
0
|
|
|
|
0
|
if ($lensType eq 65535) { |
|
|
0
|
|
|
|
|
|
5487
|
|
|
|
|
|
|
# handle Sony E-type lenses when LensType2 isn't valid (NEX/ILCE models only) |
5488
|
0
|
0
|
|
|
|
0
|
if ($$et{Model} =~ /NEX|ILCE/) { |
5489
|
0
|
0
|
|
|
|
0
|
unless (%sonyEtype) { |
5490
|
0
|
|
|
|
|
0
|
my ($index, $i, %did, $lens); |
5491
|
0
|
|
|
|
|
0
|
require Image::ExifTool::Sony; |
5492
|
0
|
|
|
|
|
0
|
foreach (sort keys %Image::ExifTool::Sony::sonyLensTypes2) { |
5493
|
0
|
|
|
|
|
0
|
($lens = $Image::ExifTool::Sony::sonyLensTypes2{$_}) =~ s/ or .*//; |
5494
|
0
|
0
|
|
|
|
0
|
next if $did{$lens}; |
5495
|
0
|
0
|
|
|
|
0
|
($i, $index) = $index ? ("65535.$index", $index + 1) : (65535, 1); |
5496
|
0
|
|
|
|
|
0
|
$did{$sonyEtype{$i} = $lens} = 1; |
5497
|
|
|
|
|
|
|
} |
5498
|
|
|
|
|
|
|
} |
5499
|
0
|
|
|
|
|
0
|
$printConv = \%sonyEtype; |
5500
|
|
|
|
|
|
|
} |
5501
|
|
|
|
|
|
|
} elsif ($lensType != 0xff00) { |
5502
|
|
|
|
|
|
|
# Patch for Metabones or other adapters on Sony E-mount cameras (ref Jos Roost) |
5503
|
|
|
|
|
|
|
# Metabones Canon EF to E-mount adapters add 0xef00, 0xbc00 or 0x7700 to the |
5504
|
|
|
|
|
|
|
# high byte for 2-byte Canon LensType values, so we need to adjust for these. |
5505
|
|
|
|
|
|
|
# Offset 0xef00 is also used by Sigma MC-11, Fotodiox and Viltrox EF-E adapters. |
5506
|
|
|
|
|
|
|
# Have to exclude A-mount Sigma Filtermatic with 'odd' LensType=0xff00. |
5507
|
0
|
|
|
|
|
0
|
require Image::ExifTool::Minolta; |
5508
|
0
|
0
|
0
|
|
|
0
|
if ($Image::ExifTool::Minolta::metabonesID{$lensType & 0xff00}) { |
|
|
0
|
|
|
|
|
|
5509
|
0
|
0
|
|
|
|
0
|
$lensType -= ($lensType >= 0xef00 ? 0xef00 : $lensType >= 0xbc00 ? 0xbc00 : 0x7700); |
|
|
0
|
|
|
|
|
|
5510
|
0
|
|
|
|
|
0
|
require Image::ExifTool::Canon; |
5511
|
0
|
|
|
|
|
0
|
$printConv = \%Image::ExifTool::Canon::canonLensTypes; |
5512
|
0
|
0
|
|
|
|
0
|
$lensTypePrt = $$printConv{$lensType} if $$printConv{$lensType}; |
5513
|
|
|
|
|
|
|
# Test for Sigma MC-11 SA-E adapter with Sigma SA lens using 0x4900 offset. |
5514
|
|
|
|
|
|
|
# (upper limit of test cuts off two highest Sigma lenses, but prevents |
5515
|
|
|
|
|
|
|
# conflict with old Minolta 25xxx and higher ID's) |
5516
|
|
|
|
|
|
|
} elsif ($lensType >= 0x4900 and $lensType <= 0x590a) { |
5517
|
0
|
|
|
|
|
0
|
require Image::ExifTool::Sigma; |
5518
|
0
|
|
|
|
|
0
|
$lensType -= 0x4900; |
5519
|
0
|
|
|
|
|
0
|
$printConv = \%Image::ExifTool::Sigma::sigmaLensTypes; |
5520
|
0
|
0
|
|
|
|
0
|
$lensTypePrt = $$printConv{$lensType} if $$printConv{$lensType}; |
5521
|
|
|
|
|
|
|
} |
5522
|
|
|
|
|
|
|
} |
5523
|
|
|
|
|
|
|
# (Min/MaxFocalLength may report the current focal length for Tamron zoom lenses) |
5524
|
|
|
|
|
|
|
} elsif ($shortFocal and $longFocal and (not $lensModel or $lensModel !~ /^TAMRON.*-\d+mm/)) { |
5525
|
|
|
|
|
|
|
# Canon (and some other makes) include makernote information |
5526
|
|
|
|
|
|
|
# which allows better lens identification |
5527
|
28
|
|
|
|
|
1765
|
require Image::ExifTool::Canon; |
5528
|
28
|
|
|
|
|
231
|
return Image::ExifTool::Canon::PrintLensID($printConv, $lensType, |
5529
|
|
|
|
|
|
|
$shortFocal, $longFocal, $maxAperture, $lensModel); |
5530
|
|
|
|
|
|
|
} |
5531
|
6
|
|
|
|
|
16
|
my $lens = $$printConv{$lensType}; |
5532
|
6
|
100
|
33
|
|
|
35
|
return ($lensModel || $lensTypePrt) unless $lens; |
5533
|
5
|
100
|
|
|
|
41
|
return $lens unless $$printConv{"$lensType.1"}; |
5534
|
4
|
|
|
|
|
21
|
$lens =~ s/ or .*//s; # remove everything after "or" |
5535
|
|
|
|
|
|
|
# make list of all possible matching lenses |
5536
|
4
|
|
|
|
|
15
|
my @lenses = ( $lens ); |
5537
|
4
|
|
|
|
|
38
|
my $i; |
5538
|
4
|
|
|
|
|
26
|
for ($i=1; $$printConv{"$lensType.$i"}; ++$i) { |
5539
|
28
|
|
|
|
|
94
|
push @lenses, $$printConv{"$lensType.$i"}; |
5540
|
|
|
|
|
|
|
} |
5541
|
|
|
|
|
|
|
# attempt to determine actual lens |
5542
|
4
|
|
|
|
|
12
|
my (@matches, @best, @user, $diff); |
5543
|
4
|
|
|
|
|
11
|
foreach $lens (@lenses) { |
5544
|
32
|
50
|
|
|
|
66
|
push @user, $lens if $Image::ExifTool::userLens{$lens}; |
5545
|
|
|
|
|
|
|
# sf = short focal |
5546
|
|
|
|
|
|
|
# lf = long focal |
5547
|
|
|
|
|
|
|
# sa = max aperture at short focal |
5548
|
|
|
|
|
|
|
# la = max aperture at long focal |
5549
|
32
|
|
|
|
|
53
|
my ($sf, $lf, $sa, $la) = GetLensInfo($lens); |
5550
|
32
|
100
|
|
|
|
63
|
next unless $sf; |
5551
|
|
|
|
|
|
|
# check against LensSpec parameters if available |
5552
|
28
|
50
|
|
|
|
52
|
if ($sf0) { |
5553
|
0
|
0
|
0
|
|
|
0
|
next if abs($sf - $sf0) > 0.5 or abs($sa - $sa0) > 0.15 or |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
5554
|
|
|
|
|
|
|
abs($lf - $lf0) > 0.5 or abs($la - $la0) > 0.15; |
5555
|
|
|
|
|
|
|
# the basic parameters match, but also check against additional lens features: |
5556
|
|
|
|
|
|
|
# for Sony A and E lenses, the full LensSpec string should match with end of LensType, |
5557
|
|
|
|
|
|
|
# excluding any part between () at the end, and preceded by a space (the space |
5558
|
|
|
|
|
|
|
# ensures that e.g. Zeiss Loxia 21mm having LensSpec "E 21mm F2.8" will not be |
5559
|
|
|
|
|
|
|
# identified as "Sony FE 21mm F2.8 (SEL28F20 + SEL075UWC)") |
5560
|
0
|
0
|
0
|
|
|
0
|
$lensSpecPrt and $lens =~ / \Q$lensSpecPrt\E( \(| GM$|$)/ and @best = ( $lens ), last; |
5561
|
|
|
|
|
|
|
# exactly-matching Sony lens should have been found above, so only add non-Sony lenses |
5562
|
0
|
0
|
|
|
|
0
|
push @best, $lens unless $lens =~ /^Sony /; |
5563
|
0
|
|
|
|
|
0
|
next; |
5564
|
|
|
|
|
|
|
} |
5565
|
|
|
|
|
|
|
# adjust focal length and aperture if teleconverter is attached (Minolta) |
5566
|
28
|
50
|
|
|
|
58
|
if ($lens =~ / \+ .*? (\d+(\.\d+)?)x( |$)/) { |
5567
|
0
|
|
|
|
|
0
|
$sf *= $1; $lf *= $1; |
|
0
|
|
|
|
|
0
|
|
5568
|
0
|
|
|
|
|
0
|
$sa *= $1; $la *= $1; |
|
0
|
|
|
|
|
0
|
|
5569
|
|
|
|
|
|
|
} |
5570
|
|
|
|
|
|
|
# see if we can rule out this lens using FocalLength and MaxAperture |
5571
|
28
|
50
|
|
|
|
46
|
if ($focalLength) { |
5572
|
28
|
100
|
|
|
|
79
|
next if $focalLength < $sf - 0.5; |
5573
|
9
|
100
|
|
|
|
29
|
next if $focalLength > $lf + 0.5; |
5574
|
|
|
|
|
|
|
} |
5575
|
8
|
50
|
|
|
|
15
|
if ($maxAperture) { |
5576
|
|
|
|
|
|
|
# it seems that most manufacturers set MaxAperture and MaxApertureValue |
5577
|
|
|
|
|
|
|
# to the maximum aperture (smallest F number) for the current focal length |
5578
|
|
|
|
|
|
|
# of the lens, so assume that MaxAperture varies with focal length and find |
5579
|
|
|
|
|
|
|
# the closest match (this is somewhat contrary to the EXIF specification which |
5580
|
|
|
|
|
|
|
# states "The smallest F number of the lens", without mention of focal length) |
5581
|
8
|
100
|
|
|
|
25
|
next if $maxAperture < $sa - 0.15; # (0.15 is arbitrary) |
5582
|
3
|
50
|
|
|
|
13
|
next if $maxAperture > $la + 0.15; |
5583
|
|
|
|
|
|
|
# now determine the best match for this aperture |
5584
|
3
|
|
|
|
|
6
|
my $aa; # approximate maximum aperture at this focal length |
5585
|
3
|
50
|
33
|
|
|
39
|
if ($sf == $lf or $sa == $la or $focalLength <= $sf) { |
|
|
0
|
33
|
|
|
|
|
5586
|
|
|
|
|
|
|
# either 1) prime lens, 2) fixed-aperture zoom, or 3) zoom at min focal |
5587
|
3
|
|
|
|
|
9
|
$aa = $sa; |
5588
|
|
|
|
|
|
|
} elsif ($focalLength >= $lf) { |
5589
|
0
|
|
|
|
|
0
|
$aa = $la; |
5590
|
|
|
|
|
|
|
} else { |
5591
|
|
|
|
|
|
|
# assume a log-log variation of max aperture with focal length |
5592
|
|
|
|
|
|
|
# (see http://regex.info/blog/2006-10-05/263) |
5593
|
0
|
|
|
|
|
0
|
$aa = exp(log($sa) + (log($la)-log($sa)) / (log($lf)-log($sf)) * |
5594
|
|
|
|
|
|
|
(log($focalLength)-log($sf))); |
5595
|
|
|
|
|
|
|
# a linear relationship between 1/FocalLength and 1/MaxAperture fits Sony better (ref 27) |
5596
|
|
|
|
|
|
|
#$aa = 1 / (1/$sa + (1/$focalLength - 1/$sf) * (1/$la - 1/$sa) / (1/$lf - 1/$sf)); |
5597
|
|
|
|
|
|
|
} |
5598
|
3
|
|
|
|
|
8
|
my $d = abs($maxAperture - $aa); |
5599
|
3
|
50
|
|
|
|
15
|
if (defined $diff) { |
5600
|
0
|
0
|
|
|
|
0
|
$d > $diff + 0.15 and next; # (0.15 is arbitrary) |
5601
|
0
|
0
|
|
|
|
0
|
$d < $diff - 0.15 and undef @best; |
5602
|
|
|
|
|
|
|
} |
5603
|
3
|
|
|
|
|
6
|
$diff = $d; |
5604
|
3
|
|
|
|
|
7
|
push @best, $lens; |
5605
|
|
|
|
|
|
|
} |
5606
|
3
|
|
|
|
|
9
|
push @matches, $lens; |
5607
|
|
|
|
|
|
|
} |
5608
|
|
|
|
|
|
|
# return the user-defined lens if it exists |
5609
|
4
|
50
|
|
|
|
17
|
if (@user) { |
5610
|
|
|
|
|
|
|
# choose the best match if we have more than one |
5611
|
0
|
0
|
|
|
|
0
|
if (@user > 1) { |
5612
|
0
|
|
|
|
|
0
|
my ($try, @good); |
5613
|
0
|
|
|
|
|
0
|
foreach $try (\@best, \@matches) { |
5614
|
0
|
|
0
|
|
|
0
|
$Image::ExifTool::userLens{$_} and push @good, $_ foreach @$try; |
5615
|
0
|
0
|
|
|
|
0
|
return join(' or ', @good) if @good; |
5616
|
|
|
|
|
|
|
} |
5617
|
|
|
|
|
|
|
} |
5618
|
0
|
|
|
|
|
0
|
return join(' or ', @user); |
5619
|
|
|
|
|
|
|
} |
5620
|
|
|
|
|
|
|
# return the best match(es) from the possible lenses, after checking against LensModel |
5621
|
4
|
100
|
|
|
|
16
|
@best = @matches unless @best; |
5622
|
4
|
100
|
|
|
|
14
|
if (@best) { |
5623
|
3
|
|
|
|
|
13
|
MatchLensModel(\@best, $lensModel); |
5624
|
3
|
|
|
|
|
79
|
return join(' or ', @best); |
5625
|
|
|
|
|
|
|
} |
5626
|
1
|
|
|
|
|
3
|
$lens = $$printConv{$lensType}; |
5627
|
1
|
50
|
33
|
|
|
5
|
return $lensModel if $lensModel and $lens =~ / or /; # (eg. Sony NEX-5N) |
5628
|
1
|
|
|
|
|
20
|
return $lens; |
5629
|
|
|
|
|
|
|
} |
5630
|
|
|
|
|
|
|
|
5631
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5632
|
|
|
|
|
|
|
# Translate date into standard EXIF format |
5633
|
|
|
|
|
|
|
# Inputs: 0) date |
5634
|
|
|
|
|
|
|
# Returns: date in format '2003:10:22' |
5635
|
|
|
|
|
|
|
# - bad formats recognized: '2003-10-22','2003/10/22','2003 10 22','20031022' |
5636
|
|
|
|
|
|
|
# - removes null terminator if it exists |
5637
|
|
|
|
|
|
|
sub ExifDate($) |
5638
|
|
|
|
|
|
|
{ |
5639
|
67
|
|
|
67
|
0
|
197
|
my $date = shift; |
5640
|
67
|
|
|
|
|
175
|
$date =~ s/\0$//; # remove any null terminator |
5641
|
|
|
|
|
|
|
# separate year:month:day with colons |
5642
|
|
|
|
|
|
|
# (have seen many other characters, including nulls, used erroneously) |
5643
|
67
|
|
|
|
|
684
|
$date =~ s/(\d{4})[^\d]*(\d{2})[^\d]*(\d{2})$/$1:$2:$3/; |
5644
|
67
|
|
|
|
|
525
|
return $date; |
5645
|
|
|
|
|
|
|
} |
5646
|
|
|
|
|
|
|
|
5647
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5648
|
|
|
|
|
|
|
# Translate time into standard EXIF format |
5649
|
|
|
|
|
|
|
# Inputs: 0) time |
5650
|
|
|
|
|
|
|
# Returns: time in format '10:30:55' |
5651
|
|
|
|
|
|
|
# - bad formats recognized: '10 30 55', '103055', '103055+0500' |
5652
|
|
|
|
|
|
|
# - removes null terminator if it exists |
5653
|
|
|
|
|
|
|
# - leaves time zone intact if specified (eg. '10:30:55+05:00') |
5654
|
|
|
|
|
|
|
sub ExifTime($) |
5655
|
|
|
|
|
|
|
{ |
5656
|
8
|
|
|
8
|
0
|
23
|
my $time = shift; |
5657
|
8
|
|
|
|
|
24
|
$time =~ tr/ /:/; # use ':' (not ' ') as a separator |
5658
|
8
|
|
|
|
|
20
|
$time =~ s/\0$//; # remove any null terminator |
5659
|
|
|
|
|
|
|
# add separators if they don't exist |
5660
|
8
|
|
|
|
|
60
|
$time =~ s/^(\d{2})(\d{2})(\d{2})/$1:$2:$3/; |
5661
|
8
|
|
|
|
|
53
|
$time =~ s/([+-]\d{2})(\d{2})\s*$/$1:$2/; # to timezone too |
5662
|
8
|
|
|
|
|
60
|
return $time; |
5663
|
|
|
|
|
|
|
} |
5664
|
|
|
|
|
|
|
|
5665
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5666
|
|
|
|
|
|
|
# Generate TIFF file from scratch (in current byte order) |
5667
|
|
|
|
|
|
|
# Inputs: 0) hash of IFD entries (TagID => Value; multiple values space-delimited) |
5668
|
|
|
|
|
|
|
# 1) raw image data reference |
5669
|
|
|
|
|
|
|
# Returns: TIFF image data, or undef on error |
5670
|
|
|
|
|
|
|
sub GenerateTIFF($$) |
5671
|
|
|
|
|
|
|
{ |
5672
|
4
|
|
|
4
|
0
|
11
|
my ($entries, $dataPt) = @_; |
5673
|
4
|
|
|
|
|
8
|
my ($rtnVal, $tag, $offsetPos); |
5674
|
|
|
|
|
|
|
|
5675
|
4
|
|
|
|
|
15
|
my $num = scalar keys %$entries; |
5676
|
4
|
|
|
|
|
21
|
my $ifdBuff = GetByteOrder() . Set16u(42) . Set32u(8) . Set16u($num); |
5677
|
4
|
|
|
|
|
13
|
my $valBuff = ''; |
5678
|
4
|
|
|
|
|
14
|
my $tagTablePtr = GetTagTable('Image::ExifTool::Exif::Main'); |
5679
|
4
|
|
|
|
|
36
|
foreach $tag (sort { $a <=> $b } keys %$entries) { |
|
165
|
|
|
|
|
207
|
|
5680
|
60
|
|
|
|
|
110
|
my $tagInfo = $$tagTablePtr{$tag}; |
5681
|
60
|
100
|
|
|
|
150
|
my $fmt = ref $tagInfo eq 'HASH' ? $$tagInfo{Writable} : 'int32u'; |
5682
|
60
|
50
|
|
|
|
89
|
return undef unless defined $fmt; |
5683
|
60
|
|
|
|
|
141
|
my $val = Image::ExifTool::WriteValue($$entries{$tag}, $fmt, -1); |
5684
|
60
|
50
|
|
|
|
219
|
return undef unless defined $val; |
5685
|
60
|
|
|
|
|
83
|
my $format = $formatNumber{$fmt}; |
5686
|
60
|
|
|
|
|
106
|
$ifdBuff .= Set16u($tag) . Set16u($format) . Set32u(length($val)/$formatSize[$format]); |
5687
|
60
|
100
|
|
|
|
122
|
$offsetPos = length($ifdBuff) if $tag == 0x111; # (remember StripOffsets position) |
5688
|
60
|
100
|
|
|
|
90
|
if (length $val > 4) { |
5689
|
12
|
|
|
|
|
33
|
$ifdBuff .= Set32u(10 + 12 * $num + 4 + length($valBuff)); |
5690
|
12
|
|
|
|
|
28
|
$valBuff .= $val; |
5691
|
|
|
|
|
|
|
} else { |
5692
|
48
|
100
|
|
|
|
97
|
$val .= "\0" x (4 - length($val)) if length $val < 4; |
5693
|
48
|
|
|
|
|
85
|
$ifdBuff .= $val; |
5694
|
|
|
|
|
|
|
} |
5695
|
|
|
|
|
|
|
} |
5696
|
4
|
|
|
|
|
24
|
$ifdBuff .= "\0\0\0\0"; # (no IFD1) |
5697
|
4
|
50
|
|
|
|
16
|
return undef unless $offsetPos; |
5698
|
4
|
|
|
|
|
20
|
Set32u(length($ifdBuff) + length($valBuff), \$ifdBuff, $offsetPos); |
5699
|
4
|
|
|
|
|
21
|
return $ifdBuff . $valBuff . $$dataPt; |
5700
|
|
|
|
|
|
|
} |
5701
|
|
|
|
|
|
|
|
5702
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5703
|
|
|
|
|
|
|
# Rebuild TIFF thumbnail(s)/preview(s) into stand-alone files with current byte order |
5704
|
|
|
|
|
|
|
# Inputs: 0) ExifTool ref, 1) SubfileType, 2) Compression, 3) ImageWidth, 4) ImageHeight, |
5705
|
|
|
|
|
|
|
# 5) BitsPerSample, 6) PhotometricInterpretation, 7) StripOffsets, 8) SamplesPerPixel, |
5706
|
|
|
|
|
|
|
# 9) RowsPerStrip, 10) StripByteCounts, 10) PlanarConfiguration, 11) Orientation |
5707
|
|
|
|
|
|
|
# Returns: 0) TIFF image or undef, 1/2) Family 0/1 groups for TIFF preview IFD |
5708
|
|
|
|
|
|
|
sub RebuildTIFF($;@) |
5709
|
|
|
|
|
|
|
{ |
5710
|
14
|
|
|
14
|
0
|
33
|
local $_; |
5711
|
14
|
|
|
|
|
31
|
my $et = $_[0]; |
5712
|
14
|
|
|
|
|
41
|
my $value = $$et{VALUE}; |
5713
|
14
|
|
|
|
|
34
|
my ($i, $j, $rtn, $grp0, $grp1); |
5714
|
14
|
50
|
|
|
|
61
|
return undef if $$et{FILE_TYPE} eq 'RWZ'; |
5715
|
|
|
|
|
|
|
SubFile: |
5716
|
14
|
|
|
|
|
39
|
for ($i=0; ; ++$i) { |
5717
|
40
|
100
|
|
|
|
144
|
my $key = 'SubfileType' . ($i ? " ($i)" : ''); |
5718
|
40
|
100
|
|
|
|
124
|
last unless defined $$value{$key}; |
5719
|
26
|
100
|
|
|
|
85
|
next unless $$value{$key} == 1; # (reduced-resolution image) |
5720
|
12
|
|
|
|
|
39
|
my $grp = $et->GetGroup($key, 1); |
5721
|
12
|
|
|
|
|
52
|
my $cmp = $et->FindValue('Compression', $grp); |
5722
|
12
|
100
|
|
|
|
38
|
next unless $cmp == 1; # (no compression) |
5723
|
6
|
|
|
|
|
31
|
my %vals = (Compression=>$cmp, PlanarConfiguration=>1, Orientation=>1); |
5724
|
6
|
|
|
|
|
25
|
foreach (qw(ImageWidth ImageHeight BitsPerSample PhotometricInterpretation |
5725
|
|
|
|
|
|
|
StripOffsets SamplesPerPixel RowsPerStrip StripByteCounts |
5726
|
|
|
|
|
|
|
PlanarConfiguration Orientation)) |
5727
|
|
|
|
|
|
|
{ |
5728
|
60
|
|
|
|
|
119
|
my $val = $et->FindValue($_, $grp); |
5729
|
60
|
100
|
|
|
|
167
|
defined $val and $vals{$_} = $val, next; |
5730
|
2
|
50
|
|
|
|
7
|
next SubFile unless defined $vals{$_}; |
5731
|
|
|
|
|
|
|
} |
5732
|
6
|
|
|
|
|
26
|
my ($w, $h) = @vals{'ImageWidth', 'ImageHeight'}; |
5733
|
6
|
|
|
|
|
37
|
my @bits = split ' ', $vals{BitsPerSample}; |
5734
|
6
|
|
|
|
|
21
|
my $rowBytes = 0; |
5735
|
6
|
|
|
|
|
49
|
$rowBytes += $w * int(($_+7)/8) foreach @bits; |
5736
|
6
|
|
|
|
|
15
|
my $dat = ''; |
5737
|
6
|
|
|
|
|
18
|
my @off = split ' ', $vals{StripOffsets}; |
5738
|
6
|
|
|
|
|
20
|
my @len = split ' ', $vals{StripByteCounts}; |
5739
|
|
|
|
|
|
|
# read the image data |
5740
|
6
|
|
|
|
|
29
|
for ($j=0; $j<@off; ++$j) { |
5741
|
6
|
100
|
|
|
|
38
|
next SubFile unless $len[$j] == $rowBytes * $vals{RowsPerStrip}; |
5742
|
4
|
|
|
|
|
23
|
my $tmp = $et->ExtractBinary($off[$j], $len[$j]); |
5743
|
4
|
50
|
|
|
|
13
|
next SubFile unless defined $tmp; |
5744
|
4
|
|
|
|
|
24
|
$dat .= $tmp; |
5745
|
|
|
|
|
|
|
} |
5746
|
|
|
|
|
|
|
# generate the TIFF image |
5747
|
|
|
|
|
|
|
my %entries = ( |
5748
|
|
|
|
|
|
|
0x0fe => 0, # SubfileType = 0 |
5749
|
|
|
|
|
|
|
0x100 => $w, # ImageWidth |
5750
|
|
|
|
|
|
|
0x101 => $h, # ImageHeight |
5751
|
|
|
|
|
|
|
0x102 => $vals{BitsPerSample},# BitsPerSample |
5752
|
|
|
|
|
|
|
0x103 => $vals{Compression},# Compression |
5753
|
|
|
|
|
|
|
0x106 => $vals{PhotometricInterpretation}, # PhotometricInterpretation |
5754
|
|
|
|
|
|
|
0x111 => 0, # StripOffsets (will be adjusted later) |
5755
|
|
|
|
|
|
|
0x112 => $vals{Orientation},# Orientation |
5756
|
|
|
|
|
|
|
0x115 => $vals{SamplesPerPixel}, # SamplesPerPixel |
5757
|
|
|
|
|
|
|
0x116 => $h, # RowsPerStrip |
5758
|
|
|
|
|
|
|
0x117 => $h * $rowBytes, # StripByteCounts |
5759
|
|
|
|
|
|
|
0x11a => 72, # XResolution = 72 |
5760
|
|
|
|
|
|
|
0x11b => 72, # YResolution = 72 |
5761
|
|
|
|
|
|
|
0x11c => $vals{PlanarConfiguration}, # PlanarConfiguration |
5762
|
4
|
|
|
|
|
77
|
0x128 => 2, # ResolutionUnit = 2 |
5763
|
|
|
|
|
|
|
); |
5764
|
4
|
|
|
|
|
20
|
my $img = GenerateTIFF(\%entries, \$dat); |
5765
|
|
|
|
|
|
|
|
5766
|
4
|
50
|
33
|
|
|
33
|
if (not defined $img) { |
|
|
50
|
|
|
|
|
|
5767
|
0
|
0
|
|
|
|
0
|
$et->Warn('Invalid ' . ($w > 256 ? 'Preview' : 'Thumbnail') . 'TIFF data'); |
5768
|
|
|
|
|
|
|
} elsif ($rtn or $w > 256) { # (call it a preview if larger than 256 pixels) |
5769
|
0
|
|
|
|
|
0
|
$et->FoundTag('PreviewTIFF', \$img, $et->GetGroup($key)); |
5770
|
|
|
|
|
|
|
} else { |
5771
|
4
|
|
|
|
|
10
|
$rtn = \$img; |
5772
|
4
|
|
|
|
|
24
|
($grp0, $grp1) = $et->GetGroup($key); |
5773
|
|
|
|
|
|
|
} |
5774
|
|
|
|
|
|
|
} |
5775
|
14
|
50
|
|
|
|
49
|
return $rtn unless wantarray; |
5776
|
14
|
|
|
|
|
411
|
return ($rtn, $grp0, $grp1); |
5777
|
|
|
|
|
|
|
} |
5778
|
|
|
|
|
|
|
|
5779
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5780
|
|
|
|
|
|
|
# Extract image from file |
5781
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object reference, 1) data offset (in file), 2) data length |
5782
|
|
|
|
|
|
|
# 3) [optional] tag name |
5783
|
|
|
|
|
|
|
# Returns: Reference to Image if specifically requested or "Binary data" message |
5784
|
|
|
|
|
|
|
# Returns undef if there was an error loading the image |
5785
|
|
|
|
|
|
|
sub ExtractImage($$$$) |
5786
|
|
|
|
|
|
|
{ |
5787
|
200
|
|
|
200
|
0
|
814
|
my ($et, $offset, $len, $tag) = @_; |
5788
|
200
|
|
|
|
|
563
|
my $dataPt = \$$et{EXIF_DATA}; |
5789
|
200
|
|
|
|
|
452
|
my $dataPos = $$et{EXIF_POS}; |
5790
|
200
|
|
|
|
|
347
|
my $image; |
5791
|
|
|
|
|
|
|
|
5792
|
|
|
|
|
|
|
# no image if length is zero, and don't try to extract binary from XMP file |
5793
|
200
|
100
|
100
|
|
|
1624
|
return undef if not $len or $$et{FILE_TYPE} eq 'XMP'; |
5794
|
|
|
|
|
|
|
|
5795
|
|
|
|
|
|
|
# take data from EXIF block if possible |
5796
|
139
|
100
|
66
|
|
|
1203
|
if (defined $dataPos and $offset>=$dataPos and $offset+$len<=$dataPos+length($$dataPt)) { |
|
|
|
100
|
|
|
|
|
5797
|
97
|
|
|
|
|
522
|
$image = substr($$dataPt, $offset-$dataPos, $len); |
5798
|
|
|
|
|
|
|
} else { |
5799
|
42
|
|
|
|
|
217
|
$image = $et->ExtractBinary($offset, $len, $tag); |
5800
|
42
|
100
|
|
|
|
143
|
return undef unless defined $image; |
5801
|
|
|
|
|
|
|
# patch for incorrect ThumbnailOffset in some Sony DSLR-A100 ARW images |
5802
|
37
|
0
|
66
|
|
|
250
|
if ($tag and $tag eq 'ThumbnailImage' and $$et{TIFF_TYPE} eq 'ARW' and |
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
0
|
|
|
|
|
5803
|
|
|
|
|
|
|
$$et{Model} eq 'DSLR-A100' and $offset < 0x10000 and |
5804
|
|
|
|
|
|
|
$image !~ /^(Binary data|\xff\xd8\xff)/) |
5805
|
|
|
|
|
|
|
{ |
5806
|
0
|
|
|
|
|
0
|
my $try = $et->ExtractBinary($offset + 0x10000, $len, $tag); |
5807
|
0
|
0
|
0
|
|
|
0
|
if (defined $try and $try =~ /^\xff\xd8\xff/) { |
5808
|
0
|
|
|
|
|
0
|
$image = $try; |
5809
|
0
|
|
|
|
|
0
|
$$et{VALUE}{ThumbnailOffset} += 0x10000; |
5810
|
0
|
|
|
|
|
0
|
$et->Warn('Adjusted incorrect A100 ThumbnailOffset', 1); |
5811
|
|
|
|
|
|
|
} |
5812
|
|
|
|
|
|
|
} |
5813
|
|
|
|
|
|
|
} |
5814
|
134
|
|
|
|
|
767
|
return $et->ValidateImage(\$image, $tag); |
5815
|
|
|
|
|
|
|
} |
5816
|
|
|
|
|
|
|
|
5817
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5818
|
|
|
|
|
|
|
# Utility routine to return tag ID string for warnings |
5819
|
|
|
|
|
|
|
# Inputs: 0) Tag ID, 1) [optional] TagInfo ref |
5820
|
|
|
|
|
|
|
# Returns: "tag 0xXXXX NAME" |
5821
|
|
|
|
|
|
|
sub TagName($;$) |
5822
|
|
|
|
|
|
|
{ |
5823
|
20
|
|
|
20
|
0
|
42
|
my ($tagID, $tagInfo) = @_; |
5824
|
20
|
100
|
|
|
|
59
|
my $tagName = $tagInfo ? ' '.$$tagInfo{Name} : ''; |
5825
|
20
|
|
|
|
|
98
|
return sprintf('tag 0x%.4x%s', $tagID, $tagName); |
5826
|
|
|
|
|
|
|
} |
5827
|
|
|
|
|
|
|
|
5828
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5829
|
|
|
|
|
|
|
# Get class name of next IFD offset for HtmlDump output |
5830
|
|
|
|
|
|
|
# Inputs: 0) ExifTool ref, 1) current class ID |
5831
|
|
|
|
|
|
|
# Returns: 0) new IFD offset name, 1) new class ID including "Offset_" for new offset |
5832
|
|
|
|
|
|
|
# 2) new "Offset_" ID |
5833
|
|
|
|
|
|
|
sub NextOffsetName($;$) |
5834
|
|
|
|
|
|
|
{ |
5835
|
0
|
|
|
0
|
0
|
0
|
my ($et, $id) = @_; |
5836
|
0
|
0
|
|
|
|
0
|
$$et{OffsetNum} = defined $$et{OffsetNum} ? $$et{OffsetNum} + 1 : 0; |
5837
|
0
|
|
|
|
|
0
|
my $offName = 'o' . $$et{OffsetNum}; |
5838
|
0
|
|
|
|
|
0
|
my $sid = "Offset_$offName"; |
5839
|
0
|
0
|
|
|
|
0
|
$id = (defined $id ? "$id " : '') . $sid; |
5840
|
0
|
|
|
|
|
0
|
return ($offName, $id, $sid); |
5841
|
|
|
|
|
|
|
} |
5842
|
|
|
|
|
|
|
|
5843
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
5844
|
|
|
|
|
|
|
# Process EXIF directory |
5845
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object reference |
5846
|
|
|
|
|
|
|
# 1) Reference to directory information hash |
5847
|
|
|
|
|
|
|
# 2) Pointer to tag table for this directory |
5848
|
|
|
|
|
|
|
# Returns: 1 on success, otherwise returns 0 and sets a Warning |
5849
|
|
|
|
|
|
|
sub ProcessExif($$$) |
5850
|
|
|
|
|
|
|
{ |
5851
|
1051
|
|
|
1051
|
0
|
2502
|
my ($et, $dirInfo, $tagTablePtr) = @_; |
5852
|
1051
|
|
|
|
|
2088
|
my $dataPt = $$dirInfo{DataPt}; |
5853
|
1051
|
|
100
|
|
|
3747
|
my $dataPos = $$dirInfo{DataPos} || 0; |
5854
|
1051
|
|
|
|
|
2010
|
my $dataLen = $$dirInfo{DataLen}; |
5855
|
1051
|
|
100
|
|
|
2836
|
my $dirStart = $$dirInfo{DirStart} || 0; |
5856
|
1051
|
|
100
|
|
|
2868
|
my $dirLen = $$dirInfo{DirLen} || $dataLen - $dirStart; |
5857
|
1051
|
|
|
|
|
2019
|
my $dirName = $$dirInfo{DirName}; |
5858
|
1051
|
|
100
|
|
|
2695
|
my $base = $$dirInfo{Base} || 0; |
5859
|
1051
|
|
|
|
|
1650
|
my $firstBase = $base; |
5860
|
1051
|
|
|
|
|
1740
|
my $raf = $$dirInfo{RAF}; |
5861
|
1051
|
|
|
|
|
3567
|
my $verbose = $et->Options('Verbose'); |
5862
|
1051
|
|
|
|
|
2447
|
my $validate = $et->Options('Validate'); |
5863
|
1051
|
|
|
|
|
3124
|
my $saveFormat = $et->Options('SaveFormat'); |
5864
|
1051
|
|
|
|
|
2249
|
my $htmlDump = $$et{HTML_DUMP}; |
5865
|
1051
|
|
|
|
|
1716
|
my $success = 1; |
5866
|
1051
|
|
|
|
|
2016
|
my ($tagKey, $dirSize, $makerAddr, $strEnc, %offsetInfo, $offName, $nextOffName); |
5867
|
1051
|
|
|
|
|
2833
|
my $inMakerNotes = $$tagTablePtr{GROUPS}{0} eq 'MakerNotes'; |
5868
|
1051
|
|
|
|
|
2964
|
my $isExif = ($tagTablePtr eq \%Image::ExifTool::Exif::Main); |
5869
|
|
|
|
|
|
|
|
5870
|
|
|
|
|
|
|
# set encoding to assume for strings |
5871
|
1051
|
100
|
|
|
|
3941
|
$strEnc = $et->Options('CharsetEXIF') if $$tagTablePtr{GROUPS}{0} eq 'EXIF'; |
5872
|
|
|
|
|
|
|
|
5873
|
|
|
|
|
|
|
# ignore non-standard EXIF while in strict MWG compatibility mode |
5874
|
1051
|
50
|
100
|
|
|
5167
|
if (($validate or $Image::ExifTool::MWG::strict) and $dirName eq 'IFD0' and |
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
5875
|
|
|
|
|
|
|
$isExif and $$et{FILE_TYPE} =~ /^(JPEG|TIFF|PSD)$/) |
5876
|
|
|
|
|
|
|
{ |
5877
|
7
|
|
|
|
|
33
|
my $path = $et->MetadataPath(); |
5878
|
7
|
50
|
|
|
|
47
|
unless ($path =~ /^(JPEG-APP1-IFD0|TIFF-IFD0|PSD-EXIFInfo-IFD0)$/) { |
5879
|
0
|
0
|
|
|
|
0
|
if ($Image::ExifTool::MWG::strict) { |
5880
|
0
|
|
|
|
|
0
|
$et->Warn("Ignored non-standard EXIF at $path"); |
5881
|
0
|
|
|
|
|
0
|
return 0; |
5882
|
|
|
|
|
|
|
} else { |
5883
|
0
|
|
|
|
|
0
|
$et->Warn("Non-standard EXIF at $path", 1); |
5884
|
|
|
|
|
|
|
} |
5885
|
|
|
|
|
|
|
} |
5886
|
|
|
|
|
|
|
} |
5887
|
|
|
|
|
|
|
# mix htmlDump and Validate into verbose so we can test for all at once |
5888
|
1051
|
50
|
|
|
|
2622
|
$verbose = -1 if $htmlDump; |
5889
|
1051
|
100
|
66
|
|
|
2659
|
$verbose = -2 if $validate and not $verbose; |
5890
|
1051
|
100
|
|
|
|
3184
|
$dirName eq 'EXIF' and $dirName = $$dirInfo{DirName} = 'IFD0'; |
5891
|
1051
|
100
|
100
|
|
|
6488
|
$$dirInfo{Multi} = 1 if $dirName =~ /^(IFD0|SubIFD)$/ and not defined $$dirInfo{Multi}; |
5892
|
|
|
|
|
|
|
# get a more descriptive name for MakerNote sub-directories |
5893
|
1051
|
|
|
|
|
2255
|
my $dir = $$dirInfo{Name}; |
5894
|
1051
|
100
|
100
|
|
|
4611
|
$dir = $dirName unless $dir and $inMakerNotes and $dir !~ /^MakerNote/; |
|
|
|
100
|
|
|
|
|
5895
|
|
|
|
|
|
|
|
5896
|
1051
|
|
|
|
|
1848
|
my ($numEntries, $dirEnd); |
5897
|
1051
|
100
|
100
|
|
|
4351
|
if ($dirStart >= 0 and $dirStart <= $dataLen-2) { |
5898
|
|
|
|
|
|
|
# make sure data is large enough (patches bug in Olympus subdirectory lengths) |
5899
|
975
|
|
|
|
|
2803
|
$numEntries = Get16u($dataPt, $dirStart); |
5900
|
975
|
|
|
|
|
1996
|
$dirSize = 2 + 12 * $numEntries; |
5901
|
975
|
|
|
|
|
1500
|
$dirEnd = $dirStart + $dirSize; |
5902
|
975
|
100
|
|
|
|
2321
|
if ($dirSize > $dirLen) { |
5903
|
361
|
50
|
66
|
|
|
1924
|
if (($verbose > 0 or $validate) and not $$dirInfo{SubIFD}) { |
|
|
|
66
|
|
|
|
|
5904
|
0
|
|
|
|
|
0
|
my $short = $dirSize - $dirLen; |
5905
|
0
|
|
|
|
|
0
|
$$et{INDENT} =~ s/..$//; # keep indent the same |
5906
|
0
|
|
|
|
|
0
|
$et->Warn("Short directory size for $dir (missing $short bytes)"); |
5907
|
0
|
|
|
|
|
0
|
$$et{INDENT} .= '| '; |
5908
|
|
|
|
|
|
|
} |
5909
|
361
|
50
|
|
|
|
994
|
undef $dirSize if $dirEnd > $dataLen; # read from file if necessary |
5910
|
|
|
|
|
|
|
} |
5911
|
|
|
|
|
|
|
} |
5912
|
|
|
|
|
|
|
# read IFD from file if necessary |
5913
|
1051
|
100
|
|
|
|
2582
|
unless ($dirSize) { |
5914
|
76
|
|
|
|
|
141
|
$success = 0; |
5915
|
76
|
50
|
|
|
|
228
|
if ($raf) { |
5916
|
|
|
|
|
|
|
# read the count of entries in this IFD |
5917
|
76
|
|
|
|
|
162
|
my $offset = $dirStart + $dataPos; |
5918
|
76
|
|
|
|
|
130
|
my ($buff, $buf2); |
5919
|
76
|
50
|
33
|
|
|
280
|
if ($raf->Seek($offset + $base, 0) and $raf->Read($buff,2) == 2) { |
5920
|
76
|
|
|
|
|
278
|
my $len = 12 * Get16u(\$buff,0); |
5921
|
|
|
|
|
|
|
# also read next IFD pointer if available |
5922
|
76
|
50
|
|
|
|
269
|
if ($raf->Read($buf2, $len+4) >= $len) { |
5923
|
76
|
|
|
|
|
209
|
$buff .= $buf2; |
5924
|
76
|
|
|
|
|
226
|
$dataPt = $$dirInfo{DataPt} = \$buff; |
5925
|
76
|
|
|
|
|
174
|
$dataPos = $$dirInfo{DataPos} = $offset; |
5926
|
76
|
|
|
|
|
180
|
$dataLen = $$dirInfo{DataLen} = length $buff; |
5927
|
76
|
|
|
|
|
153
|
$dirStart = $$dirInfo{DirStart} = 0; |
5928
|
76
|
|
|
|
|
151
|
$dirLen = $$dirInfo{DirLen} = length $buff; |
5929
|
76
|
|
|
|
|
159
|
$success = 1; |
5930
|
|
|
|
|
|
|
} |
5931
|
|
|
|
|
|
|
} |
5932
|
|
|
|
|
|
|
} |
5933
|
76
|
50
|
|
|
|
194
|
if ($success) { |
5934
|
76
|
|
|
|
|
208
|
$numEntries = Get16u($dataPt, $dirStart); |
5935
|
|
|
|
|
|
|
} else { |
5936
|
0
|
|
|
|
|
0
|
$et->Warn("Bad $dir directory", $inMakerNotes); |
5937
|
0
|
0
|
0
|
|
|
0
|
return 0 unless $inMakerNotes and $dirLen >= 14 and $dirStart >= 0 and |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
5938
|
|
|
|
|
|
|
$dirStart + $dirLen <= length($$dataPt); |
5939
|
0
|
|
|
|
|
0
|
$dirSize = $dirLen; |
5940
|
0
|
|
|
|
|
0
|
$numEntries = int(($dirSize - 2) / 12); # read what we can |
5941
|
0
|
|
|
|
|
0
|
Set16u($numEntries, $dataPt, $dirStart); |
5942
|
|
|
|
|
|
|
} |
5943
|
76
|
|
|
|
|
178
|
$dirSize = 2 + 12 * $numEntries; |
5944
|
76
|
|
|
|
|
143
|
$dirEnd = $dirStart + $dirSize; |
5945
|
|
|
|
|
|
|
} |
5946
|
1051
|
100
|
|
|
|
2622
|
$verbose > 0 and $et->VerboseDir($dirName, $numEntries); |
5947
|
1051
|
|
|
|
|
1960
|
my $bytesFromEnd = $dataLen - $dirEnd; |
5948
|
1051
|
100
|
|
|
|
2383
|
if ($bytesFromEnd < 4) { |
5949
|
4
|
50
|
33
|
|
|
22
|
unless ($bytesFromEnd==2 or $bytesFromEnd==0) { |
5950
|
0
|
|
|
|
|
0
|
$et->Warn("Illegal $dir directory size ($numEntries entries)"); |
5951
|
0
|
|
|
|
|
0
|
return 0; |
5952
|
|
|
|
|
|
|
} |
5953
|
|
|
|
|
|
|
} |
5954
|
|
|
|
|
|
|
# fix base offset for maker notes if necessary |
5955
|
1051
|
100
|
|
|
|
2782
|
if (defined $$dirInfo{MakerNoteAddr}) { |
5956
|
123
|
|
|
|
|
315
|
$makerAddr = $$dirInfo{MakerNoteAddr}; |
5957
|
123
|
|
|
|
|
366
|
delete $$dirInfo{MakerNoteAddr}; |
5958
|
123
|
100
|
|
|
|
614
|
if (Image::ExifTool::MakerNotes::FixBase($et, $dirInfo)) { |
5959
|
3
|
|
|
|
|
8
|
$base = $$dirInfo{Base}; |
5960
|
3
|
|
|
|
|
6
|
$dataPos = $$dirInfo{DataPos}; |
5961
|
|
|
|
|
|
|
} |
5962
|
|
|
|
|
|
|
} |
5963
|
1051
|
50
|
|
|
|
2437
|
if ($htmlDump) { |
5964
|
0
|
|
|
|
|
0
|
$offName = $$dirInfo{OffsetName}; |
5965
|
0
|
0
|
0
|
|
|
0
|
my $longName = $dir eq 'MakerNotes' ? ($$dirInfo{Name} || $dir) : $dir; |
5966
|
0
|
0
|
|
|
|
0
|
if (defined $makerAddr) { |
5967
|
0
|
|
|
|
|
0
|
my $hdrLen = $dirStart + $dataPos + $base - $makerAddr; |
5968
|
0
|
0
|
|
|
|
0
|
$et->HDump($makerAddr, $hdrLen, "MakerNotes header", $longName) if $hdrLen > 0; |
5969
|
|
|
|
|
|
|
} |
5970
|
0
|
0
|
|
|
|
0
|
unless ($$dirInfo{NoDumpEntryCount}) { |
5971
|
0
|
|
|
|
|
0
|
$et->HDump($dirStart + $dataPos + $base, 2, "$longName entries", |
5972
|
|
|
|
|
|
|
"Entry count: $numEntries", undef, $offName); |
5973
|
|
|
|
|
|
|
} |
5974
|
0
|
|
|
|
|
0
|
my $tip; |
5975
|
0
|
|
|
|
|
0
|
my $id = $offName; |
5976
|
0
|
0
|
|
|
|
0
|
if ($bytesFromEnd >= 4) { |
5977
|
0
|
0
|
|
|
|
0
|
my $nxt = ($dir =~ /^(.*?)(\d+)$/) ? $1 . ($2 + 1) : 'Next IFD'; |
5978
|
0
|
|
|
|
|
0
|
my $off = Get32u($dataPt, $dirEnd); |
5979
|
0
|
|
|
|
|
0
|
$tip = sprintf("$nxt offset: 0x%.4x", $off); |
5980
|
0
|
0
|
|
|
|
0
|
($nextOffName, $id) = NextOffsetName($et, $offName) if $off; |
5981
|
|
|
|
|
|
|
} |
5982
|
0
|
|
|
|
|
0
|
$et->HDump($dirEnd + $dataPos + $base, 4, "Next IFD", $tip, 0, $id); |
5983
|
|
|
|
|
|
|
} |
5984
|
|
|
|
|
|
|
|
5985
|
|
|
|
|
|
|
# patch for Canon EOS 40D firmware 1.0.4 bug (incorrect directory counts) |
5986
|
|
|
|
|
|
|
# (must do this before parsing directory or CameraSettings offset will be suspicious) |
5987
|
1051
|
50
|
66
|
|
|
3580
|
if ($inMakerNotes and $$et{Model} eq 'Canon EOS 40D' and $numEntries) { |
|
|
|
33
|
|
|
|
|
5988
|
0
|
|
|
|
|
0
|
my $entry = $dirStart + 2 + 12 * ($numEntries - 1); |
5989
|
0
|
|
|
|
|
0
|
my $fmt = Get16u($dataPt, $entry + 2); |
5990
|
0
|
0
|
0
|
|
|
0
|
if ($fmt < 1 or $fmt > 13) { |
5991
|
0
|
|
|
|
|
0
|
$et->HDump($entry+$dataPos+$base,12,"[invalid IFD entry]", |
5992
|
|
|
|
|
|
|
"Bad format type: $fmt", 1, $offName); |
5993
|
|
|
|
|
|
|
# adjust the number of directory entries |
5994
|
0
|
|
|
|
|
0
|
--$numEntries; |
5995
|
0
|
|
|
|
|
0
|
$dirEnd -= 12; |
5996
|
|
|
|
|
|
|
} |
5997
|
|
|
|
|
|
|
} |
5998
|
|
|
|
|
|
|
|
5999
|
|
|
|
|
|
|
# make sure that Compression and SubfileType are defined for this IFD (for Condition's) |
6000
|
1051
|
|
|
|
|
2762
|
$$et{Compression} = $$et{SubfileType} = ''; |
6001
|
|
|
|
|
|
|
|
6002
|
|
|
|
|
|
|
# loop through all entries in an EXIF directory (IFD) |
6003
|
1051
|
|
|
|
|
2123
|
my ($index, $valEnd, $offList, $offHash, $mapFmt, @valPos); |
6004
|
1051
|
100
|
|
|
|
2744
|
$mapFmt = $$tagTablePtr{VARS}{MAP_FORMAT} if $$tagTablePtr{VARS}; |
6005
|
|
|
|
|
|
|
|
6006
|
1051
|
|
|
|
|
2299
|
my ($warnCount, $lastID) = (0, -1); |
6007
|
1051
|
|
|
|
|
2830
|
for ($index=0; $index<$numEntries; ++$index) { |
6008
|
14986
|
50
|
|
|
|
25182
|
if ($warnCount > 10) { |
6009
|
0
|
0
|
|
|
|
0
|
$et->Warn("Too many warnings -- $dir parsing aborted", 2) and return 0; |
6010
|
|
|
|
|
|
|
} |
6011
|
14986
|
|
|
|
|
22095
|
my $entry = $dirStart + 2 + 12 * $index; |
6012
|
14986
|
|
|
|
|
27915
|
my $tagID = Get16u($dataPt, $entry); |
6013
|
14986
|
|
|
|
|
28465
|
my $format = Get16u($dataPt, $entry+2); |
6014
|
14986
|
|
|
|
|
31412
|
my $count = Get32u($dataPt, $entry+4); |
6015
|
14986
|
50
|
33
|
|
|
46966
|
if ($format < 1 or $format > 13) { |
6016
|
0
|
0
|
0
|
|
|
0
|
if ($mapFmt and $$mapFmt{$format}) { |
6017
|
0
|
|
|
|
|
0
|
$format = $$mapFmt{$format}; |
6018
|
|
|
|
|
|
|
} else { |
6019
|
0
|
|
|
|
|
0
|
$et->HDump($entry+$dataPos+$base,12,"[invalid IFD entry]", |
6020
|
|
|
|
|
|
|
"Bad format type: $format", 1, $offName); |
6021
|
|
|
|
|
|
|
# warn unless the IFD was just padded with zeros |
6022
|
0
|
0
|
0
|
|
|
0
|
if ($format or $validate) { |
6023
|
0
|
|
|
|
|
0
|
$et->Warn("Bad format ($format) for $dir entry $index", $inMakerNotes); |
6024
|
0
|
|
|
|
|
0
|
++$warnCount; |
6025
|
|
|
|
|
|
|
} |
6026
|
|
|
|
|
|
|
# assume corrupted IFD if this is our first entry (except Sony ILCE-7M2 firmware 1.21) |
6027
|
0
|
0
|
0
|
|
|
0
|
return 0 unless $index or $$et{Model} eq 'ILCE-7M2'; |
6028
|
0
|
|
|
|
|
0
|
next; |
6029
|
|
|
|
|
|
|
} |
6030
|
|
|
|
|
|
|
} |
6031
|
14986
|
|
|
|
|
24724
|
my $formatStr = $formatName[$format]; # get name of this format |
6032
|
14986
|
|
|
|
|
17985
|
my $valueDataPt = $dataPt; |
6033
|
14986
|
|
|
|
|
16609
|
my $valueDataPos = $dataPos; |
6034
|
14986
|
|
|
|
|
17286
|
my $valueDataLen = $dataLen; |
6035
|
14986
|
|
|
|
|
18223
|
my $valuePtr = $entry + 8; # pointer to value within $$dataPt |
6036
|
14986
|
|
|
|
|
31173
|
my $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID); |
6037
|
14986
|
|
|
|
|
21418
|
my ($origFormStr, $bad, $rational, $subOffName); |
6038
|
|
|
|
|
|
|
# save the EXIF format codes if requested |
6039
|
14986
|
50
|
|
|
|
23232
|
$$et{SaveFormat}{$saveFormat = $formatStr} = 1 if $saveFormat; |
6040
|
|
|
|
|
|
|
# hack to patch incorrect count in Kodak SubIFD3 tags |
6041
|
14986
|
50
|
100
|
|
|
53205
|
if ($count < 2 and ref $$tagTablePtr{$tagID} eq 'HASH' and $$tagTablePtr{$tagID}{FixCount}) { |
|
|
|
66
|
|
|
|
|
6042
|
0
|
0
|
|
|
|
0
|
$offList or ($offList, $offHash) = GetOffList($dataPt, $dirStart, $dataPos, |
6043
|
|
|
|
|
|
|
$numEntries, $tagTablePtr); |
6044
|
0
|
|
|
|
|
0
|
my $i = $$offHash{Get32u($dataPt, $valuePtr)}; |
6045
|
0
|
0
|
0
|
|
|
0
|
if (defined $i and $i < $#$offList) { |
6046
|
0
|
|
|
|
|
0
|
my $oldCount = $count; |
6047
|
0
|
|
|
|
|
0
|
$count = int(($$offList[$i+1] - $$offList[$i]) / $formatSize[$format]); |
6048
|
0
|
0
|
|
|
|
0
|
$origFormStr = $formatName[$format] . '[' . $oldCount . ']' if $oldCount != $count; |
6049
|
|
|
|
|
|
|
} |
6050
|
|
|
|
|
|
|
} |
6051
|
14986
|
100
|
100
|
|
|
26908
|
$validate and not $inMakerNotes and Image::ExifTool::Validate::ValidateExif( |
6052
|
|
|
|
|
|
|
$et, $tagTablePtr, $tagID, $tagInfo, $lastID, $dir, $count, $formatStr); |
6053
|
14986
|
|
|
|
|
22790
|
my $size = $count * $formatSize[$format]; |
6054
|
14986
|
|
|
|
|
18606
|
my $readSize = $size; |
6055
|
14986
|
100
|
|
|
|
25104
|
if ($size > 4) { |
6056
|
6739
|
50
|
0
|
|
|
13132
|
if ($size > 0x7fffffff and (not $tagInfo or not $$tagInfo{ReadFromRAF})) { |
|
|
|
33
|
|
|
|
|
6057
|
0
|
|
|
|
|
0
|
$et->Warn(sprintf("Invalid size (%u) for %s %s",$size,$dir,TagName($tagID,$tagInfo)), $inMakerNotes); |
6058
|
0
|
|
|
|
|
0
|
++$warnCount; |
6059
|
0
|
|
|
|
|
0
|
next; |
6060
|
|
|
|
|
|
|
} |
6061
|
6739
|
|
|
|
|
12239
|
$valuePtr = Get32u($dataPt, $valuePtr); |
6062
|
6739
|
100
|
100
|
|
|
14007
|
if ($validate and not $inMakerNotes) { |
6063
|
20
|
|
|
|
|
52
|
my $tagName = TagName($tagID, $tagInfo); |
6064
|
20
|
50
|
|
|
|
57
|
$et->Warn("Odd offset for $dir $tagName", 1) if $valuePtr & 0x01; |
6065
|
20
|
50
|
33
|
|
|
120
|
if ($valuePtr < 8 || ($valuePtr + $size > length($$dataPt) and |
|
|
|
33
|
|
|
|
|
6066
|
|
|
|
|
|
|
$valuePtr + $size > $$et{VALUE}{FileSize})) |
6067
|
|
|
|
|
|
|
{ |
6068
|
0
|
|
|
|
|
0
|
$et->Warn("Invalid offset for $dir $tagName"); |
6069
|
0
|
|
|
|
|
0
|
++$warnCount; |
6070
|
0
|
|
|
|
|
0
|
next; |
6071
|
|
|
|
|
|
|
} |
6072
|
20
|
50
|
33
|
|
|
84
|
if ($valuePtr + $size > $dirStart + $dataPos and $valuePtr < $dirEnd + $dataPos + 4) { |
6073
|
0
|
|
|
|
|
0
|
$et->Warn("Value for $dir $tagName overlaps IFD"); |
6074
|
|
|
|
|
|
|
} |
6075
|
20
|
|
|
|
|
43
|
foreach (@valPos) { |
6076
|
81
|
50
|
33
|
|
|
249
|
next if $$_[0] >= $valuePtr + $size or $$_[0] + $$_[1] <= $valuePtr; |
6077
|
0
|
|
|
|
|
0
|
$et->Warn("Value for $dir $tagName overlaps $$_[2]"); |
6078
|
|
|
|
|
|
|
} |
6079
|
20
|
|
|
|
|
54
|
push @valPos, [ $valuePtr, $size, $tagName ]; |
6080
|
|
|
|
|
|
|
} |
6081
|
|
|
|
|
|
|
# fix valuePtr if necessary |
6082
|
6739
|
50
|
|
|
|
13107
|
if ($$dirInfo{FixOffsets}) { |
6083
|
0
|
|
|
|
|
0
|
my $wFlag; |
6084
|
0
|
0
|
|
|
|
0
|
$valEnd or $valEnd = $dataPos + $dirEnd + 4; |
6085
|
|
|
|
|
|
|
#### eval FixOffsets ($valuePtr, $valEnd, $size, $tagID, $wFlag) |
6086
|
0
|
|
|
|
|
0
|
eval $$dirInfo{FixOffsets}; |
6087
|
|
|
|
|
|
|
} |
6088
|
6739
|
|
|
|
|
8517
|
my $suspect; |
6089
|
|
|
|
|
|
|
# offset shouldn't point into TIFF header |
6090
|
6739
|
100
|
66
|
|
|
13169
|
$valuePtr < 8 and not $$dirInfo{ZeroOffsetOK} and $suspect = $warnCount; |
6091
|
|
|
|
|
|
|
# convert offset to pointer in $$dataPt |
6092
|
6739
|
100
|
66
|
|
|
30264
|
if ($$dirInfo{EntryBased} or (ref $$tagTablePtr{$tagID} eq 'HASH' and |
|
|
|
66
|
|
|
|
|
6093
|
|
|
|
|
|
|
$$tagTablePtr{$tagID}{EntryBased})) |
6094
|
|
|
|
|
|
|
{ |
6095
|
10
|
|
|
|
|
14
|
$valuePtr += $entry; |
6096
|
|
|
|
|
|
|
} else { |
6097
|
6729
|
|
|
|
|
10086
|
$valuePtr -= $dataPos; |
6098
|
|
|
|
|
|
|
} |
6099
|
|
|
|
|
|
|
# value shouldn't overlap our directory |
6100
|
6739
|
50
|
66
|
|
|
13024
|
$suspect = $warnCount if $valuePtr < $dirEnd and $valuePtr+$size > $dirStart; |
6101
|
|
|
|
|
|
|
# load value from file if necessary |
6102
|
6739
|
100
|
100
|
|
|
19286
|
if ($valuePtr < 0 or $valuePtr+$size > $dataLen) { |
6103
|
|
|
|
|
|
|
# get value by seeking in file if we are allowed |
6104
|
449
|
|
|
|
|
625
|
my $buff; |
6105
|
449
|
50
|
|
|
|
877
|
if ($raf) { |
6106
|
|
|
|
|
|
|
# avoid loading large binary data unless necessary |
6107
|
449
|
|
|
|
|
1031
|
while ($size > BINARY_DATA_LIMIT) { |
6108
|
0
|
0
|
|
|
|
0
|
if ($tagInfo) { |
6109
|
|
|
|
|
|
|
# make large unknown blocks binary data |
6110
|
0
|
0
|
|
|
|
0
|
$$tagInfo{Binary} = 1 if $$tagInfo{Unknown}; |
6111
|
0
|
0
|
|
|
|
0
|
last unless $$tagInfo{Binary}; # must read non-binary data |
6112
|
0
|
0
|
|
|
|
0
|
last if $$tagInfo{SubDirectory}; |
6113
|
0
|
|
|
|
|
0
|
my $lcTag = lc($$tagInfo{Name}); |
6114
|
0
|
0
|
0
|
|
|
0
|
if ($$et{OPTIONS}{Binary} and |
6115
|
|
|
|
|
|
|
not $$et{EXCL_TAG_LOOKUP}{$lcTag}) |
6116
|
|
|
|
|
|
|
{ |
6117
|
|
|
|
|
|
|
# read binary data if specified unless tagsFromFile won't use it |
6118
|
0
|
0
|
0
|
|
|
0
|
last unless $$et{TAGS_FROM_FILE} and $$tagInfo{Protected}; |
6119
|
|
|
|
|
|
|
} |
6120
|
|
|
|
|
|
|
# must read if tag is specified by name |
6121
|
0
|
0
|
|
|
|
0
|
last if $$et{REQ_TAG_LOOKUP}{$lcTag}; |
6122
|
|
|
|
|
|
|
} else { |
6123
|
|
|
|
|
|
|
# must read value if needed for a condition |
6124
|
0
|
0
|
|
|
|
0
|
last if defined $tagInfo; |
6125
|
|
|
|
|
|
|
} |
6126
|
|
|
|
|
|
|
# (note: changing the value without changing $size will cause |
6127
|
|
|
|
|
|
|
# a warning in the verbose output, but we need to maintain the |
6128
|
|
|
|
|
|
|
# proper size for the htmlDump, so we can't change this) |
6129
|
0
|
|
|
|
|
0
|
$buff = "Binary data $size bytes"; |
6130
|
0
|
|
|
|
|
0
|
$readSize = length $buff; |
6131
|
0
|
|
|
|
|
0
|
last; |
6132
|
|
|
|
|
|
|
} |
6133
|
|
|
|
|
|
|
# read from file if necessary |
6134
|
449
|
50
|
|
|
|
905
|
unless (defined $buff) { |
6135
|
449
|
|
|
|
|
585
|
my $wrn; |
6136
|
449
|
|
66
|
|
|
1372
|
my $readFromRAF = ($tagInfo and $$tagInfo{ReadFromRAF}); |
6137
|
449
|
50
|
33
|
|
|
1368
|
if (not $raf->Seek($base + $valuePtr + $dataPos, 0)) { |
|
|
50
|
33
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
6138
|
0
|
|
|
|
|
0
|
$wrn = "Invalid offset for $dir entry $index"; |
6139
|
|
|
|
|
|
|
} elsif ($readFromRAF and $size > BINARY_DATA_LIMIT and |
6140
|
|
|
|
|
|
|
not $$et{REQ_TAG_LOOKUP}{lc $$tagInfo{Name}}) |
6141
|
|
|
|
|
|
|
{ |
6142
|
0
|
|
|
|
|
0
|
$buff = "$$tagInfo{Name} data $size bytes"; |
6143
|
0
|
|
|
|
|
0
|
$readSize = length $buff; |
6144
|
|
|
|
|
|
|
} elsif ($raf->Read($buff,$size) != $size) { |
6145
|
0
|
|
|
|
|
0
|
$wrn = "Error reading value for $dir entry $index"; |
6146
|
|
|
|
|
|
|
} elsif ($readFromRAF) { |
6147
|
|
|
|
|
|
|
# seek back to the start of the value |
6148
|
0
|
|
|
|
|
0
|
$raf->Seek($base + $valuePtr + $dataPos, 0); |
6149
|
|
|
|
|
|
|
} |
6150
|
449
|
50
|
|
|
|
1175
|
if ($wrn) { |
6151
|
0
|
|
|
|
|
0
|
$et->Warn($wrn, $inMakerNotes); |
6152
|
0
|
0
|
0
|
|
|
0
|
return 0 unless $inMakerNotes or $htmlDump; |
6153
|
0
|
|
|
|
|
0
|
++$warnCount; |
6154
|
0
|
0
|
|
|
|
0
|
$buff = '' unless defined $buff; |
6155
|
0
|
|
|
|
|
0
|
$readSize = length $buff; |
6156
|
0
|
|
|
|
|
0
|
$bad = 1; |
6157
|
|
|
|
|
|
|
} |
6158
|
|
|
|
|
|
|
} |
6159
|
449
|
|
|
|
|
649
|
$valueDataLen = length $buff; |
6160
|
449
|
|
|
|
|
674
|
$valueDataPt = \$buff; |
6161
|
449
|
|
|
|
|
615
|
$valueDataPos = $valuePtr + $dataPos; |
6162
|
449
|
|
|
|
|
792
|
$valuePtr = 0; |
6163
|
|
|
|
|
|
|
} else { |
6164
|
0
|
|
|
|
|
0
|
my ($tagStr, $tmpInfo, $leicaTrailer); |
6165
|
0
|
0
|
|
|
|
0
|
if ($tagInfo) { |
|
|
0
|
|
|
|
|
|
6166
|
0
|
|
|
|
|
0
|
$tagStr = $$tagInfo{Name}; |
6167
|
0
|
|
|
|
|
0
|
$leicaTrailer = $$tagInfo{LeicaTrailer}; |
6168
|
|
|
|
|
|
|
} elsif (defined $tagInfo) { |
6169
|
0
|
|
|
|
|
0
|
$tmpInfo = $et->GetTagInfo($tagTablePtr, $tagID, \ '', $formatStr, $count); |
6170
|
0
|
0
|
|
|
|
0
|
if ($tmpInfo) { |
6171
|
0
|
|
|
|
|
0
|
$tagStr = $$tmpInfo{Name}; |
6172
|
0
|
|
|
|
|
0
|
$leicaTrailer = $$tmpInfo{LeicaTrailer}; |
6173
|
|
|
|
|
|
|
} |
6174
|
|
|
|
|
|
|
} |
6175
|
0
|
0
|
0
|
|
|
0
|
if ($tagInfo and $$tagInfo{ChangeBase}) { |
6176
|
|
|
|
|
|
|
# adjust base offset for this tag only |
6177
|
|
|
|
|
|
|
#### eval ChangeBase ($dirStart,$dataPos) |
6178
|
0
|
|
|
|
|
0
|
my $newBase = eval $$tagInfo{ChangeBase}; |
6179
|
0
|
|
|
|
|
0
|
$valuePtr += $newBase; |
6180
|
|
|
|
|
|
|
} |
6181
|
0
|
0
|
|
|
|
0
|
$tagStr or $tagStr = sprintf("tag 0x%.4x",$tagID); |
6182
|
|
|
|
|
|
|
# allow PreviewImage to run outside EXIF data |
6183
|
0
|
0
|
0
|
|
|
0
|
if ($tagStr eq 'PreviewImage' and $$et{RAF}) { |
|
|
0
|
0
|
|
|
|
|
6184
|
0
|
|
|
|
|
0
|
my $pos = $$et{RAF}->Tell(); |
6185
|
0
|
|
|
|
|
0
|
$buff = $et->ExtractBinary($base + $valuePtr + $dataPos, $size, 'PreviewImage'); |
6186
|
0
|
|
|
|
|
0
|
$$et{RAF}->Seek($pos, 0); |
6187
|
0
|
|
|
|
|
0
|
$valueDataPt = \$buff; |
6188
|
0
|
|
|
|
|
0
|
$valueDataPos = $valuePtr + $dataPos; |
6189
|
0
|
|
|
|
|
0
|
$valueDataLen = $size; |
6190
|
0
|
|
|
|
|
0
|
$valuePtr = 0; |
6191
|
|
|
|
|
|
|
} elsif ($leicaTrailer and $$et{RAF}) { |
6192
|
0
|
0
|
|
|
|
0
|
if ($verbose > 0) { |
6193
|
0
|
|
|
|
|
0
|
$et->VPrint(0, "$$et{INDENT}$index) $tagStr --> (outside APP1 segment)\n"); |
6194
|
|
|
|
|
|
|
} |
6195
|
0
|
0
|
|
|
|
0
|
if ($et->Options('FastScan')) { |
6196
|
0
|
|
|
|
|
0
|
$et->Warn('Ignored Leica MakerNote trailer'); |
6197
|
|
|
|
|
|
|
} else { |
6198
|
0
|
|
|
|
|
0
|
require Image::ExifTool::Fixup; |
6199
|
|
|
|
|
|
|
$$et{LeicaTrailer} = { |
6200
|
0
|
|
0
|
|
|
0
|
TagInfo => $tagInfo || $tmpInfo, |
6201
|
|
|
|
|
|
|
Offset => $base + $valuePtr + $dataPos, |
6202
|
|
|
|
|
|
|
Size => $size, |
6203
|
|
|
|
|
|
|
Fixup => new Image::ExifTool::Fixup, |
6204
|
|
|
|
|
|
|
}; |
6205
|
|
|
|
|
|
|
} |
6206
|
|
|
|
|
|
|
} else { |
6207
|
0
|
|
|
|
|
0
|
$et->Warn("Bad offset for $dir $tagStr", $inMakerNotes); |
6208
|
0
|
|
|
|
|
0
|
++$warnCount; |
6209
|
|
|
|
|
|
|
} |
6210
|
0
|
0
|
|
|
|
0
|
unless (defined $buff) { |
6211
|
0
|
|
|
|
|
0
|
$valueDataPt = ''; |
6212
|
0
|
|
|
|
|
0
|
$valueDataPos = $valuePtr + $dataPos; |
6213
|
0
|
|
|
|
|
0
|
$valueDataLen = 0; |
6214
|
0
|
|
|
|
|
0
|
$valuePtr = 0; |
6215
|
0
|
|
|
|
|
0
|
$bad = 1; |
6216
|
|
|
|
|
|
|
} |
6217
|
|
|
|
|
|
|
} |
6218
|
|
|
|
|
|
|
} |
6219
|
|
|
|
|
|
|
# warn about suspect offsets if they didn't already cause another warning |
6220
|
6739
|
100
|
66
|
|
|
14034
|
if (defined $suspect and $suspect == $warnCount) { |
6221
|
2
|
50
|
|
|
|
5
|
my $tagStr = $tagInfo ? $$tagInfo{Name} : sprintf('tag 0x%.4x', $tagID); |
6222
|
2
|
50
|
|
|
|
8
|
if ($et->Warn("Suspicious $dir offset for $tagStr", $inMakerNotes)) { |
6223
|
2
|
|
|
|
|
3
|
++$warnCount; |
6224
|
2
|
50
|
|
|
|
7
|
next unless $verbose; |
6225
|
|
|
|
|
|
|
} |
6226
|
|
|
|
|
|
|
} |
6227
|
|
|
|
|
|
|
} |
6228
|
|
|
|
|
|
|
# treat single unknown byte as int8u |
6229
|
14984
|
100
|
100
|
|
|
29610
|
$formatStr = 'int8u' if $format == 7 and $count == 1; |
6230
|
|
|
|
|
|
|
|
6231
|
14984
|
|
|
|
|
19919
|
my ($val, $subdir, $wrongFormat); |
6232
|
14984
|
50
|
33
|
|
|
26187
|
if ($tagID > 0xf000 and $isExif) { |
6233
|
0
|
|
|
|
|
0
|
my $oldInfo = $$tagTablePtr{$tagID}; |
6234
|
0
|
0
|
0
|
|
|
0
|
if ((not $oldInfo or (ref $oldInfo eq 'HASH' and $$oldInfo{Condition} and |
|
|
|
0
|
|
|
|
|
6235
|
|
|
|
|
|
|
not $$oldInfo{PSRaw})) and not $bad) |
6236
|
|
|
|
|
|
|
{ |
6237
|
|
|
|
|
|
|
# handle special case of Photoshop RAW tags (0xfde8-0xfe58) |
6238
|
|
|
|
|
|
|
# --> generate tags from the value if possible |
6239
|
0
|
|
|
|
|
0
|
$val = ReadValue($valueDataPt,$valuePtr,$formatStr,$count,$readSize); |
6240
|
0
|
0
|
0
|
|
|
0
|
if (defined $val and $val =~ /(.*): (.*)/) { |
6241
|
0
|
|
|
|
|
0
|
my $tag = $1; |
6242
|
0
|
|
|
|
|
0
|
$val = $2; |
6243
|
0
|
|
|
|
|
0
|
$tag =~ s/'s//; # remove 's (so "Owner's Name" becomes "OwnerName") |
6244
|
0
|
|
|
|
|
0
|
$tag =~ tr/a-zA-Z0-9_//cd; # remove unknown characters |
6245
|
0
|
0
|
|
|
|
0
|
if ($tag) { |
6246
|
0
|
|
|
|
|
0
|
$tagInfo = { |
6247
|
|
|
|
|
|
|
Name => $tag, |
6248
|
|
|
|
|
|
|
Condition => '$$self{TIFF_TYPE} ne "DCR"', |
6249
|
|
|
|
|
|
|
ValueConv => '$_=$val;s/^.*: //;$_', # remove descr |
6250
|
|
|
|
|
|
|
PSRaw => 1, # (just as flag to avoid adding this again) |
6251
|
|
|
|
|
|
|
}; |
6252
|
0
|
|
|
|
|
0
|
AddTagToTable($tagTablePtr, $tagID, $tagInfo); |
6253
|
|
|
|
|
|
|
# generate conditional list if a conditional tag already existed |
6254
|
0
|
0
|
|
|
|
0
|
$$tagTablePtr{$tagID} = [ $oldInfo, $tagInfo ] if $oldInfo; |
6255
|
|
|
|
|
|
|
} |
6256
|
|
|
|
|
|
|
} |
6257
|
|
|
|
|
|
|
} |
6258
|
|
|
|
|
|
|
} |
6259
|
14984
|
100
|
100
|
|
|
39812
|
if (defined $tagInfo and not $tagInfo) { |
6260
|
387
|
50
|
|
|
|
981
|
if ($bad) { |
6261
|
0
|
|
|
|
|
0
|
undef $tagInfo; |
6262
|
|
|
|
|
|
|
} else { |
6263
|
|
|
|
|
|
|
# GetTagInfo() required the value for a Condition |
6264
|
387
|
100
|
|
|
|
1432
|
my $tmpVal = substr($$valueDataPt, $valuePtr, $readSize < 128 ? $readSize : 128); |
6265
|
|
|
|
|
|
|
# (use original format name in this call -- $formatStr may have been changed to int8u) |
6266
|
387
|
|
|
|
|
1316
|
$tagInfo = $et->GetTagInfo($tagTablePtr, $tagID, \$tmpVal, |
6267
|
|
|
|
|
|
|
$formatName[$format], $count); |
6268
|
|
|
|
|
|
|
} |
6269
|
|
|
|
|
|
|
} |
6270
|
|
|
|
|
|
|
# make sure we are handling the 'ifd' format properly |
6271
|
14984
|
50
|
66
|
|
|
42249
|
if (($format == 13 or $format == 18) and (not $tagInfo or not $$tagInfo{SubIFD})) { |
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
6272
|
0
|
|
|
|
|
0
|
my $str = sprintf('%s tag 0x%.4x IFD format not handled', $dirName, $tagID); |
6273
|
0
|
|
|
|
|
0
|
$et->Warn($str, $inMakerNotes); |
6274
|
|
|
|
|
|
|
} |
6275
|
14984
|
100
|
|
|
|
23291
|
if (defined $tagInfo) { |
6276
|
14436
|
|
|
|
|
21798
|
my $readFormat = $$tagInfo{Format}; |
6277
|
14436
|
|
|
|
|
18885
|
$subdir = $$tagInfo{SubDirectory}; |
6278
|
|
|
|
|
|
|
# unless otherwise specified, all SubDirectory data except |
6279
|
|
|
|
|
|
|
# EXIF SubIFD offsets should be unformatted |
6280
|
14436
|
100
|
100
|
|
|
29030
|
$readFormat = 'undef' if $subdir and not $$tagInfo{SubIFD} and not $readFormat; |
|
|
|
100
|
|
|
|
|
6281
|
|
|
|
|
|
|
# override EXIF format if specified |
6282
|
14436
|
100
|
|
|
|
22430
|
if ($readFormat) { |
6283
|
1737
|
|
|
|
|
2703
|
$formatStr = $readFormat; |
6284
|
1737
|
|
|
|
|
3650
|
my $newNum = $formatNumber{$formatStr}; |
6285
|
1737
|
100
|
66
|
|
|
6310
|
if ($newNum and $newNum != $format) { |
6286
|
946
|
|
|
|
|
2616
|
$origFormStr = $formatName[$format] . '[' . $count . ']'; |
6287
|
946
|
|
|
|
|
1491
|
$format = $newNum; |
6288
|
946
|
50
|
|
|
|
2268
|
$size = $readSize = $$tagInfo{FixedSize} if $$tagInfo{FixedSize}; |
6289
|
|
|
|
|
|
|
# adjust number of items for new format size |
6290
|
946
|
|
|
|
|
2627
|
$count = int($size / $formatSize[$format]); |
6291
|
|
|
|
|
|
|
} |
6292
|
|
|
|
|
|
|
} |
6293
|
|
|
|
|
|
|
# verify that offset-type values are integral |
6294
|
14436
|
50
|
100
|
|
|
46892
|
if (($$tagInfo{IsOffset} or $$tagInfo{SubIFD}) and not $intFormat{$formatStr}) { |
|
|
|
66
|
|
|
|
|
6295
|
0
|
|
|
|
|
0
|
$et->Warn(sprintf('Wrong format (%s) for %s 0x%.4x %s',$formatStr,$dir,$tagID,$$tagInfo{Name})); |
6296
|
0
|
0
|
|
|
|
0
|
if ($validate) { |
6297
|
0
|
|
|
|
|
0
|
$$et{WrongFormat}{"$dir:$$tagInfo{Name}"} = 1; |
6298
|
0
|
|
|
|
|
0
|
$offsetInfo{$tagID} = [ $tagInfo, '' ]; |
6299
|
|
|
|
|
|
|
} |
6300
|
0
|
0
|
|
|
|
0
|
next unless $verbose; |
6301
|
0
|
|
|
|
|
0
|
$wrongFormat = 1; |
6302
|
|
|
|
|
|
|
} |
6303
|
|
|
|
|
|
|
} else { |
6304
|
548
|
100
|
|
|
|
1731
|
next unless $verbose; |
6305
|
|
|
|
|
|
|
} |
6306
|
14439
|
50
|
|
|
|
23371
|
unless ($bad) { |
6307
|
|
|
|
|
|
|
# limit maximum length of data to reformat |
6308
|
|
|
|
|
|
|
# (avoids long delays when processing some corrupted files) |
6309
|
14439
|
|
|
|
|
17282
|
my $warned; |
6310
|
14439
|
50
|
33
|
|
|
25910
|
if ($count > 100000 and $formatStr !~ /^(undef|string|binary)$/) { |
6311
|
0
|
0
|
|
|
|
0
|
my $tagName = $tagInfo ? $$tagInfo{Name} : sprintf('tag 0x%.4x', $tagID); |
6312
|
|
|
|
|
|
|
# (count of 196608 is typical for ColorMap) |
6313
|
0
|
0
|
0
|
|
|
0
|
if ($tagName ne 'TransferFunction' or $count != 196608) { |
6314
|
0
|
0
|
|
|
|
0
|
my $minor = $count > 2000000 ? 0 : 2; |
6315
|
0
|
0
|
|
|
|
0
|
if ($et->Warn("Ignoring $dirName $tagName with excessive count", $minor)) { |
6316
|
0
|
0
|
|
|
|
0
|
next unless $$et{OPTIONS}{HtmlDump}; |
6317
|
0
|
|
|
|
|
0
|
$warned = 1; |
6318
|
|
|
|
|
|
|
} |
6319
|
|
|
|
|
|
|
} |
6320
|
|
|
|
|
|
|
} |
6321
|
14439
|
50
|
100
|
|
|
31956
|
if ($count > 500 and $formatStr !~ /^(undef|string|binary)$/ and |
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
6322
|
|
|
|
|
|
|
(not $tagInfo or $$tagInfo{LongBinary} or $warned) and not $$et{OPTIONS}{IgnoreMinorErrors}) |
6323
|
|
|
|
|
|
|
{ |
6324
|
0
|
0
|
|
|
|
0
|
$et->WarnOnce('Not decoding some large array(s). Ignore minor errors to decode', 2) unless $warned; |
6325
|
0
|
0
|
|
|
|
0
|
next if $$et{TAGS_FROM_FILE}; # don't generate bogus value when copying tags |
6326
|
0
|
|
|
|
|
0
|
$val = "(large array of $count $formatStr values)"; |
6327
|
|
|
|
|
|
|
} else { |
6328
|
|
|
|
|
|
|
# convert according to specified format |
6329
|
14439
|
|
|
|
|
33289
|
$val = ReadValue($valueDataPt,$valuePtr,$formatStr,$count,$readSize,\$rational); |
6330
|
|
|
|
|
|
|
# re-code if necessary |
6331
|
14439
|
0
|
33
|
|
|
30195
|
$val = $et->Decode($val, $strEnc) if $strEnc and $formatStr eq 'string' and defined $val; |
|
|
|
33
|
|
|
|
|
6332
|
|
|
|
|
|
|
} |
6333
|
|
|
|
|
|
|
} |
6334
|
|
|
|
|
|
|
|
6335
|
14439
|
100
|
|
|
|
23529
|
if ($verbose) { |
6336
|
345
|
|
|
|
|
479
|
my $tval = $val; |
6337
|
|
|
|
|
|
|
# also show as a rational |
6338
|
345
|
100
|
|
|
|
631
|
$tval .= " ($rational)" if defined $rational; |
6339
|
345
|
50
|
|
|
|
554
|
if ($htmlDump) { |
6340
|
0
|
|
|
|
|
0
|
my ($tagName, $colName); |
6341
|
0
|
0
|
0
|
|
|
0
|
if ($tagID == 0x927c and $dirName eq 'ExifIFD') { |
|
|
0
|
|
|
|
|
|
6342
|
0
|
|
|
|
|
0
|
$tagName = 'MakerNotes'; |
6343
|
|
|
|
|
|
|
} elsif ($tagInfo) { |
6344
|
0
|
|
|
|
|
0
|
$tagName = $$tagInfo{Name}; |
6345
|
|
|
|
|
|
|
} else { |
6346
|
0
|
|
|
|
|
0
|
$tagName = sprintf("Tag 0x%.4x",$tagID); |
6347
|
|
|
|
|
|
|
} |
6348
|
0
|
|
|
|
|
0
|
my $dname = sprintf("${dir}-%.2d", $index); |
6349
|
|
|
|
|
|
|
# build our tool tip |
6350
|
0
|
0
|
|
|
|
0
|
$size < 0 and $size = $count * $formatSize[$format]; |
6351
|
0
|
|
|
|
|
0
|
my $fstr = "$formatName[$format]\[$count]"; |
6352
|
0
|
0
|
0
|
|
|
0
|
$fstr = "$origFormStr read as $fstr" if $origFormStr and $origFormStr ne $fstr; |
6353
|
0
|
0
|
|
|
|
0
|
$fstr .= ' <-- WRONG' if $wrongFormat; |
6354
|
0
|
|
|
|
|
0
|
my $tip = sprintf("Tag ID: 0x%.4x\n", $tagID) . |
6355
|
|
|
|
|
|
|
"Format: $fstr\nSize: $size bytes\n"; |
6356
|
0
|
0
|
|
|
|
0
|
if ($size > 4) { |
6357
|
0
|
|
|
|
|
0
|
my $offPt = Get32u($dataPt,$entry+8); |
6358
|
|
|
|
|
|
|
# (test this with ../pics/{CanonEOS-1D_XMarkIII.hif,PanasonicDC-G9.rw2}) |
6359
|
0
|
|
0
|
|
|
0
|
my $actPt = $valuePtr + $valueDataPos + $base - ($$et{EXIF_POS} || 0) + ($$et{BASE_FUDGE} || 0); |
|
|
|
0
|
|
|
|
|
6360
|
0
|
|
|
|
|
0
|
$tip .= sprintf("Value offset: 0x%.4x\n", $offPt); |
6361
|
|
|
|
|
|
|
# highlight tag name (red for bad size) |
6362
|
0
|
0
|
0
|
|
|
0
|
my $style = ($bad or not defined $tval) ? 'V' : 'H'; |
6363
|
0
|
0
|
|
|
|
0
|
if ($actPt != $offPt) { |
6364
|
0
|
|
|
|
|
0
|
$tip .= sprintf("Actual offset: 0x%.4x\n", $actPt); |
6365
|
0
|
0
|
|
|
|
0
|
my $sign = $actPt < $offPt ? '-' : ''; |
6366
|
0
|
|
|
|
|
0
|
$tip .= sprintf("Offset base: ${sign}0x%.4x\n", abs($actPt - $offPt)); |
6367
|
0
|
0
|
|
|
|
0
|
$style = 'F' if $style eq 'H'; # purple for different offsets |
6368
|
|
|
|
|
|
|
} |
6369
|
0
|
0
|
0
|
|
|
0
|
if ($$et{EXIF_POS} and not $$et{BASE_FUDGE}) { |
6370
|
|
|
|
|
|
|
$tip .= sprintf("File offset: 0x%.4x\n", $actPt + $$et{EXIF_POS}) |
6371
|
0
|
|
|
|
|
0
|
} |
6372
|
0
|
|
|
|
|
0
|
$colName = "$tagName"; |
6373
|
0
|
0
|
|
|
|
0
|
$colName .= ' (odd)' if $offPt & 0x01; |
6374
|
|
|
|
|
|
|
} else { |
6375
|
0
|
|
|
|
|
0
|
$colName = $tagName; |
6376
|
|
|
|
|
|
|
} |
6377
|
0
|
0
|
|
|
|
0
|
$colName .= ' (err)' if $wrongFormat; |
6378
|
0
|
0
|
0
|
|
|
0
|
$colName .= ' (seq)' if $tagID <= $lastID and not $inMakerNotes; |
6379
|
0
|
|
|
|
|
0
|
$lastID = $tagID; |
6380
|
0
|
0
|
|
|
|
0
|
if (not defined $tval) { |
6381
|
0
|
|
|
|
|
0
|
$tval = ''; |
6382
|
|
|
|
|
|
|
} else { |
6383
|
0
|
0
|
|
|
|
0
|
$tval = substr($tval,0,28) . '[...]' if length($tval) > 32; |
6384
|
0
|
0
|
0
|
|
|
0
|
if ($formatStr =~ /^(string|undef|binary)/) { |
|
|
0
|
|
|
|
|
|
6385
|
|
|
|
|
|
|
# translate non-printable characters |
6386
|
0
|
|
|
|
|
0
|
$tval =~ tr/\x00-\x1f\x7f-\xff/./; |
6387
|
|
|
|
|
|
|
} elsif ($tagInfo and Image::ExifTool::IsInt($tval)) { |
6388
|
0
|
0
|
0
|
|
|
0
|
if ($$tagInfo{IsOffset} or $$tagInfo{SubIFD}) { |
|
|
0
|
|
|
|
|
|
6389
|
0
|
|
|
|
|
0
|
$tval = sprintf('0x%.4x', $tval); |
6390
|
0
|
|
0
|
|
|
0
|
my $actPt = $val + $base - ($$et{EXIF_POS} || 0) + ($$et{BASE_FUDGE} || 0); |
|
|
|
0
|
|
|
|
|
6391
|
0
|
0
|
|
|
|
0
|
if ($actPt != $val) { |
6392
|
0
|
|
|
|
|
0
|
$tval .= sprintf("\nActual offset: 0x%.4x", $actPt); |
6393
|
0
|
0
|
|
|
|
0
|
my $sign = $actPt < $val ? '-' : ''; |
6394
|
0
|
|
|
|
|
0
|
$tval .= sprintf("\nOffset base: ${sign}0x%.4x", abs($actPt - $val)); |
6395
|
|
|
|
|
|
|
} |
6396
|
|
|
|
|
|
|
} elsif ($$tagInfo{PrintHex}) { |
6397
|
0
|
|
|
|
|
0
|
$tval = sprintf('0x%x', $tval); |
6398
|
|
|
|
|
|
|
} |
6399
|
|
|
|
|
|
|
} |
6400
|
|
|
|
|
|
|
} |
6401
|
0
|
|
|
|
|
0
|
$tip .= "Value: $tval"; |
6402
|
0
|
|
|
|
|
0
|
my $id = $offName; |
6403
|
0
|
|
|
|
|
0
|
my $sid; |
6404
|
0
|
0
|
0
|
|
|
0
|
($subOffName, $id, $sid) = NextOffsetName($et, $offName) if $tagInfo and $$tagInfo{SubIFD}; |
6405
|
0
|
|
|
|
|
0
|
$et->HDump($entry+$dataPos+$base, 12, "$dname $colName", $tip, 1, $id); |
6406
|
0
|
0
|
|
|
|
0
|
next if $valueDataLen < 0; # don't process bad pointer entry |
6407
|
0
|
0
|
|
|
|
0
|
if ($size > 4) { |
6408
|
0
|
|
|
|
|
0
|
my $exifDumpPos = $valuePtr + $valueDataPos + $base; |
6409
|
0
|
|
|
|
|
0
|
my $flag = 0; |
6410
|
0
|
0
|
|
|
|
0
|
if ($subdir) { |
6411
|
0
|
0
|
|
|
|
0
|
if ($$tagInfo{MakerNotes}) { |
|
|
0
|
|
|
|
|
|
6412
|
0
|
|
|
|
|
0
|
$flag = 0x04; |
6413
|
|
|
|
|
|
|
} elsif ($$tagInfo{NestedHtmlDump}) { |
6414
|
0
|
0
|
|
|
|
0
|
$flag = $$tagInfo{NestedHtmlDump} == 2 ? 0x10 : 0x04; |
6415
|
|
|
|
|
|
|
} |
6416
|
|
|
|
|
|
|
} |
6417
|
|
|
|
|
|
|
# add value data block (underlining maker notes data) |
6418
|
0
|
|
|
|
|
0
|
$et->HDump($exifDumpPos,$size,"$tagName value",'SAME', $flag, $sid); |
6419
|
|
|
|
|
|
|
} |
6420
|
|
|
|
|
|
|
} else { |
6421
|
345
|
50
|
66
|
|
|
754
|
if ($tagID <= $lastID and not $inMakerNotes) { |
6422
|
0
|
0
|
|
|
|
0
|
my $str = $tagInfo ? ' '.$$tagInfo{Name} : ''; |
6423
|
0
|
0
|
|
|
|
0
|
if ($tagID == $lastID) { |
6424
|
0
|
|
|
|
|
0
|
$et->Warn(sprintf('Duplicate tag 0x%.4x%s in %s', $tagID, $str, $dirName)); |
6425
|
|
|
|
|
|
|
} else { |
6426
|
0
|
|
|
|
|
0
|
$et->Warn(sprintf('Tag ID 0x%.4x%s out of sequence in %s', $tagID, $str, $dirName)); |
6427
|
|
|
|
|
|
|
} |
6428
|
|
|
|
|
|
|
} |
6429
|
345
|
|
|
|
|
442
|
$lastID = $tagID; |
6430
|
345
|
100
|
|
|
|
606
|
if ($verbose > 0) { |
6431
|
257
|
|
|
|
|
381
|
my $fstr = $formatName[$format]; |
6432
|
257
|
100
|
|
|
|
403
|
$fstr = "$origFormStr read as $fstr" if $origFormStr; |
6433
|
257
|
|
|
|
|
760
|
$et->VerboseInfo($tagID, $tagInfo, |
6434
|
|
|
|
|
|
|
Table => $tagTablePtr, |
6435
|
|
|
|
|
|
|
Index => $index, |
6436
|
|
|
|
|
|
|
Value => $tval, |
6437
|
|
|
|
|
|
|
DataPt => $valueDataPt, |
6438
|
|
|
|
|
|
|
DataPos => $valueDataPos + $base, |
6439
|
|
|
|
|
|
|
Size => $size, |
6440
|
|
|
|
|
|
|
Start => $valuePtr, |
6441
|
|
|
|
|
|
|
Format => $fstr, |
6442
|
|
|
|
|
|
|
Count => $count, |
6443
|
|
|
|
|
|
|
); |
6444
|
|
|
|
|
|
|
} |
6445
|
|
|
|
|
|
|
} |
6446
|
345
|
100
|
66
|
|
|
1156
|
next if not $tagInfo or $wrongFormat; |
6447
|
|
|
|
|
|
|
} |
6448
|
14436
|
50
|
|
|
|
23088
|
next unless defined $val; |
6449
|
|
|
|
|
|
|
#.............................................................................. |
6450
|
|
|
|
|
|
|
# Handle SubDirectory tag types |
6451
|
|
|
|
|
|
|
# |
6452
|
14436
|
100
|
|
|
|
22927
|
if ($subdir) { |
6453
|
|
|
|
|
|
|
# don't process empty subdirectories |
6454
|
1245
|
50
|
|
|
|
3156
|
unless ($size) { |
6455
|
0
|
0
|
0
|
|
|
0
|
unless ($$tagInfo{MakerNotes} or $inMakerNotes) { |
6456
|
0
|
|
|
|
|
0
|
$et->Warn("Empty $$tagInfo{Name} data", 1); |
6457
|
|
|
|
|
|
|
} |
6458
|
0
|
|
|
|
|
0
|
next; |
6459
|
|
|
|
|
|
|
} |
6460
|
1245
|
|
|
|
|
2322
|
my (@values, $newTagTable, $dirNum, $newByteOrder, $invalid); |
6461
|
1245
|
|
|
|
|
2563
|
my $tagStr = $$tagInfo{Name}; |
6462
|
1245
|
100
|
|
|
|
3143
|
if ($$subdir{MaxSubdirs}) { |
6463
|
144
|
|
|
|
|
606
|
@values = split ' ', $val; |
6464
|
|
|
|
|
|
|
# limit the number of subdirectories we parse |
6465
|
144
|
|
|
|
|
426
|
my $over = @values - $$subdir{MaxSubdirs}; |
6466
|
144
|
50
|
|
|
|
467
|
if ($over > 0) { |
6467
|
0
|
|
|
|
|
0
|
$et->Warn("Ignoring $over $tagStr directories"); |
6468
|
0
|
|
|
|
|
0
|
splice @values, $$subdir{MaxSubdirs}; |
6469
|
|
|
|
|
|
|
} |
6470
|
144
|
|
|
|
|
359
|
$val = shift @values; |
6471
|
|
|
|
|
|
|
} |
6472
|
1245
|
100
|
|
|
|
2929
|
if ($$subdir{TagTable}) { |
6473
|
902
|
|
|
|
|
2685
|
$newTagTable = GetTagTable($$subdir{TagTable}); |
6474
|
902
|
50
|
|
|
|
2408
|
$newTagTable or warn("Unknown tag table $$subdir{TagTable}"), next; |
6475
|
|
|
|
|
|
|
} else { |
6476
|
343
|
|
|
|
|
617
|
$newTagTable = $tagTablePtr; # use existing table |
6477
|
|
|
|
|
|
|
} |
6478
|
|
|
|
|
|
|
# loop through all sub-directories specified by this tag |
6479
|
1245
|
|
|
|
|
2412
|
for ($dirNum=0; ; ++$dirNum) { |
6480
|
1251
|
|
|
|
|
1891
|
my $subdirBase = $base; |
6481
|
1251
|
|
|
|
|
1797
|
my $subdirDataPt = $valueDataPt; |
6482
|
1251
|
|
|
|
|
1782
|
my $subdirDataPos = $valueDataPos; |
6483
|
1251
|
|
|
|
|
1667
|
my $subdirDataLen = $valueDataLen; |
6484
|
1251
|
|
|
|
|
1834
|
my $subdirStart = $valuePtr; |
6485
|
1251
|
100
|
|
|
|
3156
|
if (defined $$subdir{Start}) { |
6486
|
|
|
|
|
|
|
# set local $valuePtr relative to file $base for eval |
6487
|
443
|
|
|
|
|
840
|
my $valuePtr = $subdirStart + $subdirDataPos; |
6488
|
|
|
|
|
|
|
#### eval Start ($valuePtr, $val) |
6489
|
443
|
|
|
|
|
23112
|
my $newStart = eval($$subdir{Start}); |
6490
|
443
|
50
|
|
|
|
2467
|
unless (Image::ExifTool::IsInt($newStart)) { |
6491
|
0
|
|
|
|
|
0
|
$et->Warn("Bad value for $tagStr"); |
6492
|
0
|
|
|
|
|
0
|
last; |
6493
|
|
|
|
|
|
|
} |
6494
|
|
|
|
|
|
|
# convert back to relative to $subdirDataPt |
6495
|
443
|
|
|
|
|
1216
|
$newStart -= $subdirDataPos; |
6496
|
|
|
|
|
|
|
# adjust directory size if necessary |
6497
|
443
|
50
|
66
|
|
|
1533
|
unless ($$tagInfo{SubIFD} or $$subdir{BadOffset}) { |
6498
|
51
|
|
|
|
|
110
|
$size -= $newStart - $subdirStart; |
6499
|
|
|
|
|
|
|
} |
6500
|
443
|
|
|
|
|
916
|
$subdirStart = $newStart; |
6501
|
|
|
|
|
|
|
} |
6502
|
|
|
|
|
|
|
# this is a pain, but some maker notes are always a specific |
6503
|
|
|
|
|
|
|
# byte order, regardless of the byte order of the file |
6504
|
1251
|
|
|
|
|
3099
|
my $oldByteOrder = GetByteOrder(); |
6505
|
1251
|
|
|
|
|
2434
|
$newByteOrder = $$subdir{ByteOrder}; |
6506
|
1251
|
100
|
|
|
|
2502
|
if ($newByteOrder) { |
6507
|
171
|
100
|
|
|
|
1338
|
if ($newByteOrder =~ /^Little/i) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
6508
|
31
|
|
|
|
|
70
|
$newByteOrder = 'II'; |
6509
|
|
|
|
|
|
|
} elsif ($newByteOrder =~ /^Big/i) { |
6510
|
29
|
|
|
|
|
62
|
$newByteOrder = 'MM'; |
6511
|
|
|
|
|
|
|
} elsif ($$subdir{OffsetPt}) { |
6512
|
0
|
|
|
|
|
0
|
undef $newByteOrder; |
6513
|
0
|
|
|
|
|
0
|
warn "Can't have variable byte ordering for SubDirectories using OffsetPt"; |
6514
|
0
|
|
|
|
|
0
|
last; |
6515
|
|
|
|
|
|
|
} elsif ($subdirStart + 2 <= $subdirDataLen) { |
6516
|
|
|
|
|
|
|
# attempt to determine the byte ordering by checking |
6517
|
|
|
|
|
|
|
# the number of directory entries. This is an int16u |
6518
|
|
|
|
|
|
|
# that should be a reasonable value. |
6519
|
111
|
|
|
|
|
343
|
my $num = Get16u($subdirDataPt, $subdirStart); |
6520
|
111
|
100
|
100
|
|
|
545
|
if ($num & 0xff00 and ($num>>8) > ($num&0xff)) { |
6521
|
|
|
|
|
|
|
# This looks wrong, we shouldn't have this many entries |
6522
|
4
|
|
|
|
|
72
|
my %otherOrder = ( II=>'MM', MM=>'II' ); |
6523
|
4
|
|
|
|
|
15
|
$newByteOrder = $otherOrder{$oldByteOrder}; |
6524
|
|
|
|
|
|
|
} else { |
6525
|
107
|
|
|
|
|
229
|
$newByteOrder = $oldByteOrder; |
6526
|
|
|
|
|
|
|
} |
6527
|
|
|
|
|
|
|
} |
6528
|
|
|
|
|
|
|
} else { |
6529
|
1080
|
|
|
|
|
1832
|
$newByteOrder = $oldByteOrder; |
6530
|
|
|
|
|
|
|
} |
6531
|
|
|
|
|
|
|
# set base offset if necessary |
6532
|
1251
|
100
|
|
|
|
3235
|
if ($$subdir{Base}) { |
6533
|
|
|
|
|
|
|
# calculate subdirectory start relative to $base for eval |
6534
|
35
|
|
|
|
|
86
|
my $start = $subdirStart + $subdirDataPos; |
6535
|
|
|
|
|
|
|
#### eval Base ($start,$base) |
6536
|
35
|
|
|
|
|
1600
|
$subdirBase = eval($$subdir{Base}) + $base; |
6537
|
|
|
|
|
|
|
} |
6538
|
|
|
|
|
|
|
# add offset to the start of the directory if necessary |
6539
|
1251
|
100
|
|
|
|
3117
|
if ($$subdir{OffsetPt}) { |
6540
|
|
|
|
|
|
|
#### eval OffsetPt ($valuePtr) |
6541
|
24
|
|
|
|
|
1057
|
my $pos = eval $$subdir{OffsetPt}; |
6542
|
24
|
50
|
|
|
|
133
|
if ($pos + 4 > $subdirDataLen) { |
6543
|
0
|
|
|
|
|
0
|
$et->Warn("Bad $tagStr OffsetPt"); |
6544
|
0
|
|
|
|
|
0
|
last; |
6545
|
|
|
|
|
|
|
} |
6546
|
24
|
|
|
|
|
125
|
SetByteOrder($newByteOrder); |
6547
|
24
|
|
|
|
|
94
|
$subdirStart += Get32u($subdirDataPt, $pos); |
6548
|
24
|
|
|
|
|
79
|
SetByteOrder($oldByteOrder); |
6549
|
|
|
|
|
|
|
} |
6550
|
1251
|
100
|
100
|
|
|
5315
|
if ($subdirStart < 0 or $subdirStart + 2 > $subdirDataLen) { |
6551
|
|
|
|
|
|
|
# convert $subdirStart back to a file offset |
6552
|
31
|
50
|
|
|
|
107
|
if ($raf) { |
6553
|
|
|
|
|
|
|
# reset SubDirectory buffer (we will load it later) |
6554
|
31
|
|
|
|
|
72
|
my $buff = ''; |
6555
|
31
|
|
|
|
|
73
|
$subdirDataPt = \$buff; |
6556
|
31
|
|
|
|
|
74
|
$subdirDataLen = $size = length $buff; |
6557
|
|
|
|
|
|
|
} else { |
6558
|
0
|
|
|
|
|
0
|
my $msg = "Bad $tagStr SubDirectory start"; |
6559
|
0
|
0
|
|
|
|
0
|
if ($verbose > 0) { |
6560
|
0
|
0
|
|
|
|
0
|
if ($subdirStart < 0) { |
6561
|
0
|
|
|
|
|
0
|
$msg .= " (directory start $subdirStart is before EXIF start)"; |
6562
|
|
|
|
|
|
|
} else { |
6563
|
0
|
|
|
|
|
0
|
my $end = $subdirStart + $size; |
6564
|
0
|
|
|
|
|
0
|
$msg .= " (directory end is $end but EXIF size is only $subdirDataLen)"; |
6565
|
|
|
|
|
|
|
} |
6566
|
|
|
|
|
|
|
} |
6567
|
0
|
|
|
|
|
0
|
$et->Warn($msg, $inMakerNotes); |
6568
|
0
|
|
|
|
|
0
|
last; |
6569
|
|
|
|
|
|
|
} |
6570
|
|
|
|
|
|
|
} |
6571
|
|
|
|
|
|
|
|
6572
|
|
|
|
|
|
|
# must update subdirDataPos if $base changes for this subdirectory |
6573
|
1251
|
|
|
|
|
2281
|
$subdirDataPos += $base - $subdirBase; |
6574
|
|
|
|
|
|
|
|
6575
|
|
|
|
|
|
|
# build information hash for new directory |
6576
|
|
|
|
|
|
|
my %subdirInfo = ( |
6577
|
|
|
|
|
|
|
Name => $tagStr, |
6578
|
|
|
|
|
|
|
Base => $subdirBase, |
6579
|
|
|
|
|
|
|
DataPt => $subdirDataPt, |
6580
|
|
|
|
|
|
|
DataPos => $subdirDataPos, |
6581
|
|
|
|
|
|
|
DataLen => $subdirDataLen, |
6582
|
|
|
|
|
|
|
DirStart => $subdirStart, |
6583
|
|
|
|
|
|
|
DirLen => $size, |
6584
|
|
|
|
|
|
|
RAF => $raf, |
6585
|
|
|
|
|
|
|
Parent => $dirName, |
6586
|
|
|
|
|
|
|
DirName => $$subdir{DirName}, |
6587
|
|
|
|
|
|
|
FixBase => $$subdir{FixBase}, |
6588
|
|
|
|
|
|
|
FixOffsets => $$subdir{FixOffsets}, |
6589
|
|
|
|
|
|
|
EntryBased => $$subdir{EntryBased}, |
6590
|
|
|
|
|
|
|
TagInfo => $tagInfo, |
6591
|
|
|
|
|
|
|
SubIFD => $$tagInfo{SubIFD}, |
6592
|
1251
|
|
|
|
|
13455
|
Subdir => $subdir, |
6593
|
|
|
|
|
|
|
OffsetName => $subOffName, |
6594
|
|
|
|
|
|
|
); |
6595
|
|
|
|
|
|
|
# (remember: some cameras incorrectly write maker notes in IFD0) |
6596
|
1251
|
100
|
|
|
|
3199
|
if ($$tagInfo{MakerNotes}) { |
6597
|
|
|
|
|
|
|
# don't parse makernotes if FastScan > 1 |
6598
|
130
|
|
|
|
|
655
|
my $fast = $et->Options('FastScan'); |
6599
|
130
|
100
|
66
|
|
|
563
|
last if $fast and $fast > 1; |
6600
|
129
|
|
|
|
|
392
|
$subdirInfo{MakerNoteAddr} = $valuePtr + $valueDataPos + $base; |
6601
|
129
|
100
|
|
|
|
500
|
$subdirInfo{NoFixBase} = 1 if defined $$subdir{Base}; |
6602
|
|
|
|
|
|
|
} |
6603
|
|
|
|
|
|
|
# set directory IFD name from group name of family 1 if it exists, |
6604
|
|
|
|
|
|
|
# unless the tag is writable as a block in which case group 1 may |
6605
|
|
|
|
|
|
|
# have been set automatically |
6606
|
1250
|
100
|
100
|
|
|
6724
|
if ($$tagInfo{Groups} and not $$tagInfo{Writable}) { |
6607
|
392
|
|
|
|
|
1023
|
$subdirInfo{DirName} = $$tagInfo{Groups}{1}; |
6608
|
|
|
|
|
|
|
# number multiple subdirectories |
6609
|
392
|
100
|
|
|
|
998
|
$subdirInfo{DirName} =~ s/\d*$/$dirNum/ if $dirNum; |
6610
|
|
|
|
|
|
|
} |
6611
|
1250
|
|
|
|
|
3623
|
SetByteOrder($newByteOrder); # set byte order for this subdir |
6612
|
|
|
|
|
|
|
# validate the subdirectory if necessary |
6613
|
1250
|
|
|
|
|
2006
|
my $dirData = $subdirDataPt; # set data pointer to be used in eval |
6614
|
|
|
|
|
|
|
#### eval Validate ($val, $dirData, $subdirStart, $size) |
6615
|
1250
|
|
|
|
|
1929
|
my $ok = 0; |
6616
|
1250
|
50
|
66
|
|
|
26639
|
if (defined $$subdir{Validate} and not eval $$subdir{Validate}) { |
6617
|
0
|
|
|
|
|
0
|
$et->Warn("Invalid $tagStr data", $inMakerNotes); |
6618
|
0
|
|
|
|
|
0
|
$invalid = 1; |
6619
|
|
|
|
|
|
|
} else { |
6620
|
1250
|
100
|
100
|
|
|
4771
|
if (not $subdirInfo{DirName} and $inMakerNotes) { |
6621
|
622
|
|
|
|
|
1391
|
$subdirInfo{DirName} = $$tagInfo{Name}; |
6622
|
|
|
|
|
|
|
} |
6623
|
|
|
|
|
|
|
# process the subdirectory |
6624
|
1250
|
|
|
|
|
6239
|
$ok = $et->ProcessDirectory(\%subdirInfo, $newTagTable, $$subdir{ProcessProc}); |
6625
|
|
|
|
|
|
|
} |
6626
|
|
|
|
|
|
|
# print debugging information if there were errors |
6627
|
1250
|
50
|
66
|
|
|
5390
|
if (not $ok and $verbose > 1 and $subdirStart != $valuePtr) { |
|
|
|
33
|
|
|
|
|
6628
|
0
|
|
|
|
|
0
|
my $out = $et->Options('TextOut'); |
6629
|
0
|
|
|
|
|
0
|
printf $out "%s (SubDirectory start = 0x%x)\n", $$et{INDENT}, $subdirStart; |
6630
|
|
|
|
|
|
|
} |
6631
|
1250
|
|
|
|
|
3625
|
SetByteOrder($oldByteOrder); # restore original byte swapping |
6632
|
|
|
|
|
|
|
|
6633
|
1250
|
100
|
|
|
|
7178
|
@values or last; |
6634
|
6
|
|
|
|
|
49
|
$val = shift @values; # continue with next subdir |
6635
|
|
|
|
|
|
|
} |
6636
|
1245
|
|
|
|
|
4342
|
my $doMaker = $et->Options('MakerNotes'); |
6637
|
1245
|
100
|
100
|
|
|
10344
|
next unless $doMaker or $$et{REQ_TAG_LOOKUP}{lc($tagStr)} or $$tagInfo{BlockExtract}; |
|
|
|
100
|
|
|
|
|
6638
|
|
|
|
|
|
|
# extract as a block if specified |
6639
|
204
|
100
|
|
|
|
1013
|
if ($$tagInfo{MakerNotes}) { |
6640
|
|
|
|
|
|
|
# save maker note byte order (if it was significant and valid) |
6641
|
20
|
50
|
33
|
|
|
166
|
if ($$subdir{ByteOrder} and not $invalid) { |
6642
|
|
|
|
|
|
|
$$et{MAKER_NOTE_BYTE_ORDER} = |
6643
|
|
|
|
|
|
|
defined ($$et{UnknownByteOrder}) ? |
6644
|
20
|
100
|
|
|
|
112
|
$$et{UnknownByteOrder} : $newByteOrder; |
6645
|
|
|
|
|
|
|
} |
6646
|
20
|
50
|
33
|
|
|
203
|
if ($doMaker and $doMaker eq '2') { |
|
|
50
|
33
|
|
|
|
|
6647
|
|
|
|
|
|
|
# extract maker notes without rebuilding (no fixup information) |
6648
|
0
|
|
|
|
|
0
|
delete $$et{MAKER_NOTE_FIXUP}; |
6649
|
|
|
|
|
|
|
} elsif (not $$tagInfo{NotIFD} or $$tagInfo{IsPhaseOne}) { |
6650
|
|
|
|
|
|
|
# this is a pain, but we must rebuild EXIF-type maker notes to |
6651
|
|
|
|
|
|
|
# include all the value data if data was outside the maker notes |
6652
|
|
|
|
|
|
|
my %makerDirInfo = ( |
6653
|
|
|
|
|
|
|
Name => $tagStr, |
6654
|
|
|
|
|
|
|
Base => $base, |
6655
|
|
|
|
|
|
|
DataPt => $valueDataPt, |
6656
|
|
|
|
|
|
|
DataPos => $valueDataPos, |
6657
|
|
|
|
|
|
|
DataLen => $valueDataLen, |
6658
|
|
|
|
|
|
|
DirStart => $valuePtr, |
6659
|
|
|
|
|
|
|
DirLen => $size, |
6660
|
|
|
|
|
|
|
RAF => $raf, |
6661
|
|
|
|
|
|
|
Parent => $dirName, |
6662
|
|
|
|
|
|
|
DirName => 'MakerNotes', |
6663
|
|
|
|
|
|
|
FixOffsets => $$subdir{FixOffsets}, |
6664
|
20
|
|
|
|
|
215
|
TagInfo => $tagInfo, |
6665
|
|
|
|
|
|
|
); |
6666
|
20
|
|
|
|
|
49
|
my $val2; |
6667
|
20
|
50
|
|
|
|
121
|
if ($$tagInfo{IsPhaseOne}) { |
6668
|
0
|
|
|
|
|
0
|
$$et{DropTags} = 1; |
6669
|
0
|
|
|
|
|
0
|
$val2 = Image::ExifTool::PhaseOne::WritePhaseOne($et, \%makerDirInfo, $newTagTable); |
6670
|
0
|
|
|
|
|
0
|
delete $$et{DropTags}; |
6671
|
|
|
|
|
|
|
} else { |
6672
|
20
|
100
|
|
|
|
78
|
$makerDirInfo{FixBase} = 1 if $$subdir{FixBase}; |
6673
|
|
|
|
|
|
|
# rebuild maker notes (creates $$et{MAKER_NOTE_FIXUP}) |
6674
|
20
|
|
|
|
|
137
|
$val2 = RebuildMakerNotes($et, \%makerDirInfo, $newTagTable); |
6675
|
|
|
|
|
|
|
} |
6676
|
20
|
50
|
|
|
|
157
|
if (defined $val2) { |
|
|
0
|
|
|
|
|
|
6677
|
20
|
|
|
|
|
112
|
$val = $val2; |
6678
|
|
|
|
|
|
|
} elsif ($size > 4) { |
6679
|
0
|
|
|
|
|
0
|
$et->Warn('Error rebuilding maker notes (may be corrupt)'); |
6680
|
|
|
|
|
|
|
} |
6681
|
|
|
|
|
|
|
} |
6682
|
|
|
|
|
|
|
} else { |
6683
|
|
|
|
|
|
|
# extract this directory as a block if specified |
6684
|
184
|
100
|
|
|
|
934
|
next unless $$tagInfo{Writable}; |
6685
|
|
|
|
|
|
|
} |
6686
|
|
|
|
|
|
|
} |
6687
|
|
|
|
|
|
|
#.............................................................................. |
6688
|
|
|
|
|
|
|
# convert to absolute offsets if this tag is an offset |
6689
|
|
|
|
|
|
|
#### eval IsOffset ($val, $et) |
6690
|
13227
|
100
|
100
|
|
|
35609
|
if ($$tagInfo{IsOffset} and eval $$tagInfo{IsOffset}) { |
6691
|
224
|
100
|
|
|
|
1007
|
my $offsetBase = $$tagInfo{IsOffset} eq '2' ? $firstBase : $base; |
6692
|
224
|
|
|
|
|
584
|
$offsetBase += $$et{BASE}; |
6693
|
|
|
|
|
|
|
# handle offsets which use a wrong base (Minolta A200) |
6694
|
224
|
50
|
|
|
|
687
|
if ($$tagInfo{WrongBase}) { |
6695
|
0
|
|
|
|
|
0
|
my $self = $et; |
6696
|
|
|
|
|
|
|
#### eval WrongBase ($self) |
6697
|
0
|
|
0
|
|
|
0
|
$offsetBase += eval $$tagInfo{WrongBase} || 0; |
6698
|
|
|
|
|
|
|
} |
6699
|
224
|
|
|
|
|
925
|
my @vals = split(' ',$val); |
6700
|
224
|
|
|
|
|
597
|
foreach $val (@vals) { |
6701
|
224
|
|
|
|
|
658
|
$val += $offsetBase; |
6702
|
|
|
|
|
|
|
} |
6703
|
224
|
|
|
|
|
711
|
$val = join(' ', @vals); |
6704
|
|
|
|
|
|
|
} |
6705
|
13227
|
100
|
|
|
|
20467
|
if ($validate) { |
6706
|
70
|
100
|
66
|
|
|
231
|
if ($$tagInfo{OffsetPair}) { |
|
|
100
|
|
|
|
|
|
6707
|
10
|
|
|
|
|
34
|
$offsetInfo{$tagID} = [ $tagInfo, $val ]; |
6708
|
|
|
|
|
|
|
} elsif ($saveForValidate{$tagID} and $isExif) { |
6709
|
10
|
|
|
|
|
24
|
$offsetInfo{$tagID} = $val; |
6710
|
|
|
|
|
|
|
} |
6711
|
|
|
|
|
|
|
} |
6712
|
|
|
|
|
|
|
# save the value of this tag |
6713
|
13227
|
|
|
|
|
30260
|
$tagKey = $et->FoundTag($tagInfo, $val); |
6714
|
13227
|
100
|
|
|
|
24672
|
if (defined $tagKey) { |
6715
|
|
|
|
|
|
|
# set the group 1 name for tags in specified tables |
6716
|
13216
|
100
|
|
|
|
37506
|
$et->SetGroup($tagKey, $dirName) if $$tagTablePtr{SET_GROUP1}; |
6717
|
|
|
|
|
|
|
# save original components of rational numbers (used when copying) |
6718
|
13216
|
100
|
|
|
|
25186
|
$$et{RATIONAL}{$tagKey} = $rational if defined $rational; |
6719
|
13216
|
50
|
|
|
|
35993
|
$$et{TAG_EXTRA}{$tagKey}{G6} = $saveFormat if $saveFormat; |
6720
|
|
|
|
|
|
|
} |
6721
|
|
|
|
|
|
|
} |
6722
|
|
|
|
|
|
|
|
6723
|
|
|
|
|
|
|
# validate image data offsets for this IFD |
6724
|
1051
|
100
|
100
|
|
|
3323
|
if ($validate and %offsetInfo) { |
6725
|
5
|
|
|
|
|
27
|
Image::ExifTool::Validate::ValidateOffsetInfo($et, \%offsetInfo, $$dirInfo{DirName}, $inMakerNotes) |
6726
|
|
|
|
|
|
|
} |
6727
|
|
|
|
|
|
|
|
6728
|
|
|
|
|
|
|
# scan for subsequent IFD's if specified |
6729
|
1051
|
100
|
66
|
|
|
4941
|
if ($$dirInfo{Multi} and $bytesFromEnd >= 4) { |
|
|
100
|
|
|
|
|
|
6730
|
|
|
|
|
|
|
# use same directory information for trailing directory, |
6731
|
|
|
|
|
|
|
# but change the start location (ProcessDirectory will |
6732
|
|
|
|
|
|
|
# test to make sure we don't reprocess the same dir twice) |
6733
|
289
|
|
|
|
|
2403
|
my %newDirInfo = %$dirInfo; |
6734
|
289
|
|
|
|
|
1186
|
$newDirInfo{Multi} = 0; # prevent recursion |
6735
|
289
|
|
|
|
|
668
|
$newDirInfo{OffsetName} = $nextOffName; |
6736
|
289
|
|
|
|
|
1824
|
$$et{INDENT} =~ s/..$//; # keep indent the same |
6737
|
289
|
|
|
|
|
606
|
for (;;) { |
6738
|
458
|
100
|
|
|
|
1648
|
my $offset = Get32u($dataPt, $dirEnd) or last; |
6739
|
169
|
|
|
|
|
481
|
$newDirInfo{DirStart} = $offset - $dataPos; |
6740
|
|
|
|
|
|
|
# increment IFD number |
6741
|
169
|
50
|
|
|
|
1427
|
my $ifdNum = $newDirInfo{DirName} =~ s/(\d+)$// ? $1 : 0; |
6742
|
169
|
|
|
|
|
593
|
$newDirInfo{DirName} .= $ifdNum + 1; |
6743
|
|
|
|
|
|
|
# must validate SubIFD1 because the nextIFD pointer is invalid for some RAW formats |
6744
|
169
|
50
|
33
|
|
|
729
|
if ($newDirInfo{DirName} ne 'SubIFD1' or ValidateIFD(\%newDirInfo)) { |
|
|
0
|
0
|
|
|
|
|
6745
|
169
|
|
|
|
|
310
|
my $cur = pop @{$$et{PATH}}; |
|
169
|
|
|
|
|
497
|
|
6746
|
169
|
50
|
|
|
|
703
|
$et->ProcessDirectory(\%newDirInfo, $tagTablePtr) or $success = 0; |
6747
|
169
|
|
|
|
|
402
|
push @{$$et{PATH}}, $cur; |
|
169
|
|
|
|
|
484
|
|
6748
|
169
|
50
|
33
|
|
|
959
|
if ($success and $newDirInfo{BytesFromEnd} >= 4) { |
6749
|
169
|
|
|
|
|
495
|
$dataPt = $newDirInfo{DataPt}; |
6750
|
169
|
|
|
|
|
324
|
$dataPos = $newDirInfo{DataPos}; |
6751
|
169
|
|
|
|
|
430
|
$dirEnd = $newDirInfo{DirEnd}; |
6752
|
169
|
|
|
|
|
368
|
next; |
6753
|
|
|
|
|
|
|
} |
6754
|
|
|
|
|
|
|
} elsif ($verbose or $$et{TIFF_TYPE} eq 'TIFF') { |
6755
|
0
|
|
|
|
|
0
|
$et->Warn('Ignored bad IFD linked from SubIFD'); |
6756
|
|
|
|
|
|
|
} |
6757
|
0
|
|
|
|
|
0
|
last; |
6758
|
|
|
|
|
|
|
} |
6759
|
|
|
|
|
|
|
} elsif (defined $$dirInfo{Multi}) { |
6760
|
|
|
|
|
|
|
# return necessary parameters for parsing next IFD |
6761
|
170
|
|
|
|
|
522
|
$$dirInfo{DirEnd} = $dirEnd; |
6762
|
170
|
|
|
|
|
353
|
$$dirInfo{OffsetName} = $nextOffName; |
6763
|
170
|
|
|
|
|
381
|
$$dirInfo{BytesFromEnd} = $bytesFromEnd; |
6764
|
|
|
|
|
|
|
} |
6765
|
1051
|
|
|
|
|
4384
|
return $success; |
6766
|
|
|
|
|
|
|
} |
6767
|
|
|
|
|
|
|
|
6768
|
|
|
|
|
|
|
1; # end |
6769
|
|
|
|
|
|
|
|
6770
|
|
|
|
|
|
|
__END__ |