source: gs2-extensions/parallel-building/trunk/src/perllib/cpan/Image/ExifTool/Exif.pm@ 24626

Last change on this file since 24626 was 24626, checked in by jmt12, 13 years ago

An (almost) complete copy of the perllib directory from a (circa SEP2011) head checkout from Greenstone 2 trunk - in order to try and make merging in this extension a little easier later on (as there have been some major changes to buildcol.pl commited in the main trunk but not in the x64 branch)

File size: 152.9 KB
Line 
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/english/hyoujunka/kikaku/pdf/DC-008-2010_E.pdf (Exif 2.3)
38# 25) Vesa Kivisto private communication (7D)
39# 26) Jeremy Brown private communication
40# JD) Jens Duttke private communication
41#------------------------------------------------------------------------------
42
43package Image::ExifTool::Exif;
44
45use strict;
46use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber %intFormat
47 %lightSource %flash %compression %photometricInterpretation %orientation
48 %subfileType);
49use Image::ExifTool qw(:DataAccess :Utils);
50use Image::ExifTool::MakerNotes;
51
52$VERSION = '3.21';
53
54sub ProcessExif($$$);
55sub WriteExif($$$);
56sub CheckExif($$$);
57sub RebuildMakerNotes($$$);
58sub EncodeExifText($$);
59sub ValidateIFD($;$);
60sub ProcessTiffIFD($$$);
61sub PrintParameter($$$);
62sub GetOffList($$$$$);
63sub PrintLensInfo($);
64sub ConvertLensInfo($);
65
66# size limit for loading binary data block into memory
67sub BINARY_DATA_LIMIT { return 10 * 1024 * 1024; }
68
69# byte sizes for the various EXIF format types below
70@formatSize = (undef,1,1,2,4,8,1,1,2,4,8,4,8,4,2,8,8,8,8);
71
72@formatName = (
73 undef, 'int8u', 'string', 'int16u',
74 'int32u', 'rational64u', 'int8s', 'undef',
75 'int16s', 'int32s', 'rational64s', 'float',
76 'double', 'ifd', 'unicode', 'complex',
77 'int64u', 'int64s', 'ifd64', # (new BigTIFF formats)
78);
79
80# hash to look up EXIF format numbers by name
81# (format types are all lower case)
82%formatNumber = (
83 'int8u' => 1, # BYTE
84 'string' => 2, # ASCII
85 'int16u' => 3, # SHORT
86 'int32u' => 4, # LONG
87 'rational64u' => 5, # RATIONAL
88 'int8s' => 6, # SBYTE
89 'undef' => 7, # UNDEFINED
90 'binary' => 7, # (treat binary data as undef)
91 'int16s' => 8, # SSHORT
92 'int32s' => 9, # SLONG
93 'rational64s' => 10, # SRATIONAL
94 'float' => 11, # FLOAT
95 'double' => 12, # DOUBLE
96 'ifd' => 13, # IFD (with int32u format)
97 'unicode' => 14, # UNICODE [see Note below]
98 'complex' => 15, # COMPLEX [see Note below]
99 'int64u' => 16, # LONG8 [BigTIFF]
100 'int64s' => 17, # SLONG8 [BigTIFF]
101 'ifd64' => 18, # IFD8 (with int64u format) [BigTIFF]
102 # Note: unicode and complex types are not yet properly supported by ExifTool.
103 # These are types which have been observed in the Adobe DNG SDK code, but
104 # aren't fully supported there either. We know the sizes, but that's about it.
105 # We don't know if the unicode is null terminated, or the format for complex
106 # (although I suspect it would be two 4-byte floats, real and imaginary).
107);
108
109# lookup for integer format strings
110%intFormat = (
111 'int8u' => 1,
112 'int16u' => 3,
113 'int32u' => 4,
114 'int8s' => 6,
115 'int16s' => 8,
116 'int32s' => 9,
117 'ifd' => 13,
118 'int64u' => 16,
119 'int64s' => 17,
120 'ifd64' => 18,
121);
122
123# EXIF LightSource PrintConv values
124%lightSource = (
125 0 => 'Unknown',
126 1 => 'Daylight',
127 2 => 'Fluorescent',
128 3 => 'Tungsten (Incandescent)',
129 4 => 'Flash',
130 9 => 'Fine Weather',
131 10 => 'Cloudy',
132 11 => 'Shade',
133 12 => 'Daylight Fluorescent', # (D 5700 - 7100K)
134 13 => 'Day White Fluorescent', # (N 4600 - 5500K)
135 14 => 'Cool White Fluorescent', # (W 3800 - 4500K)
136 15 => 'White Fluorescent', # (WW 3250 - 3800K)
137 16 => 'Warm White Fluorescent', # (L 2600 - 3250K)
138 17 => 'Standard Light A',
139 18 => 'Standard Light B',
140 19 => 'Standard Light C',
141 20 => 'D55',
142 21 => 'D65',
143 22 => 'D75',
144 23 => 'D50',
145 24 => 'ISO Studio Tungsten',
146 255 => 'Other',
147);
148
149# EXIF Flash values
150%flash = (
151 OTHER => sub {
152 # translate "Off" and "On" when writing
153 my ($val, $inv) = @_;
154 return undef unless $inv and $val =~ /^(off|on)$/i;
155 return lc $val eq 'off' ? 0x00 : 0x01;
156 },
157 0x00 => 'No Flash',
158 0x01 => 'Fired',
159 0x05 => 'Fired, Return not detected',
160 0x07 => 'Fired, Return detected',
161 0x08 => 'On, Did not fire', # not charged up?
162 0x09 => 'On, Fired',
163 0x0d => 'On, Return not detected',
164 0x0f => 'On, Return detected',
165 0x10 => 'Off, Did not fire',
166 0x14 => 'Off, Did not fire, Return not detected',
167 0x18 => 'Auto, Did not fire',
168 0x19 => 'Auto, Fired',
169 0x1d => 'Auto, Fired, Return not detected',
170 0x1f => 'Auto, Fired, Return detected',
171 0x20 => 'No flash function',
172 0x30 => 'Off, No flash function',
173 0x41 => 'Fired, Red-eye reduction',
174 0x45 => 'Fired, Red-eye reduction, Return not detected',
175 0x47 => 'Fired, Red-eye reduction, Return detected',
176 0x49 => 'On, Red-eye reduction',
177 0x4d => 'On, Red-eye reduction, Return not detected',
178 0x4f => 'On, Red-eye reduction, Return detected',
179 0x50 => 'Off, Red-eye reduction',
180 0x58 => 'Auto, Did not fire, Red-eye reduction',
181 0x59 => 'Auto, Fired, Red-eye reduction',
182 0x5d => 'Auto, Fired, Red-eye reduction, Return not detected',
183 0x5f => 'Auto, Fired, Red-eye reduction, Return detected',
184);
185
186# TIFF Compression values
187# (values with format "Xxxxx XXX Compressed" are used to identify RAW file types)
188%compression = (
189 1 => 'Uncompressed',
190 2 => 'CCITT 1D',
191 3 => 'T4/Group 3 Fax',
192 4 => 'T6/Group 4 Fax',
193 5 => 'LZW',
194 6 => 'JPEG (old-style)', #3
195 7 => 'JPEG', #4
196 8 => 'Adobe Deflate', #3
197 9 => 'JBIG B&W', #3
198 10 => 'JBIG Color', #3
199 99 => 'JPEG', #16
200 262 => 'Kodak 262', #16
201 32766 => 'Next', #3
202 32767 => 'Sony ARW Compressed', #16
203 32769 => 'Packed RAW', #PH (used by Epson, Nikon, Samsung)
204 32770 => 'Samsung SRW Compressed', #PH
205 32771 => 'CCIRLEW', #3
206 32773 => 'PackBits',
207 32809 => 'Thunderscan', #3
208 32867 => 'Kodak KDC Compressed', #PH
209 32895 => 'IT8CTPAD', #3
210 32896 => 'IT8LW', #3
211 32897 => 'IT8MP', #3
212 32898 => 'IT8BL', #3
213 32908 => 'PixarFilm', #3
214 32909 => 'PixarLog', #3
215 32946 => 'Deflate', #3
216 32947 => 'DCS', #3
217 34661 => 'JBIG', #3
218 34676 => 'SGILog', #3
219 34677 => 'SGILog24', #3
220 34712 => 'JPEG 2000', #3
221 34713 => 'Nikon NEF Compressed', #PH
222 34715 => 'JBIG2 TIFF FX', #20
223 34718 => 'Microsoft Document Imaging (MDI) Binary Level Codec', #18
224 34719 => 'Microsoft Document Imaging (MDI) Progressive Transform Codec', #18
225 34720 => 'Microsoft Document Imaging (MDI) Vector', #18
226 65000 => 'Kodak DCR Compressed', #PH
227 65535 => 'Pentax PEF Compressed', #Jens
228);
229
230%photometricInterpretation = (
231 0 => 'WhiteIsZero',
232 1 => 'BlackIsZero',
233 2 => 'RGB',
234 3 => 'RGB Palette',
235 4 => 'Transparency Mask',
236 5 => 'CMYK',
237 6 => 'YCbCr',
238 8 => 'CIELab',
239 9 => 'ICCLab', #3
240 10 => 'ITULab', #3
241 32803 => 'Color Filter Array', #2
242 32844 => 'Pixar LogL', #3
243 32845 => 'Pixar LogLuv', #3
244 34892 => 'Linear Raw', #2
245);
246
247%orientation = (
248 1 => 'Horizontal (normal)',
249 2 => 'Mirror horizontal',
250 3 => 'Rotate 180',
251 4 => 'Mirror vertical',
252 5 => 'Mirror horizontal and rotate 270 CW',
253 6 => 'Rotate 90 CW',
254 7 => 'Mirror horizontal and rotate 90 CW',
255 8 => 'Rotate 270 CW',
256);
257
258%subfileType = (
259 0 => 'Full-resolution Image',
260 1 => 'Reduced-resolution image',
261 2 => 'Single page of multi-page image',
262 3 => 'Single page of multi-page reduced-resolution image',
263 4 => 'Transparency mask',
264 5 => 'Transparency mask of reduced-resolution image',
265 6 => 'Transparency mask of multi-page image',
266 7 => 'Transparency mask of reduced-resolution multi-page image',
267 0xffffffff => 'invalid', #(found in E5700 NEF's)
268 BITMASK => {
269 0 => 'Reduced resolution',
270 1 => 'Single page',
271 2 => 'Transparency mask',
272 3 => 'TIFF/IT final page', #20
273 4 => 'TIFF-FX mixed raster content', #20
274 },
275);
276
277# PrintConv for parameter tags
278%Image::ExifTool::Exif::printParameter = (
279 PrintConv => {
280 0 => 'Normal',
281 OTHER => \&Image::ExifTool::Exif::PrintParameter,
282 },
283);
284
285# ValueConv that makes long values binary type
286my %longBin = (
287 ValueConv => 'length($val) > 64 ? \$val : $val',
288 ValueConvInv => '$val',
289);
290
291# PrintConv for SampleFormat (0x153)
292my %sampleFormat = (
293 1 => 'Unsigned', # unsigned integer
294 2 => 'Signed', # two's complement signed integer
295 3 => 'Float', # IEEE floating point
296 4 => 'Undefined',
297 5 => 'Complex int', # complex integer (ref 3)
298 6 => 'Complex float', # complex IEEE floating point (ref 3)
299);
300
301# main EXIF tag table
302%Image::ExifTool::Exif::Main = (
303 GROUPS => { 0 => 'EXIF', 1 => 'IFD0', 2 => 'Image'},
304 WRITE_PROC => \&WriteExif,
305 WRITE_GROUP => 'ExifIFD', # default write group
306 SET_GROUP1 => 1, # set group1 name to directory name for all tags in table
307 0x1 => {
308 Name => 'InteropIndex',
309 Description => 'Interoperability Index',
310 PrintConv => {
311 R98 => 'R98 - DCF basic file (sRGB)',
312 R03 => 'R03 - DCF option file (Adobe RGB)',
313 THM => 'THM - DCF thumbnail file',
314 },
315 },
316 0x2 => { #5
317 Name => 'InteropVersion',
318 Description => 'Interoperability Version',
319 RawConv => '$val=~s/\0+$//; $val', # (some idiots add null terminators)
320 },
321 0x0b => { #PH
322 Name => 'ProcessingSoftware',
323 Notes => 'used by ACD Systems Digital Imaging',
324 },
325 0xfe => {
326 Name => 'SubfileType',
327 # set priority directory if this is the full resolution image
328 DataMember => 'SubfileType',
329 RawConv => '$self->SetPriorityDir() if $val eq "0"; $$self{SubfileType} = $val',
330 PrintConv => \%subfileType,
331 },
332 0xff => {
333 Name => 'OldSubfileType',
334 # set priority directory if this is the full resolution image
335 RawConv => '$self->SetPriorityDir() if $val eq "1"; $val',
336 PrintConv => {
337 1 => 'Full-resolution image',
338 2 => 'Reduced-resolution image',
339 3 => 'Single page of multi-page image',
340 },
341 },
342 0x100 => {
343 Name => 'ImageWidth',
344 # even though Group 1 is set dynamically we need to register IFD1 once
345 # so it will show up in the group lists
346 Groups => { 1 => 'IFD1' },
347 # Note: priority 0 tags automatically have their priority increased for the
348 # priority direcory (the directory with a SubfileType of "Full-resolution image")
349 Priority => 0,
350 },
351 0x101 => {
352 Name => 'ImageHeight',
353 Notes => 'called ImageLength by the EXIF spec.',
354 Priority => 0,
355 },
356 0x102 => {
357 Name => 'BitsPerSample',
358 Priority => 0,
359 },
360 0x103 => {
361 Name => 'Compression',
362 DataMember => 'Compression',
363 SeparateTable => 'Compression',
364 RawConv => q{
365 Image::ExifTool::Exif::IdentifyRawFile($self, $val);
366 return $$self{Compression} = $val;
367 },
368 PrintConv => \%compression,
369 Priority => 0,
370 },
371 0x106 => {
372 Name => 'PhotometricInterpretation',
373 PrintConv => \%photometricInterpretation,
374 Priority => 0,
375 },
376 0x107 => {
377 Name => 'Thresholding',
378 PrintConv => {
379 1 => 'No dithering or halftoning',
380 2 => 'Ordered dither or halftone',
381 3 => 'Randomized dither',
382 },
383 },
384 0x108 => 'CellWidth',
385 0x109 => 'CellLength',
386 0x10a => {
387 Name => 'FillOrder',
388 PrintConv => {
389 1 => 'Normal',
390 2 => 'Reversed',
391 },
392 },
393 0x10d => 'DocumentName',
394 0x10e => {
395 Name => 'ImageDescription',
396 Priority => 0,
397 },
398 0x10f => {
399 Name => 'Make',
400 Groups => { 2 => 'Camera' },
401 DataMember => 'Make',
402 # remove trailing blanks and save as an ExifTool member variable
403 RawConv => '$val =~ s/\s+$//; $$self{Make} = $val',
404 # NOTE: trailing "blanks" (spaces) are removed from all EXIF tags which
405 # may be "unknown" (filled with spaces) according to the EXIF spec.
406 # This allows conditional replacement with "exiftool -TAG-= -TAG=VALUE".
407 # - also removed are any other trailing whitespace characters
408 },
409 0x110 => {
410 Name => 'Model',
411 Description => 'Camera Model Name',
412 Groups => { 2 => 'Camera' },
413 DataMember => 'Model',
414 # remove trailing blanks and save as an ExifTool member variable
415 RawConv => '$val =~ s/\s+$//; $$self{Model} = $val',
416 },
417 0x111 => [
418 {
419 Condition => q[
420 $$self{TIFF_TYPE} eq 'MRW' and $$self{DIR_NAME} eq 'IFD0' and
421 $$self{Model} =~ /^DiMAGE A200/
422 ],
423 Name => 'StripOffsets',
424 IsOffset => 1,
425 OffsetPair => 0x117, # point to associated byte counts
426 # A200 stores this information in the wrong byte order!!
427 ValueConv => '$val=join(" ",unpack("N*",pack("V*",split(" ",$val))));\$val',
428 ByteOrder => 'LittleEndian',
429 },
430 {
431 Condition => q[
432 ($$self{TIFF_TYPE} ne 'CR2' or $$self{DIR_NAME} ne 'IFD0') and
433 ($$self{TIFF_TYPE} ne 'DNG' or $$self{DIR_NAME} !~ /^SubIFD[12]$/)
434 ],
435 Name => 'StripOffsets',
436 IsOffset => 1,
437 OffsetPair => 0x117, # point to associated byte counts
438 ValueConv => 'length($val) > 32 ? \$val : $val',
439 },
440 {
441 Condition => '$$self{DIR_NAME} eq "IFD0"',
442 Name => 'PreviewImageStart',
443 IsOffset => 1,
444 OffsetPair => 0x117,
445 Notes => q{
446 PreviewImageStart in IFD0 of CR2 images and SubIFD1 of DNG images, and
447 JpgFromRawStart in SubIFD2 of DNG images
448 },
449 DataTag => 'PreviewImage',
450 Writable => 'int32u',
451 WriteGroup => 'IFD0',
452 WriteCondition => '$$self{TIFF_TYPE} eq "CR2"',
453 Protected => 2,
454 },
455 {
456 Condition => '$$self{DIR_NAME} eq "SubIFD1"',
457 Name => 'PreviewImageStart',
458 IsOffset => 1,
459 OffsetPair => 0x117,
460 DataTag => 'PreviewImage',
461 Writable => 'int32u',
462 WriteGroup => 'SubIFD1',
463 WriteCondition => '$$self{TIFF_TYPE} eq "DNG"',
464 Protected => 2,
465 },
466 {
467 Name => 'JpgFromRawStart',
468 IsOffset => 1,
469 OffsetPair => 0x117,
470 DataTag => 'JpgFromRaw',
471 Writable => 'int32u',
472 WriteGroup => 'SubIFD2',
473 WriteCondition => '$$self{TIFF_TYPE} eq "DNG"',
474 Protected => 2,
475 },
476 ],
477 0x112 => {
478 Name => 'Orientation',
479 PrintConv => \%orientation,
480 Priority => 0, # so PRIORITY_DIR takes precedence
481 },
482 0x115 => {
483 Name => 'SamplesPerPixel',
484 Priority => 0,
485 },
486 0x116 => {
487 Name => 'RowsPerStrip',
488 Priority => 0,
489 },
490 0x117 => [
491 {
492 Condition => q[
493 $$self{TIFF_TYPE} eq 'MRW' and $$self{DIR_NAME} eq 'IFD0' and
494 $$self{Model} =~ /^DiMAGE A200/
495 ],
496 Name => 'StripByteCounts',
497 OffsetPair => 0x111, # point to associated offset
498 # A200 stores this information in the wrong byte order!!
499 ValueConv => '$val=join(" ",unpack("N*",pack("V*",split(" ",$val))));\$val',
500 ByteOrder => 'LittleEndian',
501 },
502 {
503 Condition => q[
504 ($$self{TIFF_TYPE} ne 'CR2' or $$self{DIR_NAME} ne 'IFD0') and
505 ($$self{TIFF_TYPE} ne 'DNG' or $$self{DIR_NAME} !~ /^SubIFD[12]$/)
506 ],
507 Name => 'StripByteCounts',
508 OffsetPair => 0x111, # point to associated offset
509 ValueConv => 'length($val) > 32 ? \$val : $val',
510 },
511 {
512 Condition => '$$self{DIR_NAME} eq "IFD0"',
513 Name => 'PreviewImageLength',
514 OffsetPair => 0x111,
515 Notes => q{
516 PreviewImageLength in IFD0 of CR2 images and SubIFD1 of DNG images, and
517 JpgFromRawLength in SubIFD2 of DNG images
518 },
519 DataTag => 'PreviewImage',
520 Writable => 'int32u',
521 WriteGroup => 'IFD0',
522 WriteCondition => '$$self{TIFF_TYPE} eq "CR2"',
523 Protected => 2,
524 },
525 {
526 Condition => '$$self{DIR_NAME} eq "SubIFD1"',
527 Name => 'PreviewImageLength',
528 OffsetPair => 0x111,
529 DataTag => 'PreviewImage',
530 Writable => 'int32u',
531 WriteGroup => 'SubIFD1',
532 WriteCondition => '$$self{TIFF_TYPE} eq "DNG"',
533 Protected => 2,
534 },
535 {
536 Name => 'JpgFromRawLength',
537 OffsetPair => 0x111,
538 DataTag => 'JpgFromRaw',
539 Writable => 'int32u',
540 WriteGroup => 'SubIFD2',
541 WriteCondition => '$$self{TIFF_TYPE} eq "DNG"',
542 Protected => 2,
543 },
544 ],
545 0x118 => 'MinSampleValue',
546 0x119 => 'MaxSampleValue',
547 0x11a => {
548 Name => 'XResolution',
549 Priority => 0, # so PRIORITY_DIR takes precedence
550 },
551 0x11b => {
552 Name => 'YResolution',
553 Priority => 0,
554 },
555 0x11c => {
556 Name => 'PlanarConfiguration',
557 PrintConv => {
558 1 => 'Chunky',
559 2 => 'Planar',
560 },
561 Priority => 0,
562 },
563 0x11d => 'PageName',
564 0x11e => 'XPosition',
565 0x11f => 'YPosition',
566 0x120 => {
567 Name => 'FreeOffsets',
568 IsOffset => 1,
569 OffsetPair => 0x121,
570 ValueConv => 'length($val) > 32 ? \$val : $val',
571 },
572 0x121 => {
573 Name => 'FreeByteCounts',
574 OffsetPair => 0x120,
575 ValueConv => 'length($val) > 32 ? \$val : $val',
576 },
577 0x122 => {
578 Name => 'GrayResponseUnit',
579 PrintConv => { #3
580 1 => 0.1,
581 2 => 0.001,
582 3 => 0.0001,
583 4 => 0.00001,
584 5 => 0.000001,
585 },
586 },
587 0x123 => {
588 Name => 'GrayResponseCurve',
589 Binary => 1,
590 },
591 0x124 => {
592 Name => 'T4Options',
593 PrintConv => { BITMASK => {
594 0 => '2-Dimensional encoding',
595 1 => 'Uncompressed',
596 2 => 'Fill bits added',
597 } }, #3
598 },
599 0x125 => {
600 Name => 'T6Options',
601 PrintConv => { BITMASK => {
602 1 => 'Uncompressed',
603 } }, #3
604 },
605 0x128 => {
606 Name => 'ResolutionUnit',
607 Notes => 'the value 1 is not standard EXIF',
608 PrintConv => {
609 1 => 'None',
610 2 => 'inches',
611 3 => 'cm',
612 },
613 Priority => 0,
614 },
615 0x129 => 'PageNumber',
616 0x12c => 'ColorResponseUnit', #9
617 0x12d => {
618 Name => 'TransferFunction',
619 Binary => 1,
620 },
621 0x131 => {
622 Name => 'Software',
623 RawConv => '$val =~ s/\s+$//; $val', # trim trailing blanks
624 },
625 0x132 => {
626 Name => 'ModifyDate',
627 Groups => { 2 => 'Time' },
628 Notes => 'called DateTime by the EXIF spec.',
629 PrintConv => '$self->ConvertDateTime($val)',
630 },
631 0x13b => {
632 Name => 'Artist',
633 Groups => { 2 => 'Author' },
634 Notes => 'becomes a list-type tag when the MWG module is loaded',
635 RawConv => '$val =~ s/\s+$//; $val', # trim trailing blanks
636 },
637 0x13c => 'HostComputer',
638 0x13d => {
639 Name => 'Predictor',
640 PrintConv => {
641 1 => 'None',
642 2 => 'Horizontal differencing',
643 },
644 },
645 0x13e => {
646 Name => 'WhitePoint',
647 Groups => { 2 => 'Camera' },
648 },
649 0x13f => {
650 Name => 'PrimaryChromaticities',
651 Priority => 0,
652 },
653 0x140 => {
654 Name => 'ColorMap',
655 Format => 'binary',
656 Binary => 1,
657 },
658 0x141 => 'HalftoneHints',
659 0x142 => 'TileWidth',
660 0x143 => 'TileLength',
661 0x144 => {
662 Name => 'TileOffsets',
663 IsOffset => 1,
664 OffsetPair => 0x145,
665 ValueConv => 'length($val) > 32 ? \$val : $val',
666 },
667 0x145 => {
668 Name => 'TileByteCounts',
669 OffsetPair => 0x144,
670 ValueConv => 'length($val) > 32 ? \$val : $val',
671 },
672 0x146 => 'BadFaxLines', #3
673 0x147 => { #3
674 Name => 'CleanFaxData',
675 PrintConv => {
676 0 => 'Clean',
677 1 => 'Regenerated',
678 2 => 'Unclean',
679 },
680 },
681 0x148 => 'ConsecutiveBadFaxLines', #3
682 0x14a => [
683 {
684 Name => 'SubIFD',
685 # use this opportunity to identify an ARW image, and if so we
686 # must decide if this is a SubIFD or the A100 raw data
687 # (use SubfileType, Compression and FILE_TYPE to identify ARW/SR2,
688 # then call SetARW to finish the job)
689 Condition => q{
690 $$self{DIR_NAME} ne 'IFD0' or $$self{FILE_TYPE} ne 'TIFF' or
691 $$self{Make} !~ /^SONY/ or
692 not $$self{SubfileType} or $$self{SubfileType} != 1 or
693 not $$self{Compression} or $$self{Compression} != 6 or
694 not require Image::ExifTool::Sony or
695 Image::ExifTool::Sony::SetARW($self, $valPt)
696 },
697 Groups => { 1 => 'SubIFD' },
698 Flags => 'SubIFD',
699 SubDirectory => {
700 Start => '$val',
701 MaxSubdirs => 3,
702 },
703 },
704 { #16
705 Name => 'A100DataOffset',
706 Notes => 'the data offset in original Sony DSLR-A100 ARW images',
707 DataMember => 'A100DataOffset',
708 RawConv => '$$self{A100DataOffset} = $val',
709 IsOffset => 1,
710 },
711 ],
712 0x14c => {
713 Name => 'InkSet',
714 PrintConv => { #3
715 1 => 'CMYK',
716 2 => 'Not CMYK',
717 },
718 },
719 0x14d => 'InkNames', #3
720 0x14e => 'NumberofInks', #3
721 0x150 => 'DotRange',
722 0x151 => 'TargetPrinter',
723 0x152 => {
724 Name => 'ExtraSamples',
725 PrintConv => { #20
726 0 => 'Unspecified',
727 1 => 'Associated Alpha',
728 2 => 'Unassociated Alpha',
729 },
730 },
731 0x153 => {
732 Name => 'SampleFormat',
733 Notes => 'SamplesPerPixel values',
734 PrintConvColumns => 2,
735 PrintConv => [ \%sampleFormat, \%sampleFormat, \%sampleFormat, \%sampleFormat ],
736 },
737 0x154 => 'SMinSampleValue',
738 0x155 => 'SMaxSampleValue',
739 0x156 => 'TransferRange',
740 0x157 => 'ClipPath', #3
741 0x158 => 'XClipPathUnits', #3
742 0x159 => 'YClipPathUnits', #3
743 0x15a => { #3
744 Name => 'Indexed',
745 PrintConv => { 0 => 'Not indexed', 1 => 'Indexed' },
746 },
747 0x15b => {
748 Name => 'JPEGTables',
749 Binary => 1,
750 },
751 0x15f => { #10
752 Name => 'OPIProxy',
753 PrintConv => {
754 0 => 'Higher resolution image does not exist',
755 1 => 'Higher resolution image exists',
756 },
757 },
758 # 0x181 => 'Decode', #20 (typo! - should be 0x1b1, ref 21)
759 # 0x182 => 'DefaultImageColor', #20 (typo! - should be 0x1b2, ref 21)
760 0x190 => { #3
761 Name => 'GlobalParametersIFD',
762 Groups => { 1 => 'GlobParamIFD' },
763 Flags => 'SubIFD',
764 SubDirectory => {
765 DirName => 'GlobParamIFD',
766 Start => '$val',
767 },
768 },
769 0x191 => { #3
770 Name => 'ProfileType',
771 PrintConv => { 0 => 'Unspecified', 1 => 'Group 3 FAX' },
772 },
773 0x192 => { #3
774 Name => 'FaxProfile',
775 PrintConv => {
776 0 => 'Unknown',
777 1 => 'Minimal B&W lossless, S',
778 2 => 'Extended B&W lossless, F',
779 3 => 'Lossless JBIG B&W, J',
780 4 => 'Lossy color and grayscale, C',
781 5 => 'Lossless color and grayscale, L',
782 6 => 'Mixed raster content, M',
783 7 => 'Profile T', #20
784 255 => 'Multi Profiles', #20
785 },
786 },
787 0x193 => { #3
788 Name => 'CodingMethods',
789 PrintConv => { BITMASK => {
790 0 => 'Unspecified compression',
791 1 => 'Modified Huffman',
792 2 => 'Modified Read',
793 3 => 'Modified MR',
794 4 => 'JBIG',
795 5 => 'Baseline JPEG',
796 6 => 'JBIG color',
797 } },
798 },
799 0x194 => 'VersionYear', #3
800 0x195 => 'ModeNumber', #3
801 0x1b1 => 'Decode', #3
802 0x1b2 => 'DefaultImageColor', #3 (changed to ImageBaseColor, ref 21)
803 0x1b3 => 'T82Options', #20
804 0x1b5 => { #19
805 Name => 'JPEGTables',
806 Binary => 1,
807 },
808 0x200 => {
809 Name => 'JPEGProc',
810 PrintConv => {
811 1 => 'Baseline',
812 14 => 'Lossless',
813 },
814 },
815 0x201 => [
816 {
817 Name => 'ThumbnailOffset',
818 Notes => q{
819 ThumbnailOffset in IFD1 of JPEG and some TIFF-based images, IFD0 of MRW
820 images and AVI videos, and the SubIFD in IFD1 of SRW images;
821 PreviewImageStart in MakerNotes and IFD0 of ARW and SR2 images;
822 JpgFromRawStart in SubIFD of NEF images and IFD2 of PEF images; and
823 OtherImageStart in everything else
824 },
825 # thumbnail is found in IFD1 of JPEG and TIFF images, and
826 # IFD0 of EXIF information in FujiFilm AVI (RIFF) videos
827 Condition => q{
828 $$self{DIR_NAME} eq 'IFD1' or
829 ($$self{FILE_TYPE} eq 'RIFF' and $$self{DIR_NAME} eq 'IFD0')
830 },
831 IsOffset => 1,
832 OffsetPair => 0x202,
833 DataTag => 'ThumbnailImage',
834 Writable => 'int32u',
835 WriteGroup => 'IFD1',
836 # according to the EXIF spec. a JPEG-compressed thumbnail image may not
837 # be stored in a TIFF file, but these TIFF-based RAW image formats
838 # use IFD1 for a JPEG-compressed thumbnail: CR2, ARW, SR2 and PEF.
839 # (SRF also stores a JPEG image in IFD1, but it is actually a preview
840 # and we don't yet write SRF anyway)
841 WriteCondition => q{
842 $$self{FILE_TYPE} ne "TIFF" or
843 $$self{TIFF_TYPE} =~ /^(CR2|ARW|SR2|PEF)$/
844 },
845 Protected => 2,
846 },
847 {
848 Name => 'ThumbnailOffset',
849 # thumbnail in IFD0 of MRW images (Minolta A200)
850 Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} eq "MRW"',
851 IsOffset => 1,
852 OffsetPair => 0x202,
853 # A200 uses the wrong base offset for this pointer!!
854 WrongBase => '$$self{Model} =~ /^DiMAGE A200/ ? $$self{MRW_WrongBase} : undef',
855 DataTag => 'ThumbnailImage',
856 Writable => 'int32u',
857 WriteGroup => 'IFD0',
858 WriteCondition => '$$self{FILE_TYPE} eq "MRW"',
859 Protected => 2,
860 },
861 {
862 Name => 'ThumbnailOffset',
863 # in SubIFD of IFD1 in Samsung SRW images
864 Condition => q{
865 $$self{TIFF_TYPE} eq 'SRW' and $$self{DIR_NAME} eq 'SubIFD' and
866 $$self{PATH}[-2] eq 'IFD1'
867 },
868 IsOffset => 1,
869 OffsetPair => 0x202,
870 DataTag => 'ThumbnailImage',
871 Writable => 'int32u',
872 WriteGroup => 'SubIFD',
873 WriteCondition => '$$self{TIFF_TYPE} eq "SRW"',
874 Protected => 2,
875 },
876 {
877 Name => 'PreviewImageStart',
878 Condition => '$$self{DIR_NAME} eq "MakerNotes"',
879 IsOffset => 1,
880 OffsetPair => 0x202,
881 DataTag => 'PreviewImage',
882 Writable => 'int32u',
883 WriteGroup => 'MakerNotes',
884 # (no WriteCondition necessary because MakerNotes won't be created)
885 Protected => 2,
886 },
887 {
888 Name => 'PreviewImageStart',
889 # PreviewImage in IFD0 of ARW and SR2 files for all models
890 Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} =~ /^(ARW|SR2)$/',
891 IsOffset => 1,
892 OffsetPair => 0x202,
893 DataTag => 'PreviewImage',
894 Writable => 'int32u',
895 WriteGroup => 'IFD0',
896 WriteCondition => '$$self{TIFF_TYPE} =~ /^(ARW|SR2)$/',
897 Protected => 2,
898 },
899 {
900 Name => 'JpgFromRawStart',
901 Condition => '$$self{DIR_NAME} eq "SubIFD"',
902 IsOffset => 1,
903 OffsetPair => 0x202,
904 DataTag => 'JpgFromRaw',
905 Writable => 'int32u',
906 WriteGroup => 'SubIFD',
907 # JpgFromRaw is in SubIFD of NEF, NRW and SRW files
908 WriteCondition => '$$self{TIFF_TYPE} =~ /^(NEF|NRW|SRW)$/',
909 Protected => 2,
910 },
911 {
912 Name => 'JpgFromRawStart',
913 Condition => '$$self{DIR_NAME} eq "IFD2"',
914 IsOffset => 1,
915 OffsetPair => 0x202,
916 DataTag => 'JpgFromRaw',
917 Writable => 'int32u',
918 WriteGroup => 'IFD2',
919 # JpgFromRaw is in IFD2 of PEF files
920 WriteCondition => '$$self{TIFF_TYPE} eq "PEF"',
921 Protected => 2,
922 },
923 {
924 Name => 'OtherImageStart',
925 IsOffset => 1,
926 OffsetPair => 0x202,
927 },
928 ],
929 0x202 => [
930 {
931 Name => 'ThumbnailLength',
932 Notes => q{
933 ThumbnailLength in IFD1 of JPEG and some TIFF-based images, IFD0 of MRW
934 images and AVI videos, and the SubIFD in IFD1 of SRW images;
935 PreviewImageLength in MakerNotes and IFD0 of ARW and SR2 images;
936 JpgFromRawLength in SubIFD of NEF images, and IFD2 of PEF images; and
937 OtherImageLength in everything else
938 },
939 Condition => q{
940 $$self{DIR_NAME} eq 'IFD1' or
941 ($$self{FILE_TYPE} eq 'RIFF' and $$self{DIR_NAME} eq 'IFD0')
942 },
943 OffsetPair => 0x201,
944 DataTag => 'ThumbnailImage',
945 Writable => 'int32u',
946 WriteGroup => 'IFD1',
947 WriteCondition => q{
948 $$self{FILE_TYPE} ne "TIFF" or
949 $$self{TIFF_TYPE} =~ /^(CR2|ARW|SR2|PEF)$/
950 },
951 Protected => 2,
952 },
953 {
954 Name => 'ThumbnailLength',
955 # thumbnail in IFD0 of MRW images (Minolta A200)
956 Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} eq "MRW"',
957 OffsetPair => 0x201,
958 DataTag => 'ThumbnailImage',
959 Writable => 'int32u',
960 WriteGroup => 'IFD0',
961 WriteCondition => '$$self{FILE_TYPE} eq "MRW"',
962 Protected => 2,
963 },
964 {
965 Name => 'ThumbnailLength',
966 # in SubIFD of IFD1 in Samsung SRW images
967 Condition => q{
968 $$self{TIFF_TYPE} eq 'SRW' and $$self{DIR_NAME} eq 'SubIFD' and
969 $$self{PATH}[-2] eq 'IFD1'
970 },
971 OffsetPair => 0x201,
972 DataTag => 'ThumbnailImage',
973 Writable => 'int32u',
974 WriteGroup => 'SubIFD',
975 WriteCondition => '$$self{TIFF_TYPE} eq "SRW"',
976 Protected => 2,
977 },
978 {
979 Name => 'PreviewImageLength',
980 Condition => '$$self{DIR_NAME} eq "MakerNotes"',
981 OffsetPair => 0x201,
982 DataTag => 'PreviewImage',
983 Writable => 'int32u',
984 WriteGroup => 'MakerNotes',
985 # (no WriteCondition necessary because MakerNotes won't be created)
986 Protected => 2,
987 },
988 {
989 Name => 'PreviewImageLength',
990 # PreviewImage in IFD0 of ARW and SR2 files for all models
991 Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} =~ /^(ARW|SR2)$/',
992 OffsetPair => 0x201,
993 DataTag => 'PreviewImage',
994 Writable => 'int32u',
995 WriteGroup => 'IFD0',
996 WriteCondition => '$$self{TIFF_TYPE} =~ /^(ARW|SR2)$/',
997 Protected => 2,
998 },
999 {
1000 Name => 'JpgFromRawLength',
1001 Condition => '$$self{DIR_NAME} eq "SubIFD"',
1002 OffsetPair => 0x201,
1003 DataTag => 'JpgFromRaw',
1004 Writable => 'int32u',
1005 WriteGroup => 'SubIFD',
1006 WriteCondition => '$$self{TIFF_TYPE} =~ /^(NEF|NRW|SRW)$/',
1007 Protected => 2,
1008 },
1009 {
1010 Name => 'JpgFromRawLength',
1011 Condition => '$$self{DIR_NAME} eq "IFD2"',
1012 OffsetPair => 0x201,
1013 DataTag => 'JpgFromRaw',
1014 Writable => 'int32u',
1015 WriteGroup => 'IFD2',
1016 WriteCondition => '$$self{TIFF_TYPE} eq "PEF"',
1017 Protected => 2,
1018 },
1019 {
1020 Name => 'OtherImageLength',
1021 OffsetPair => 0x201,
1022 },
1023 ],
1024 0x203 => 'JPEGRestartInterval',
1025 0x205 => 'JPEGLosslessPredictors',
1026 0x206 => 'JPEGPointTransforms',
1027 0x207 => {
1028 Name => 'JPEGQTables',
1029 IsOffset => 1,
1030 # this tag is not supported for writing, so define an
1031 # invalid offset pair to cause a "No size tag" error to be
1032 # generated if we try to write a file containing this tag
1033 OffsetPair => -1,
1034 },
1035 0x208 => {
1036 Name => 'JPEGDCTables',
1037 IsOffset => 1,
1038 OffsetPair => -1, # (see comment for JPEGQTables)
1039 },
1040 0x209 => {
1041 Name => 'JPEGACTables',
1042 IsOffset => 1,
1043 OffsetPair => -1, # (see comment for JPEGQTables)
1044 },
1045 0x211 => {
1046 Name => 'YCbCrCoefficients',
1047 Priority => 0,
1048 },
1049 0x212 => {
1050 Name => 'YCbCrSubSampling',
1051 PrintConvColumns => 2,
1052 PrintConv => \%Image::ExifTool::JPEG::yCbCrSubSampling,
1053 Priority => 0,
1054 },
1055 0x213 => {
1056 Name => 'YCbCrPositioning',
1057 PrintConv => {
1058 1 => 'Centered',
1059 2 => 'Co-sited',
1060 },
1061 Priority => 0,
1062 },
1063 0x214 => {
1064 Name => 'ReferenceBlackWhite',
1065 Priority => 0,
1066 },
1067 0x22f => 'StripRowCounts',
1068 0x2bc => {
1069 Name => 'ApplicationNotes', # (writable directory!)
1070 Writable => 'int8u',
1071 Format => 'undef',
1072 Flags => [ 'Binary', 'Protected' ],
1073 # this could be an XMP block
1074 SubDirectory => {
1075 DirName => 'XMP',
1076 TagTable => 'Image::ExifTool::XMP::Main',
1077 },
1078 },
1079 0x3e7 => 'USPTOMiscellaneous', #20
1080 0x1000 => 'RelatedImageFileFormat', #5
1081 0x1001 => 'RelatedImageWidth', #5
1082 0x1002 => { #5
1083 Name => 'RelatedImageHeight',
1084 Notes => 'called RelatedImageLength by the DCF spec.',
1085 },
1086 # (0x474x tags written by MicrosoftPhoto)
1087 0x4746 => 'Rating', #PH
1088 0x4747 => { # (written by Digital Image Pro)
1089 Name => 'XP_DIP_XML',
1090 Format => 'undef',
1091 # the following reference indicates this is Unicode:
1092 # http://social.msdn.microsoft.com/Forums/en-US/isvvba/thread/ce6edcbb-8fc2-40c6-ad98-85f5d835ddfb
1093 ValueConv => '$self->Decode($val,"UCS2","II")',
1094 },
1095 0x4748 => {
1096 Name => 'StitchInfo',
1097 SubDirectory => {
1098 TagTable => 'Image::ExifTool::Microsoft::Stitch',
1099 ByteOrder => 'LittleEndian', #PH (NC)
1100 },
1101 },
1102 0x4749 => 'RatingPercent', #PH
1103 0x800d => 'ImageID', #10
1104 0x80a3 => { Name => 'WangTag1', Binary => 1 }, #20
1105 0x80a4 => { Name => 'WangAnnotation', Binary => 1 },
1106 0x80a5 => { Name => 'WangTag3', Binary => 1 }, #20
1107 0x80a6 => { #20
1108 Name => 'WangTag4',
1109 PrintConv => 'length($val) <= 64 ? $val : \$val',
1110 },
1111 0x80e3 => 'Matteing', #9
1112 0x80e4 => 'DataType', #9
1113 0x80e5 => 'ImageDepth', #9
1114 0x80e6 => 'TileDepth', #9
1115 0x827d => 'Model2',
1116 0x828d => 'CFARepeatPatternDim', #12
1117 0x828e => {
1118 Name => 'CFAPattern2', #12
1119 Format => 'int8u', # (written incorrectly as 'undef' in Nikon NRW images)
1120 },
1121 0x828f => { #12
1122 Name => 'BatteryLevel',
1123 Groups => { 2 => 'Camera' },
1124 },
1125 0x8290 => {
1126 Name => 'KodakIFD',
1127 Groups => { 1 => 'KodakIFD' },
1128 Flags => 'SubIFD',
1129 Notes => 'used in various types of Kodak images',
1130 SubDirectory => {
1131 TagTable => 'Image::ExifTool::Kodak::IFD',
1132 DirName => 'KodakIFD',
1133 Start => '$val',
1134 },
1135 },
1136 0x8298 => {
1137 Name => 'Copyright',
1138 Groups => { 2 => 'Author' },
1139 Format => 'undef',
1140 Notes => q{
1141 may contain copyright notices for photographer and editor, separated by a
1142 newline in ExifTool
1143 },
1144 # internally the strings are separated by a null character in this format:
1145 # Photographer only: photographer + NULL
1146 # Both: photographer + NULL + editor + NULL
1147 # Editor only: SPACE + NULL + editor + NULL
1148 # 1) translate first NULL to a newline, removing trailing blanks
1149 # 2) truncate at second NULL and remove trailing blanks
1150 # 3) remove trailing newline if it exists
1151 # (this is done as a RawConv so conditional replaces will work properly)
1152 RawConv => '$_=$val; s/ *\0/\n/; s/ *\0.*//s; s/\n$//; $_',
1153 },
1154 0x829a => {
1155 Name => 'ExposureTime',
1156 PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
1157 },
1158 0x829d => {
1159 Name => 'FNumber',
1160 PrintConv => 'sprintf("%.1f",$val)',
1161 },
1162 0x82a5 => { #3
1163 Name => 'MDFileTag',
1164 Notes => 'tags 0x82a5-0x82ac are used in Molecular Dynamics GEL files',
1165 },
1166 0x82a6 => 'MDScalePixel', #3
1167 0x82a7 => 'MDColorTable', #3
1168 0x82a8 => 'MDLabName', #3
1169 0x82a9 => 'MDSampleInfo', #3
1170 0x82aa => 'MDPrepDate', #3
1171 0x82ab => 'MDPrepTime', #3
1172 0x82ac => 'MDFileUnits', #3
1173 0x830e => 'PixelScale',
1174 0x8335 => 'AdventScale', #20
1175 0x8336 => 'AdventRevision', #20
1176 0x835c => 'UIC1Tag', #23
1177 0x835d => 'UIC2Tag', #23
1178 0x835e => 'UIC3Tag', #23
1179 0x835f => 'UIC4Tag', #23
1180 0x83bb => { #12
1181 Name => 'IPTC-NAA', # (writable directory!)
1182 # this should actually be written as 'undef' (see
1183 # http://www.awaresystems.be/imaging/tiff/tifftags/iptc.html),
1184 # but Photoshop writes it as int32u and Nikon Capture won't read
1185 # anything else, so we do the same thing here... Doh!
1186 Format => 'undef', # convert binary values as undef
1187 Writable => 'int32u', # but write int32u format code in IFD
1188 WriteGroup => 'IFD0',
1189 Flags => [ 'Binary', 'Protected' ],
1190 SubDirectory => {
1191 DirName => 'IPTC',
1192 TagTable => 'Image::ExifTool::IPTC::Main',
1193 },
1194 },
1195 0x847e => 'IntergraphPacketData', #3
1196 0x847f => 'IntergraphFlagRegisters', #3
1197 0x8480 => 'IntergraphMatrix',
1198 0x8481 => 'INGRReserved', #20
1199 0x8482 => {
1200 Name => 'ModelTiePoint',
1201 Groups => { 2 => 'Location' },
1202 },
1203 0x84e0 => 'Site', #9
1204 0x84e1 => 'ColorSequence', #9
1205 0x84e2 => 'IT8Header', #9
1206 0x84e3 => { #9
1207 Name => 'RasterPadding',
1208 PrintConv => { #20
1209 0 => 'Byte',
1210 1 => 'Word',
1211 2 => 'Long Word',
1212 9 => 'Sector',
1213 10 => 'Long Sector',
1214 },
1215 },
1216 0x84e4 => 'BitsPerRunLength', #9
1217 0x84e5 => 'BitsPerExtendedRunLength', #9
1218 0x84e6 => 'ColorTable', #9
1219 0x84e7 => { #9
1220 Name => 'ImageColorIndicator',
1221 PrintConv => { #20
1222 0 => 'Unspecified Image Color',
1223 1 => 'Specified Image Color',
1224 },
1225 },
1226 0x84e8 => { #9
1227 Name => 'BackgroundColorIndicator',
1228 PrintConv => { #20
1229 0 => 'Unspecified Background Color',
1230 1 => 'Specified Background Color',
1231 },
1232 },
1233 0x84e9 => 'ImageColorValue', #9
1234 0x84ea => 'BackgroundColorValue', #9
1235 0x84eb => 'PixelIntensityRange', #9
1236 0x84ec => 'TransparencyIndicator', #9
1237 0x84ed => 'ColorCharacterization', #9
1238 0x84ee => { #9
1239 Name => 'HCUsage',
1240 PrintConv => { #20
1241 0 => 'CT',
1242 1 => 'Line Art',
1243 2 => 'Trap',
1244 },
1245 },
1246 0x84ef => 'TrapIndicator', #17
1247 0x84f0 => 'CMYKEquivalent', #17
1248 0x8546 => { #11
1249 Name => 'SEMInfo',
1250 Notes => 'found in some scanning electron microscope images',
1251 },
1252 0x8568 => {
1253 Name => 'AFCP_IPTC',
1254 SubDirectory => {
1255 # must change directory name so we don't create this directory
1256 DirName => 'AFCP_IPTC',
1257 TagTable => 'Image::ExifTool::IPTC::Main',
1258 },
1259 },
1260 0x85b8 => 'PixelMagicJBIGOptions', #20
1261 0x85d8 => {
1262 Name => 'ModelTransform',
1263 Groups => { 2 => 'Location' },
1264 },
1265 0x8602 => { #16
1266 Name => 'WB_GRGBLevels',
1267 Notes => 'found in IFD0 of Leaf MOS images',
1268 },
1269 # 0x8603 - Leaf CatchLight color matrix (ref 16)
1270 0x8606 => {
1271 Name => 'LeafData',
1272 Format => 'undef', # avoid converting huge block to string of int8u's!
1273 SubDirectory => {
1274 DirName => 'LeafIFD',
1275 TagTable => 'Image::ExifTool::Leaf::Main',
1276 },
1277 },
1278 0x8649 => { #19
1279 Name => 'PhotoshopSettings',
1280 Format => 'binary',
1281 SubDirectory => {
1282 DirName => 'Photoshop',
1283 TagTable => 'Image::ExifTool::Photoshop::Main',
1284 },
1285 },
1286 0x8769 => {
1287 Name => 'ExifOffset',
1288 Groups => { 1 => 'ExifIFD' },
1289 SubIFD => 2,
1290 SubDirectory => {
1291 DirName => 'ExifIFD',
1292 Start => '$val',
1293 },
1294 },
1295 0x8773 => {
1296 Name => 'ICC_Profile',
1297 SubDirectory => {
1298 TagTable => 'Image::ExifTool::ICC_Profile::Main',
1299 },
1300 },
1301 0x877f => { #20
1302 Name => 'TIFF_FXExtensions',
1303 PrintConv => { BITMASK => {
1304 0 => 'Resolution/Image Width',
1305 1 => 'N Layer Profile M',
1306 2 => 'Shared Data',
1307 3 => 'B&W JBIG2',
1308 4 => 'JBIG2 Profile M',
1309 }},
1310 },
1311 0x8780 => { #20
1312 Name => 'MultiProfiles',
1313 PrintConv => { BITMASK => {
1314 0 => 'Profile S',
1315 1 => 'Profile F',
1316 2 => 'Profile J',
1317 3 => 'Profile C',
1318 4 => 'Profile L',
1319 5 => 'Profile M',
1320 6 => 'Profile T',
1321 7 => 'Resolution/Image Width',
1322 8 => 'N Layer Profile M',
1323 9 => 'Shared Data',
1324 10 => 'JBIG2 Profile M',
1325 }},
1326 },
1327 0x8781 => { #22
1328 Name => 'SharedData',
1329 IsOffset => 1,
1330 # this tag is not supported for writing, so define an
1331 # invalid offset pair to cause a "No size tag" error to be
1332 # generated if we try to write a file containing this tag
1333 OffsetPair => -1,
1334 },
1335 0x8782 => 'T88Options', #20
1336 0x87ac => 'ImageLayer',
1337 0x87af => {
1338 Name => 'GeoTiffDirectory',
1339 Format => 'binary',
1340 Binary => 1,
1341 },
1342 0x87b0 => {
1343 Name => 'GeoTiffDoubleParams',
1344 Format => 'binary',
1345 Binary => 1,
1346 },
1347 0x87b1 => {
1348 Name => 'GeoTiffAsciiParams',
1349 Binary => 1,
1350 },
1351 0x8822 => {
1352 Name => 'ExposureProgram',
1353 Groups => { 2 => 'Camera' },
1354 Notes => 'the value of 9 is not standard EXIF, but is used by the Canon EOS 7D',
1355 PrintConv => {
1356 0 => 'Not Defined',
1357 1 => 'Manual',
1358 2 => 'Program AE',
1359 3 => 'Aperture-priority AE',
1360 4 => 'Shutter speed priority AE',
1361 5 => 'Creative (Slow speed)',
1362 6 => 'Action (High speed)',
1363 7 => 'Portrait',
1364 8 => 'Landscape',
1365 9 => 'Bulb', #25
1366 },
1367 },
1368 0x8824 => {
1369 Name => 'SpectralSensitivity',
1370 Groups => { 2 => 'Camera' },
1371 },
1372 0x8825 => {
1373 Name => 'GPSInfo',
1374 Groups => { 1 => 'GPS' },
1375 Flags => 'SubIFD',
1376 SubDirectory => {
1377 DirName => 'GPS',
1378 TagTable => 'Image::ExifTool::GPS::Main',
1379 Start => '$val',
1380 },
1381 },
1382 0x8827 => {
1383 Name => 'ISO',
1384 Notes => q{
1385 called ISOSpeedRatings by EXIF 2.2, then PhotographicSensitivity by the EXIF
1386 2.3 spec.
1387 },
1388 PrintConv => '$val=~s/\s+/, /g; $val',
1389 },
1390 0x8828 => {
1391 Name => 'Opto-ElectricConvFactor',
1392 Notes => 'called OECF by the EXIF spec.',
1393 Binary => 1,
1394 },
1395 0x8829 => 'Interlace', #12
1396 0x882a => 'TimeZoneOffset', #12
1397 0x882b => 'SelfTimerMode', #12
1398 0x8830 => { #24
1399 Name => 'SensitivityType',
1400 Notes => 'applies to EXIF:ISO tag',
1401 PrintConv => {
1402 0 => 'Unknown',
1403 1 => 'Standard Output Sensitivity',
1404 2 => 'Recommended Exposure Index',
1405 3 => 'ISO Speed',
1406 4 => 'Standard Output Sensitivity and Recommended Exposure Index',
1407 5 => 'Standard Output Sensitivity and ISO Speed',
1408 6 => 'Recommended Exposure Index and ISO Speed',
1409 7 => 'Standard Output Sensitivity, Recommended Exposure Index and ISO Speed',
1410 },
1411 },
1412 0x8831 => 'StandardOutputSensitivity', #24
1413 0x8832 => 'RecommendedExposureIndex', #24
1414 0x8833 => 'ISOSpeed', #24
1415 0x8834 => { #24
1416 Name => 'ISOSpeedLatitudeyyy',
1417 Description => 'ISO Speed Latitude yyy',
1418 },
1419 0x8835 => { #24
1420 Name => 'ISOSpeedLatitudezzz',
1421 Description => 'ISO Speed Latitude zzz',
1422 },
1423 0x885c => 'FaxRecvParams', #9
1424 0x885d => 'FaxSubAddress', #9
1425 0x885e => 'FaxRecvTime', #9
1426 0x888a => { #PH
1427 Name => 'LeafSubIFD',
1428 Format => 'int32u', # Leaf incorrectly uses 'undef' format!
1429 Groups => { 1 => 'LeafSubIFD' },
1430 Flags => 'SubIFD',
1431 SubDirectory => {
1432 TagTable => 'Image::ExifTool::Leaf::SubIFD',
1433 Start => '$val',
1434 },
1435 },
1436 0x9000 => {
1437 Name => 'ExifVersion',
1438 RawConv => '$val=~s/\0+$//; $val', # (some idiots add null terminators)
1439 },
1440 0x9003 => {
1441 Name => 'DateTimeOriginal',
1442 Description => 'Date/Time Original',
1443 Groups => { 2 => 'Time' },
1444 Notes => 'date/time when original image was taken',
1445 PrintConv => '$self->ConvertDateTime($val)',
1446 },
1447 0x9004 => {
1448 Name => 'CreateDate',
1449 Groups => { 2 => 'Time' },
1450 Notes => 'called DateTimeDigitized by the EXIF spec.',
1451 PrintConv => '$self->ConvertDateTime($val)',
1452 },
1453 0x9101 => {
1454 Name => 'ComponentsConfiguration',
1455 Format => 'int8u',
1456 PrintConvColumns => 2,
1457 PrintConv => {
1458 0 => '-',
1459 1 => 'Y',
1460 2 => 'Cb',
1461 3 => 'Cr',
1462 4 => 'R',
1463 5 => 'G',
1464 6 => 'B',
1465 OTHER => sub {
1466 my ($val, $inv, $conv) = @_;
1467 my @a = split /,?\s+/, $val;
1468 if ($inv) {
1469 my %invConv;
1470 $invConv{lc $$conv{$_}} = $_ foreach keys %$conv;
1471 # strings like "YCbCr" and "RGB" still work for writing
1472 @a = $a[0] =~ /(Y|Cb|Cr|R|G|B)/g if @a == 1;
1473 foreach (@a) {
1474 $_ = $invConv{lc $_};
1475 return undef unless defined $_;
1476 }
1477 push @a, 0 while @a < 4;
1478 } else {
1479 foreach (@a) {
1480 $_ = $$conv{$_} || "Err ($_)";
1481 }
1482 }
1483 return join ', ', @a;
1484 },
1485 },
1486 },
1487 0x9102 => 'CompressedBitsPerPixel',
1488 0x9201 => {
1489 Name => 'ShutterSpeedValue',
1490 Format => 'rational64s', # Leica M8 patch (incorrectly written as rational64u)
1491 ValueConv => 'abs($val)<100 ? 2**(-$val) : 0',
1492 PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
1493 },
1494 0x9202 => {
1495 Name => 'ApertureValue',
1496 ValueConv => '2 ** ($val / 2)',
1497 PrintConv => 'sprintf("%.1f",$val)',
1498 },
1499 0x9203 => 'BrightnessValue',
1500 0x9204 => {
1501 Name => 'ExposureCompensation',
1502 Format => 'rational64s', # Leica M8 patch (incorrectly written as rational64u)
1503 Notes => 'called ExposureBiasValue by the EXIF spec.',
1504 PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)',
1505 },
1506 0x9205 => {
1507 Name => 'MaxApertureValue',
1508 Groups => { 2 => 'Camera' },
1509 ValueConv => '2 ** ($val / 2)',
1510 PrintConv => 'sprintf("%.1f",$val)',
1511 },
1512 0x9206 => {
1513 Name => 'SubjectDistance',
1514 Groups => { 2 => 'Camera' },
1515 PrintConv => '$val =~ /^(inf|undef)$/ ? $val : "${val} m"',
1516 },
1517 0x9207 => {
1518 Name => 'MeteringMode',
1519 Groups => { 2 => 'Camera' },
1520 PrintConv => {
1521 0 => 'Unknown',
1522 1 => 'Average',
1523 2 => 'Center-weighted average',
1524 3 => 'Spot',
1525 4 => 'Multi-spot',
1526 5 => 'Multi-segment',
1527 6 => 'Partial',
1528 255 => 'Other',
1529 },
1530 },
1531 0x9208 => {
1532 Name => 'LightSource',
1533 Groups => { 2 => 'Camera' },
1534 SeparateTable => 'LightSource',
1535 PrintConv => \%lightSource,
1536 },
1537 0x9209 => {
1538 Name => 'Flash',
1539 Groups => { 2 => 'Camera' },
1540 Flags => 'PrintHex',
1541 SeparateTable => 'Flash',
1542 PrintConv => \%flash,
1543 },
1544 0x920a => {
1545 Name => 'FocalLength',
1546 Groups => { 2 => 'Camera' },
1547 PrintConv => 'sprintf("%.1f mm",$val)',
1548 },
1549 # Note: tags 0x920b-0x9217 are duplicates of 0xa20b-0xa217
1550 # (The TIFF standard uses 0xa2xx, but you'll find both in images)
1551 0x920b => { #12
1552 Name => 'FlashEnergy',
1553 Groups => { 2 => 'Camera' },
1554 },
1555 0x920c => 'SpatialFrequencyResponse', #12 (not in Fuji images - PH)
1556 0x920d => 'Noise', #12
1557 0x920e => 'FocalPlaneXResolution', #12
1558 0x920f => 'FocalPlaneYResolution', #12
1559 0x9210 => { #12
1560 Name => 'FocalPlaneResolutionUnit',
1561 Groups => { 2 => 'Camera' },
1562 PrintConv => {
1563 1 => 'None',
1564 2 => 'inches',
1565 3 => 'cm',
1566 4 => 'mm',
1567 5 => 'um',
1568 },
1569 },
1570 0x9211 => 'ImageNumber', #12
1571 0x9212 => { #12
1572 Name => 'SecurityClassification',
1573 PrintConv => {
1574 T => 'Top Secret',
1575 S => 'Secret',
1576 C => 'Confidential',
1577 R => 'Restricted',
1578 U => 'Unclassified',
1579 },
1580 },
1581 0x9213 => 'ImageHistory', #12
1582 0x9214 => {
1583 Name => 'SubjectArea',
1584 Groups => { 2 => 'Camera' },
1585 },
1586 0x9215 => 'ExposureIndex', #12
1587 0x9216 => 'TIFF-EPStandardID', #12
1588 0x9217 => { #12
1589 Name => 'SensingMethod',
1590 Groups => { 2 => 'Camera' },
1591 Notes => 'values 1 and 6 are not standard EXIF',
1592 PrintConv => {
1593 1 => 'Monochrome area', #12 (not standard EXIF)
1594 2 => 'One-chip color area',
1595 3 => 'Two-chip color area',
1596 4 => 'Three-chip color area',
1597 5 => 'Color sequential area',
1598 6 => 'Monochrome linear', #12 (not standard EXIF)
1599 7 => 'Trilinear',
1600 8 => 'Color sequential linear',
1601 },
1602 },
1603 0x9213 => 'ImageHistory',
1604 0x923a => 'CIP3DataFile', #20
1605 0x923b => 'CIP3Sheet', #20
1606 0x923c => 'CIP3Side', #20
1607 0x923f => 'StoNits', #9
1608 # handle maker notes as a conditional list
1609 0x927c => \@Image::ExifTool::MakerNotes::Main,
1610 0x9286 => {
1611 Name => 'UserComment',
1612 # may consider forcing a Format of 'undef' for this tag because I have
1613 # seen other applications write it incorrectly as 'string' or 'int8u'
1614 RawConv => 'Image::ExifTool::Exif::ConvertExifText($self,$val)',
1615 },
1616 0x9290 => {
1617 Name => 'SubSecTime',
1618 Groups => { 2 => 'Time' },
1619 ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks
1620 },
1621 0x9291 => {
1622 Name => 'SubSecTimeOriginal',
1623 Groups => { 2 => 'Time' },
1624 ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks
1625 },
1626 0x9292 => {
1627 Name => 'SubSecTimeDigitized',
1628 Groups => { 2 => 'Time' },
1629 ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks
1630 },
1631 # The following 3 tags are found in MSOffice TIFF images
1632 # References:
1633 # http://social.msdn.microsoft.com/Forums/en-US/os_standocs/thread/03086d55-294a-49d5-967a-5303d34c40f8/
1634 # 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
1635 # http://www.microsoft.com/downloads/details.aspx?FamilyID=0dbc435d-3544-4f4b-9092-2f2643d64a39&displaylang=en#filelist
1636 0x932f => 'MSDocumentText',
1637 0x9330 => {
1638 Name => 'MSPropertySetStorage',
1639 Binary => 1,
1640 },
1641 0x9331 => {
1642 Name => 'MSDocumentTextPosition',
1643 Binary => 1, # (just in case -- don't know what format this is)
1644 },
1645 0x935c => { #3/19
1646 Name => 'ImageSourceData',
1647 Binary => 1,
1648 },
1649 0x9c9b => {
1650 Name => 'XPTitle',
1651 Format => 'undef',
1652 ValueConv => '$self->Decode($val,"UCS2","II")',
1653 },
1654 0x9c9c => {
1655 Name => 'XPComment',
1656 Format => 'undef',
1657 ValueConv => '$self->Decode($val,"UCS2","II")',
1658 },
1659 0x9c9d => {
1660 Name => 'XPAuthor',
1661 Groups => { 2 => 'Author' },
1662 Format => 'undef',
1663 ValueConv => '$self->Decode($val,"UCS2","II")',
1664 },
1665 0x9c9e => {
1666 Name => 'XPKeywords',
1667 Format => 'undef',
1668 ValueConv => '$self->Decode($val,"UCS2","II")',
1669 },
1670 0x9c9f => {
1671 Name => 'XPSubject',
1672 Format => 'undef',
1673 ValueConv => '$self->Decode($val,"UCS2","II")',
1674 },
1675 0xa000 => {
1676 Name => 'FlashpixVersion',
1677 RawConv => '$val=~s/\0+$//; $val', # (some idiots add null terminators)
1678 },
1679 0xa001 => {
1680 Name => 'ColorSpace',
1681 Notes => q{
1682 the value of 0x2 is not standard EXIF. Instead, an Adobe RGB image is
1683 indicated by "Uncalibrated" with an InteropIndex of "R03". The values
1684 0xfffd and 0xfffe are also non-standard, and are used by some Sony cameras
1685 },
1686 PrintHex => 1,
1687 PrintConv => {
1688 1 => 'sRGB',
1689 2 => 'Adobe RGB',
1690 0xffff => 'Uncalibrated',
1691 # Sony uses these definitions: (ref JD)
1692 # 0xffff => 'Adobe RGB', (conflicts with Uncalibrated)
1693 0xfffe => 'ICC Profile',
1694 0xfffd => 'Wide Gamut RGB',
1695 },
1696 },
1697 0xa002 => {
1698 Name => 'ExifImageWidth',
1699 Notes => 'called PixelXDimension by the EXIF spec.',
1700 },
1701 0xa003 => {
1702 Name => 'ExifImageHeight',
1703 Notes => 'called PixelYDimension by the EXIF spec.',
1704 },
1705 0xa004 => 'RelatedSoundFile',
1706 0xa005 => {
1707 Name => 'InteropOffset',
1708 Groups => { 1 => 'InteropIFD' },
1709 Flags => 'SubIFD',
1710 Description => 'Interoperability Offset',
1711 SubDirectory => {
1712 DirName => 'InteropIFD',
1713 Start => '$val',
1714 },
1715 },
1716 0xa20b => {
1717 Name => 'FlashEnergy',
1718 Groups => { 2 => 'Camera' },
1719 },
1720 0xa20c => {
1721 Name => 'SpatialFrequencyResponse',
1722 PrintConv => 'Image::ExifTool::Exif::PrintSFR($val)',
1723 },
1724 0xa20d => 'Noise',
1725 0xa20e => { Name => 'FocalPlaneXResolution', Groups => { 2 => 'Camera' } },
1726 0xa20f => { Name => 'FocalPlaneYResolution', Groups => { 2 => 'Camera' } },
1727 0xa210 => {
1728 Name => 'FocalPlaneResolutionUnit',
1729 Groups => { 2 => 'Camera' },
1730 Notes => 'values 1, 4 and 5 are not standard EXIF',
1731 PrintConv => {
1732 1 => 'None', # (not standard EXIF)
1733 2 => 'inches',
1734 3 => 'cm',
1735 4 => 'mm', # (not standard EXIF)
1736 5 => 'um', # (not standard EXIF)
1737 },
1738 },
1739 0xa211 => 'ImageNumber',
1740 0xa212 => 'SecurityClassification',
1741 0xa213 => 'ImageHistory',
1742 0xa214 => {
1743 Name => 'SubjectLocation',
1744 Groups => { 2 => 'Camera' },
1745 },
1746 0xa215 => 'ExposureIndex',
1747 0xa216 => 'TIFF-EPStandardID',
1748 0xa217 => {
1749 Name => 'SensingMethod',
1750 Groups => { 2 => 'Camera' },
1751 PrintConv => {
1752 1 => 'Not defined',
1753 2 => 'One-chip color area',
1754 3 => 'Two-chip color area',
1755 4 => 'Three-chip color area',
1756 5 => 'Color sequential area',
1757 7 => 'Trilinear',
1758 8 => 'Color sequential linear',
1759 },
1760 },
1761 0xa300 => {
1762 Name => 'FileSource',
1763 PrintConv => {
1764 1 => 'Film Scanner',
1765 2 => 'Reflection Print Scanner',
1766 3 => 'Digital Camera',
1767 # handle the case where Sigma incorrectly gives this tag a count of 4
1768 "\3\0\0\0" => 'Sigma Digital Camera',
1769 },
1770 },
1771 0xa301 => {
1772 Name => 'SceneType',
1773 PrintConv => {
1774 1 => 'Directly photographed',
1775 },
1776 },
1777 0xa302 => {
1778 Name => 'CFAPattern',
1779 PrintConv => 'Image::ExifTool::Exif::PrintCFAPattern($val)',
1780 },
1781 0xa401 => {
1782 Name => 'CustomRendered',
1783 PrintConv => {
1784 0 => 'Normal',
1785 1 => 'Custom',
1786 },
1787 },
1788 0xa402 => {
1789 Name => 'ExposureMode',
1790 Groups => { 2 => 'Camera' },
1791 PrintConv => {
1792 0 => 'Auto',
1793 1 => 'Manual',
1794 2 => 'Auto bracket',
1795 # have seen 3 for Samsung EX1 images - PH
1796 },
1797 },
1798 0xa403 => {
1799 Name => 'WhiteBalance',
1800 Groups => { 2 => 'Camera' },
1801 # set Priority to zero to keep this WhiteBalance from overriding the
1802 # MakerNotes WhiteBalance, since the MakerNotes WhiteBalance and is more
1803 # accurate and contains more information (if it exists)
1804 Priority => 0,
1805 PrintConv => {
1806 0 => 'Auto',
1807 1 => 'Manual',
1808 },
1809 },
1810 0xa404 => {
1811 Name => 'DigitalZoomRatio',
1812 Groups => { 2 => 'Camera' },
1813 },
1814 0xa405 => {
1815 Name => 'FocalLengthIn35mmFormat',
1816 Notes => 'called FocalLengthIn35mmFilm by the EXIF spec.',
1817 Groups => { 2 => 'Camera' },
1818 PrintConv => '"$val mm"',
1819 },
1820 0xa406 => {
1821 Name => 'SceneCaptureType',
1822 Groups => { 2 => 'Camera' },
1823 PrintConv => {
1824 0 => 'Standard',
1825 1 => 'Landscape',
1826 2 => 'Portrait',
1827 3 => 'Night',
1828 },
1829 },
1830 0xa407 => {
1831 Name => 'GainControl',
1832 Groups => { 2 => 'Camera' },
1833 PrintConv => {
1834 0 => 'None',
1835 1 => 'Low gain up',
1836 2 => 'High gain up',
1837 3 => 'Low gain down',
1838 4 => 'High gain down',
1839 },
1840 },
1841 0xa408 => {
1842 Name => 'Contrast',
1843 Groups => { 2 => 'Camera' },
1844 PrintConv => {
1845 0 => 'Normal',
1846 1 => 'Low',
1847 2 => 'High',
1848 },
1849 },
1850 0xa409 => {
1851 Name => 'Saturation',
1852 Groups => { 2 => 'Camera' },
1853 PrintConv => {
1854 0 => 'Normal',
1855 1 => 'Low',
1856 2 => 'High',
1857 },
1858 },
1859 0xa40a => {
1860 Name => 'Sharpness',
1861 Groups => { 2 => 'Camera' },
1862 PrintConv => {
1863 0 => 'Normal',
1864 1 => 'Soft',
1865 2 => 'Hard',
1866 },
1867 },
1868 0xa40b => {
1869 Name => 'DeviceSettingDescription',
1870 Groups => { 2 => 'Camera' },
1871 Binary => 1,
1872 },
1873 0xa40c => {
1874 Name => 'SubjectDistanceRange',
1875 Groups => { 2 => 'Camera' },
1876 PrintConv => {
1877 0 => 'Unknown',
1878 1 => 'Macro',
1879 2 => 'Close',
1880 3 => 'Distant',
1881 },
1882 },
1883 # 0xa40d - int16u: 0 (GE E1486 TW)
1884 # 0xa40e - int16u: 1 (GE E1486 TW)
1885 0xa420 => 'ImageUniqueID',
1886 0xa430 => { #24
1887 Name => 'OwnerName',
1888 Notes => 'called CameraOwnerName by the EXIF spec.',
1889 },
1890 0xa431 => { #24
1891 Name => 'SerialNumber',
1892 Notes => 'called BodySerialNumber by the EXIF spec.',
1893 },
1894 0xa432 => { #24
1895 Name => 'LensInfo',
1896 Notes => q{
1897 4 rational values giving focal and aperture ranges, called LensSpecification
1898 by the EXIF spec.
1899 },
1900 # convert to the form "12-20mm f/3.8-4.5" or "50mm f/1.4"
1901 PrintConv => \&Image::ExifTool::Exif::PrintLensInfo,
1902 },
1903 0xa433 => 'LensMake', #24
1904 0xa434 => 'LensModel', #24
1905 0xa435 => 'LensSerialNumber', #24
1906 0xa480 => 'GDALMetadata', #3
1907 0xa481 => 'GDALNoData', #3
1908 0xa500 => 'Gamma',
1909 0xafc0 => 'ExpandSoftware', #JD (Opanda)
1910 0xafc1 => 'ExpandLens', #JD (Opanda)
1911 0xafc2 => 'ExpandFilm', #JD (Opanda)
1912 0xafc3 => 'ExpandFilterLens', #JD (Opanda)
1913 0xafc4 => 'ExpandScanner', #JD (Opanda)
1914 0xafc5 => 'ExpandFlashLamp', #JD (Opanda)
1915#
1916# Windows Media Photo / HD Photo (WDP/HDP) tags
1917#
1918 0xbc01 => { #13
1919 Name => 'PixelFormat',
1920 PrintHex => 1,
1921 Format => 'undef',
1922 Notes => q{
1923 tags 0xbc** are used in Windows HD Photo (HDP and WDP) images. The actual
1924 PixelFormat values are 16-byte GUID's but the leading 15 bytes,
1925 '6fddc324-4e03-4bfe-b1853-d77768dc9', have been removed below to avoid
1926 unnecessary clutter
1927 },
1928 ValueConv => q{
1929 require Image::ExifTool::ASF;
1930 $val = Image::ExifTool::ASF::GetGUID($val);
1931 # GUID's are too long, so remove redundant information
1932 $val =~ s/^6fddc324-4e03-4bfe-b185-3d77768dc9//i and $val = hex($val);
1933 return $val;
1934 },
1935 PrintConv => {
1936 0x0d => '24-bit RGB',
1937 0x0c => '24-bit BGR',
1938 0x0e => '32-bit BGR',
1939 0x15 => '48-bit RGB',
1940 0x12 => '48-bit RGB Fixed Point',
1941 0x3b => '48-bit RGB Half',
1942 0x18 => '96-bit RGB Fixed Point',
1943 0x1b => '128-bit RGB Float',
1944 0x0f => '32-bit BGRA',
1945 0x16 => '64-bit RGBA',
1946 0x1d => '64-bit RGBA Fixed Point',
1947 0x3a => '64-bit RGBA Half',
1948 0x1e => '128-bit RGBA Fixed Point',
1949 0x19 => '128-bit RGBA Float',
1950 0x10 => '32-bit PBGRA',
1951 0x17 => '64-bit PRGBA',
1952 0x1a => '128-bit PRGBA Float',
1953 0x1c => '32-bit CMYK',
1954 0x2c => '40-bit CMYK Alpha',
1955 0x1f => '64-bit CMYK',
1956 0x2d => '80-bit CMYK Alpha',
1957 0x20 => '24-bit 3 Channels',
1958 0x21 => '32-bit 4 Channels',
1959 0x22 => '40-bit 5 Channels',
1960 0x23 => '48-bit 6 Channels',
1961 0x24 => '56-bit 7 Channels',
1962 0x25 => '64-bit 8 Channels',
1963 0x2e => '32-bit 3 Channels Alpha',
1964 0x2f => '40-bit 4 Channels Alpha',
1965 0x30 => '48-bit 5 Channels Alpha',
1966 0x31 => '56-bit 6 Channels Alpha',
1967 0x32 => '64-bit 7 Channels Alpha',
1968 0x33 => '72-bit 8 Channels Alpha',
1969 0x26 => '48-bit 3 Channels',
1970 0x27 => '64-bit 4 Channels',
1971 0x28 => '80-bit 5 Channels',
1972 0x29 => '96-bit 6 Channels',
1973 0x2a => '112-bit 7 Channels',
1974 0x2b => '128-bit 8 Channels',
1975 0x34 => '64-bit 3 Channels Alpha',
1976 0x35 => '80-bit 4 Channels Alpha',
1977 0x36 => '96-bit 5 Channels Alpha',
1978 0x37 => '112-bit 6 Channels Alpha',
1979 0x38 => '128-bit 7 Channels Alpha',
1980 0x39 => '144-bit 8 Channels Alpha',
1981 0x08 => '8-bit Gray',
1982 0x0b => '16-bit Gray',
1983 0x13 => '16-bit Gray Fixed Point',
1984 0x3e => '16-bit Gray Half',
1985 0x3f => '32-bit Gray Fixed Point',
1986 0x11 => '32-bit Gray Float',
1987 0x05 => 'Black & White',
1988 0x09 => '16-bit BGR555',
1989 0x0a => '16-bit BGR565',
1990 0x13 => '32-bit BGR101010',
1991 0x3d => '32-bit RGBE',
1992 },
1993 },
1994 0xbc02 => { #13
1995 Name => 'Transformation',
1996 PrintConv => {
1997 0 => 'Horizontal (normal)',
1998 1 => 'Mirror vertical',
1999 2 => 'Mirror horizontal',
2000 3 => 'Rotate 180',
2001 4 => 'Rotate 90 CW',
2002 5 => 'Mirror horizontal and rotate 90 CW',
2003 6 => 'Mirror horizontal and rotate 270 CW',
2004 7 => 'Rotate 270 CW',
2005 },
2006 },
2007 0xbc03 => { #13
2008 Name => 'Uncompressed',
2009 PrintConv => { 0 => 'No', 1 => 'Yes' },
2010 },
2011 0xbc04 => { #13
2012 Name => 'ImageType',
2013 PrintConv => { BITMASK => {
2014 0 => 'Preview',
2015 1 => 'Page',
2016 } },
2017 },
2018 0xbc80 => 'ImageWidth', #13
2019 0xbc81 => 'ImageHeight', #13
2020 0xbc82 => 'WidthResolution', #13
2021 0xbc83 => 'HeightResolution', #13
2022 0xbcc0 => { #13
2023 Name => 'ImageOffset',
2024 IsOffset => 1,
2025 OffsetPair => 0xbcc1, # point to associated byte count
2026 },
2027 0xbcc1 => { #13
2028 Name => 'ImageByteCount',
2029 OffsetPair => 0xbcc0, # point to associated offset
2030 },
2031 0xbcc2 => { #13
2032 Name => 'AlphaOffset',
2033 IsOffset => 1,
2034 OffsetPair => 0xbcc3, # point to associated byte count
2035 },
2036 0xbcc3 => { #13
2037 Name => 'AlphaByteCount',
2038 OffsetPair => 0xbcc2, # point to associated offset
2039 },
2040 0xbcc4 => { #13
2041 Name => 'ImageDataDiscard',
2042 PrintConv => {
2043 0 => 'Full Resolution',
2044 1 => 'Flexbits Discarded',
2045 2 => 'HighPass Frequency Data Discarded',
2046 3 => 'Highpass and LowPass Frequency Data Discarded',
2047 },
2048 },
2049 0xbcc5 => { #13
2050 Name => 'AlphaDataDiscard',
2051 PrintConv => {
2052 0 => 'Full Resolution',
2053 1 => 'Flexbits Discarded',
2054 2 => 'HighPass Frequency Data Discarded',
2055 3 => 'Highpass and LowPass Frequency Data Discarded',
2056 },
2057 },
2058#
2059 0xc427 => 'OceScanjobDesc', #3
2060 0xc428 => 'OceApplicationSelector', #3
2061 0xc429 => 'OceIDNumber', #3
2062 0xc42a => 'OceImageLogic', #3
2063 0xc44f => { Name => 'Annotations', Binary => 1 }, #7/19
2064 0xc4a5 => {
2065 Name => 'PrintIM', # (writable directory!)
2066 # must set Writable here so this tag will be saved with MakerNotes option
2067 Writable => 'undef',
2068 WriteGroup => 'IFD0',
2069 Description => 'Print Image Matching',
2070 SubDirectory => {
2071 TagTable => 'Image::ExifTool::PrintIM::Main',
2072 },
2073 },
2074 0xc580 => { #20
2075 Name => 'USPTOOriginalContentType',
2076 PrintConv => {
2077 0 => 'Text or Drawing',
2078 1 => 'Grayscale',
2079 2 => 'Color',
2080 },
2081 },
2082#
2083# DNG tags 0xc6XX and 0xc7XX (ref 2 unless otherwise stated)
2084#
2085 0xc612 => {
2086 Name => 'DNGVersion',
2087 Notes => 'tags 0xc612-0xc761 are used in DNG images unless otherwise noted',
2088 DataMember => 'DNGVersion',
2089 RawConv => '$$self{DNGVersion} = $val',
2090 PrintConv => '$val =~ tr/ /./; $val',
2091 },
2092 0xc613 => 'DNGBackwardVersion',
2093 0xc614 => 'UniqueCameraModel',
2094 0xc615 => {
2095 Name => 'LocalizedCameraModel',
2096 Format => 'string',
2097 PrintConv => '$self->Printable($val, 0)',
2098 },
2099 0xc616 => {
2100 Name => 'CFAPlaneColor',
2101 PrintConv => q{
2102 my @cols = qw(Red Green Blue Cyan Magenta Yellow White);
2103 my @vals = map { $cols[$_] || "Unknown($_)" } split(' ', $val);
2104 return join(',', @vals);
2105 },
2106 },
2107 0xc617 => {
2108 Name => 'CFALayout',
2109 PrintConv => {
2110 1 => 'Rectangular',
2111 2 => 'Even columns offset down 1/2 row',
2112 3 => 'Even columns offset up 1/2 row',
2113 4 => 'Even rows offset right 1/2 column',
2114 5 => 'Even rows offset left 1/2 column',
2115 # the following are new for DNG 1.3:
2116 6 => 'Even rows offset up by 1/2 row, even columns offset left by 1/2 column',
2117 7 => 'Even rows offset up by 1/2 row, even columns offset right by 1/2 column',
2118 8 => 'Even rows offset down by 1/2 row, even columns offset left by 1/2 column',
2119 9 => 'Even rows offset down by 1/2 row, even columns offset right by 1/2 column',
2120 },
2121 },
2122 0xc618 => { Name => 'LinearizationTable', Binary => 1 },
2123 0xc619 => 'BlackLevelRepeatDim',
2124 0xc61a => 'BlackLevel',
2125 0xc61b => { Name => 'BlackLevelDeltaH', %longBin },
2126 0xc61c => { Name => 'BlackLevelDeltaV', %longBin },
2127 0xc61d => 'WhiteLevel',
2128 0xc61e => 'DefaultScale',
2129 0xc61f => 'DefaultCropOrigin',
2130 0xc620 => 'DefaultCropSize',
2131 0xc621 => 'ColorMatrix1',
2132 0xc622 => 'ColorMatrix2',
2133 0xc623 => 'CameraCalibration1',
2134 0xc624 => 'CameraCalibration2',
2135 0xc625 => 'ReductionMatrix1',
2136 0xc626 => 'ReductionMatrix2',
2137 0xc627 => 'AnalogBalance',
2138 0xc628 => 'AsShotNeutral',
2139 0xc629 => 'AsShotWhiteXY',
2140 0xc62a => 'BaselineExposure',
2141 0xc62b => 'BaselineNoise',
2142 0xc62c => 'BaselineSharpness',
2143 0xc62d => 'BayerGreenSplit',
2144 0xc62e => 'LinearResponseLimit',
2145 0xc62f => {
2146 Name => 'CameraSerialNumber',
2147 Groups => { 2 => 'Camera' },
2148 },
2149 0xc630 => {
2150 Name => 'DNGLensInfo',
2151 Groups => { 2 => 'Camera' },
2152 PrintConv =>\&PrintLensInfo,
2153 },
2154 0xc631 => 'ChromaBlurRadius',
2155 0xc632 => 'AntiAliasStrength',
2156 0xc633 => 'ShadowScale',
2157 0xc634 => [
2158 {
2159 Condition => '$$self{TIFF_TYPE} =~ /^(ARW|SR2)$/',
2160 Name => 'SR2Private',
2161 Groups => { 1 => 'SR2' },
2162 Flags => 'SubIFD',
2163 Format => 'int32u',
2164 # some utilites have problems unless this is int8u format:
2165 # - Adobe Camera Raw 5.3 gives an error
2166 # - Apple Preview 10.5.8 gets the wrong white balance
2167 FixFormat => 'int8u', # (stupid Sony)
2168 SubDirectory => {
2169 DirName => 'SR2Private',
2170 TagTable => 'Image::ExifTool::Sony::SR2Private',
2171 Start => '$val',
2172 },
2173 },
2174 {
2175 Condition => '$$valPt =~ /^Adobe\0/',
2176 Name => 'DNGAdobeData',
2177 NestedHtmlDump => 1,
2178 SubDirectory => { TagTable => 'Image::ExifTool::DNG::AdobeData' },
2179 Format => 'undef', # written incorrectly as int8u (change to undef for speed)
2180 },
2181 {
2182 Condition => '$$valPt =~ /^(PENTAX |SAMSUNG)\0/',
2183 Name => 'MakerNotePentax',
2184 MakerNotes => 1, # (causes "MakerNotes header" to be identified in HtmlDump output)
2185 Binary => 1,
2186 # Note: Don't make this block-writable for a few reasons:
2187 # 1) It would be dangerous (possibly confusing Pentax software)
2188 # 2) It is a different format from the JPEG version of MakerNotePentax
2189 # 3) It is converted to JPEG format by RebuildMakerNotes() when copying
2190 SubDirectory => {
2191 TagTable => 'Image::ExifTool::Pentax::Main',
2192 Start => '$valuePtr + 10',
2193 Base => '$start - 10',
2194 ByteOrder => 'Unknown', # easier to do this than read byteorder word
2195 },
2196 Format => 'undef', # written incorrectly as int8u (change to undef for speed)
2197 },
2198 {
2199 Name => 'DNGPrivateData',
2200 Binary => 1,
2201 Format => 'undef',
2202 },
2203 ],
2204 0xc635 => {
2205 Name => 'MakerNoteSafety',
2206 PrintConv => {
2207 0 => 'Unsafe',
2208 1 => 'Safe',
2209 },
2210 },
2211 0xc640 => { #15
2212 Name => 'RawImageSegmentation',
2213 # (int16u[3], not writable)
2214 Notes => q{
2215 used in segmented Canon CR2 images. 3 numbers: 1. Number of segments minus
2216 one; 2. Pixel width of segments except last; 3. Pixel width of last segment
2217 },
2218 },
2219 0xc65a => {
2220 Name => 'CalibrationIlluminant1',
2221 SeparateTable => 'LightSource',
2222 PrintConv => \%lightSource,
2223 },
2224 0xc65b => {
2225 Name => 'CalibrationIlluminant2',
2226 SeparateTable => 'LightSource',
2227 PrintConv => \%lightSource,
2228 },
2229 0xc65c => 'BestQualityScale',
2230 0xc65d => {
2231 Name => 'RawDataUniqueID',
2232 Format => 'undef',
2233 ValueConv => 'uc(unpack("H*",$val))',
2234 },
2235 0xc660 => { #3
2236 Name => 'AliasLayerMetadata',
2237 Notes => 'used by Alias Sketchbook Pro',
2238 },
2239 0xc68b => {
2240 Name => 'OriginalRawFileName',
2241 Format => 'string', # sometimes written as int8u
2242 },
2243 0xc68c => {
2244 Name => 'OriginalRawFileData', # (writable directory!)
2245 Writable => 'undef', # must be defined here so tag will be extracted if specified
2246 WriteGroup => 'IFD0',
2247 Flags => [ 'Binary', 'Protected' ],
2248 SubDirectory => {
2249 TagTable => 'Image::ExifTool::DNG::OriginalRaw',
2250 },
2251 },
2252 0xc68d => 'ActiveArea',
2253 0xc68e => 'MaskedAreas',
2254 0xc68f => {
2255 Name => 'AsShotICCProfile',
2256 Binary => 1,
2257 Writable => 'undef', # must be defined here so tag will be extracted if specified
2258 SubDirectory => {
2259 DirName => 'AsShotICCProfile',
2260 TagTable => 'Image::ExifTool::ICC_Profile::Main',
2261 },
2262 },
2263 0xc690 => 'AsShotPreProfileMatrix',
2264 0xc691 => {
2265 Name => 'CurrentICCProfile',
2266 Binary => 1,
2267 Writable => 'undef', # must be defined here so tag will be extracted if specified
2268 SubDirectory => {
2269 DirName => 'CurrentICCProfile',
2270 TagTable => 'Image::ExifTool::ICC_Profile::Main',
2271 },
2272 },
2273 0xc692 => 'CurrentPreProfileMatrix',
2274 0xc6bf => 'ColorimetricReference',
2275 0xc6d2 => { #JD (Panasonic DMC-TZ5)
2276 # this text is UTF-8 encoded (hooray!) - PH (TZ5)
2277 Name => 'PanasonicTitle',
2278 Format => 'string', # written incorrectly as 'undef'
2279 Notes => 'proprietary Panasonic tag used for baby/pet name, etc',
2280 # panasonic always records this tag (64 zero bytes),
2281 # so ignore it unless it contains valid information
2282 RawConv => 'length($val) ? $val : undef',
2283 ValueConv => '$self->Decode($val, "UTF8")',
2284 },
2285 0xc6d3 => { #PH (Panasonic DMC-FS7)
2286 Name => 'PanasonicTitle2',
2287 Format => 'string', # written incorrectly as 'undef'
2288 Notes => 'proprietary Panasonic tag used for baby/pet name with age',
2289 # panasonic always records this tag (128 zero bytes),
2290 # so ignore it unless it contains valid information
2291 RawConv => 'length($val) ? $val : undef',
2292 ValueConv => '$self->Decode($val, "UTF8")',
2293 },
2294 0xc6f3 => 'CameraCalibrationSig',
2295 0xc6f4 => 'ProfileCalibrationSig',
2296 0xc6f5 => {
2297 Name => 'ProfileIFD', # (ExtraCameraProfiles)
2298 Groups => { 1 => 'ProfileIFD' },
2299 Flags => 'SubIFD',
2300 SubDirectory => {
2301 ProcessProc => \&ProcessTiffIFD,
2302 WriteProc => \&ProcessTiffIFD,
2303 DirName => 'ProfileIFD',
2304 Start => '$val',
2305 Base => '$start', # offsets relative to start of TIFF-like header
2306 MaxSubdirs => 10,
2307 Magic => 0x4352, # magic number for TIFF-like header
2308 },
2309 },
2310 0xc6f6 => 'AsShotProfileName',
2311 0xc6f7 => 'NoiseReductionApplied',
2312 0xc6f8 => 'ProfileName',
2313 0xc6f9 => 'ProfileHueSatMapDims',
2314 0xc6fa => 'ProfileHueSatMapData1',
2315 0xc6fb => 'ProfileHueSatMapData2',
2316 0xc6fc => {
2317 Name => 'ProfileToneCurve',
2318 Binary => 1,
2319 },
2320 0xc6fd => {
2321 Name => 'ProfileEmbedPolicy',
2322 PrintConv => {
2323 0 => 'Allow Copying',
2324 1 => 'Embed if Used',
2325 2 => 'Never Embed',
2326 3 => 'No Restrictions',
2327 },
2328 },
2329 0xc6fe => 'ProfileCopyright',
2330 0xc714 => 'ForwardMatrix1',
2331 0xc715 => 'ForwardMatrix2',
2332 0xc716 => 'PreviewApplicationName',
2333 0xc717 => 'PreviewApplicationVersion',
2334 0xc718 => 'PreviewSettingsName',
2335 0xc719 => {
2336 Name => 'PreviewSettingsDigest',
2337 Format => 'undef',
2338 ValueConv => 'unpack("H*", $val)',
2339 },
2340 0xc71a => 'PreviewColorSpace',
2341 0xc71b => {
2342 Name => 'PreviewDateTime',
2343 Groups => { 2 => 'Time' },
2344 ValueConv => q{
2345 require Image::ExifTool::XMP;
2346 return Image::ExifTool::XMP::ConvertXMPDate($val);
2347 },
2348 },
2349 0xc71c => {
2350 Name => 'RawImageDigest',
2351 Format => 'undef',
2352 ValueConv => 'unpack("H*", $val)',
2353 },
2354 0xc71d => {
2355 Name => 'OriginalRawFileDigest',
2356 Format => 'undef',
2357 ValueConv => 'unpack("H*", $val)',
2358 },
2359 0xc71e => 'SubTileBlockSize',
2360 0xc71f => 'RowInterleaveFactor',
2361 0xc725 => 'ProfileLookTableDims',
2362 0xc726 => {
2363 Name => 'ProfileLookTableData',
2364 Binary => 1,
2365 },
2366 0xc740 => { # DNG 1.3
2367 Name => 'OpcodeList1',
2368 Binary => 1,
2369 # opcodes:
2370 # 1 => 'WarpRectilinear',
2371 # 2 => 'WarpFisheye',
2372 # 3 => 'FixVignetteRadial',
2373 # 4 => 'FixBadPixelsConstant',
2374 # 5 => 'FixBadPixelsList',
2375 # 6 => 'TrimBounds',
2376 # 7 => 'MapTable',
2377 # 8 => 'MapPolynomial',
2378 # 9 => 'GainMap',
2379 # 10 => 'DeltaPerRow',
2380 # 11 => 'DeltaPerColumn',
2381 # 12 => 'ScalePerRow',
2382 # 13 => 'ScalePerColumn',
2383 },
2384 0xc741 => { # DNG 1.3
2385 Name => 'OpcodeList2',
2386 Binary => 1,
2387 },
2388 0xc74e => { # DNG 1.3
2389 Name => 'OpcodeList3',
2390 Binary => 1,
2391 },
2392 0xc761 => 'NoiseProfile', # DNG 1.3
2393 0xea1c => { #13
2394 Name => 'Padding',
2395 Binary => 1,
2396 Writable => 'undef',
2397 # must start with 0x1c 0xea by the WM Photo specification
2398 # (not sure what should happen if padding is only 1 byte)
2399 # (why does MicrosoftPhoto write "1c ea 00 00 00 08"?)
2400 RawConvInv => '$val=~s/^../\x1c\xea/s; $val',
2401 },
2402 0xea1d => {
2403 Name => 'OffsetSchema',
2404 Notes => "Microsoft's ill-conceived maker note offset difference",
2405 # From the Microsoft documentation:
2406 #
2407 # Any time the "Maker Note" is relocated by Windows, the Exif MakerNote
2408 # tag (37500) is updated automatically to reference the new location. In
2409 # addition, Windows records the offset (or difference) between the old and
2410 # new locations in the Exif OffsetSchema tag (59933). If the "Maker Note"
2411 # contains relative references, the developer can add the value in
2412 # OffsetSchema to the original references to find the correct information.
2413 #
2414 # My recommendation is for other developers to ignore this tag because the
2415 # information it contains is unreliable. It will be wrong if the image has
2416 # been subsequently edited by another application that doesn't recognize the
2417 # new Microsoft tag.
2418 #
2419 # The new tag unfortunately only gives the difference between the new maker
2420 # note offset and the original offset. Instead, it should have been designed
2421 # to store the original offset. The new offset may change if the image is
2422 # edited, which will invalidate the tag as currently written. If instead the
2423 # original offset had been stored, the new difference could be easily
2424 # calculated because the new maker note offset is known.
2425 #
2426 # I exchanged emails with a Microsoft technical representative, pointing out
2427 # this problem shortly after they released the update (Feb 2007), but so far
2428 # they have taken no steps to address this.
2429 },
2430
2431 # tags in the range 0xfde8-0xfe58 have been observed in PS7 files
2432 # generated from RAW images. They are all strings with the
2433 # tag name at the start of the string. To accomodate these types
2434 # of tags, all tags with values above 0xf000 are handled specially
2435 # by ProcessExif().
2436
2437 0xfe00 => {
2438 Name => 'KDC_IFD',
2439 Groups => { 1 => 'KDC_IFD' },
2440 Flags => 'SubIFD',
2441 Notes => 'used in some Kodak KDC images',
2442 SubDirectory => {
2443 TagTable => 'Image::ExifTool::Kodak::KDC_IFD',
2444 DirName => 'KDC_IFD',
2445 Start => '$val',
2446 },
2447 },
2448);
2449
2450# EXIF Composite tags (plus other more general Composite tags)
2451%Image::ExifTool::Exif::Composite = (
2452 GROUPS => { 2 => 'Image' },
2453 ImageSize => {
2454 Require => {
2455 0 => 'ImageWidth',
2456 1 => 'ImageHeight',
2457 },
2458 Desire => {
2459 2 => 'ExifImageWidth',
2460 3 => 'ExifImageHeight',
2461 },
2462 # use ExifImageWidth/Height only for Canon and Phase One TIFF-base RAW images
2463 ValueConv => q{
2464 return "$val[2]x$val[3]" if $val[2] and $val[3] and
2465 $$self{TIFF_TYPE} =~ /^(CR2|Canon 1D RAW|IIQ|EIP)$/;
2466 return "$val[0]x$val[1]";
2467 },
2468 },
2469 # pick the best shutter speed value
2470 ShutterSpeed => {
2471 Desire => {
2472 0 => 'ExposureTime',
2473 1 => 'ShutterSpeedValue',
2474 2 => 'BulbDuration',
2475 },
2476 ValueConv => '($val[2] and $val[2]>0) ? $val[2] : (defined($val[0]) ? $val[0] : $val[1])',
2477 PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
2478 },
2479 Aperture => {
2480 Desire => {
2481 0 => 'FNumber',
2482 1 => 'ApertureValue',
2483 },
2484 RawConv => '($val[0] || $val[1]) ? $val : undef',
2485 ValueConv => '$val[0] || $val[1]',
2486 PrintConv => 'sprintf("%.1f", $val)',
2487 },
2488 LightValue => {
2489 Notes => 'calculated LV -- similar to exposure value but includes ISO speed',
2490 Require => {
2491 0 => 'Aperture',
2492 1 => 'ShutterSpeed',
2493 2 => 'ISO',
2494 },
2495 ValueConv => 'Image::ExifTool::Exif::CalculateLV($val[0],$val[1],$prt[2])',
2496 PrintConv => 'sprintf("%.1f",$val)',
2497 },
2498 FocalLength35efl => { #26/PH
2499 Description => 'Focal Length',
2500 Notes => 'this value may be incorrect if the image has been resized',
2501 Groups => { 2 => 'Camera' },
2502 Require => {
2503 0 => 'FocalLength',
2504 },
2505 Desire => {
2506 1 => 'ScaleFactor35efl',
2507 },
2508 ValueConv => 'ToFloat(@val); ($val[0] || 0) * ($val[1] || 1)',
2509 PrintConv => '$val[1] ? sprintf("%.1f mm (35 mm equivalent: %.1f mm)", $val[0], $val) : sprintf("%.1f mm", $val)',
2510 },
2511 ScaleFactor35efl => { #26/PH
2512 Description => 'Scale Factor To 35 mm Equivalent',
2513 Notes => 'this value and any derived values may be incorrect if image has been resized',
2514 Groups => { 2 => 'Camera' },
2515 Desire => {
2516 0 => 'FocalLength',
2517 1 => 'FocalLengthIn35mmFormat',
2518 2 => 'Composite:DigitalZoom',
2519 3 => 'FocalPlaneDiagonal',
2520 4 => 'FocalPlaneXSize',
2521 5 => 'FocalPlaneYSize',
2522 6 => 'FocalPlaneResolutionUnit',
2523 7 => 'FocalPlaneXResolution',
2524 8 => 'FocalPlaneYResolution',
2525 9 => 'ExifImageWidth',
2526 10 => 'ExifImageHeight',
2527 11 => 'CanonImageWidth',
2528 12 => 'CanonImageHeight',
2529 13 => 'ImageWidth',
2530 14 => 'ImageHeight',
2531 },
2532 ValueConv => 'Image::ExifTool::Exif::CalcScaleFactor35efl(@val)',
2533 PrintConv => 'sprintf("%.1f", $val)',
2534 },
2535 CircleOfConfusion => {
2536 Notes => q{
2537 this value may be incorrect if the image has been resized. Calculated as
2538 D/1440, where D is the focal plane diagonal in mm
2539 },
2540 Groups => { 2 => 'Camera' },
2541 Require => 'ScaleFactor35efl',
2542 ValueConv => 'sqrt(24*24+36*36) / ($val * 1440)',
2543 PrintConv => 'sprintf("%.3f mm",$val)',
2544 },
2545 HyperfocalDistance => {
2546 Notes => 'this value may be incorrect if the image has been resized',
2547 Groups => { 2 => 'Camera' },
2548 Require => {
2549 0 => 'FocalLength',
2550 1 => 'Aperture',
2551 2 => 'CircleOfConfusion',
2552 },
2553 ValueConv => q{
2554 ToFloat(@val);
2555 return 'inf' unless $val[1] and $val[2];
2556 return $val[0] * $val[0] / ($val[1] * $val[2] * 1000);
2557 },
2558 PrintConv => 'sprintf("%.2f m", $val)',
2559 },
2560 DOF => {
2561 Description => 'Depth Of Field',
2562 Notes => 'this value may be incorrect if the image has been resized',
2563 Require => {
2564 0 => 'FocalLength',
2565 1 => 'Aperture',
2566 2 => 'CircleOfConfusion',
2567 },
2568 Desire => {
2569 3 => 'FocusDistance', # focus distance in metres (0 is infinity)
2570 4 => 'SubjectDistance',
2571 5 => 'ObjectDistance',
2572 },
2573 ValueConv => q{
2574 ToFloat(@val);
2575 my ($d, $f) = ($val[3], $val[0]);
2576 if (defined $d) {
2577 $d or $d = 1e10; # (use large number for infinity)
2578 } else {
2579 $d = $val[4] || $val[5];
2580 return undef unless defined $d;
2581 }
2582 return 0 unless $f and $val[2];
2583 my $t = $val[1] * $val[2] * ($d * 1000 - $f) / ($f * $f);
2584 my @v = ($d / (1 + $t), $d / (1 - $t));
2585 $v[1] < 0 and $v[1] = 0; # 0 means 'inf'
2586 return join(' ',@v);
2587 },
2588 PrintConv => q{
2589 $val =~ tr/,/./; # in case locale is whacky
2590 my @v = split ' ', $val;
2591 $v[1] or return sprintf("inf (%.2f m - inf)", $v[0]);
2592 return sprintf("%.2f m (%.2f - %.2f)",$v[1]-$v[0],$v[0],$v[1]);
2593 },
2594 },
2595 FOV => {
2596 Description => 'Field Of View',
2597 Notes => q{
2598 calculated for the long image dimension, this value may be incorrect for
2599 fisheye lenses, or if the image has been resized
2600 },
2601 Require => {
2602 0 => 'FocalLength',
2603 1 => 'ScaleFactor35efl',
2604 },
2605 Desire => {
2606 2 => 'FocusDistance', # (multiply by 1000 to convert to mm)
2607 },
2608 # ref http://www.bobatkins.com/photography/technical/field_of_view.html
2609 # (calculations below apply to rectilinear lenses only, not fisheye)
2610 ValueConv => q{
2611 ToFloat(@val);
2612 return undef unless $val[0] and $val[1];
2613 my $corr = 1;
2614 if ($val[2]) {
2615 my $d = 1000 * $val[2] - $val[0];
2616 $corr += $val[0]/$d if $d > 0;
2617 }
2618 my $fd2 = atan2(36, 2*$val[0]*$val[1]*$corr);
2619 my @fov = ( $fd2 * 360 / 3.14159 );
2620 if ($val[2] and $val[2] > 0 and $val[2] < 10000) {
2621 push @fov, 2 * $val[2] * sin($fd2) / cos($fd2);
2622 }
2623 return join(' ', @fov);
2624 },
2625 PrintConv => q{
2626 my @v = split(' ',$val);
2627 my $str = sprintf("%.1f deg", $v[0]);
2628 $str .= sprintf(" (%.2f m)", $v[1]) if $v[1];
2629 return $str;
2630 },
2631 },
2632 # generate DateTimeOriginal from Date and Time Created if not extracted already
2633 DateTimeOriginal => {
2634 Condition => 'not defined $$self{VALUE}{DateTimeOriginal}',
2635 Description => 'Date/Time Original',
2636 Groups => { 2 => 'Time' },
2637 Desire => {
2638 0 => 'DateTimeCreated',
2639 1 => 'DateCreated',
2640 2 => 'TimeCreated',
2641 },
2642 ValueConv => q{
2643 return $val[0] if $val[0] and $val[0]=~/ /;
2644 return undef unless $val[1] and $val[2];
2645 return "$val[1] $val[2]";
2646 },
2647 PrintConv => '$self->ConvertDateTime($val)',
2648 },
2649 ThumbnailImage => {
2650 Writable => 1,
2651 WriteCheck => '$self->CheckImage(\$val)',
2652 WriteAlso => {
2653 # (the 0xfeedfeed values are translated in the Exif write routine)
2654 ThumbnailOffset => 'defined $val ? 0xfeedfeed : undef',
2655 ThumbnailLength => 'defined $val ? 0xfeedfeed : undef',
2656 },
2657 Require => {
2658 0 => 'ThumbnailOffset',
2659 1 => 'ThumbnailLength',
2660 },
2661 # retrieve the thumbnail from our EXIF data
2662 RawConv => 'Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],"ThumbnailImage")',
2663 },
2664 PreviewImage => {
2665 Writable => 1,
2666 WriteCheck => '$self->CheckImage(\$val)',
2667 DelCheck => '$val = ""; return undef', # can't delete, so set to empty string
2668 WriteAlso => {
2669 PreviewImageStart => 'defined $val ? 0xfeedfeed : undef',
2670 PreviewImageLength => 'defined $val ? 0xfeedfeed : undef',
2671 PreviewImageValid => 'defined $val and length $val ? 1 : 0',
2672 },
2673 Require => {
2674 0 => 'PreviewImageStart',
2675 1 => 'PreviewImageLength',
2676 },
2677 Desire => {
2678 2 => 'PreviewImageValid',
2679 # (DNG and A100 ARW may be have 2 preview images)
2680 3 => 'PreviewImageStart (1)',
2681 4 => 'PreviewImageLength (1)',
2682 },
2683 # note: extract 2nd preview, but ignore double-referenced preview
2684 # (in A100 ARW images, the 2nd PreviewImageLength from IFD0 may be wrong anyway)
2685 RawConv => q{
2686 if ($val[3] and $val[4] and $val[0] ne $val[3]) {
2687 my %val = (
2688 0 => 'PreviewImageStart (1)',
2689 1 => 'PreviewImageLength (1)',
2690 2 => 'PreviewImageValid',
2691 );
2692 $self->FoundTag($tagInfo, \%val);
2693 }
2694 return undef if defined $val[2] and not $val[2];
2695 return Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],'PreviewImage');
2696 },
2697 },
2698 JpgFromRaw => {
2699 Writable => 1,
2700 WriteCheck => '$self->CheckImage(\$val)',
2701 WriteAlso => {
2702 JpgFromRawStart => 'defined $val ? 0xfeedfeed : undef',
2703 JpgFromRawLength => 'defined $val ? 0xfeedfeed : undef',
2704 },
2705 Require => {
2706 0 => 'JpgFromRawStart',
2707 1 => 'JpgFromRawLength',
2708 },
2709 RawConv => 'Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],"JpgFromRaw")',
2710 },
2711 OtherImage => {
2712 Require => {
2713 0 => 'OtherImageStart',
2714 1 => 'OtherImageLength',
2715 },
2716 # retrieve the thumbnail from our EXIF data
2717 RawConv => 'Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],"OtherImage")',
2718 },
2719 PreviewImageSize => {
2720 Require => {
2721 0 => 'PreviewImageWidth',
2722 1 => 'PreviewImageHeight',
2723 },
2724 ValueConv => '"$val[0]x$val[1]"',
2725 },
2726 SubSecDateTimeOriginal => {
2727 Description => 'Date/Time Original',
2728 Groups => { 2 => 'Time' },
2729 Require => {
2730 0 => 'EXIF:DateTimeOriginal',
2731 1 => 'SubSecTimeOriginal',
2732 },
2733 # be careful here just in case there is a timezone following the seconds
2734 ValueConv => q{
2735 return undef if $val[1] eq '';
2736 $_ = $val[0]; s/( \d{2}:\d{2}:\d{2})/$1\.$val[1]/; $_;
2737 },
2738 PrintConv => '$self->ConvertDateTime($val)',
2739 },
2740 SubSecCreateDate => {
2741 Description => 'Create Date',
2742 Groups => { 2 => 'Time' },
2743 Require => {
2744 0 => 'EXIF:CreateDate',
2745 1 => 'SubSecTimeDigitized',
2746 },
2747 ValueConv => q{
2748 return undef if $val[1] eq '';
2749 $_ = $val[0]; s/( \d{2}:\d{2}:\d{2})/$1\.$val[1]/; $_;
2750 },
2751 PrintConv => '$self->ConvertDateTime($val)',
2752 },
2753 SubSecModifyDate => {
2754 Description => 'Modify Date',
2755 Groups => { 2 => 'Time' },
2756 Require => {
2757 0 => 'EXIF:ModifyDate',
2758 1 => 'SubSecTime',
2759 },
2760 ValueConv => q{
2761 return undef if $val[1] eq '';
2762 $_ = $val[0]; s/( \d{2}:\d{2}:\d{2})/$1\.$val[1]/; $_;
2763 },
2764 PrintConv => '$self->ConvertDateTime($val)',
2765 },
2766 CFAPattern => {
2767 Require => {
2768 0 => 'CFARepeatPatternDim',
2769 1 => 'CFAPattern2',
2770 },
2771 # generate CFAPattern
2772 ValueConv => q{
2773 my @a = split / /, $val[0];
2774 my @b = split / /, $val[1];
2775 return '?' unless @a==2 and @b==$a[0]*$a[1];
2776 return Set16u($a[0]) . Set16u($a[1]) . pack('C*', @b);
2777 },
2778 PrintConv => 'Image::ExifTool::Exif::PrintCFAPattern($val)',
2779 },
2780 RedBalance => {
2781 Groups => { 2 => 'Camera' },
2782 Desire => {
2783 0 => 'WB_RGGBLevels',
2784 1 => 'WB_RGBGLevels',
2785 2 => 'WB_RBGGLevels',
2786 3 => 'WB_GRBGLevels',
2787 4 => 'WB_GRGBLevels',
2788 5 => 'WB_GBRGLevels',
2789 6 => 'WB_RGBLevels',
2790 7 => 'WB_RBLevels',
2791 8 => 'WBRedLevel', # red
2792 9 => 'WBGreenLevel',
2793 },
2794 ValueConv => 'Image::ExifTool::Exif::RedBlueBalance(0,@val)',
2795 PrintConv => 'int($val * 1e6 + 0.5) * 1e-6',
2796 },
2797 BlueBalance => {
2798 Groups => { 2 => 'Camera' },
2799 Desire => {
2800 0 => 'WB_RGGBLevels',
2801 1 => 'WB_RGBGLevels',
2802 2 => 'WB_RBGGLevels',
2803 3 => 'WB_GRBGLevels',
2804 4 => 'WB_GRGBLevels',
2805 5 => 'WB_GBRGLevels',
2806 6 => 'WB_RGBLevels',
2807 7 => 'WB_RBLevels',
2808 8 => 'WBBlueLevel', # blue
2809 9 => 'WBGreenLevel',
2810 },
2811 ValueConv => 'Image::ExifTool::Exif::RedBlueBalance(1,@val)',
2812 PrintConv => 'int($val * 1e6 + 0.5) * 1e-6',
2813 },
2814 GPSPosition => {
2815 Groups => { 2 => 'Location' },
2816 Require => {
2817 0 => 'GPSLatitude',
2818 1 => 'GPSLongitude',
2819 },
2820 ValueConv => '"$val[0] $val[1]"',
2821 PrintConv => '"$prt[0], $prt[1]"',
2822 },
2823 LensID => {
2824 Groups => { 2 => 'Camera' },
2825 Require => {
2826 0 => 'LensType',
2827 },
2828 Desire => {
2829 1 => 'FocalLength',
2830 2 => 'MaxAperture',
2831 3 => 'MaxApertureValue',
2832 4 => 'ShortFocal',
2833 5 => 'LongFocal',
2834 6 => 'LensModel',
2835 7 => 'LensFocalRange',
2836 },
2837 Notes => q{
2838 attempt to identify the actual lens from all lenses with a given LensType.
2839 Applies only to LensType values with a lookup table. May be configured
2840 by adding user-defined lenses
2841 },
2842 # this LensID is only valid if the LensType has a PrintConv or is a model name
2843 ValueConv => q{
2844 return $val[0] if ref $$self{TAG_INFO}{LensType}{PrintConv} eq "HASH" or
2845 $prt[0] =~ /(mm|\d\/F)/;
2846 return undef;
2847 },
2848 PrintConv => 'Image::ExifTool::Exif::PrintLensID($self, $prt[0], @val)',
2849 },
2850);
2851
2852# table for unknown IFD entries
2853%Image::ExifTool::Exif::Unknown = (
2854 GROUPS => { 0 => 'EXIF', 1 => 'UnknownIFD', 2 => 'Image'},
2855 WRITE_PROC => \&WriteExif,
2856);
2857
2858# add our composite tags
2859Image::ExifTool::AddCompositeTags('Image::ExifTool::Exif');
2860
2861
2862#------------------------------------------------------------------------------
2863# AutoLoad our writer routines when necessary
2864#
2865sub AUTOLOAD
2866{
2867 return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_);
2868}
2869
2870#------------------------------------------------------------------------------
2871# Identify RAW file type for some TIFF-based formats using Compression value
2872# Inputs: 0) ExifTool object reference, 1) Compression value
2873# - sets TIFF_TYPE and FileType if identified
2874sub IdentifyRawFile($$)
2875{
2876 my ($exifTool, $comp) = @_;
2877 if ($$exifTool{FILE_TYPE} eq 'TIFF' and not $$exifTool{IdentifiedRawFile}) {
2878 if ($compression{$comp} and $compression{$comp} =~ /^\w+ ([A-Z]{3}) Compressed$/) {
2879 $exifTool->OverrideFileType($$exifTool{TIFF_TYPE} = $1);
2880 $$exifTool{IdentifiedRawFile} = 1;
2881 }
2882 }
2883}
2884
2885#------------------------------------------------------------------------------
2886# Calculate LV (Light Value)
2887# Inputs: 0) Aperture, 1) ShutterSpeed, 2) ISO
2888# Returns: LV value (and converts input values to floating point if necessary)
2889sub CalculateLV($$$)
2890{
2891 local $_;
2892 # do validity checks on arguments
2893 return undef unless @_ >= 3;
2894 foreach (@_) {
2895 return undef unless $_ and /([+-]?(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?)/ and $1 > 0;
2896 $_ = $1; # extract float from any other garbage
2897 }
2898 # (A light value of 0 is defined as f/1.0 at 1 second with ISO 100)
2899 return (2*log($_[0]) - log($_[1]) - log($_[2]/100)) / log(2);
2900}
2901
2902#------------------------------------------------------------------------------
2903# Calculate scale factor for 35mm effective focal length (ref 26/PH)
2904# Inputs: 0) Focal length
2905# 1) Focal length in 35mm format
2906# 2) Canon digital zoom factor
2907# 3) Focal plane diagonal size (in mm)
2908# 4/5) Focal plane X/Y size (in mm)
2909# 6) focal plane resolution units (1=None,2=inches,3=cm,4=mm,5=um)
2910# 7/8) Focal plane X/Y resolution
2911# 9/10,11/12...) Image width/height in order of precedence (first valid pair is used)
2912# Returns: 35mm conversion factor (or undefined if it can't be calculated)
2913sub CalcScaleFactor35efl
2914{
2915 my $res = $_[6]; # save resolution units (in case they have been converted to string)
2916 Image::ExifTool::ToFloat(@_);
2917 my $focal = shift;
2918 my $foc35 = shift;
2919
2920 return $foc35 / $focal if $focal and $foc35;
2921
2922 my $digz = shift || 1;
2923 my $diag = shift;
2924 unless ($diag and Image::ExifTool::IsFloat($diag)) {
2925 undef $diag;
2926 my $xsize = shift;
2927 my $ysize = shift;
2928 if ($xsize and $ysize) {
2929 # validate by checking aspect ratio because FocalPlaneX/YSize is not reliable
2930 my $a = $xsize / $ysize;
2931 if (abs($a-1.3333) < .1 or abs($a-1.5) < .1) {
2932 $diag = sqrt($xsize * $xsize + $ysize * $ysize);
2933 }
2934 }
2935 unless ($diag) {
2936 # get number of mm in units (assume inches unless otherwise specified)
2937 my %lkup = ( 3=>10, 4=>1, 5=>0.001 , cm=>10, mm=>1, um=>0.001 );
2938 my $units = $lkup{ shift() || $res || '' } || 25.4;
2939 my $x_res = shift || return undef;
2940 my $y_res = shift || return undef;
2941 Image::ExifTool::IsFloat($x_res) and $x_res != 0 or return undef;
2942 Image::ExifTool::IsFloat($y_res) and $y_res != 0 or return undef;
2943 my ($w, $h);
2944 for (;;) {
2945 @_ < 2 and return undef;
2946 $w = shift;
2947 $h = shift;
2948 next unless $w and $h;
2949 my $a = $w / $h;
2950 last if $a > 0.5 and $a < 2; # stop if we get a reasonable value
2951 }
2952 # calculate focal plane size in mm
2953 $w *= $units / $x_res;
2954 $h *= $units / $y_res;
2955 $diag = sqrt($w*$w+$h*$h);
2956 # make sure size is reasonable
2957 return undef unless $diag > 1 and $diag < 100;
2958 }
2959 }
2960 return sqrt(36*36+24*24) * $digz / $diag;
2961}
2962
2963#------------------------------------------------------------------------------
2964# Print exposure compensation fraction
2965sub PrintFraction($)
2966{
2967 my $val = shift;
2968 my $str;
2969 if (defined $val) {
2970 $val *= 1.00001; # avoid round-off errors
2971 if (not $val) {
2972 $str = '0';
2973 } elsif (int($val)/$val > 0.999) {
2974 $str = sprintf("%+d", int($val));
2975 } elsif ((int($val*2))/($val*2) > 0.999) {
2976 $str = sprintf("%+d/2", int($val * 2));
2977 } elsif ((int($val*3))/($val*3) > 0.999) {
2978 $str = sprintf("%+d/3", int($val * 3));
2979 } else {
2980 $str = sprintf("%+.3g", $val);
2981 }
2982 }
2983 return $str;
2984}
2985
2986#------------------------------------------------------------------------------
2987# Convert fraction or number to floating point value (or 'undef' or 'inf')
2988sub ConvertFraction($)
2989{
2990 my $val = shift;
2991 if ($val =~ m{([-+]?\d+)/(\d+)}) {
2992 $val = $2 ? $1 / $2 : ($1 ? 'inf' : 'undef');
2993 }
2994 return $val;
2995}
2996
2997#------------------------------------------------------------------------------
2998# Convert EXIF text to something readable
2999# Inputs: 0) ExifTool object reference, 1) EXIF text
3000# Returns: text encoded according to Charset option (with trailing spaces removed)
3001sub ConvertExifText($$)
3002{
3003 my ($exifTool, $val) = @_;
3004 return $val if length($val) < 8;
3005 my $id = substr($val, 0, 8);
3006 my $str = substr($val, 8);
3007 # Note: allow spaces instead of nulls in the ID codes because
3008 # it is fairly common for camera manufacturers to get this wrong
3009 if ($id =~ /^(ASCII)?[\0 ]+$/) {
3010 # truncate at null terminator (shouldn't have a null based on the
3011 # EXIF spec, but it seems that few people actually read the spec)
3012 $str =~ s/\0.*//s;
3013 # by the EXIF spec, the following string should be "UNICODE\0", but
3014 # apparently Kodak sometimes uses "Unicode\0" in the APP3 "Meta" information.
3015 # However, unfortunately Ricoh uses "Unicode\0" in the RR30 EXIF UserComment
3016 # when the text is actually ASCII, so only recognize uppercase "UNICODE\0".
3017 } elsif ($id =~ /^UNICODE[\0 ]$/) {
3018 # MicrosoftPhoto writes as little-endian even in big-endian EXIF,
3019 # so we must guess at the true byte ordering
3020 $str = $exifTool->Decode($str, 'UCS2', 'Unknown');
3021 } elsif ($id =~ /^JIS[\0 ]{5}$/) {
3022 $str = $exifTool->Decode($str, 'JIS', 'Unknown');
3023 } else {
3024 $exifTool->Warn("Invalid EXIF text encoding");
3025 $str = $id . $str;
3026 }
3027 $str =~ s/ +$//; # trim trailing blanks
3028 return $str;
3029}
3030
3031#------------------------------------------------------------------------------
3032# Print conversion for SpatialFrequencyResponse
3033sub PrintSFR($)
3034{
3035 my $val = shift;
3036 return $val unless length $val > 4;
3037 my ($n, $m) = (Get16u(\$val, 0), Get16u(\$val, 2));
3038 my @cols = split /\0/, substr($val, 4), $n+1;
3039 my $pos = length($val) - 8 * $n * $m;
3040 return $val unless @cols == $n+1 and $pos >= 4;
3041 pop @cols;
3042 my ($i, $j);
3043 for ($i=0; $i<$n; ++$i) {
3044 my @rows;
3045 for ($j=0; $j<$m; ++$j) {
3046 push @rows, Image::ExifTool::GetRational64u(\$val, $pos + 8*($i+$j*$n));
3047 }
3048 $cols[$i] .= '=' . join(',',@rows) . '';
3049 }
3050 return join '; ', @cols;
3051}
3052
3053#------------------------------------------------------------------------------
3054# Print numerical parameter value (with sign, or 'Normal' for zero)
3055# Inputs: 0) value, 1) flag for inverse conversion, 2) conversion hash reference
3056sub PrintParameter($$$)
3057{
3058 my ($val, $inv, $conv) = @_;
3059 return $val if $inv;
3060 if ($val > 0) {
3061 if ($val > 0xfff0) { # a negative value in disguise?
3062 $val = $val - 0x10000;
3063 } else {
3064 $val = "+$val";
3065 }
3066 }
3067 return $val;
3068}
3069
3070#------------------------------------------------------------------------------
3071# Convert parameter back to standard EXIF value
3072# 0,0.00,etc or "Normal" => 0
3073# -1,-2,etc or "Soft" or "Low" => 1
3074# +1,+2,1,2,etc or "Hard" or "High" => 2
3075sub ConvertParameter($)
3076{
3077 my $val = shift;
3078 my $isFloat = Image::ExifTool::IsFloat($val);
3079 # normal is a value of zero
3080 return 0 if $val =~ /\bn/i or ($isFloat and $val == 0);
3081 # "soft", "low" or any negative number is a value of 1
3082 return 1 if $val =~ /\b(s|l)/i or ($isFloat and $val < 0);
3083 # "hard", "high" or any positive number is a value of 2
3084 return 2 if $val =~ /\bh/i or $isFloat;
3085 return undef;
3086}
3087
3088#------------------------------------------------------------------------------
3089# Calculate Red/BlueBalance
3090# Inputs: 0) 0=red, 1=blue, 1-7) WB_RGGB/RGBG/RBGG/GRBG/GRGB/RGB/RBLevels,
3091# 8) red or blue level, 9) green level
3092my @rggbLookup = (
3093 # indices for R, G, G and B components in input value
3094 [ 0, 1, 2, 3 ], # 0 RGGB
3095 [ 0, 1, 3, 2 ], # 1 RGBG
3096 [ 0, 2, 3, 1 ], # 2 RBGG
3097 [ 1, 0, 3, 2 ], # 3 GRBG
3098 [ 1, 0, 2, 3 ], # 4 GRGB
3099 [ 2, 3, 0, 1 ], # 5 GBRG
3100 [ 0, 1, 1, 2 ], # 6 RGB
3101 [ 0, 256, 256, 1 ], # 7 RB (green level is 256)
3102);
3103sub RedBlueBalance($@)
3104{
3105 my $blue = shift;
3106 my ($i, $val, $levels);
3107 for ($i=0; $i<@rggbLookup; ++$i) {
3108 $levels = shift or next;
3109 my @levels = split ' ', $levels;
3110 next if @levels < 2;
3111 my $lookup = $rggbLookup[$i];
3112 my $g = $$lookup[1]; # get green level or index
3113 if ($g < 4) {
3114 next if @levels < 3;
3115 $g = ($levels[$g] + $levels[$$lookup[2]]) / 2 or next;
3116 } elsif ($levels[$$lookup[$blue * 3]] < 4) {
3117 $g = 1; # Some Nikon cameras use a scaling factor of 1 (E5700)
3118 }
3119 $val = $levels[$$lookup[$blue * 3]] / $g;
3120 last;
3121 }
3122 $val = $_[0] / $_[1] if not defined $val and ($_[0] and $_[1]);
3123 return $val;
3124}
3125
3126#------------------------------------------------------------------------------
3127# Print exposure time as a fraction
3128sub PrintExposureTime($)
3129{
3130 my $secs = shift;
3131 if ($secs < 0.25001 and $secs > 0) {
3132 return sprintf("1/%d",int(0.5 + 1/$secs));
3133 }
3134 $_ = sprintf("%.1f",$secs);
3135 s/\.0$//;
3136 return $_;
3137}
3138
3139#------------------------------------------------------------------------------
3140# Print CFA Pattern
3141sub PrintCFAPattern($)
3142{
3143 my $val = shift;
3144 return '<truncated data>' unless length $val > 4;
3145 # some panasonic cameras (SV-AS3, SV-AS30) write this in ascii (very odd)
3146 $val =~ /^[0-6]+$/ and $val =~ tr/0-6/\x00-\x06/;
3147 my ($nx, $ny) = (Get16u(\$val, 0), Get16u(\$val, 2));
3148 return '<zero pattern size>' unless $nx and $ny;
3149 my $end = 4 + $nx * $ny;
3150 if ($end > length $val) {
3151 # try swapping byte order (I have seen this order different than in EXIF)
3152 ($nx, $ny) = unpack('n2',pack('v2',$nx,$ny));
3153 $end = 4 + $nx * $ny;
3154 return '<invalid pattern size>' if $end > length $val;
3155 }
3156 my @cfaColor = qw(Red Green Blue Cyan Magenta Yellow White);
3157 my ($pos, $rtnVal) = (4, '[');
3158 for (;;) {
3159 $rtnVal .= $cfaColor[Get8u(\$val,$pos)] || 'Unknown';
3160 last if ++$pos >= $end;
3161 ($pos - 4) % $ny and $rtnVal .= ',', next;
3162 $rtnVal .= '][';
3163 }
3164 return $rtnVal . ']';
3165}
3166
3167#------------------------------------------------------------------------------
3168# Print conversion for lens info
3169# Inputs: 0) string of values (min focal, max focal, min F, max F)
3170# Returns: string in the form "12-20mm f/3.8-4.5" or "50mm f/1.4"
3171sub PrintLensInfo($)
3172{
3173 my $val = shift;
3174 my @vals = split ' ', $val;
3175 return $val unless @vals == 4;
3176 my $c = 0;
3177 foreach (@vals) {
3178 Image::ExifTool::IsFloat($_) and ++$c, next;
3179 $_ eq 'inf' and $_ = '?', ++$c, next;
3180 $_ eq 'undef' and $_ = '?', ++$c, next;
3181 }
3182 return $val unless $c == 4;
3183 $val = "$vals[1]mm f/$vals[2]";
3184 $val = "$vals[0]-$val" if $vals[0] ne $vals[1];
3185 $val .= "-$vals[3]" if $vals[3] ne $vals[2];
3186 return $val;
3187}
3188
3189#------------------------------------------------------------------------------
3190# Get lens info from lens model string
3191# Inputs: 0) lens string, 1) flag to allow unknown "?" values
3192# Returns: 0) min focal, 1) max focal, 2) min aperture, 3) max aperture
3193# Notes: returns empty list if lens string could not be parsed
3194sub GetLensInfo($;$)
3195{
3196 my ($lens, $unk) = @_;
3197 # extract focal length and aperture ranges for this lens
3198 my $pat = '\\d+(?:\\.\\d+)?';
3199 $pat .= '|\\?' if $unk;
3200 return () unless $lens =~ /($pat)(?:-($pat))?\s*mm.*?(?:[fF]\/?\s*)($pat)(?:-($pat))?/;
3201 # ($1=short focal, $2=long focal, $3=max aperture wide, $4=max aperture tele)
3202 my @a = ($1, $2, $3, $4);
3203 $a[1] or $a[1] = $a[0];
3204 $a[3] or $a[3] = $a[2];
3205 if ($unk) {
3206 local $_;
3207 $_ eq '?' and $_ = 'undef' foreach @a;
3208 }
3209 return @a;
3210}
3211
3212#------------------------------------------------------------------------------
3213# Attempt to identify the specific lens if multiple lenses have the same LensType
3214# Inputs: 0) ExifTool object ref, 1) LensType string, 2) LensType value,
3215# 3) FocalLength, 4) MaxAperture, 5) MaxApertureValue, 6) ShortFocal,
3216# 7) LongFocal, 8) LensModel, 9) LensFocalRange
3217sub PrintLensID($$@)
3218{
3219 my ($exifTool, $lensTypePrt, $lensType, $focalLength, $maxAperture,
3220 $maxApertureValue, $shortFocal, $longFocal, $lensModel, $lensFocalRange) = @_;
3221 # the rest of the logic relies on the LensType lookup:
3222 return undef unless defined $lensType;
3223 my $printConv = $exifTool->{TAG_INFO}{LensType}{PrintConv};
3224 # just copy LensType PrintConv value if it was a lens name
3225 # (Olympus or Panasonic -- just exclude things like Nikon and Leaf LensType)
3226 unless (ref $printConv eq 'HASH') {
3227 return $lensTypePrt if $lensTypePrt =~ /mm/;
3228 return $lensTypePrt if $lensTypePrt =~ s/(\d)\/F/$1mm F/;
3229 return undef;
3230 }
3231 # use MaxApertureValue if MaxAperture is not available
3232 $maxAperture = $maxApertureValue unless $maxAperture;
3233 if ($lensFocalRange and $lensFocalRange =~ /^(\d+)(?: to (\d+))?$/) {
3234 ($shortFocal, $longFocal) = ($1, $2 || $1);
3235 }
3236 if ($shortFocal and $longFocal) {
3237 # Canon includes makernote information which allows better lens identification
3238 require Image::ExifTool::Canon;
3239 return Image::ExifTool::Canon::PrintLensID($printConv, $lensType,
3240 $shortFocal, $longFocal, $maxAperture, $lensModel);
3241 }
3242 my $lens = $$printConv{$lensType};
3243 return ($lensModel || $lensTypePrt) unless $lens;
3244 return $lens unless $$printConv{"$lensType.1"};
3245 $lens =~ s/ or .*//s; # remove everything after "or"
3246 # make list of all possible matching lenses
3247 my @lenses = ( $lens );
3248 my $i;
3249 for ($i=1; $$printConv{"$lensType.$i"}; ++$i) {
3250 push @lenses, $$printConv{"$lensType.$i"};
3251 }
3252 # attempt to determine actual lens
3253 my (@matches, @best, @user, $diff);
3254 foreach $lens (@lenses) {
3255 if ($Image::ExifTool::userLens{$lens}) {
3256 push @user, $lens;
3257 next;
3258 }
3259 my ($sf, $lf, $sa, $la) = GetLensInfo($lens);
3260 next unless $sf;
3261 # see if we can rule out this lens using FocalLength and MaxAperture
3262 if ($focalLength) {
3263 next if $focalLength < $sf - 0.5;
3264 next if $focalLength > $lf + 0.5;
3265 }
3266 if ($maxAperture) {
3267 # it seems that most manufacturers set MaxAperture and MaxApertureValue
3268 # to the maximum aperture (smallest F number) for the current focal length
3269 # of the lens, so assume that MaxAperture varies with focal length and find
3270 # the closest match (this is somewhat contrary to the EXIF specification which
3271 # states "The smallest F number of the lens", without mention of focal length)
3272 next if $maxAperture < $sa - 0.15; # (0.15 is arbitrary)
3273 next if $maxAperture > $la + 0.15;
3274 # now determine the best match for this aperture
3275 my $aa; # approximate maximum aperture at this focal length
3276 if ($sf == $lf or $sa == $la) {
3277 $aa = $sa;
3278 } else {
3279 # assume a log-log variation of max aperture with focal length
3280 # (see http://regex.info/blog/2006-10-05/263)
3281 $aa = exp(log($sa) + (log($la)-log($sa)) / (log($lf)-log($sf)) *
3282 (log($focalLength)-log($sf)));
3283 }
3284 my $d = abs($maxAperture - $aa);
3285 if (defined $diff) {
3286 $d > $diff + 0.15 and next; # (0.15 is arbitrary)
3287 $d < $diff - 0.15 and undef @best;
3288 }
3289 $diff = $d;
3290 push @best, $lens;
3291 }
3292 push @matches, $lens;
3293 }
3294 return join(' or ', @user) if @user;
3295 return join(' or ', @best) if @best;
3296 return join(' or ', @matches) if @matches;
3297 return $$printConv{$lensType};
3298}
3299
3300#------------------------------------------------------------------------------
3301# translate date into standard EXIF format
3302# Inputs: 0) date
3303# Returns: date in format '2003:10:22'
3304# - bad formats recognized: '2003-10-22','2003/10/22','2003 10 22','20031022'
3305# - removes null terminator if it exists
3306sub ExifDate($)
3307{
3308 my $date = shift;
3309 $date =~ s/\0$//; # remove any null terminator
3310 # separate year:month:day with colons (instead of -, /, space or nothing)
3311 $date =~ s/(\d{4})[- \/:]*(\d{2})[- \/:]*(\d{2})$/$1:$2:$3/;
3312 return $date;
3313}
3314
3315#------------------------------------------------------------------------------
3316# translate time into standard EXIF format
3317# Inputs: 0) time
3318# Returns: time in format '10:30:55'
3319# - bad formats recognized: '10 30 55', '103055', '103055+0500'
3320# - removes null terminator if it exists
3321# - leaves time zone intact if specified (ie. '10:30:55+05:00')
3322sub ExifTime($)
3323{
3324 my $time = shift;
3325 $time =~ tr/ /:/; # use ':' (not ' ') as a separator
3326 $time =~ s/\0$//; # remove any null terminator
3327 # add separators if they don't exist
3328 $time =~ s/^(\d{2})(\d{2})(\d{2})/$1:$2:$3/;
3329 $time =~ s/([+-]\d{2})(\d{2})\s*$/$1:$2/; # to timezone too
3330 return $time;
3331}
3332
3333#------------------------------------------------------------------------------
3334# extract image from file
3335# Inputs: 0) ExifTool object reference, 1) data offset (in file), 2) data length
3336# 3) [optional] tag name
3337# Returns: Reference to Image if specifically requested or "Binary data" message
3338# Returns undef if there was an error loading the image
3339sub ExtractImage($$$$)
3340{
3341 my ($exifTool, $offset, $len, $tag) = @_;
3342 my $dataPt = \$exifTool->{EXIF_DATA};
3343 my $dataPos = $exifTool->{EXIF_POS};
3344 my $image;
3345
3346 # no image if length is zero, and don't try to extract binary from XMP file
3347 return undef if not $len or $$exifTool{FILE_TYPE} eq 'XMP';
3348
3349 # take data from EXIF block if possible
3350 if (defined $dataPos and $offset>=$dataPos and $offset+$len<=$dataPos+length($$dataPt)) {
3351 $image = substr($$dataPt, $offset-$dataPos, $len);
3352 } else {
3353 $image = $exifTool->ExtractBinary($offset, $len, $tag);
3354 return undef unless defined $image;
3355 # patch for incorrect ThumbnailOffset in some Sony DSLR-A100 ARW images
3356 if ($tag and $tag eq 'ThumbnailImage' and $$exifTool{TIFF_TYPE} eq 'ARW' and
3357 $$exifTool{Model} eq 'DSLR-A100' and $offset < 0x10000 and
3358 $image !~ /^(Binary data|\xff\xd8\xff)/)
3359 {
3360 my $try = $exifTool->ExtractBinary($offset + 0x10000, $len, $tag);
3361 if (defined $try and $try =~ /^\xff\xd8\xff/) {
3362 $image = $try;
3363 $exifTool->{VALUE}->{ThumbnailOffset} += 0x10000;
3364 $exifTool->Warn('Adjusted incorrect A100 ThumbnailOffset', 1);
3365 }
3366 }
3367 }
3368 return $exifTool->ValidateImage(\$image, $tag);
3369}
3370
3371#------------------------------------------------------------------------------
3372# Process EXIF directory
3373# Inputs: 0) ExifTool object reference
3374# 1) Reference to directory information hash
3375# 2) Pointer to tag table for this directory
3376# Returns: 1 on success, otherwise returns 0 and sets a Warning
3377sub ProcessExif($$$)
3378{
3379 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
3380 my $dataPt = $$dirInfo{DataPt};
3381 my $dataPos = $$dirInfo{DataPos} || 0;
3382 my $dataLen = $$dirInfo{DataLen};
3383 my $dirStart = $$dirInfo{DirStart} || 0;
3384 my $dirLen = $$dirInfo{DirLen} || $dataLen - $dirStart;
3385 my $dirName = $$dirInfo{DirName};
3386 my $base = $$dirInfo{Base} || 0;
3387 my $firstBase = $base;
3388 my $raf = $$dirInfo{RAF};
3389 my $verbose = $exifTool->Options('Verbose');
3390 my $htmlDump = $exifTool->{HTML_DUMP};
3391 my $success = 1;
3392 my ($tagKey, $dirSize, $makerAddr);
3393 my $inMakerNotes = $tagTablePtr->{GROUPS}{0} eq 'MakerNotes';
3394
3395 # ignore non-standard EXIF while in strict MWG compatibility mode
3396 if ($Image::ExifTool::MWG::strict and $dirName eq 'IFD0' and
3397 $tagTablePtr eq \%Image::ExifTool::Exif::Main and
3398 $$exifTool{FILE_TYPE} =~ /^(JPEG|TIFF|PSD)$/)
3399 {
3400 my $path = $exifTool->MetadataPath();
3401 unless ($path =~ /^(JPEG-APP1-IFD0|TIFF-IFD0|PSD-EXIFInfo-IFD0)$/) {
3402 $exifTool->Warn("Ignored non-standard EXIF at $path");
3403 return 1;
3404 }
3405 }
3406 $verbose = -1 if $htmlDump; # mix htmlDump into verbose so we can test for both at once
3407 $dirName eq 'EXIF' and $dirName = $$dirInfo{DirName} = 'IFD0';
3408 $$dirInfo{Multi} = 1 if $dirName =~ /^(IFD0|SubIFD)$/ and not defined $$dirInfo{Multi};
3409 # get a more descriptive name for MakerNote sub-directories
3410 my $name = $$dirInfo{Name};
3411 $name = $dirName unless $name and $inMakerNotes and $name !~ /^MakerNote/;
3412
3413 my ($numEntries, $dirEnd);
3414 if ($dirStart >= 0 and $dirStart <= $dataLen-2) {
3415 # make sure data is large enough (patches bug in Olympus subdirectory lengths)
3416 $numEntries = Get16u($dataPt, $dirStart);
3417 $dirSize = 2 + 12 * $numEntries;
3418 $dirEnd = $dirStart + $dirSize;
3419 if ($dirSize > $dirLen) {
3420 if ($verbose > 0 and not $$dirInfo{SubIFD}) {
3421 my $short = $dirSize - $dirLen;
3422 $exifTool->Warn("Short directory size (missing $short bytes)");
3423 }
3424 undef $dirSize if $dirEnd > $dataLen; # read from file if necessary
3425 }
3426 }
3427 # read IFD from file if necessary
3428 unless ($dirSize) {
3429 $success = 0;
3430 if ($raf) {
3431 # read the count of entries in this IFD
3432 my $offset = $dirStart + $dataPos;
3433 my ($buff, $buf2);
3434 if ($raf->Seek($offset + $base, 0) and $raf->Read($buff,2) == 2) {
3435 my $len = 12 * Get16u(\$buff,0);
3436 # also read next IFD pointer if available
3437 if ($raf->Read($buf2, $len+4) >= $len) {
3438 $buff .= $buf2;
3439 # make copy of dirInfo since we're going to modify it
3440 my %newDirInfo = %$dirInfo;
3441 $dirInfo = \%newDirInfo;
3442 # update directory parameters for the newly loaded IFD
3443 $dataPt = $$dirInfo{DataPt} = \$buff;
3444 $dataPos = $$dirInfo{DataPos} = $offset;
3445 $dataLen = $$dirInfo{DataLen} = length $buff;
3446 $dirStart = $$dirInfo{DirStart} = 0;
3447 $dirLen = $$dirInfo{DirLen} = length $buff;
3448 $success = 1;
3449 }
3450 }
3451 }
3452 unless ($success) {
3453 $exifTool->Warn("Bad $name directory");
3454 return 0;
3455 }
3456 $numEntries = Get16u($dataPt, $dirStart);
3457 $dirSize = 2 + 12 * $numEntries;
3458 $dirEnd = $dirStart + $dirSize;
3459 }
3460 $verbose > 0 and $exifTool->VerboseDir($dirName, $numEntries);
3461 my $bytesFromEnd = $dataLen - $dirEnd;
3462 if ($bytesFromEnd < 4) {
3463 unless ($bytesFromEnd==2 or $bytesFromEnd==0) {
3464 $exifTool->Warn(sprintf"Illegal $name directory size (0x%x entries)",$numEntries);
3465 return 0;
3466 }
3467 }
3468 # fix base offset for maker notes if necessary
3469 if (defined $$dirInfo{MakerNoteAddr}) {
3470 $makerAddr = $$dirInfo{MakerNoteAddr};
3471 delete $$dirInfo{MakerNoteAddr};
3472 if (Image::ExifTool::MakerNotes::FixBase($exifTool, $dirInfo)) {
3473 $base = $$dirInfo{Base};
3474 $dataPos = $$dirInfo{DataPos};
3475 }
3476 }
3477 if ($htmlDump) {
3478 my $longName = $name eq 'MakerNotes' ? ($$dirInfo{Name} || $name) : $name;
3479 if (defined $makerAddr) {
3480 my $hdrLen = $dirStart + $dataPos + $base - $makerAddr;
3481 $exifTool->HDump($makerAddr, $hdrLen, "MakerNotes header", $longName) if $hdrLen > 0;
3482 }
3483 $exifTool->HDump($dirStart + $dataPos + $base, 2, "$longName entries",
3484 "Entry count: $numEntries");
3485 my $tip;
3486 if ($bytesFromEnd >= 4) {
3487 my $nxt = ($name =~ /^(.*?)(\d+)$/) ? $1 . ($2 + 1) : 'Next IFD';
3488 $tip = sprintf("$nxt offset: 0x%.4x", Get32u($dataPt, $dirEnd));
3489 }
3490 $exifTool->HDump($dirEnd + $dataPos + $base, 4, "Next IFD", $tip, 0);
3491 }
3492
3493 # patch for Canon EOS 40D firmware 1.0.4 bug (incorrect directory counts)
3494 # (must do this before parsing directory or CameraSettings offset will be suspicious)
3495 if ($inMakerNotes and $$exifTool{Model} eq 'Canon EOS 40D') {
3496 my $entry = $dirStart + 2 + 12 * ($numEntries - 1);
3497 my $fmt = Get16u($dataPt, $entry + 2);
3498 if ($fmt < 1 or $fmt > 13) {
3499 $exifTool->HDump($entry+$dataPos+$base,12,"[invalid IFD entry]",
3500 "Bad format type: $fmt", 1);
3501 # adjust the number of directory entries
3502 --$numEntries;
3503 $dirEnd -= 12;
3504 }
3505 }
3506
3507 # loop through all entries in an EXIF directory (IFD)
3508 my ($index, $valEnd, $offList, $offHash);
3509 my $warnCount = 0;
3510 for ($index=0; $index<$numEntries; ++$index) {
3511 if ($warnCount > 10) {
3512 $exifTool->Warn("Too many warnings -- $name parsing aborted", 1) and return 0;
3513 }
3514 my $entry = $dirStart + 2 + 12 * $index;
3515 my $tagID = Get16u($dataPt, $entry);
3516 my $format = Get16u($dataPt, $entry+2);
3517 my $count = Get32u($dataPt, $entry+4);
3518 if ($format < 1 or $format > 13) {
3519 $exifTool->HDump($entry+$dataPos+$base,12,"[invalid IFD entry]",
3520 "Bad format type: $format", 1);
3521 # warn unless the IFD was just padded with zeros
3522 if ($format) {
3523 $exifTool->Warn(sprintf("Unknown format ($format) for $name tag 0x%x",$tagID));
3524 ++$warnCount;
3525 }
3526 return 0 unless $index; # assume corrupted IFD if this is our first entry
3527 next;
3528 }
3529 my $formatStr = $formatName[$format]; # get name of this format
3530 my $valueDataPt = $dataPt;
3531 my $valueDataPos = $dataPos;
3532 my $valueDataLen = $dataLen;
3533 my $valuePtr = $entry + 8; # pointer to value within $$dataPt
3534 my $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $tagID);
3535 my $origFormStr;
3536 # hack to patch incorrect count in Kodak SubIFD3 tags
3537 if ($count < 2 and ref $$tagTablePtr{$tagID} eq 'HASH' and $$tagTablePtr{$tagID}{FixCount}) {
3538 $offList or ($offList, $offHash) = GetOffList($dataPt, $dirStart, $dataPos,
3539 $numEntries, $tagTablePtr);
3540 my $i = $$offHash{Get32u($dataPt, $valuePtr)};
3541 if (defined $i and $i < $#$offList) {
3542 my $oldCount = $count;
3543 $count = int(($$offList[$i+1] - $$offList[$i]) / $formatSize[$format]);
3544 $origFormStr = $formatName[$format] . '[' . $oldCount . ']' if $oldCount != $count;
3545 }
3546 }
3547 my $size = $count * $formatSize[$format];
3548 my $readSize = $size;
3549 if ($size > 4) {
3550 if ($size > 0x7fffffff) {
3551 $exifTool->Warn(sprintf("Invalid size ($size) for $name tag 0x%x",$tagID));
3552 ++$warnCount;
3553 next;
3554 }
3555 $valuePtr = Get32u($dataPt, $valuePtr);
3556 # fix valuePtr if necessary
3557 if ($$dirInfo{FixOffsets}) {
3558 my $wFlag;
3559 $valEnd or $valEnd = $dataPos + $dirEnd + 4;
3560 #### eval FixOffsets ($valuePtr, $valEnd, $size, $tagID, $wFlag)
3561 eval $$dirInfo{FixOffsets};
3562 }
3563 my $suspect;
3564 # offset shouldn't point into TIFF header
3565 $valuePtr < 8 and $suspect = $warnCount;
3566 # convert offset to pointer in $$dataPt
3567 if ($$dirInfo{EntryBased} or (ref $$tagTablePtr{$tagID} eq 'HASH' and
3568 $tagTablePtr->{$tagID}{EntryBased}))
3569 {
3570 $valuePtr += $entry;
3571 } else {
3572 $valuePtr -= $dataPos;
3573 }
3574 # value shouldn't overlap our directory
3575 $suspect = $warnCount if $valuePtr < $dirEnd and $valuePtr+$size > $dirStart;
3576 # load value from file if necessary
3577 if ($valuePtr < 0 or $valuePtr+$size > $dataLen) {
3578 # get value by seeking in file if we are allowed
3579 my $buff;
3580 if ($raf) {
3581 # avoid loading large binary data unless necessary
3582 # (ie. ImageSourceData -- layers in Photoshop TIFF image)
3583 while ($size > BINARY_DATA_LIMIT) {
3584 if ($tagInfo) {
3585 # make large unknown blocks binary data
3586 $$tagInfo{Binary} = 1 if $$tagInfo{Unknown};
3587 last unless $$tagInfo{Binary}; # must read non-binary data
3588 last if $$tagInfo{SubDirectory}; # must read SubDirectory data
3589 if ($exifTool->{OPTIONS}{Binary}) {
3590 # read binary data if specified unless tagsFromFile won't use it
3591 last unless $$exifTool{TAGS_FROM_FILE} and $$tagInfo{Protected};
3592 }
3593 # must read if tag is specified by name
3594 last if $exifTool->{REQ_TAG_LOOKUP}{lc($$tagInfo{Name})};
3595 } else {
3596 # must read value if needed for a condition
3597 last if defined $tagInfo;
3598 }
3599 # (note: changing the value without changing $size will cause
3600 # a warning in the verbose output, but we need to maintain the
3601 # proper size for the htmlDump, so we can't change this)
3602 $buff = "Binary data $size bytes";
3603 $readSize = length $buff;
3604 last;
3605 }
3606 # read from file if necessary
3607 unless (defined $buff or
3608 ($raf->Seek($base + $valuePtr + $dataPos,0) and
3609 $raf->Read($buff,$size) == $size))
3610 {
3611 $exifTool->Warn("Error reading value for $name entry $index", $inMakerNotes);
3612 return 0 unless $inMakerNotes;
3613 ++$warnCount;
3614 $buff = '' unless defined $buff;
3615 $readSize = length $buff;
3616 }
3617 $valueDataPt = \$buff;
3618 $valueDataPos = $valuePtr + $dataPos;
3619 $valueDataLen = length $buff;
3620 $valuePtr = 0;
3621 } else {
3622 my ($tagStr, $tmpInfo);
3623 if ($tagInfo) {
3624 $tagStr = $$tagInfo{Name};
3625 } elsif (defined $tagInfo) {
3626 $tmpInfo = $exifTool->GetTagInfo($tagTablePtr, $tagID, \ '', $formatStr, $count);
3627 $tagStr = $$tmpInfo{Name} if $tmpInfo;
3628 }
3629 if ($tagInfo and $$tagInfo{ChangeBase}) {
3630 # adjust base offset for this tag only
3631 #### eval ChangeBase ($dirStart,$dataPos)
3632 my $newBase = eval $$tagInfo{ChangeBase};
3633 $valuePtr += $newBase;
3634 }
3635 $tagStr or $tagStr = sprintf("tag 0x%x",$tagID);
3636 # allow PreviewImage to run outside EXIF data
3637 if ($tagStr eq 'PreviewImage' and $exifTool->{RAF}) {
3638 my $pos = $exifTool->{RAF}->Tell();
3639 $buff = $exifTool->ExtractBinary($base + $valuePtr + $dataPos, $size, 'PreviewImage');
3640 $exifTool->{RAF}->Seek($pos, 0);
3641 $valueDataPt = \$buff;
3642 $valueDataPos = $valuePtr + $dataPos;
3643 $valueDataLen = $size;
3644 $valuePtr = 0;
3645 } elsif ($tagStr eq 'MakerNoteLeica6' and $exifTool->{RAF}) {
3646 if ($verbose > 0) {
3647 $exifTool->VPrint(0, "$$exifTool{INDENT}$index) $tagStr --> (outside APP1 segment)\n");
3648 }
3649 if ($exifTool->Options('FastScan')) {
3650 $exifTool->Warn('Ignored Leica MakerNote trailer');
3651 } else {
3652 $$exifTool{LeicaTrailer} = {
3653 TagInfo => $tagInfo || $tmpInfo,
3654 Offset => $base + $valuePtr + $dataPos,
3655 Size => $size,
3656 };
3657 }
3658 } else {
3659 $exifTool->Warn("Bad $name offset for $tagStr");
3660 ++$warnCount;
3661 }
3662 unless (defined $buff) {
3663 next unless $htmlDump and $size < 1000000;
3664 $valueDataPt = \ (' ' x $size);
3665 $valueDataPos = $valuePtr + $dataPos;
3666 $valueDataLen = -1; # flag the bad pointer
3667 $valuePtr = 0;
3668 }
3669 }
3670 }
3671 # warn about suspect offsets if they didn't already cause another warning
3672 if (defined $suspect and $suspect == $warnCount) {
3673 my $tagStr = $tagInfo ? $$tagInfo{Name} : sprintf('tag 0x%.4x', $tagID);
3674 if ($exifTool->Warn("Suspicious $name offset for $tagStr", $inMakerNotes)) {
3675 ++$warnCount;
3676 next unless $verbose;
3677 }
3678 }
3679 }
3680 # treat single unknown byte as int8u
3681 $formatStr = 'int8u' if $format == 7 and $count == 1;
3682
3683 my ($val, $subdir, $wrongFormat);
3684 if ($tagID > 0xf000 and $tagTablePtr eq \%Image::ExifTool::Exif::Main) {
3685 my $oldInfo = $$tagTablePtr{$tagID};
3686 if (not $oldInfo or (ref $oldInfo eq 'HASH' and $$oldInfo{Condition})) {
3687 # handle special case of Photoshop RAW tags (0xfde8-0xfe58)
3688 # --> generate tags from the value if possible
3689 $val = ReadValue($valueDataPt,$valuePtr,$formatStr,$count,$readSize);
3690 if (defined $val and $val =~ /(.*): (.*)/) {
3691 my $tag = $1;
3692 $val = $2;
3693 $tag =~ s/'s//; # remove 's (so "Owner's Name" becomes "OwnerName")
3694 $tag =~ tr/a-zA-Z0-9_//cd; # remove unknown characters
3695 if ($tag) {
3696 $tagInfo = {
3697 Name => $tag,
3698 ValueConv => '$_=$val;s/.*: //;$_', # remove descr
3699 };
3700 Image::ExifTool::AddTagToTable($tagTablePtr, $tagID, $tagInfo);
3701 # generate conditional list if a conditional tag already existed
3702 $$tagTablePtr{$tagID} = [ $oldInfo, $tagInfo ] if $oldInfo;
3703 }
3704 }
3705 }
3706 }
3707 if (defined $tagInfo and not $tagInfo) {
3708 # GetTagInfo() required the value for a Condition
3709 my $tmpVal = substr($$valueDataPt, $valuePtr, $readSize < 128 ? $readSize : 128);
3710 # (use original format name in this call -- $formatStr may have been changed to int8u)
3711 $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $tagID, \$tmpVal,
3712 $formatName[$format], $count);
3713 }
3714 # make sure we are handling the 'ifd' format properly
3715 if (($format == 13 or $format == 18) and (not $tagInfo or not $$tagInfo{SubIFD})) {
3716 my $str = sprintf('%s tag 0x%.4x IFD format not handled', $dirName, $tagID);
3717 $exifTool->Warn($str, $inMakerNotes);
3718 }
3719 if (defined $tagInfo) {
3720 $subdir = $$tagInfo{SubDirectory};
3721 # override EXIF format if specified
3722 if ($$tagInfo{Format}) {
3723 $formatStr = $$tagInfo{Format};
3724 my $newNum = $formatNumber{$formatStr};
3725 if ($newNum and $newNum != $format) {
3726 $origFormStr = $formatName[$format] . '[' . $count . ']';
3727 $format = $newNum;
3728 # adjust number of items for new format size
3729 $count = int($size / $formatSize[$format]);
3730 }
3731 }
3732 # verify that offset-type values are integral
3733 if (($$tagInfo{IsOffset} or $$tagInfo{SubIFD}) and not $intFormat{$formatStr}) {
3734 $exifTool->Warn("Wrong format ($formatStr) for $name $$tagInfo{Name}");
3735 next unless $verbose;
3736 $wrongFormat = 1;
3737 }
3738 } else {
3739 next unless $verbose;
3740 }
3741 # convert according to specified format
3742 $val = ReadValue($valueDataPt,$valuePtr,$formatStr,$count,$readSize);
3743
3744 if ($verbose) {
3745 my $tval = $val;
3746 if ($formatStr =~ /^rational64([su])$/ and defined $tval) {
3747 # show numerator/denominator separately
3748 my $f = ReadValue($valueDataPt,$valuePtr,"int32$1",$count*2,$readSize);
3749 $f =~ s/(-?\d+) (-?\d+)/$1\/$2/g;
3750 $tval .= " ($f)";
3751 }
3752 if ($htmlDump) {
3753 my ($tagName, $colName);
3754 if ($tagID == 0x927c and $dirName eq 'ExifIFD') {
3755 $tagName = 'MakerNotes';
3756 } elsif ($tagInfo) {
3757 $tagName = $$tagInfo{Name};
3758 } else {
3759 $tagName = sprintf("Tag 0x%.4x",$tagID);
3760 }
3761 my $dname = sprintf("${name}-%.2d", $index);
3762 # build our tool tip
3763 $size < 0 and $size = $count * $formatSize[$format];
3764 my $fstr = "$formatName[$format]\[$count]";
3765 $fstr = "$origFormStr read as $fstr" if $origFormStr and $origFormStr ne $fstr;
3766 $fstr .= ' <-- WRONG' if $wrongFormat;
3767 my $tip = sprintf("Tag ID: 0x%.4x\n", $tagID) .
3768 "Format: $fstr\nSize: $size bytes\n";
3769 if ($size > 4) {
3770 my $offPt = Get32u($dataPt,$entry+8);
3771 my $actPt = $valuePtr + $valueDataPos + $base - ($$exifTool{EXIF_POS} || 0);
3772 $tip .= sprintf("Value offset: 0x%.4x\n", $offPt);
3773 # highlight tag name (red for bad size)
3774 my $style = ($valueDataLen < 0 or not defined $tval) ? 'V' : 'H';
3775 if ($actPt != $offPt) {
3776 $tip .= sprintf("Actual offset: 0x%.4x\n", $actPt);
3777 my $sign = $actPt < $offPt ? '-' : '';
3778 $tip .= sprintf("Offset base: ${sign}0x%.4x\n", abs($actPt - $offPt));
3779 $style = 'F' if $style eq 'H'; # purple for different offsets
3780 }
3781 $colName = "<span class=$style>$tagName</span>";
3782 $colName .= ' <span class=V>(odd)</span>' if $offPt & 0x01;
3783 } else {
3784 $colName = $tagName;
3785 }
3786 $colName .= ' <span class=V>(err)</span>' if $wrongFormat;
3787 if ($valueDataLen < 0 or not defined $tval) {
3788 $tval = '<bad offset>';
3789 } else {
3790 $tval = substr($tval,0,28) . '[...]' if length($tval) > 32;
3791 if ($formatStr =~ /^(string|undef|binary)/) {
3792 # translate non-printable characters
3793 $tval =~ tr/\x00-\x1f\x7f-\xff/./;
3794 } elsif ($tagInfo and Image::ExifTool::IsInt($tval)) {
3795 if ($$tagInfo{IsOffset} or $$tagInfo{SubIFD}) {
3796 $tval = sprintf('0x%.4x', $tval);
3797 my $actPt = $val + $base - ($$exifTool{EXIF_POS} || 0);
3798 if ($actPt != $val) {
3799 $tval .= sprintf("\nActual offset: 0x%.4x", $actPt);
3800 my $sign = $actPt < $val ? '-' : '';
3801 $tval .= sprintf("\nOffset base: ${sign}0x%.4x", abs($actPt - $val));
3802 }
3803 } elsif ($$tagInfo{PrintHex}) {
3804 $tval = sprintf('0x%x', $tval);
3805 }
3806 }
3807 }
3808 $tip .= "Value: $tval";
3809 $exifTool->HDump($entry+$dataPos+$base, 12, "$dname $colName", $tip, 1);
3810 next if $valueDataLen < 0; # don't process bad pointer entry
3811 if ($size > 4) {
3812 my $exifDumpPos = $valuePtr + $valueDataPos + $base;
3813 my $flag = 0;
3814 if ($subdir) {
3815 if ($$tagInfo{MakerNotes}) {
3816 $flag = 0x04;
3817 } elsif ($$tagInfo{NestedHtmlDump}) {
3818 $flag = $$tagInfo{NestedHtmlDump} == 2 ? 0x10 : 0x04;
3819 }
3820 }
3821 # add value data block (underlining maker notes data)
3822 $exifTool->HDump($exifDumpPos,$size,"$tagName value",'SAME', $flag);
3823 }
3824 } else {
3825 my $fstr = $formatName[$format];
3826 $fstr = "$origFormStr read as $fstr" if $origFormStr;
3827 $exifTool->VerboseInfo($tagID, $tagInfo,
3828 Table => $tagTablePtr,
3829 Index => $index,
3830 Value => $tval,
3831 DataPt => $valueDataPt,
3832 DataPos => $valueDataPos + $base,
3833 Size => $size,
3834 Start => $valuePtr,
3835 Format => $fstr,
3836 Count => $count,
3837 );
3838 }
3839 next if not $tagInfo or $wrongFormat;
3840 }
3841 next unless defined $val;
3842#..............................................................................
3843# Handle SubDirectory tag types
3844#
3845 if ($subdir) {
3846 # don't process empty subdirectories
3847 unless ($size) {
3848 unless ($$tagInfo{MakerNotes} or $inMakerNotes) {
3849 $exifTool->Warn("Empty $$tagInfo{Name} data", 1);
3850 }
3851 next;
3852 }
3853 my (@values, $newTagTable, $dirNum, $newByteOrder, $invalid);
3854 my $tagStr = $$tagInfo{Name};
3855 if ($$subdir{MaxSubdirs}) {
3856 @values = split ' ', $val;
3857 # limit the number of subdirectories we parse
3858 my $over = @values - $$subdir{MaxSubdirs};
3859 if ($over > 0) {
3860 $exifTool->Warn("Ignoring $over $tagStr directories");
3861 pop @values while $over--;
3862 }
3863 $val = shift @values;
3864 }
3865 if ($$subdir{TagTable}) {
3866 $newTagTable = GetTagTable($$subdir{TagTable});
3867 $newTagTable or warn("Unknown tag table $$subdir{TagTable}"), next;
3868 } else {
3869 $newTagTable = $tagTablePtr; # use existing table
3870 }
3871 # loop through all sub-directories specified by this tag
3872 for ($dirNum=0; ; ++$dirNum) {
3873 my $subdirBase = $base;
3874 my $subdirDataPt = $valueDataPt;
3875 my $subdirDataPos = $valueDataPos;
3876 my $subdirDataLen = $valueDataLen;
3877 my $subdirStart = $valuePtr;
3878 if (defined $$subdir{Start}) {
3879 # set local $valuePtr relative to file $base for eval
3880 my $valuePtr = $subdirStart + $subdirDataPos;
3881 #### eval Start ($valuePtr, $val)
3882 my $newStart = eval($$subdir{Start});
3883 unless (Image::ExifTool::IsInt($newStart)) {
3884 $exifTool->Warn("Bad value for $tagStr");
3885 last;
3886 }
3887 # convert back to relative to $subdirDataPt
3888 $newStart -= $subdirDataPos;
3889 # must adjust directory size if start changed
3890 $size -= $newStart - $subdirStart unless $$subdir{BadOffset};
3891 $subdirStart = $newStart;
3892 }
3893 # this is a pain, but some maker notes are always a specific
3894 # byte order, regardless of the byte order of the file
3895 my $oldByteOrder = GetByteOrder();
3896 $newByteOrder = $$subdir{ByteOrder};
3897 if ($newByteOrder) {
3898 if ($newByteOrder =~ /^Little/i) {
3899 $newByteOrder = 'II';
3900 } elsif ($newByteOrder =~ /^Big/i) {
3901 $newByteOrder = 'MM';
3902 } elsif ($$subdir{OffsetPt}) {
3903 undef $newByteOrder;
3904 warn "Can't have variable byte ordering for SubDirectories using OffsetPt";
3905 last;
3906 } elsif ($subdirStart + 2 <= $subdirDataLen) {
3907 # attempt to determine the byte ordering by checking
3908 # at the number of directory entries. This is an int16u
3909 # that should be a reasonable value.
3910 my $num = Get16u($subdirDataPt, $subdirStart);
3911 if ($num & 0xff00 and ($num>>8) > ($num&0xff)) {
3912 # This looks wrong, we shouldn't have this many entries
3913 my %otherOrder = ( II=>'MM', MM=>'II' );
3914 $newByteOrder = $otherOrder{$oldByteOrder};
3915 } else {
3916 $newByteOrder = $oldByteOrder;
3917 }
3918 }
3919 } else {
3920 $newByteOrder = $oldByteOrder;
3921 }
3922 # set base offset if necessary
3923 if ($$subdir{Base}) {
3924 # calculate subdirectory start relative to $base for eval
3925 my $start = $subdirStart + $subdirDataPos;
3926 #### eval Base ($start,$base)
3927 $subdirBase = eval($$subdir{Base}) + $base;
3928 }
3929 # add offset to the start of the directory if necessary
3930 if ($$subdir{OffsetPt}) {
3931 #### eval OffsetPt ($valuePtr)
3932 my $pos = eval $$subdir{OffsetPt};
3933 if ($pos + 4 > $subdirDataLen) {
3934 $exifTool->Warn("Bad $tagStr OffsetPt");
3935 last;
3936 }
3937 SetByteOrder($newByteOrder);
3938 $subdirStart += Get32u($subdirDataPt, $pos);
3939 SetByteOrder($oldByteOrder);
3940 }
3941 if ($subdirStart < 0 or $subdirStart + 2 > $subdirDataLen) {
3942 # convert $subdirStart back to a file offset
3943 if ($raf) {
3944 # reset SubDirectory buffer (we will load it later)
3945 my $buff = '';
3946 $subdirDataPt = \$buff;
3947 $subdirDataLen = $size = length $buff;
3948 } else {
3949 my $msg = "Bad $tagStr SubDirectory start";
3950 if ($verbose > 0) {
3951 if ($subdirStart < 0) {
3952 $msg .= " (directory start $subdirStart is before EXIF start)";
3953 } else {
3954 my $end = $subdirStart + $size;
3955 $msg .= " (directory end is $end but EXIF size is only $subdirDataLen)";
3956 }
3957 }
3958 $exifTool->Warn($msg);
3959 last;
3960 }
3961 }
3962
3963 # must update subdirDataPos if $base changes for this subdirectory
3964 $subdirDataPos += $base - $subdirBase;
3965
3966 # build information hash for new directory
3967 my %subdirInfo = (
3968 Name => $tagStr,
3969 Base => $subdirBase,
3970 DataPt => $subdirDataPt,
3971 DataPos => $subdirDataPos,
3972 DataLen => $subdirDataLen,
3973 DirStart => $subdirStart,
3974 DirLen => $size,
3975 RAF => $raf,
3976 Parent => $dirName,
3977 DirName => $$subdir{DirName},
3978 FixBase => $$subdir{FixBase},
3979 FixOffsets => $$subdir{FixOffsets},
3980 EntryBased => $$subdir{EntryBased},
3981 TagInfo => $tagInfo,
3982 SubIFD => $$tagInfo{SubIFD},
3983 Subdir => $subdir,
3984 );
3985 # (remember: some cameras incorrectly write maker notes in IFD0)
3986 if ($$tagInfo{MakerNotes}) {
3987 # don't parse makernotes if FastScan > 1
3988 my $fast = $exifTool->Options('FastScan');
3989 last if $fast and $fast > 1;
3990 $subdirInfo{MakerNoteAddr} = $valuePtr + $valueDataPos + $base;
3991 $subdirInfo{NoFixBase} = 1 if defined $$subdir{Base};
3992 }
3993 # set directory IFD name from group name of family 1 if it exists,
3994 # unless the tag is extracted as a block in which case group 1 may
3995 # have been set automatically if the block was previously extracted
3996 if ($$tagInfo{Groups} and not $$tagInfo{BlockExtract}) {
3997 $subdirInfo{DirName} = $tagInfo->{Groups}{1};
3998 # number multiple subdirectories
3999 $subdirInfo{DirName} =~ s/\d*$/$dirNum/ if $dirNum;
4000 }
4001 SetByteOrder($newByteOrder); # set byte order for this subdir
4002 # validate the subdirectory if necessary
4003 my $dirData = $subdirDataPt; # set data pointer to be used in eval
4004 #### eval Validate ($val, $dirData, $subdirStart, $size)
4005 my $ok = 0;
4006 if (defined $$subdir{Validate} and not eval $$subdir{Validate}) {
4007 $exifTool->Warn("Invalid $tagStr data");
4008 $invalid = 1;
4009 } else {
4010 # process the subdirectory
4011 $ok = $exifTool->ProcessDirectory(\%subdirInfo, $newTagTable, $$subdir{ProcessProc});
4012 }
4013 # print debugging information if there were errors
4014 if (not $ok and $verbose > 1 and $subdirStart != $valuePtr) {
4015 my $out = $exifTool->Options('TextOut');
4016 printf $out "%s (SubDirectory start = 0x%x)\n", $exifTool->{INDENT}, $subdirStart;
4017 }
4018 SetByteOrder($oldByteOrder); # restore original byte swapping
4019
4020 @values or last;
4021 $val = shift @values; # continue with next subdir
4022 }
4023 my $doMaker = $exifTool->Options('MakerNotes');
4024 next unless $doMaker or $exifTool->{REQ_TAG_LOOKUP}{lc($tagStr)} or
4025 $$tagInfo{BlockExtract};
4026 # extract as a block if specified
4027 if ($$tagInfo{MakerNotes}) {
4028 # save maker note byte order (if it was significant and valid)
4029 if ($$subdir{ByteOrder} and not $invalid) {
4030 $exifTool->{MAKER_NOTE_BYTE_ORDER} =
4031 defined ($exifTool->{UnknownByteOrder}) ?
4032 $exifTool->{UnknownByteOrder} : $newByteOrder;
4033 }
4034 if ($doMaker and $doMaker eq '2') {
4035 # extract maker notes without rebuilding (no fixup information)
4036 delete $exifTool->{MAKER_NOTE_FIXUP};
4037 } elsif (not $$tagInfo{NotIFD}) {
4038 # this is a pain, but we must rebuild EXIF-typemaker notes to
4039 # include all the value data if data was outside the maker notes
4040 my %makerDirInfo = (
4041 Name => $tagStr,
4042 Base => $base,
4043 DataPt => $valueDataPt,
4044 DataPos => $valueDataPos,
4045 DataLen => $valueDataLen,
4046 DirStart => $valuePtr,
4047 DirLen => $size,
4048 RAF => $raf,
4049 Parent => $dirName,
4050 DirName => 'MakerNotes',
4051 FixOffsets => $$subdir{FixOffsets},
4052 TagInfo => $tagInfo,
4053 );
4054 $makerDirInfo{FixBase} = 1 if $$subdir{FixBase};
4055 # rebuild maker notes (creates $exifTool->{MAKER_NOTE_FIXUP})
4056 my $val2 = RebuildMakerNotes($exifTool, $newTagTable, \%makerDirInfo);
4057 if (defined $val2) {
4058 $val = $val2;
4059 } else {
4060 $exifTool->Warn('Error rebuilding maker notes (may be corrupt)');
4061 }
4062 }
4063 } else {
4064 # extract this directory as a block if specified
4065 next unless $$tagInfo{Writable};
4066 }
4067 }
4068 #..............................................................................
4069 # convert to absolute offsets if this tag is an offset
4070 #### eval IsOffset ($val, $exifTool)
4071 if ($$tagInfo{IsOffset} and eval $$tagInfo{IsOffset}) {
4072 my $offsetBase = $$tagInfo{IsOffset} eq '2' ? $firstBase : $base;
4073 $offsetBase += $$exifTool{BASE};
4074 # handle offsets which use a wrong base (Minolta A200)
4075 if ($$tagInfo{WrongBase}) {
4076 my $self = $exifTool;
4077 #### eval WrongBase ($self)
4078 $offsetBase += eval $$tagInfo{WrongBase} || 0;
4079 }
4080 my @vals = split(' ',$val);
4081 foreach $val (@vals) {
4082 $val += $offsetBase;
4083 }
4084 $val = join(' ', @vals);
4085 }
4086 # save the value of this tag
4087 $tagKey = $exifTool->FoundTag($tagInfo, $val);
4088 # set the group 1 name for tags in specified tables
4089 if (defined $tagKey and $$tagTablePtr{SET_GROUP1}) {
4090 $exifTool->SetGroup($tagKey, $dirName);
4091 }
4092 }
4093
4094 # scan for subsequent IFD's if specified
4095 if ($$dirInfo{Multi} and $bytesFromEnd >= 4) {
4096 my $offset = Get32u($dataPt, $dirEnd);
4097 if ($offset) {
4098 my $subdirStart = $offset - $dataPos;
4099 # use same directory information for trailing directory,
4100 # but change the start location (ProcessDirectory will
4101 # test to make sure we don't reprocess the same dir twice)
4102 my %newDirInfo = %$dirInfo;
4103 $newDirInfo{DirStart} = $subdirStart;
4104 # increment IFD number
4105 my $ifdNum = $newDirInfo{DirName} =~ s/(\d+)$// ? $1 : 0;
4106 $newDirInfo{DirName} .= $ifdNum + 1;
4107 # must validate SubIFD1 because the nextIFD pointer is invalid for some RAW formats
4108 if ($newDirInfo{DirName} ne 'SubIFD1' or ValidateIFD(\%newDirInfo)) {
4109 $exifTool->{INDENT} =~ s/..$//; # keep indent the same
4110 my $cur = pop @{$$exifTool{PATH}};
4111 $exifTool->ProcessDirectory(\%newDirInfo, $tagTablePtr) or $success = 0;
4112 push @{$$exifTool{PATH}}, $cur;
4113 } elsif ($verbose or $exifTool->{TIFF_TYPE} eq 'TIFF') {
4114 $exifTool->Warn('Ignored bad IFD linked from SubIFD');
4115 }
4116 }
4117 }
4118 return $success;
4119}
4120
41211; # end
4122
4123__END__
4124
4125=head1 NAME
4126
4127Image::ExifTool::Exif - Read EXIF/TIFF meta information
4128
4129=head1 SYNOPSIS
4130
4131This module is required by Image::ExifTool.
4132
4133=head1 DESCRIPTION
4134
4135This module contains routines required by Image::ExifTool for processing
4136EXIF and TIFF meta information.
4137
4138=head1 AUTHOR
4139
4140Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
4141
4142This library is free software; you can redistribute it and/or modify it
4143under the same terms as Perl itself.
4144
4145=head1 REFERENCES
4146
4147=over 4
4148
4149=item L<http://www.exif.org/Exif2-2.PDF>
4150
4151=item L<http://www.cipa.jp/english/hyoujunka/kikaku/pdf/DC-008-2010_E.pdf>
4152
4153=item L<http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf>
4154
4155=item L<http://partners.adobe.com/public/developer/en/tiff/TIFFPM6.pdf>
4156
4157=item L<http://www.adobe.com/products/dng/pdfs/dng_spec.pdf>
4158
4159=item L<http://www.awaresystems.be/imaging/tiff/tifftags.html>
4160
4161=item L<http://www.remotesensing.org/libtiff/TIFFTechNote2.html>
4162
4163=item L<http://www.exif.org/dcf.PDF>
4164
4165=item L<http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html>
4166
4167=item L<http://www.fine-view.com/jp/lab/doc/ps6ffspecsv2.pdf>
4168
4169=item L<http://www.ozhiker.com/electronics/pjmt/jpeg_info/meta.html>
4170
4171=item L<http://hul.harvard.edu/jhove/tiff-tags.html>
4172
4173=item L<http://www.microsoft.com/whdc/xps/wmphoto.mspx>
4174
4175=item L<http://www.asmail.be/msg0054681802.html>
4176
4177=item L<http://crousseau.free.fr/imgfmt_raw.htm>
4178
4179=item L<http://www.cybercom.net/~dcoffin/dcraw/>
4180
4181=item L<http://www.digitalpreservation.gov/formats/content/tiff_tags.shtml>
4182
4183=item L<http://community.roxen.com/developers/idocs/rfc/rfc3949.html>
4184
4185=item L<http://tools.ietf.org/html/draft-ietf-fax-tiff-fx-extension1-01>
4186
4187=back
4188
4189=head1 ACKNOWLEDGEMENTS
4190
4191Thanks to Jeremy Brown for the 35efl tags, and Matt Madrid for his help with
4192the XP character code conversions.
4193
4194=head1 SEE ALSO
4195
4196L<Image::ExifTool::TagNames/EXIF Tags>,
4197L<Image::ExifTool(3pm)|Image::ExifTool>
4198
4199=cut
Note: See TracBrowser for help on using the repository browser.