source: gs2-extensions/parallel-building/trunk/src/perllib/cpan/Image/ExifTool/MakerNotes.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: 57.1 KB
Line 
1#------------------------------------------------------------------------------
2# File: MakerNotes.pm
3#
4# Description: Read and write EXIF maker notes
5#
6# Revisions: 11/11/2004 - P. Harvey Created
7#------------------------------------------------------------------------------
8
9package Image::ExifTool::MakerNotes;
10
11use strict;
12use vars qw($VERSION);
13use Image::ExifTool qw(:DataAccess);
14use Image::ExifTool::Exif;
15
16sub ProcessUnknown($$$);
17sub ProcessUnknownOrPreview($$$);
18sub ProcessCanon($$$);
19sub ProcessGE2($$$);
20sub WriteUnknownOrPreview($$$);
21sub FixLeicaBase($$;$);
22
23$VERSION = '1.66';
24
25my $debug; # set to 1 to enable debugging code
26
27# conditional list of maker notes
28# Notes:
29# - This is NOT a normal tag table!
30# - All byte orders are now specified because we can now
31# write maker notes into a file with different byte ordering!
32# - Put these in alphabetical order to make TagNames documentation nicer.
33@Image::ExifTool::MakerNotes::Main = (
34 # decide which MakerNotes to use (based on camera make/model)
35 {
36 Name => 'MakerNoteCanon',
37 # (starts with an IFD)
38 Condition => '$$self{Make} =~ /^Canon/',
39 SubDirectory => {
40 TagTable => 'Image::ExifTool::Canon::Main',
41 ProcessProc => \&ProcessCanon,
42 ByteOrder => 'Unknown',
43 },
44 },
45 {
46 Name => 'MakerNoteCasio',
47 # do negative lookahead assertion just to get tags
48 # in a nice order for documentation
49 # (starts with an IFD)
50 Condition => '$$self{Make}=~/^CASIO/ and $$valPt!~/^(QVC|DCI)\0/',
51 SubDirectory => {
52 TagTable => 'Image::ExifTool::Casio::Main',
53 ByteOrder => 'Unknown',
54 },
55 },
56 {
57 Name => 'MakerNoteCasio2',
58 # (starts with "QVC\0" [Casio] or "DCI\0" [Concord])
59 # (also found in AVI and MOV videos)
60 Condition => '$$valPt =~ /^(QVC|DCI)\0/',
61 SubDirectory => {
62 TagTable => 'Image::ExifTool::Casio::Type2',
63 Start => '$valuePtr + 6',
64 ByteOrder => 'Unknown',
65 FixBase => 1, # necessary for AVI and MOV videos
66 },
67 },
68 {
69 # The Fuji maker notes use a structure similar to a self-contained
70 # TIFF file, but with "FUJIFILM" instead of the standard TIFF header
71 Name => 'MakerNoteFujiFilm',
72 # (starts with "FUJIFILM" -- also used by some Leica, Minolta and Sharp models)
73 # (GE FujiFilm models start with "GENERALE")
74 Condition => '$$valPt =~ /^(FUJIFILM|GENERALE)/',
75 SubDirectory => {
76 TagTable => 'Image::ExifTool::FujiFilm::Main',
77 # there is an 8-byte maker tag (FUJIFILM) we must skip over
78 OffsetPt => '$valuePtr+8',
79 # the pointers are relative to the subdirectory start
80 # (before adding the offsetPt) - PH
81 Base => '$start',
82 ByteOrder => 'LittleEndian',
83 },
84 },
85 {
86 Name => 'MakerNoteGE',
87 Condition => '$$valPt =~ /^GE(\0\0|NIC\0)/',
88 SubDirectory => {
89 TagTable => 'Image::ExifTool::GE::Main',
90 Start => '$valuePtr + 18',
91 FixBase => 1,
92 AutoFix => 1,
93 ByteOrder => 'Unknown',
94 },
95 },
96 {
97 Name => 'MakerNoteGE2',
98 Condition => '$$valPt =~ /^GE\x0c\0\0\0\x16\0\0\0/',
99 # Note: we will get a "Maker notes could not be parsed" warning when writing
100 # these maker notes because they aren't currently supported for writing
101 SubDirectory => {
102 TagTable => 'Image::ExifTool::FujiFilm::Main',
103 ProcessProc => \&ProcessGE2,
104 Start => '$valuePtr + 12',
105 Base => '$start - 6',
106 ByteOrder => 'LittleEndian',
107 # hard patch for crazy offsets
108 FixOffsets => '$valuePtr -= 210 if $tagID >= 0x1303',
109 },
110 },
111 # (the GE X5 has really messed up EXIF-like maker notes starting with
112 # "GENIC\x0c\0" --> currently not decoded)
113 {
114 Name => 'MakerNoteHP', # PhotoSmart 720 (also Vivitar 3705, 3705B and 3715)
115 Condition => '$$valPt =~ /^(Hewlett-Packard|Vivitar)/',
116 SubDirectory => {
117 TagTable => 'Image::ExifTool::HP::Main',
118 ProcessProc => \&ProcessUnknown,
119 ByteOrder => 'Unknown',
120 },
121 },
122 {
123 Name => 'MakerNoteHP2', # PhotoSmart E427
124 # (this type of maker note also used by BenQ, Mustek, Sanyo, Traveler and Vivitar)
125 Condition => '$$valPt =~ /^610[\0-\4]/',
126 NotIFD => 1,
127 SubDirectory => {
128 TagTable => 'Image::ExifTool::HP::Type2',
129 Start => '$valuePtr',
130 ByteOrder => 'LittleEndian',
131 },
132 },
133 {
134 Name => 'MakerNoteHP4', # PhotoSmart M627
135 Condition => '$$valPt =~ /^IIII\x04\0/',
136 NotIFD => 1,
137 SubDirectory => {
138 TagTable => 'Image::ExifTool::HP::Type4',
139 Start => '$valuePtr',
140 ByteOrder => 'LittleEndian',
141 },
142 },
143 {
144 Name => 'MakerNoteHP6', # PhotoSmart M425, M525 and M527
145 Condition => '$$valPt =~ /^IIII\x06\0/',
146 NotIFD => 1,
147 SubDirectory => {
148 TagTable => 'Image::ExifTool::HP::Type6',
149 Start => '$valuePtr',
150 ByteOrder => 'LittleEndian',
151 },
152 },
153 {
154 Name => 'MakerNoteISL', # (used in Samsung GX20 samples)
155 Condition => '$$valPt =~ /^ISLMAKERNOTE000\0/',
156 # this maker notes starts with a TIFF-like header at offset 0x10
157 SubDirectory => {
158 TagTable => 'Image::ExifTool::Unknown::Main',
159 Start => '$valuePtr + 24',
160 Base => '$start - 8',
161 ByteOrder => 'Unknown',
162 },
163 },
164 {
165 Name => 'MakerNoteJVC',
166 Condition => '$$valPt=~/^JVC /',
167 SubDirectory => {
168 TagTable => 'Image::ExifTool::JVC::Main',
169 Start => '$valuePtr + 4',
170 ByteOrder => 'Unknown',
171 },
172 },
173 {
174 Name => 'MakerNoteJVCText',
175 Condition => '$$self{Make}=~/^(JVC|Victor)/ and $$valPt=~/^VER:/',
176 NotIFD => 1,
177 SubDirectory => {
178 TagTable => 'Image::ExifTool::JVC::Text',
179 },
180 },
181 {
182 Name => 'MakerNoteKodak1a',
183 Condition => '$$self{Make}=~/^EASTMAN KODAK/ and $$valPt=~/^KDK INFO/',
184 NotIFD => 1,
185 SubDirectory => {
186 TagTable => 'Image::ExifTool::Kodak::Main',
187 Start => '$valuePtr + 8',
188 ByteOrder => 'BigEndian',
189 },
190 },
191 {
192 Name => 'MakerNoteKodak1b',
193 Condition => '$$self{Make}=~/^EASTMAN KODAK/ and $$valPt=~/^KDK/',
194 NotIFD => 1,
195 SubDirectory => {
196 TagTable => 'Image::ExifTool::Kodak::Main',
197 Start => '$valuePtr + 8',
198 ByteOrder => 'LittleEndian',
199 },
200 },
201 {
202 # used by various Kodak, HP, Pentax and Minolta models
203 Name => 'MakerNoteKodak2',
204 Condition => q{
205 $$valPt =~ /^.{8}Eastman Kodak/s or
206 $$valPt =~ /^\x01\0[\0\x01]\0\0\0\x04\0[a-zA-Z]{4}/
207 },
208 NotIFD => 1,
209 SubDirectory => {
210 TagTable => 'Image::ExifTool::Kodak::Type2',
211 ByteOrder => 'BigEndian',
212 },
213 },
214 {
215 # not much to key on here, but we know the
216 # upper byte of the year should be 0x07:
217 Name => 'MakerNoteKodak3',
218 Condition => q{
219 $$self{Make} =~ /^EASTMAN KODAK/ and
220 $$valPt =~ /^(?!MM|II).{12}\x07/s and
221 $$valPt !~ /^(MM|II|AOC)/
222 },
223 NotIFD => 1,
224 SubDirectory => {
225 TagTable => 'Image::ExifTool::Kodak::Type3',
226 ByteOrder => 'BigEndian',
227 },
228 },
229 {
230 Name => 'MakerNoteKodak4',
231 Condition => q{
232 $$self{Make} =~ /^Eastman Kodak/ and
233 $$valPt =~ /^.{41}JPG/s and
234 $$valPt !~ /^(MM|II|AOC)/
235 },
236 NotIFD => 1,
237 SubDirectory => {
238 TagTable => 'Image::ExifTool::Kodak::Type4',
239 ByteOrder => 'BigEndian',
240 },
241 },
242 {
243 Name => 'MakerNoteKodak5',
244 Condition => q{
245 $$self{Make}=~/^EASTMAN KODAK/ and
246 ($$self{Model}=~/CX(4200|4230|4300|4310|6200|6230)/ or
247 # try to pick up similar models we haven't tested yet
248 $$valPt=~/^\0(\x1a\x18|\x3a\x08|\x59\xf8|\x14\x80)\0/)
249 },
250 NotIFD => 1,
251 SubDirectory => {
252 TagTable => 'Image::ExifTool::Kodak::Type5',
253 ByteOrder => 'BigEndian',
254 },
255 },
256 {
257 Name => 'MakerNoteKodak6a',
258 Condition => q{
259 $$self{Make}=~/^EASTMAN KODAK/ and
260 $$self{Model}=~/DX3215/
261 },
262 NotIFD => 1,
263 SubDirectory => {
264 TagTable => 'Image::ExifTool::Kodak::Type6',
265 ByteOrder => 'BigEndian',
266 },
267 },
268 {
269 Name => 'MakerNoteKodak6b',
270 Condition => q{
271 $$self{Make}=~/^EASTMAN KODAK/ and
272 $$self{Model}=~/DX3700/
273 },
274 NotIFD => 1,
275 SubDirectory => {
276 TagTable => 'Image::ExifTool::Kodak::Type6',
277 ByteOrder => 'LittleEndian',
278 },
279 },
280 {
281 Name => 'MakerNoteKodak7',
282 # look for something that looks like a serial number
283 # (confirmed serial numbers have the format KXXXX########, but we also
284 # accept other strings from sample images that may be serial numbers)
285 Condition => q{
286 $$self{Make}=~/Kodak/i and
287 $$valPt =~ /^[CK][A-Z\d]{3} ?[A-Z\d]{1,2}\d{2}[A-Z\d]\d{4}[ \0]/
288 },
289 NotIFD => 1,
290 SubDirectory => {
291 TagTable => 'Image::ExifTool::Kodak::Type7',
292 ByteOrder => 'LittleEndian',
293 },
294 },
295 {
296 Name => 'MakerNoteKodak8a',
297 # IFD-format maker notes: look for reasonable number of
298 # entries and check format and count of first IFD entry
299 Condition => q{
300 $$self{Make}=~/Kodak/i and
301 ($$valPt =~ /^\0[\x02-\x7f]..\0[\x01-\x0c]\0\0/s or
302 $$valPt =~ /^[\x02-\x7f]\0..[\x01-\x0c]\0..\0\0/s)
303 },
304 SubDirectory => {
305 TagTable => 'Image::ExifTool::Kodak::Type8',
306 ProcessProc => \&ProcessUnknown,
307 ByteOrder => 'Unknown',
308 },
309 },
310 {
311 Name => 'MakerNoteKodak8b',
312 # TIFF-format maker notes
313 Condition => q{
314 $$self{Make}=~/Kodak/i and
315 $$valPt =~ /^(MM\0\x2a\0\0\0\x08|II\x2a\0\x08\0\0\0)/
316 },
317 SubDirectory => {
318 TagTable => 'Image::ExifTool::Kodak::Type8',
319 ProcessProc => \&ProcessUnknown,
320 ByteOrder => 'Unknown',
321 Start => '$valuePtr + 8',
322 Base => '$start - 8',
323 },
324 },
325 {
326 Name => 'MakerNoteKodak9',
327 # test header and Kodak:DateTimeOriginal
328 Condition => '$$valPt =~ m{^IIII[\x02\x03]\0.{14}\d{4}/\d{2}/\d{2} }s',
329 NotIFD => 1,
330 SubDirectory => {
331 TagTable => 'Image::ExifTool::Kodak::Type9',
332 ByteOrder => 'LittleEndian',
333 },
334 },
335 {
336 Name => 'MakerNoteKodak10',
337 # yet another type of Kodak IFD-format maker notes:
338 # this type begins with a byte order indicator,
339 # followed immediately by the IFD
340 Condition => q{
341 $$self{Make}=~/Kodak/i and
342 $$valPt =~ /^(MM\0[\x02-\x7f]|II[\x02-\x7f]\0)/
343 },
344 SubDirectory => {
345 TagTable => 'Image::ExifTool::Kodak::Type10',
346 ProcessProc => \&ProcessUnknown,
347 ByteOrder => 'Unknown',
348 Start => '$valuePtr + 2',
349 },
350 },
351 {
352 Name => 'MakerNoteKodakUnknown',
353 Condition => '$$self{Make}=~/Kodak/i and $$valPt!~/^AOC\0/',
354 NotIFD => 1,
355 SubDirectory => {
356 TagTable => 'Image::ExifTool::Kodak::Unknown',
357 ByteOrder => 'BigEndian',
358 },
359 },
360 {
361 Name => 'MakerNoteKyocera',
362 # (starts with "KYOCERA")
363 Condition => '$$valPt =~ /^KYOCERA/',
364 SubDirectory => {
365 TagTable => 'Image::ExifTool::Unknown::Main',
366 Start => '$valuePtr + 22',
367 Base => '$start + 2',
368 EntryBased => 1,
369 ByteOrder => 'Unknown',
370 },
371 },
372 {
373 Name => 'MakerNoteMinolta',
374 Condition => q{
375 $$self{Make}=~/^(Konica Minolta|Minolta)/i and
376 $$valPt !~ /^(MINOL|CAMER|MLY0|KC|\+M\+M|\xd7)/
377 },
378 SubDirectory => {
379 TagTable => 'Image::ExifTool::Minolta::Main',
380 ByteOrder => 'Unknown',
381 },
382 },
383 {
384 # the DiMAGE E323 (MINOL) and E500 (CAMER), and some models
385 # of Mustek, Pentax, Ricoh and Vivitar (CAMER).
386 Name => 'MakerNoteMinolta2',
387 Condition => '$$valPt =~ /^(MINOL|CAMER)\0/ and $$self{OlympusCAMER} = 1',
388 SubDirectory => {
389 # these models use Olympus tags in the range 0x200-0x221 plus 0xf00
390 TagTable => 'Image::ExifTool::Olympus::Main',
391 Start => '$valuePtr + 8',
392 ByteOrder => 'Unknown',
393 },
394 },
395 {
396 # /^MLY0/ - DiMAGE G400, G500, G530, G600
397 # /^KC/ - Revio KD-420Z, DiMAGE E203
398 # /^+M+M/ - DiMAGE E201
399 # /^\xd7/ - DiMAGE RD3000
400 Name => 'MakerNoteMinolta3',
401 Condition => '$$self{Make} =~ /^(Konica Minolta|Minolta)/i',
402 Binary => 1,
403 Notes => 'not EXIF-based',
404 },
405 {
406 # this maker notes starts with a standard TIFF header at offset 0x0a
407 Name => 'MakerNoteNikon',
408 Condition => '$$self{Make}=~/^NIKON/i and $$valPt=~/^Nikon\x00\x02/',
409 SubDirectory => {
410 TagTable => 'Image::ExifTool::Nikon::Main',
411 Start => '$valuePtr + 18',
412 Base => '$start - 8',
413 ByteOrder => 'Unknown',
414 },
415 },
416 {
417 # older Nikon maker notes
418 Name => 'MakerNoteNikon2',
419 Condition => '$$self{Make}=~/^NIKON/ and $$valPt=~/^Nikon\x00\x01/',
420 SubDirectory => {
421 TagTable => 'Image::ExifTool::Nikon::Type2',
422 Start => '$valuePtr + 8',
423 ByteOrder => 'LittleEndian',
424 },
425 },
426 {
427 # headerless Nikon maker notes
428 Name => 'MakerNoteNikon3',
429 Condition => '$$self{Make}=~/^NIKON/i',
430 SubDirectory => {
431 TagTable => 'Image::ExifTool::Nikon::Main',
432 ByteOrder => 'Unknown', # most are little-endian, but D1 is big
433 },
434 },
435 {
436 Name => 'MakerNoteOlympus',
437 # (if Make is 'SEIKO EPSON CORP.', starts with "EPSON\0")
438 # (if Make is 'OLYMPUS OPTICAL CO.,LTD' or 'OLYMPUS CORPORATION',
439 # starts with "OLYMP\0")
440 Condition => '$$valPt =~ /^(OLYMP|EPSON)\0/',
441 SubDirectory => {
442 TagTable => 'Image::ExifTool::Olympus::Main',
443 Start => '$valuePtr + 8',
444 ByteOrder => 'Unknown',
445 },
446 },
447 {
448 Name => 'MakerNoteOlympus2',
449 # new Olympus maker notes start with "OLYMPUS\0"
450 Condition => '$$valPt =~ /^OLYMPUS\0/',
451 SubDirectory => {
452 TagTable => 'Image::ExifTool::Olympus::Main',
453 Start => '$valuePtr + 12',
454 Base => '$start - 12',
455 ByteOrder => 'Unknown',
456 },
457 },
458 {
459 Name => 'MakerNoteLeica',
460 # (starts with "LEICA\0\0\0")
461 Condition => '$$self{Make} eq "LEICA"',
462 SubDirectory => {
463 # many Leica models use the same format as Panasonic
464 TagTable => 'Image::ExifTool::Panasonic::Main',
465 Start => '$valuePtr + 8',
466 ByteOrder => 'Unknown',
467 },
468 },
469 {
470 Name => 'MakerNoteLeica2', # used by the M8
471 # (starts with "LEICA\0\0\0")
472 Condition => '$$self{Make} =~ /^Leica Camera AG/ and $$valPt =~ /^LEICA\0\0\0/',
473 SubDirectory => {
474 TagTable => 'Image::ExifTool::Panasonic::Leica2',
475 # (the offset base is different in JPEG and DNG images, but we
476 # can copy makernotes from one to the other, so we need special
477 # logic to decide which base to apply)
478 ProcessProc => \&FixLeicaBase,
479 Start => '$valuePtr + 8',
480 Base => '$start', # (- 8 for DNG images!)
481 ByteOrder => 'Unknown',
482 },
483 },
484 {
485 Name => 'MakerNoteLeica3', # used by the R8 and R9
486 # (starts with IFD)
487 Condition => '$$self{Make} =~ /^Leica Camera AG/ and $$valPt !~ /^LEICA/ and $$self{Model} ne "S2"',
488 SubDirectory => {
489 TagTable => 'Image::ExifTool::Panasonic::Leica3',
490 Start => '$valuePtr',
491 ByteOrder => 'Unknown',
492 },
493 },
494 {
495 Name => 'MakerNoteLeica4', # used by the M9
496 # (M9 starts with "LEICA0\x03\0")
497 Condition => '$$self{Make} =~ /^Leica Camera AG/ and $$valPt =~ /^LEICA0/',
498 SubDirectory => {
499 TagTable => 'Image::ExifTool::Panasonic::Leica4',
500 Start => '$valuePtr + 8',
501 Base => '$start - 8', # (yay! Leica fixed the M8 problem)
502 ByteOrder => 'Unknown',
503 },
504 },
505 {
506 Name => 'MakerNoteLeica5', # used by the X1
507 # (X1 starts with "LEICA\0\x01\0", Make is "LEICA CAMERA AG")
508 Condition => '$$valPt =~ /^LEICA\0\x01\0/',
509 SubDirectory => {
510 TagTable => 'Image::ExifTool::Panasonic::Leica5',
511 Start => '$valuePtr + 8',
512 Base => '$start - 8',
513 ByteOrder => 'Unknown',
514 },
515 },
516 {
517 Name => 'MakerNoteLeica6', # used by the S2 (CAUTION: this tag name is special cased in the code)
518 # (S2 starts with "LEICA\0\x02\xff", Make is "LEICA CAMERA AG",
519 # but maker notes aren't loaded at the time this is tested)
520 Condition => '$$self{Model} eq "S2"',
521 DataTag => 'LeicaTrailer', # (generates fixup name for this tag)
522 SubDirectory => {
523 TagTable => 'Image::ExifTool::Panasonic::Leica6',
524 Start => '$valuePtr + 8',
525 ByteOrder => 'Unknown',
526 # NOTE: Leica uses absolute file offsets when this maker note is stored
527 # as a JPEG trailer -- this case is handled by ProcessLeicaTrailer in
528 # Panasonic.pm, and any "Base" defined here is ignored for this case.
529 # ExifTool may also create S2 maker notes inside the APP1 segment when
530 # copying from other files, and for this the normal EXIF offsets are used,
531 # Base should not be defined!
532 },
533 },
534 {
535 Name => 'MakerNotePanasonic',
536 # (starts with "Panasonic\0")
537 Condition => '$$valPt=~/^Panasonic/',
538 SubDirectory => {
539 TagTable => 'Image::ExifTool::Panasonic::Main',
540 Start => '$valuePtr + 12',
541 ByteOrder => 'Unknown',
542 },
543 },
544 {
545 Name => 'MakerNotePanasonic2',
546 # (starts with "Panasonic\0")
547 Condition => '$$self{Make}=~/^Panasonic/ and $$valPt=~/^MKE/',
548 SubDirectory => {
549 TagTable => 'Image::ExifTool::Panasonic::Type2',
550 ByteOrder => 'LittleEndian',
551 },
552 },
553 {
554 Name => 'MakerNotePentax',
555 # (starts with "AOC\0", but so does MakerNotePentax3)
556 # (also used by some Samsung models)
557 Condition => q{
558 $$valPt=~/^AOC\0/ and
559 $$self{Model} !~ /^PENTAX Optio ?[34]30RS\s*$/
560 },
561 SubDirectory => {
562 TagTable => 'Image::ExifTool::Pentax::Main',
563 # process as Unknown maker notes because the start offset and
564 # byte ordering are so variable
565 ProcessProc => \&ProcessUnknown,
566 # offsets can be totally whacky for Pentax maker notes,
567 # so attempt to fix the offset base if possible
568 FixBase => 1,
569 ByteOrder => 'Unknown',
570 },
571 },
572 {
573 Name => 'MakerNotePentax2',
574 # (starts with an IFD)
575 # Casio-like maker notes used only by the Optio 330 and 430
576 Condition => '$$self{Make}=~/^Asahi/ and $$valPt!~/^AOC\0/',
577 SubDirectory => {
578 TagTable => 'Image::ExifTool::Pentax::Type2',
579 ProcessProc => \&ProcessUnknown,
580 FixBase => 1,
581 ByteOrder => 'Unknown',
582 },
583 },
584 {
585 Name => 'MakerNotePentax3',
586 # (starts with "AOC\0", like the more common Pentax maker notes)
587 # Casio maker notes used only by the Optio 330RS and 430RS
588 Condition => '$$self{Make}=~/^Asahi/',
589 SubDirectory => {
590 TagTable => 'Image::ExifTool::Casio::Type2',
591 ProcessProc => \&ProcessUnknown,
592 FixBase => 1,
593 ByteOrder => 'Unknown',
594 },
595 },
596 {
597 Name => 'MakerNotePentax4',
598 # (starts with 3 or 4 digits)
599 # HP2-like text-based maker notes used by Optio E20
600 Condition => '$$self{Make}=~/^PENTAX/ and $$valPt=~/^\d{3}/',
601 NotIFD => 1,
602 SubDirectory => {
603 TagTable => 'Image::ExifTool::Pentax::Type4',
604 Start => '$valuePtr',
605 ByteOrder => 'LittleEndian',
606 },
607 },
608 {
609 Name => 'MakerNotePentax5',
610 # (starts with "PENTAX \0")
611 Condition => '$$valPt=~/^PENTAX \0/',
612 SubDirectory => {
613 TagTable => 'Image::ExifTool::Pentax::Main',
614 Start => '$valuePtr + 10',
615 Base => '$start - 10',
616 ByteOrder => 'Unknown',
617 },
618 },
619 {
620 Name => 'MakerNotePhaseOne',
621 # Starts with: 'IIIITwaR' or 'IIIICwaR' (have seen both written by P25)
622 # (have also seen code which expects 'MMMMRawT')
623 Condition => q{
624 return undef unless $$valPt =~ /^(IIII.waR|MMMMRaw.)/s;
625 $self->OverrideFileType($$self{TIFF_TYPE} = 'IIQ') if $count > 1000000;
626 return 1;
627 },
628 NotIFD => 1,
629 Binary => 1,
630 PutFirst => 1, # place immediately after TIFF header
631 Notes => 'the raw image data in PhaseOne IIQ images',
632 },
633 {
634 Name => 'MakerNoteReconyx',
635 Condition => '$$valPt =~ /^\x01\xf1[\x02\x03]\x00/',
636 SubDirectory => {
637 TagTable => 'Image::ExifTool::Reconyx::Main',
638 ByteOrder => 'Little-endian',
639 },
640 },
641 {
642 Name => 'MakerNoteRicoh',
643 # (my test R50 image starts with " \x02\x01" - PH)
644 Condition => '$$self{Make}=~/^RICOH/ and $$valPt=~/^(Ricoh| )/i',
645 SubDirectory => {
646 TagTable => 'Image::ExifTool::Ricoh::Main',
647 Start => '$valuePtr + 8',
648 ByteOrder => 'Unknown',
649 },
650 },
651 {
652 Name => 'MakerNoteRicohText',
653 Condition => '$$self{Make}=~/^RICOH/',
654 NotIFD => 1,
655 SubDirectory => {
656 TagTable => 'Image::ExifTool::Ricoh::Text',
657 ByteOrder => 'Unknown',
658 },
659 },
660 {
661 Name => 'MakerNoteSamsung1a',
662 # Samsung STMN maker notes WITHOUT PreviewImage
663 Condition => '$$valPt =~ /^STMN\d{3}.\0{4}/s',
664 Binary => 1,
665 Notes => 'Samsung "STMN" maker notes without PreviewImage',
666 },
667 {
668 Name => 'MakerNoteSamsung1b',
669 # Samsung STMN maker notes WITH PreviewImage
670 Condition => '$$valPt =~ /^STMN\d{3}/',
671 SubDirectory => {
672 TagTable => 'Image::ExifTool::Samsung::Type1',
673 },
674 },
675 {
676 Name => 'MakerNoteSamsung2',
677 # Samsung EXIF-format maker notes
678 Condition => q{
679 $$self{Make} eq 'SAMSUNG' and ($$self{TIFF_TYPE} eq 'SRW' or
680 $$valPt=~/^(\0.\0\x01\0\x07\0{3}\x04|.\0\x01\0\x07\0\x04\0{3})0100/s)
681 },
682 SubDirectory => {
683 TagTable => 'Image::ExifTool::Samsung::Type2',
684 # Samsung is very inconsistent here, and uses absolute offsets for some
685 # models and relative offsets for others, so process as Unknown
686 ProcessProc => \&ProcessUnknown,
687 FixBase => 1,
688 ByteOrder => 'Unknown',
689 },
690 },
691 {
692 Name => 'MakerNoteSanyo',
693 # (starts with "SANYO\0")
694 Condition => '$$self{Make}=~/^SANYO/ and $$self{Model}!~/^(C4|J\d|S\d)\b/',
695 SubDirectory => {
696 TagTable => 'Image::ExifTool::Sanyo::Main',
697 Validate => '$val =~ /^SANYO/',
698 Start => '$valuePtr + 8',
699 ByteOrder => 'Unknown',
700 },
701 },
702 {
703 Name => 'MakerNoteSanyoC4',
704 # The C4 offsets are wrong by 12, so they must be fixed
705 Condition => '$$self{Make}=~/^SANYO/ and $$self{Model}=~/^C4\b/',
706 SubDirectory => {
707 TagTable => 'Image::ExifTool::Sanyo::Main',
708 Validate => '$val =~ /^SANYO/',
709 Start => '$valuePtr + 8',
710 FixBase => 1,
711 ByteOrder => 'Unknown',
712 },
713 },
714 {
715 Name => 'MakerNoteSanyoPatch',
716 # The J1, J2, J4, S1, S3 and S4 offsets are completely screwy
717 Condition => '$$self{Make}=~/^SANYO/',
718 SubDirectory => {
719 TagTable => 'Image::ExifTool::Sanyo::Main',
720 Validate => '$val =~ /^SANYO/',
721 Start => '$valuePtr + 8',
722 ByteOrder => 'Unknown',
723 FixOffsets => 'Image::ExifTool::Sanyo::FixOffsets($valuePtr, $valEnd, $size, $tagID, $wFlag)',
724 },
725 },
726 {
727 Name => 'MakerNoteSigma',
728 # (starts with "SIGMA\0")
729 Condition => '$$self{Make}=~/^(SIGMA|FOVEON)/',
730 SubDirectory => {
731 TagTable => 'Image::ExifTool::Sigma::Main',
732 Validate => '$val =~ /^(SIGMA|FOVEON)/',
733 Start => '$valuePtr + 10',
734 ByteOrder => 'Unknown',
735 },
736 },
737 {
738 Name => 'MakerNoteSony',
739 # (starts with "SONY DSC \0" or "SONY CAM \0")
740 Condition => '$$self{Make}=~/^SONY/ and $$valPt=~/^SONY (DSC|CAM)/',
741 SubDirectory => {
742 TagTable => 'Image::ExifTool::Sony::Main',
743 Start => '$valuePtr + 12',
744 ByteOrder => 'Unknown',
745 },
746 },
747 {
748 Name => 'MakerNoteSony2',
749 # (starts with "SONY PI\0" -- DSC-S650/S700/S750)
750 Condition => '$$self{Make}=~/^SONY/ and $$valPt=~/^SONY PI\0/ and $$self{OlympusCAMER}=1',
751 SubDirectory => {
752 TagTable => 'Image::ExifTool::Olympus::Main',
753 Start => '$valuePtr + 12',
754 ByteOrder => 'Unknown',
755 },
756 },
757 {
758 Name => 'MakerNoteSony3',
759 # (starts with "PREMI\0" -- DSC-S45/S500)
760 Condition => '$$self{Make}=~/^SONY/ and $$valPt=~/^(PREMI)\0/ and $$self{OlympusCAMER}=1',
761 SubDirectory => {
762 TagTable => 'Image::ExifTool::Olympus::Main',
763 Start => '$valuePtr + 8',
764 ByteOrder => 'Unknown',
765 },
766 },
767 {
768 Name => 'MakerNoteSony4', # used in SR2 and ARW images
769 Condition => '$$self{Make}=~/^SONY/ and $$valPt!~/^\x01\x00/',
770 SubDirectory => {
771 TagTable => 'Image::ExifTool::Sony::Main',
772 Start => '$valuePtr',
773 ByteOrder => 'Unknown',
774 },
775 },
776 {
777 Name => 'MakerNoteSonyEricsson',
778 Condition => '$$valPt =~ /^SEMC MS\0/',
779 SubDirectory => {
780 TagTable => 'Image::ExifTool::Sony::Ericsson',
781 Start => '$valuePtr + 20',
782 Base => '$start - 8',
783 ByteOrder => 'Unknown',
784 },
785 },
786 {
787 Name => 'MakerNoteSonySRF',
788 Condition => '$$self{Make}=~/^SONY/',
789 SubDirectory => {
790 TagTable => 'Image::ExifTool::Sony::SRF',
791 Start => '$valuePtr',
792 ByteOrder => 'Unknown',
793 },
794 },
795 {
796 Name => 'MakerNoteUnknownText',
797 Condition => '$$valPt =~ /^[\x09\x0d\x0a\x20-\x7e]+\0*$/',
798 Notes => 'unknown text-based maker notes',
799 # show as binary if it is too long
800 ValueConv => 'length($val) > 64 ? \$val : $val',
801 ValueConvInv => '$val',
802 },
803 {
804 Name => 'MakerNoteUnknown',
805 PossiblePreview => 1,
806 SubDirectory => {
807 TagTable => 'Image::ExifTool::Unknown::Main',
808 ProcessProc => \&ProcessUnknownOrPreview,
809 WriteProc => \&WriteUnknownOrPreview,
810 ByteOrder => 'Unknown',
811 FixBase => 2,
812 },
813 },
814);
815
816# insert writable properties so we can write our maker notes
817my $tagInfo;
818foreach $tagInfo (@Image::ExifTool::MakerNotes::Main) {
819 $$tagInfo{Writable} = 'undef';
820 $$tagInfo{WriteGroup} = 'ExifIFD';
821 $$tagInfo{Groups} = { 1 => 'MakerNotes' };
822 next unless $$tagInfo{SubDirectory};
823 # make all SubDirectory tags block-writable
824 $$tagInfo{Binary} = 1,
825 $$tagInfo{MakerNotes} = 1;
826}
827
828#------------------------------------------------------------------------------
829# Get normal offset of value data from end of maker note IFD
830# Inputs: 0) ExifTool object reference
831# Returns: Array: 0) relative flag (undef for no change)
832# 1) normal offset from end of IFD to first value (empty if unknown)
833# 2-N) other possible offsets used by some models
834# Notes: Directory size should be validated before calling this routine
835sub GetMakerNoteOffset($)
836{
837 my $exifTool = shift;
838 # figure out where we expect the value data based on camera type
839 my $make = $exifTool->{Make};
840 my $model = $exifTool->{Model};
841 my ($relative, @offsets);
842
843 # normally value data starts 4 bytes after end of directory, so this is the default.
844 # offsets of 0 and 4 are always allowed even if not specified,
845 # but the first offset specified is the one used when writing
846 if ($make =~ /^Canon/) {
847 push @offsets, ($model =~ /\b(20D|350D|REBEL XT|Kiss Digital N)\b/) ? 6 : 4;
848 # some Canon models (FV-M30, Optura50, Optura60) leave 24 unused bytes
849 # at the end of the IFD (2 spare IFD entries?)
850 push @offsets, 28 if $model =~ /\b(FV\b|OPTURA)/;
851 # some Canon PowerShot models leave 12 unused bytes
852 push @offsets, 16 if $model =~ /(PowerShot|IXUS|IXY)/;
853 } elsif ($make =~ /^CASIO/) {
854 # Casio AVI and MOV images use no padding, and their JPEG's use 4,
855 # except some models like the EX-S770,Z65,Z70,Z75 and Z700 which use 16,
856 # and the EX-Z35 which uses 2 (grrrr...)
857 push @offsets, $$exifTool{FILE_TYPE} =~ /^(RIFF|MOV)$/ ? 0 : (4, 16, 2);
858 } elsif ($make =~ /^(General Imaging Co.|GEDSC IMAGING CORP.)/i) {
859 push @offsets, 0;
860 } elsif ($make =~ /^KYOCERA/) {
861 push @offsets, 12;
862 } elsif ($make =~ /^Leica Camera AG/) {
863 if ($model eq 'S2') {
864 # lots of empty space before first value in S2 images
865 push @offsets, 4, ($$exifTool{FILE_TYPE} eq 'JPEG' ? 286 : 274);
866 } elsif ($model =~ /^(R8|R9|M8)\b/) {
867 push @offsets, 6;
868 } else {
869 push @offsets, 4;
870 }
871 } elsif ($make =~ /^OLYMPUS/ and $model =~ /^E-(1|300|330)\b/) {
872 push @offsets, 16;
873 } elsif ($make =~ /^OLYMPUS/ and
874 # these Olympus models are just weird
875 $model =~ /^(C2500L|C-1Z?|C-5000Z|X-2|C720UZ|C725UZ|C150|C2Z|E-10|E-20|FerrariMODEL2003|u20D|u10D)\b/)
876 {
877 # no expected offset --> determine offset empirically via FixBase()
878 } elsif ($make =~ /^(Panasonic|JVC)\b/) {
879 push @offsets, 0;
880 } elsif ($make =~ /^SONY/) {
881 # DSLR and "PREMI" models use an offset of 4
882 if ($model =~ /DSLR/ or $$exifTool{OlympusCAMER}) {
883 push @offsets, 4;
884 } else {
885 push @offsets, 0;
886 }
887 } elsif ($make eq 'FUJIFILM') {
888 # some models have offset of 6, so allow that too (A345,A350,A360,A370)
889 push @offsets, 4, 6;
890 } elsif ($make =~ /^TOSHIBA/) {
891 # similar to Canon, can also have 24 bytes of padding
892 push @offsets, 0, 24;
893 } elsif ($make =~ /^PENTAX/) {
894 push @offsets, 4;
895 # the Pentax addressing mode is determined automatically, but
896 # sometimes the algorithm gets it wrong, but Pentax always uses
897 # absolute addressing, so force it to be absolute
898 $relative = 0;
899 } elsif ($make =~ /^Konica Minolta/i) {
900 # patch for DiMAGE X50, Xg, Z2 and Z10
901 push @offsets, 4, -16;
902 } elsif ($make =~ /^Minolta/) {
903 # patch for DiMAGE 7, X20 and Z1
904 push @offsets, 4, -8, -12;
905 } else {
906 push @offsets, 4; # the normal offset
907 }
908 return ($relative, @offsets);
909}
910
911#------------------------------------------------------------------------------
912# Get hash of value offsets / block sizes
913# Inputs: 0) Data pointer, 1) offset to start of directory,
914# 2) hash ref to return value pointers based on tag ID
915# Returns: 0) hash reference: keys are offsets, values are block sizes
916# 1) same thing, but with keys adjusted for value-based offsets
917# Notes: Directory size should be validated before calling this routine
918# - calculates MIN and MAX offsets in entry-based hash
919sub GetValueBlocks($$;$)
920{
921 my ($dataPt, $dirStart, $tagPtr) = @_;
922 my $numEntries = Get16u($dataPt, $dirStart);
923 my ($index, $valPtr, %valBlock, %valBlkAdj, $end);
924 for ($index=0; $index<$numEntries; ++$index) {
925 my $entry = $dirStart + 2 + 12 * $index;
926 my $format = Get16u($dataPt, $entry+2);
927 last if $format < 1 or $format > 13;
928 my $count = Get32u($dataPt, $entry+4);
929 my $size = $count * $Image::ExifTool::Exif::formatSize[$format];
930 next if $size <= 4;
931 $valPtr = Get32u($dataPt, $entry+8);
932 $tagPtr and $$tagPtr{Get16u($dataPt, $entry)} = $valPtr;
933 # save location and size of longest block at this offset
934 unless (defined $valBlock{$valPtr} and $valBlock{$valPtr} > $size) {
935 $valBlock{$valPtr} = $size;
936 }
937 # adjust for case of value-based offsets
938 $valPtr += 12 * $index;
939 unless (defined $valBlkAdj{$valPtr} and $valBlkAdj{$valPtr} > $size) {
940 $valBlkAdj{$valPtr} = $size;
941 my $end = $valPtr + $size;
942 if (defined $valBlkAdj{MIN}) {
943 # save minimum only if it has a value of 12 or greater
944 $valBlkAdj{MIN} = $valPtr if $valBlkAdj{MIN} < 12 or $valBlkAdj{MIN} > $valPtr;
945 $valBlkAdj{MAX} = $end if $valBlkAdj{MAX} > $end;
946 } else {
947 $valBlkAdj{MIN} = $valPtr;
948 $valBlkAdj{MAX} = $end;
949 }
950 }
951 }
952 return(\%valBlock, \%valBlkAdj);
953}
954
955#------------------------------------------------------------------------------
956# Fix base for value offsets in maker notes IFD (if necessary)
957# Inputs: 0) ExifTool object ref, 1) DirInfo hash ref
958# Return: amount of base shift (and $dirInfo Base and DataPos are updated,
959# FixedBy is set if offsets fixed, and Relative or EntryBased may be set)
960sub FixBase($$)
961{
962 local $_;
963 my ($exifTool, $dirInfo) = @_;
964 # don't fix base if fixing offsets individually or if we don't want to fix them
965 return 0 if $$dirInfo{FixOffsets} or $$dirInfo{NoFixBase};
966
967 my $dataPt = $$dirInfo{DataPt};
968 my $dataPos = $$dirInfo{DataPos};
969 my $dirStart = $$dirInfo{DirStart} || 0;
970 my $entryBased = $$dirInfo{EntryBased};
971 my $dirName = $$dirInfo{DirName};
972 my $fixBase = $exifTool->Options('FixBase');
973 my $setBase = (defined $fixBase and $fixBase ne '') ? 1 : 0;
974 my ($fix, $fixedBy, %tagPtr);
975
976 # get hash of value block positions
977 my ($valBlock, $valBlkAdj) = GetValueBlocks($dataPt, $dirStart, \%tagPtr);
978 return 0 unless %$valBlock;
979 # get sorted list of value offsets
980 my @valPtrs = sort { $a <=> $b } keys %$valBlock;
981#
982# handle special case of Canon maker notes with TIFF footer containing original offset
983#
984 if ($$exifTool{Make} =~ /^Canon/ and $$dirInfo{DirLen} > 8) {
985 my $footerPos = $dirStart + $$dirInfo{DirLen} - 8;
986 my $footer = substr($$dataPt, $footerPos, 8);
987 if ($footer =~ /^(II\x2a\0|MM\0\x2a)/ and # check for TIFF footer
988 substr($footer,0,2) eq GetByteOrder()) # validate byte ordering
989 {
990 my $oldOffset = Get32u(\$footer, 4);
991 my $newOffset = $dirStart + $dataPos;
992 if ($setBase) {
993 $fix = $fixBase;
994 } else {
995 $fix = $newOffset - $oldOffset;
996 return 0 unless $fix;
997 # Picasa and ACDSee have a bug where they update other offsets without
998 # updating the TIFF footer (PH - 2009/02/25), so test for this case:
999 # validate Canon maker note footer fix by checking offset of last value
1000 my $maxPt = $valPtrs[-1] + $$valBlock{$valPtrs[-1]};
1001 # compare to end of maker notes, taking 8-byte footer into account
1002 my $endDiff = $dirStart + $$dirInfo{DirLen} - ($maxPt - $dataPos) - 8;
1003 # ignore footer offset only if end difference is exactly correct
1004 # (allow for possible padding byte, although I have never seen this)
1005 if (not $endDiff or $endDiff == 1) {
1006 $exifTool->Warn('Canon maker note footer may be invalid (ignored)',1);
1007 return 0;
1008 }
1009 }
1010 $exifTool->Warn("Adjusted $dirName base by $fix",1);
1011 $$dirInfo{FixedBy} = $fix;
1012 $$dirInfo{Base} += $fix;
1013 $$dirInfo{DataPos} -= $fix;
1014 return $fix;
1015 }
1016 }
1017#
1018# analyze value offsets to see if they need fixing. The first task is to determine
1019# the minimum valid offset used (this is tricky, because we have to weed out bad
1020# offsets written by some cameras)
1021#
1022 my $minPt = $$dirInfo{MinOffset} = $valPtrs[0]; # if life were simple, this would be it
1023 my $ifdLen = 2 + 12 * Get16u($$dirInfo{DataPt}, $dirStart);
1024 my $ifdEnd = $dirStart + $ifdLen;
1025 my ($relative, @offsets) = GetMakerNoteOffset($exifTool);
1026 my $makeDiff = $offsets[0];
1027 my $verbose = $exifTool->Options('Verbose');
1028 my ($diff, $shift);
1029
1030 # calculate expected minimum value offset
1031 my $expected = $dataPos + $ifdEnd + (defined $makeDiff ? $makeDiff : 4);
1032 $debug and print "$expected expected\n";
1033
1034 # zero our counters
1035 my ($countNeg12, $countZero, $countOverlap) = (0, 0, 0);
1036 my ($valPtr, $last);
1037 foreach $valPtr (@valPtrs) {
1038 printf("%d - %d (%d)\n", $valPtr, $valPtr + $$valBlock{$valPtr},
1039 $valPtr - ($last || 0)) if $debug;
1040 if (defined $last) {
1041 my $gap = $valPtr - $last;
1042 if ($gap == 0 or $gap == 1) {
1043 ++$countZero;
1044 } elsif ($gap == -12 and not $entryBased) {
1045 # you get this when value offsets are relative to the IFD entry
1046 ++$countNeg12;
1047 } elsif ($gap < 0) {
1048 # any other negative difference indicates overlapping values
1049 ++$countOverlap if $valPtr; # (but ignore zero value pointers)
1050 } elsif ($gap >= $ifdLen) {
1051 # ignore previous minimum if we took a jump to near the expected value
1052 # (some values can be stored before the IFD)
1053 $minPt = $valPtr if abs($valPtr - $expected) <= 4;
1054 }
1055 # an offset less than 12 is surely garbage, so ignore it
1056 $minPt = $valPtr if $minPt < 12;
1057 }
1058 $last = $valPtr + $$valBlock{$valPtr};
1059 }
1060 # could this IFD be using entry-based offsets?
1061 if ((($countNeg12 > $countZero and $$valBlkAdj{MIN} >= $ifdLen - 2) or
1062 ($$valBlkAdj{MIN} == $ifdLen - 2 or $$valBlkAdj{MIN} == $ifdLen + 2)
1063 ) and $$valBlkAdj{MAX} <= $$dirInfo{DirLen}-2)
1064 {
1065 # looks like these offsets are entry-based, so use the offsets
1066 # which have been correcting for individual entry position
1067 $entryBased = 1;
1068 $verbose and $exifTool->Warn("$dirName offsets are entry-based",1);
1069 } else {
1070 # calculate offset difference from end of IFD to first value
1071 $diff = ($minPt - $dataPos) - $ifdEnd;
1072 $shift = 0;
1073 $countOverlap and $exifTool->Warn("Overlapping $dirName values",1);
1074 if ($entryBased) {
1075 $exifTool->Warn("$dirName offsets do NOT look entry-based",1);
1076 undef $entryBased;
1077 undef $relative;
1078 }
1079 # use PrintIM tag to do special check for correct absolute offsets
1080 if ($tagPtr{0xe00}) {
1081 my $ptr = $tagPtr{0xe00} - $dataPos;
1082 return 0 if $ptr > 0 and $ptr <= length($$dataPt) - 8 and
1083 substr($$dataPt, $ptr, 8) eq "PrintIM\0";
1084 }
1085 # allow a range of reasonable differences for Unknown maker notes
1086 if ($$dirInfo{FixBase} and $$dirInfo{FixBase} == 2) {
1087 return 0 if $diff >=0 and $diff <= 24;
1088 }
1089 # (used for testing to extract differences)
1090 # $exifTool->FoundTag('Diff', $diff);
1091 }
1092#
1093# handle entry-based offsets
1094#
1095 if ($entryBased) {
1096 $debug and print "--> entry-based!\n";
1097 # most of my entry-based samples have first value immediately
1098 # after last IFD entry (ie. no padding or next IFD pointer)
1099 $makeDiff = 0;
1100 push @offsets, 4; # but some do have a next IFD pointer
1101 # corrected entry-based offsets are relative to start of first entry
1102 my $expected = 12 * Get16u($$dirInfo{DataPt}, $dirStart);
1103 $diff = $$valBlkAdj{MIN} - $expected;
1104 # set up directory to read values with entry-based offsets
1105 # (ignore everything and set base to start of first entry)
1106 $shift = $dataPos + $dirStart + 2;
1107 $$dirInfo{Base} += $shift;
1108 $$dirInfo{DataPos} -= $shift;
1109 $$dirInfo{EntryBased} = 1;
1110 $$dirInfo{Relative} = 1; # entry-based offsets are relative
1111 delete $$dirInfo{FixBase}; # no automatic base fix
1112 undef $fixBase unless $setBase;
1113 }
1114#
1115# return without doing shift if offsets look OK
1116#
1117 unless ($setBase) {
1118 # don't try to fix offsets for whacky cameras
1119 return $shift unless defined $makeDiff;
1120 # normal value data starts 4 bytes after IFD, but allow 0 or 4...
1121 return $shift if $diff == 0 or $diff == 4;
1122 # also check for allowed make-specific differences
1123 foreach (@offsets) {
1124 return $shift if $diff == $_;
1125 }
1126 }
1127#
1128# apply the fix, or issue a warning
1129#
1130 # use default padding of 4 bytes unless already specified
1131 $makeDiff = 4 unless defined $makeDiff;
1132 $fix = $makeDiff - $diff; # assume standard diff for this make
1133
1134 if ($$dirInfo{FixBase}) {
1135 # set flag if offsets are relative (base is at or above directory start)
1136 if ($dataPos - $fix + $dirStart <= 0) {
1137 $$dirInfo{Relative} = (defined $relative) ? $relative : 1;
1138 }
1139 if ($setBase) {
1140 $fixedBy = $fixBase;
1141 $fix += $fixBase;
1142 }
1143 } elsif (defined $fixBase) {
1144 $fix = $fixBase if $fixBase ne '';
1145 $fixedBy = $fix;
1146 } else {
1147 # print warning unless difference looks reasonable
1148 if ($diff < 0 or $diff > 16 or ($diff & 0x01)) {
1149 $exifTool->Warn("Possibly incorrect maker notes offsets (fix by $fix?)",1);
1150 }
1151 # don't do the fix (but we already adjusted base if entry-based)
1152 return $shift;
1153 }
1154 if (defined $fixedBy) {
1155 $exifTool->Warn("Adjusted $dirName base by $fixedBy",1);
1156 $$dirInfo{FixedBy} = $fixedBy;
1157 }
1158 $$dirInfo{Base} += $fix;
1159 $$dirInfo{DataPos} -= $fix;
1160 return $fix + $shift;
1161}
1162
1163#------------------------------------------------------------------------------
1164# Find start of IFD in unknown maker notes
1165# Inputs: 0) reference to directory information
1166# Returns: offset to IFD on success, undefined otherwise
1167# - dirInfo may contain TagInfo reference for tag associated with directory
1168# - on success, updates DirStart, DirLen, Base and DataPos in dirInfo
1169# - also sets Relative flag in dirInfo if offsets are relative to IFD
1170# Note: Changes byte ordering!
1171sub LocateIFD($$)
1172{
1173 my ($exifTool, $dirInfo) = @_;
1174 my $dataPt = $$dirInfo{DataPt};
1175 my $dirStart = $$dirInfo{DirStart} || 0;
1176 # (ignore MakerNotes DirLen since sometimes this is incorrect)
1177 my $size = $$dirInfo{DataLen} - $dirStart;
1178 my $dirLen = $$dirInfo{DirLen} || $size;
1179 my $tagInfo = $$dirInfo{TagInfo};
1180 my $ifdOffsetPos;
1181 # the IFD should be within the first 32 bytes
1182 # (Kyocera sets the current record at 22 bytes)
1183 my ($firstTry, $lastTry) = (0, 32);
1184
1185 # make sure Base and DataPos are defined
1186 $$dirInfo{Base} or $$dirInfo{Base} = 0;
1187 $$dirInfo{DataPos} or $$dirInfo{DataPos} = 0;
1188#
1189# use tag information (if provided) to determine directory location
1190#
1191 if ($tagInfo and $$tagInfo{SubDirectory}) {
1192 my $subdir = $$tagInfo{SubDirectory};
1193 unless ($$subdir{ProcessProc} and
1194 ($$subdir{ProcessProc} eq \&ProcessUnknown or
1195 $$subdir{ProcessProc} eq \&ProcessUnknownOrPreview))
1196 {
1197 # look for the IFD at the "Start" specified in our SubDirectory information
1198 my $valuePtr = $dirStart;
1199 my $newStart = $dirStart;
1200 if (defined $$subdir{Start}) {
1201 #### eval Start ($valuePtr)
1202 $newStart = eval($$subdir{Start});
1203 }
1204 if ($$subdir{Base}) {
1205 # calculate subdirectory start relative to $base for eval
1206 my $start = $newStart + $$dirInfo{DataPos};
1207 my $base = $$dirInfo{Base} || 0;
1208 #### eval Base ($start,$base)
1209 my $baseShift = eval($$subdir{Base});
1210 # shift directory base (note: we may do this again below
1211 # if an OffsetPt is defined, but that doesn't matter since
1212 # the base shift is relative to DataPos, which we set too)
1213 $$dirInfo{Base} += $baseShift;
1214 $$dirInfo{DataPos} -= $baseShift;
1215 # this is a relative directory if Base depends on $start
1216 if ($$subdir{Base} =~ /\$start\b/) {
1217 $$dirInfo{Relative} = 1;
1218 # hack to fix Leica quirk
1219 if ($$subdir{ProcessProc} and $$subdir{ProcessProc} eq \&FixLeicaBase) {
1220 my $oldStart = $$dirInfo{DirStart};
1221 $$dirInfo{DirStart} = $newStart;
1222 FixLeicaBase($exifTool, $dirInfo);
1223 $$dirInfo{DirStart} = $oldStart;
1224 }
1225 }
1226 }
1227 # add offset to the start of the directory if necessary
1228 if ($$subdir{OffsetPt}) {
1229 if ($$subdir{ByteOrder} =~ /^Little/i) {
1230 SetByteOrder('II');
1231 } elsif ($$subdir{ByteOrder} =~ /^Big/i) {
1232 SetByteOrder('MM');
1233 } else {
1234 warn "Can't have variable byte ordering for SubDirectories using OffsetPt\n";
1235 return undef;
1236 }
1237 #### eval OffsetPt ($valuePtr)
1238 $ifdOffsetPos = eval($$subdir{OffsetPt}) - $dirStart;
1239 }
1240 # pinpoint position to look for this IFD
1241 $firstTry = $lastTry = $newStart - $dirStart;
1242 }
1243 }
1244#
1245# scan for something that looks like an IFD
1246#
1247 if ($dirLen >= 14 + $firstTry) { # minimum size for an IFD
1248 my $offset;
1249IFD_TRY: for ($offset=$firstTry; $offset<=$lastTry; $offset+=2) {
1250 last if $offset + 14 > $dirLen; # 14 bytes is minimum size for an IFD
1251 my $pos = $dirStart + $offset;
1252#
1253# look for a standard TIFF header (Nikon uses it, others may as well),
1254#
1255 if (SetByteOrder(substr($$dataPt, $pos, 2)) and
1256 Get16u($dataPt, $pos + 2) == 0x2a)
1257 {
1258 $ifdOffsetPos = 4;
1259 }
1260 if (defined $ifdOffsetPos) {
1261 # get pointer to IFD
1262 my $ptr = Get32u($dataPt, $pos + $ifdOffsetPos);
1263 if ($ptr >= $ifdOffsetPos + 4 and $ptr + $offset + 14 <= $dirLen) {
1264 # shift directory start and shorten dirLen accordingly
1265 $$dirInfo{DirStart} += $ptr + $offset;
1266 $$dirInfo{DirLen} -= $ptr + $offset;
1267 # shift pointer base to the start of the TIFF header
1268 my $shift = $$dirInfo{DataPos} + $dirStart + $offset;
1269 $$dirInfo{Base} += $shift;
1270 $$dirInfo{DataPos} -= $shift;
1271 $$dirInfo{Relative} = 1; # set "relative offsets" flag
1272 return $ptr + $offset;
1273 }
1274 undef $ifdOffsetPos;
1275 }
1276#
1277# look for a standard IFD (starts with 2-byte entry count)
1278#
1279 my $num = Get16u($dataPt, $pos);
1280 next unless $num;
1281 # number of entries in an IFD should be between 1 and 255
1282 if (!($num & 0xff)) {
1283 # lower byte is zero -- byte order could be wrong
1284 ToggleByteOrder();
1285 $num >>= 8;
1286 } elsif ($num & 0xff00) {
1287 # upper byte isn't zero -- not an IFD
1288 next;
1289 }
1290 my $bytesFromEnd = $size - ($offset + 2 + 12 * $num);
1291 if ($bytesFromEnd < 4) {
1292 next unless $bytesFromEnd == 2 or $bytesFromEnd == 0;
1293 }
1294 # do a quick validation of all format types
1295 my $index;
1296 for ($index=0; $index<$num; ++$index) {
1297 my $entry = $pos + 2 + 12 * $index;
1298 my $format = Get16u($dataPt, $entry+2);
1299 my $count = Get32u($dataPt, $entry+4);
1300 # allow everything to be zero if not first entry
1301 # because some manufacturers pad with null entries
1302 next unless $format or $count or $index == 0;
1303 # patch for Canon EOS 40D firmware 1.0.4 bug: allow zero format for last entry
1304 next if $format==0 and $index==$num-1 and $$exifTool{Model}=~/EOS 40D/;
1305 # (would like to verify tag ID, but some manufactures don't
1306 # sort entries in order of tag ID so we don't have much of
1307 # a handle to verify this field)
1308 # verify format
1309 next IFD_TRY if $format < 1 or $format > 13;
1310 # count must be reasonable (can't test for zero count because
1311 # cameras like the 1DmkIII use this value)
1312 next IFD_TRY if $count & 0xff000000;
1313 # extra tests to avoid mis-identifying Samsung makernotes (GT-I9000, etc)
1314 next unless $num == 1;
1315 my $valueSize = $count * $Image::ExifTool::Exif::formatSize[$format];
1316 if ($valueSize > 4) {
1317 next IFD_TRY if $valueSize > $size;
1318 my $valuePtr = Get32u($dataPt, $entry+8);
1319 next IFD_TRY if $valuePtr > 0x10000;
1320 }
1321 }
1322 $$dirInfo{DirStart} += $offset; # update directory start
1323 $$dirInfo{DirLen} -= $offset;
1324 return $offset; # success!!
1325 }
1326 }
1327 return undef;
1328}
1329
1330#------------------------------------------------------------------------------
1331# Fix base offset for Leica maker notes
1332# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
1333# Returns: 1 on success, and updates $dirInfo if necessary for new directory
1334sub FixLeicaBase($$;$)
1335{
1336 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
1337 my $dataPt = $$dirInfo{DataPt};
1338 my $dirStart = $$dirInfo{DirStart} || 0;
1339 # get hash of value block positions
1340 my ($valBlock, $valBlkAdj) = GetValueBlocks($dataPt, $dirStart);
1341 if (%$valBlock) {
1342 # get sorted list of value offsets
1343 my @valPtrs = sort { $a <=> $b } keys %$valBlock;
1344 my $numEntries = Get16u($dataPt, $dirStart);
1345 my $diff = $valPtrs[0] - ($numEntries * 12 + 4);
1346 if ($diff > 8) {
1347 $$dirInfo{Base} -= 8;
1348 $$dirInfo{DataPos} += 8;
1349 }
1350 }
1351 my $success = 1;
1352 if ($tagTablePtr) {
1353 $success = Image::ExifTool::Exif::ProcessExif($exifTool, $dirInfo, $tagTablePtr);
1354 }
1355 return $success;
1356}
1357
1358#------------------------------------------------------------------------------
1359# Process Canon maker notes
1360# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
1361# Returns: 1 on success
1362sub ProcessCanon($$$)
1363{
1364 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
1365 # identify Canon MakerNote footer in HtmlDump
1366 # (this code moved from FixBase so it also works for Adobe MakN in DNG images)
1367 if ($$exifTool{HTML_DUMP} and $$dirInfo{DirLen} > 8) {
1368 my $dataPos = $$dirInfo{DataPos};
1369 my $dirStart = $$dirInfo{DirStart} || 0;
1370 my $footerPos = $dirStart + $$dirInfo{DirLen} - 8;
1371 my $footer = substr(${$$dirInfo{DataPt}}, $footerPos, 8);
1372 if ($footer =~ /^(II\x2a\0|MM\0\x2a)/ and substr($footer,0,2) eq GetByteOrder()) {
1373 my $oldOffset = Get32u(\$footer, 4);
1374 my $newOffset = $dirStart + $dataPos;
1375 my $str = sprintf('Original maker note offset: 0x%.4x', $oldOffset);
1376 if ($oldOffset != $newOffset) {
1377 $str .= sprintf("\nCurrent maker note offset: 0x%.4x", $newOffset);
1378 }
1379 my $filePos = ($$dirInfo{Base} || 0) + $dataPos + $footerPos;
1380 $exifTool->HDump($filePos, 8, '[Canon MakerNotes footer]', $str);
1381 }
1382 }
1383 # process as normal
1384 return Image::ExifTool::Exif::ProcessExif($exifTool, $dirInfo, $tagTablePtr);
1385}
1386
1387#------------------------------------------------------------------------------
1388# Process GE type 2 maker notes
1389# Inputs: 0) ExifTool object ref, 1) DirInfo ref, 2) tag table ref
1390# Returns: 1 on success
1391sub ProcessGE2($$$)
1392{
1393 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
1394 my $dataPt = $$dirInfo{DataPt} or return 0;
1395 my $dirStart = $$dirInfo{DirStart} || 0;
1396
1397 # these maker notes are missing the IFD entry count, but they
1398 # always have 25 entries, so write the entry count manually
1399 Set16u(25, $dataPt, $dirStart);
1400 return Image::ExifTool::Exif::ProcessExif($exifTool, $dirInfo, $tagTablePtr);
1401}
1402
1403#------------------------------------------------------------------------------
1404# Process unknown maker notes or PreviewImage
1405# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
1406# Returns: 1 on success, and updates $dirInfo if necessary for new directory
1407sub ProcessUnknownOrPreview($$$)
1408{
1409 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
1410 my $dataPt = $$dirInfo{DataPt};
1411 my $dirStart = $$dirInfo{DirStart};
1412 my $dirLen = $$dirInfo{DirLen};
1413 # check to see if this is a preview image
1414 if ($dirLen > 6 and substr($$dataPt, $dirStart, 3) eq "\xff\xd8\xff") {
1415 $exifTool->VerboseDir('PreviewImage');
1416 if ($$exifTool{HTML_DUMP}) {
1417 my $pos = $$dirInfo{DataPos} + $$dirInfo{Base} + $dirStart;
1418 $exifTool->HDump($pos, $dirLen, '(MakerNotes:PreviewImage data)', "Size: $dirLen bytes")
1419 }
1420 $exifTool->FoundTag('PreviewImage', substr($$dataPt, $dirStart, $dirLen));
1421 return 1;
1422 }
1423 return ProcessUnknown($exifTool, $dirInfo, $tagTablePtr);
1424}
1425
1426#------------------------------------------------------------------------------
1427# Write unknown maker notes or PreviewImage
1428# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
1429# Returns: directory data, '' to delete, or undef on error
1430sub WriteUnknownOrPreview($$$)
1431{
1432 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
1433 my $dataPt = $$dirInfo{DataPt};
1434 my $dirStart = $$dirInfo{DirStart};
1435 my $dirLen = $$dirInfo{DirLen};
1436 my $newVal;
1437 # check to see if this is a preview image
1438 if ($dirLen > 6 and substr($$dataPt, $dirStart, 3) eq "\xff\xd8\xff") {
1439 if ($$exifTool{NEW_VALUE}{$Image::ExifTool::Extra{PreviewImage}}) {
1440 # write or delete new preview (if deleted, it can't currently be added back again)
1441 $newVal = $exifTool->GetNewValues('PreviewImage') || '';
1442 if ($exifTool->Options('Verbose') > 1) {
1443 $exifTool->VerboseValue("- MakerNotes:PreviewImage", substr($$dataPt, $dirStart, $dirLen));
1444 $exifTool->VerboseValue("+ MakerNotes:PreviewImage", $newVal) if $newVal;
1445 }
1446 ++$$exifTool{CHANGED};
1447 } else {
1448 $newVal = substr($$dataPt, $dirStart, $dirLen);
1449 }
1450 } else {
1451 # rewrite MakerNote IFD
1452 $newVal = Image::ExifTool::Exif::WriteExif($exifTool, $dirInfo, $tagTablePtr);
1453 }
1454 return $newVal;
1455}
1456
1457#------------------------------------------------------------------------------
1458# Process unknown maker notes assuming it is in EXIF IFD format
1459# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
1460# Returns: 1 on success, and updates $dirInfo if necessary for new directory
1461sub ProcessUnknown($$$)
1462{
1463 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
1464 my $success = 0;
1465
1466 my $loc = LocateIFD($exifTool, $dirInfo);
1467 if (defined $loc) {
1468 $exifTool->{UnknownByteOrder} = GetByteOrder();
1469 if ($exifTool->Options('Verbose') > 1) {
1470 my $out = $exifTool->Options('TextOut');
1471 my $indent = $exifTool->{INDENT};
1472 $indent =~ s/\| $/ /;
1473 printf $out "${indent}Found IFD at offset 0x%.4x in maker notes:\n",
1474 $$dirInfo{DirStart} + $$dirInfo{DataPos} + $$dirInfo{Base};
1475 }
1476 $success = Image::ExifTool::Exif::ProcessExif($exifTool, $dirInfo, $tagTablePtr);
1477 } else {
1478 $exifTool->{UnknownByteOrder} = ''; # indicates we tried but didn't set byte order
1479 $exifTool->Warn("Unrecognized $$dirInfo{DirName}", 1);
1480 }
1481 return $success;
1482}
1483
1484
14851; # end
1486
1487__END__
1488
1489=head1 NAME
1490
1491Image::ExifTool::MakerNotes - Read and write EXIF maker notes
1492
1493=head1 SYNOPSIS
1494
1495This module is required by Image::ExifTool.
1496
1497=head1 DESCRIPTION
1498
1499This module contains definitions required by Image::ExifTool to interpret
1500maker notes in EXIF information.
1501
1502=head1 AUTHOR
1503
1504Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
1505
1506This library is free software; you can redistribute it and/or modify it
1507under the same terms as Perl itself.
1508
1509=head1 SEE ALSO
1510
1511L<Image::ExifTool::TagNames(3pm)|Image::ExifTool::TagNames>,
1512L<Image::ExifTool(3pm)|Image::ExifTool>
1513
1514=cut
Note: See TracBrowser for help on using the repository browser.