source: gs2-extensions/parallel-building/trunk/src/perllib/cpan/Image/ExifTool/Panasonic.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: Panasonic.pm
3#
4# Description: Panasonic/Leica maker notes tags
5#
6# Revisions: 11/10/2004 - P. Harvey Created
7#
8# References: 1) http://www.compton.nu/panasonic.html (based on FZ10)
9# 2) Derived from DMC-FZ3 samples from dpreview.com
10# 3) http://johnst.org/sw/exiftags/
11# 4) Tels (http://bloodgate.com/) private communication (tests with FZ5)
12# 7) http://homepage3.nifty.com/kamisaka/makernote/makernote_pana.htm (2007/10/02)
13# 8) Marcel Coenen private communication (DMC-FZ50)
14# 9) http://forums.dpreview.com/forums/read.asp?forum=1033&message=22756430
15# 10) http://bretteville.com/pdfs/M8Metadata_v2.pdf
16# 11) http://www.digital-leica.com/lens_codes/index.html
17# 12) Joerg - http://www.cpanforum.com/threads/11602 (LX3 firmware 2.0)
18# 13) Michael Byczkowski private communication (Leica M9)
19# 14) Carl Bretteville private communication (M9)
20# 15) Zdenek Mihula private communication (TZ8)
21# JD) Jens Duttke private communication (TZ3,FZ30,FZ50)
22#------------------------------------------------------------------------------
23
24package Image::ExifTool::Panasonic;
25
26use strict;
27use vars qw($VERSION);
28use Image::ExifTool qw(:DataAccess :Utils);
29use Image::ExifTool::Exif;
30
31$VERSION = '1.59';
32
33sub ProcessPanasonicType2($$$);
34sub WhiteBalanceConv($;$$);
35
36# Leica lens types (ref 10)
37my %leicaLensType = (
38 OTHER => sub {
39 my ($val, $inv, $conv) = @_;
40 return undef if $inv or not $val =~ s/ .*//;
41 return $$conv{$val};
42 },
43 Notes => q{
44 Entries with 2 numbers give the lower 2 bits of the LensType value which are
45 used to identify certain manually coded lenses on the M9, or the focal
46 length of some multi-focal lenses.
47 },
48 # All M9 codes (two numbers: first the LensID then the lower 2 bits)
49 # are ref PH with samples from ref 13. From ref 10, the lower 2 bits of
50 # the LensType value give the frame selector position for most lenses,
51 # although for the 28-35-50mm (at least) it gives the focal length selection.
52 # The M9 also gives the focal length selection but for other lenses the
53 # lower 3 bits don't change with frame selector position except for the lens
54 # shows as uncoded for certain lenses and some incorrect positions of the
55 # frame selector. The bits are zero for uncoded lenses when manually coding
56 # from the menu on the M9. - PH
57 '0 0' => 'Uncoded lens',
58#
59# NOTE: MUST ADD ENTRY TO %frameSelectorBits below when a new lens is added!!!!
60#
61 # model number(s):
62 1 => 'Elmarit-M 21mm f/2.8', # 11134
63 3 => 'Elmarit-M 28mm f/2.8 (III)', # 11804
64 4 => 'Tele-Elmarit-M 90mm f/2.8 (II)', # 11800
65 5 => 'Summilux-M 50mm f/1.4 (II)', # 11868/11856/11114
66 6 => 'Summicron-M 35mm f/2 (IV)', # 11310/11311
67 '6 0' => 'Summilux-M 35mm f/1.4', # 11869/11870/11860
68 7 => 'Summicron-M 90mm f/2 (II)', # 11136/11137
69 9 => 'Elmarit-M 135mm f/2.8 (I/II)', # 11829
70 '9 0' => 'Apo-Telyt-M 135mm f/3.4', # 11889
71 16 => 'Tri-Elmar-M 16-18-21mm f/4 ASPH.',# 11626
72 '16 1' => 'Tri-Elmar-M 16-18-21mm f/4 ASPH. (at 16mm)',
73 '16 2' => 'Tri-Elmar-M 16-18-21mm f/4 ASPH. (at 18mm)',
74 '16 3' => 'Tri-Elmar-M 16-18-21mm f/4 ASPH. (at 21mm)',
75 23 => 'Summicron-M 50mm f/2 (III)', # 11817, version (I) in camera menu
76 24 => 'Elmarit-M 21mm f/2.8 ASPH.', # 11135/11897
77 25 => 'Elmarit-M 24mm f/2.8 ASPH.', # 11878/11898
78 26 => 'Summicron-M 28mm f/2 ASPH.', # 11604
79 27 => 'Elmarit-M 28mm f/2.8 (IV)', # 11809
80 28 => 'Elmarit-M 28mm f/2.8 ASPH.', # 11606
81 29 => 'Summilux-M 35mm f/1.4 ASPH.', # 11874/11883
82 '29 0' => 'Summilux-M 35mm f/1.4 ASPHERICAL', # 11873 (different from "ASPH." model!)
83 30 => 'Summicron-M 35mm f/2 ASPH.', # 11879/11882
84 31 => 'Noctilux-M 50mm f/1', # 11821/11822
85 '31 0' => 'Noctilux-M 50mm f/1.2', # 11820
86 32 => 'Summilux-M 50mm f/1.4 ASPH.', # 11891/11892
87 33 => 'Summicron-M 50mm f/2 (IV, V)', # 11819/11825/11826/11816, version (II,III) in camera menu
88 34 => 'Elmar-M 50mm f/2.8', # 11831/11823/11825
89 35 => 'Summilux-M 75mm f/1.4', # 11814/11815/11810
90 36 => 'Apo-Summicron-M 75mm f/2 ASPH.', # 11637
91 37 => 'Apo-Summicron-M 90mm f/2 ASPH.', # 11884/11885
92 38 => 'Elmarit-M 90mm f/2.8', # 11807/11808, version (II) in camera menu
93 39 => 'Macro-Elmar-M 90mm f/4', # 11633/11634
94 '39 0' => 'Tele-Elmar-M 135mm f/4 (II)',# 11861
95 40 => 'Macro-Adapter M', # 14409
96 42 => 'Tri-Elmar-M 28-35-50mm f/4 ASPH.',# 11625
97 '42 1' => 'Tri-Elmar-M 28-35-50mm f/4 ASPH. (at 28mm)',
98 '42 2' => 'Tri-Elmar-M 28-35-50mm f/4 ASPH. (at 35mm)',
99 '42 3' => 'Tri-Elmar-M 28-35-50mm f/4 ASPH. (at 50mm)',
100 43 => 'Summarit-M 35mm f/2.5', # ? (ref PH)
101 44 => 'Summarit-M 50mm f/2.5', # ? (ref PH)
102 45 => 'Summarit-M 75mm f/2.5', # ? (ref PH)
103 46 => 'Summarit-M 90mm f/2.5', # ?
104 47 => 'Summilux-M 21mm f/1.4 ASPH.', # ? (ref 11)
105 48 => 'Summilux-M 24mm f/1.4 ASPH.', # ? (ref 11)
106 49 => 'Noctilux-M 50mm f/0.95 ASPH.', # ? (ref 11)
107 50 => 'Elmar-M 24mm f/3.8 ASPH.', # ? (ref 11)
108 52 => 'Super-Elmar-M 18mm f/3.8 ASPH.', # ? (ref PH/11)
109);
110
111# M9 frame selector bits for each lens
112# 1 = towards lens = 28/90mm or 21mm or Adapter (or Elmarit-M 135mm f/2.8)
113# 2 = away from lens = 24/35mm (or 35/135mm on the M9)
114# 3 = middle position = 50/75mm or 18mm
115my %frameSelectorBits = (
116 1 => 1,
117 3 => 1,
118 4 => 1,
119 5 => 3,
120 6 => 2,
121 7 => 1,
122 9 => 1, # (because lens has special magnifier for the rangefinder)
123 16 => 1, # or 2 or 3
124 23 => 3,
125 24 => 1,
126 25 => 2,
127 26 => 1,
128 27 => 1,
129 28 => 1,
130 29 => 2,
131 30 => 2,
132 31 => 3,
133 32 => 3,
134 33 => 3,
135 34 => 3,
136 35 => 3,
137 36 => 3,
138 37 => 1,
139 38 => 1,
140 39 => 1,
141 40 => 1,
142 42 => 1, # or 2 or 3
143 43 => 2, # (NC)
144 44 => 3, # (NC)
145 45 => 3,
146 46 => 1, # (NC)
147 47 => 1, # (NC)
148 48 => 2, # (NC)
149 49 => 3, # (NC)
150 50 => 2, # (NC)
151 52 => 3,
152);
153
154# conversions for ShootingMode and SceneMode
155my %shootingMode = (
156 1 => 'Normal',
157 2 => 'Portrait',
158 3 => 'Scenery',
159 4 => 'Sports',
160 5 => 'Night Portrait',
161 6 => 'Program',
162 7 => 'Aperture Priority',
163 8 => 'Shutter Priority',
164 9 => 'Macro',
165 10 => 'Spot', #7
166 11 => 'Manual',
167 12 => 'Movie Preview', #PH (LZ6)
168 13 => 'Panning',
169 14 => 'Simple', #PH (LZ6)
170 15 => 'Color Effects', #7
171 16 => 'Self Portrait', #PH (TZ5)
172 17 => 'Economy', #7
173 18 => 'Fireworks',
174 19 => 'Party',
175 20 => 'Snow',
176 21 => 'Night Scenery',
177 22 => 'Food', #7
178 23 => 'Baby', #JD
179 24 => 'Soft Skin', #PH (LZ6)
180 25 => 'Candlelight', #PH (LZ6)
181 26 => 'Starry Night', #PH (LZ6)
182 27 => 'High Sensitivity', #7 (LZ6)
183 28 => 'Panorama Assist', #7
184 29 => 'Underwater', #7
185 30 => 'Beach', #PH (LZ6)
186 31 => 'Aerial Photo', #PH (LZ6)
187 32 => 'Sunset', #PH (LZ6)
188 33 => 'Pet', #JD
189 34 => 'Intelligent ISO', #PH (LZ6)
190 35 => 'Clipboard', #7
191 36 => 'High Speed Continuous Shooting', #7
192 37 => 'Intelligent Auto', #7
193 39 => 'Multi-aspect', #PH (TZ5)
194 41 => 'Transform', #PH (FS7)
195 42 => 'Flash Burst', #PH (FZ28)
196 43 => 'Pin Hole', #PH (FZ28)
197 44 => 'Film Grain', #PH (FZ28)
198 45 => 'My Color', #PH (GF1)
199 46 => 'Photo Frame', #PH (FS7)
200 51 => 'HDR', #12
201);
202
203%Image::ExifTool::Panasonic::Main = (
204 WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
205 CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
206 GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
207 WRITABLE => 1,
208 0x01 => {
209 Name => 'ImageQuality',
210 Writable => 'int16u',
211 PrintConv => {
212 2 => 'High',
213 3 => 'Normal',
214 6 => 'Very High', #3 (Leica)
215 7 => 'Raw', #3 (Leica)
216 9 => 'Motion Picture', #PH (LZ6)
217 },
218 },
219 0x02 => {
220 Name => 'FirmwareVersion',
221 Writable => 'undef',
222 Notes => q{
223 for some camera models such as the FZ30 this may be an internal production
224 reference number and not the actual firmware version
225 }, # (ref http://www.stevesforums.com/forums/view_topic.php?id=87764&forum_id=23&)
226 # (can be either binary or ascii -- add decimal points if binary)
227 ValueConv => '$val=~/[\0-\x2f]/ ? join(" ",unpack("C*",$val)) : $val',
228 ValueConvInv => q{
229 $val =~ /(\d+ ){3}\d+/ and $val = pack('C*',split(' ', $val));
230 length($val) == 4 or warn "Version must be 4 numbers\n";
231 return $val;
232 },
233 PrintConv => '$val=~tr/ /./; $val',
234 PrintConvInv => '$val=~tr/./ /; $val',
235 },
236 0x03 => {
237 Name => 'WhiteBalance',
238 Writable => 'int16u',
239 PrintConv => {
240 1 => 'Auto',
241 2 => 'Daylight',
242 3 => 'Cloudy',
243 4 => 'Incandescent', #PH
244 5 => 'Manual',
245 8 => 'Flash',
246 10 => 'Black & White', #3 (Leica)
247 11 => 'Manual', #PH (FZ8)
248 12 => 'Shade', #PH (FS7)
249 },
250 },
251 0x07 => {
252 Name => 'FocusMode',
253 Writable => 'int16u',
254 PrintConv => {
255 1 => 'Auto',
256 2 => 'Manual',
257 4 => 'Auto, Focus button', #4
258 5 => 'Auto, Continuous', #4
259 # have seens 6 for GF1 - PH
260 },
261 },
262 0x0f => [
263 {
264 Name => 'AFAreaMode',
265 Condition => '$$self{Model} =~ /DMC-FZ10\b/', #JD
266 Writable => 'int8u',
267 Count => 2,
268 Notes => 'DMC-FZ10',
269 PrintConv => {
270 '0 1' => 'Spot Mode On',
271 '0 16' => 'Spot Mode Off',
272 },
273 },{
274 Name => 'AFAreaMode',
275 Writable => 'int8u',
276 Count => 2,
277 Notes => 'other models',
278 PrintConv => { #PH
279 '0 1' => '9-area', # (FS7)
280 '0 16' => '3-area (high speed)', # (FZ8)
281 '1 0' => 'Spot Focusing', # (FZ8)
282 '1 1' => '5-area', # (FZ8)
283 '16' => 'Normal?', # (only mode for DMC-LC20)
284 '16 0' => '1-area', # (FZ8)
285 '16 16' => '1-area (high speed)', # (FZ8)
286 '32 0' => 'Auto or Face Detect', # (Face Detect for FS7, Auto is DMC-L1 guess)
287 '32 1' => '3-area (left)?', # (DMC-L1 guess)
288 '32 2' => '3-area (center)?', # (DMC-L1 guess)
289 '32 3' => '3-area (right)?', # (DMC-L1 guess)
290 '64 0' => 'Face Detect',
291 },
292 },
293 ],
294 0x1a => {
295 Name => 'ImageStabilization',
296 Writable => 'int16u',
297 PrintConv => {
298 2 => 'On, Mode 1',
299 3 => 'Off',
300 4 => 'On, Mode 2',
301 # GF1 also has a mode 3
302 },
303 },
304 0x1c => {
305 Name => 'MacroMode',
306 Writable => 'int16u',
307 PrintConv => {
308 1 => 'On',
309 2 => 'Off',
310 0x101 => 'Tele-Macro', #7
311 0x201 => 'Macro Zoom', #PH (FS7)
312 },
313 },
314 0x1f => {
315 Name => 'ShootingMode',
316 Writable => 'int16u',
317 PrintConvColumns => 2,
318 PrintConv => \%shootingMode,
319 },
320 0x20 => {
321 Name => 'Audio',
322 Writable => 'int16u',
323 PrintConv => { 1 => 'Yes', 2 => 'No' },
324 },
325 0x21 => { #2
326 Name => 'DataDump',
327 Writable => 0,
328 Binary => 1,
329 },
330 # 0x22 - normally 0, but 2 for 'Simple' ShootingMode in LZ6 sample - PH
331 0x23 => {
332 Name => 'WhiteBalanceBias',
333 Format => 'int16s',
334 Writable => 'int16s',
335 ValueConv => '$val / 3',
336 ValueConvInv => '$val * 3',
337 PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)',
338 PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)',
339 },
340 0x24 => {
341 Name => 'FlashBias',
342 Format => 'int16s',
343 Writable => 'int16s',
344 },
345 0x25 => { #PH
346 Name => 'InternalSerialNumber',
347 Writable => 'undef',
348 Count => 16,
349 Notes => q{
350 this number is unique, and contains the date of manufacture, but is not the
351 same as the number printed on the camera body
352 },
353 PrintConv => q{
354 return $val unless $val=~/^([A-Z]\d{2})(\d{2})(\d{2})(\d{2})(\d{4})/;
355 my $yr = $2 + ($2 < 70 ? 2000 : 1900);
356 return "($1) $yr:$3:$4 no. $5";
357 },
358 PrintConvInv => '$_=$val; tr/A-Z0-9//dc; s/(.{3})(19|20)/$1/; $_',
359 },
360 0x26 => { #PH
361 Name => 'PanasonicExifVersion',
362 Writable => 'undef',
363 },
364 # 0x27 - values: 0 (LZ6,FX10K)
365 0x28 => {
366 Name => 'ColorEffect',
367 Writable => 'int16u',
368 # FX30 manual: (ColorMode) natural, vivid, cool, warm, b/w, sepia
369 PrintConv => {
370 1 => 'Off',
371 2 => 'Warm',
372 3 => 'Cool',
373 4 => 'Black & White',
374 5 => 'Sepia',
375 6 => 'Happy', #PH (FX70) (yes, really. you wouldn't want sad colors now would you?)
376 },
377 },
378 0x29 => { #JD
379 Name => 'TimeSincePowerOn',
380 Writable => 'int32u',
381 Notes => q{
382 time in 1/100 s from when the camera was powered on to when the image is
383 written to memory card
384 },
385 ValueConv => '$val / 100',
386 ValueConvInv => '$val * 100',
387 PrintConv => sub { # convert to format "[DD days ]HH:MM:SS.ss"
388 my $val = shift;
389 my $str = '';
390 if ($val >= 24 * 3600) {
391 my $d = int($val / (24 * 3600));
392 $str .= "$d days ";
393 $val -= $d * 24 * 3600;
394 }
395 my $h = int($val / 3600);
396 $val -= $h * 3600;
397 my $m = int($val / 60);
398 $val -= $m * 60;
399 my $s = int($val);
400 my $f = 100 * ($val - int($val));
401 return sprintf("%s%.2d:%.2d:%.2d.%.2d",$str,$h,$m,$s,$f);
402 },
403 PrintConvInv => sub {
404 my $val = shift;
405 my @vals = ($val =~ /\d+(?:\.\d*)?/g);
406 my $sec = 0;
407 $sec += 24 * 3600 * shift(@vals) if @vals > 3;
408 $sec += 3600 * shift(@vals) if @vals > 2;
409 $sec += 60 * shift(@vals) if @vals > 1;
410 $sec += shift(@vals) if @vals;
411 return $sec;
412 },
413 },
414 0x2a => { #4
415 Name => 'BurstMode',
416 Writable => 'int16u',
417 Notes => 'decoding may be different for some models',
418 PrintConv => {
419 0 => 'Off',
420 1 => 'On', #PH (TZ5) [was "Low/High Quality" from ref 4]
421 2 => 'Infinite',
422 4 => 'Unlimited', #PH (TZ5)
423 },
424 },
425 0x2b => { #4
426 Name => 'SequenceNumber',
427 Writable => 'int32u',
428 },
429 0x2c => [
430 {
431 Name => 'ContrastMode',
432 Condition => '$$self{Model} !~ /^DMC-(FX10|G1|L1|L10|LC80|GF1|TZ10|ZS7)$/',
433 Flags => 'PrintHex',
434 Writable => 'int16u',
435 Notes => q{
436 this decoding seems to work for some models such as the LC1, LX2, FZ7, FZ8,
437 FZ18 and FZ50, but may not be correct for other models such as the FX10, G1, L1,
438 L10 and LC80
439 },
440 PrintConv => {
441 0 => 'Normal',
442 1 => 'Low',
443 2 => 'High',
444 # 3 - observed with LZ6 and TZ5 in Fireworks mode - PH
445 # 5 - observed with FX01, FX40 and FP8 (EXIF contrast "Normal") - PH
446 6 => 'Medium Low', #PH (FZ18)
447 7 => 'Medium High', #PH (FZ18)
448 # DMC-LC1 values:
449 0x100 => 'Low',
450 0x110 => 'Normal',
451 0x120 => 'High',
452 }
453 },{
454 Name => 'ContrastMode',
455 Condition => '$$self{Model} eq "DMC-GF1"',
456 Notes => 'these values are used by the GF1',
457 Writable => 'int16u',
458 PrintConv => {
459 0 => '-2',
460 1 => '-1',
461 2 => 'Normal',
462 3 => '+1',
463 4 => '+2',
464 # Note: Other Contrast tags will be "Normal" in any of these modes:
465 7 => 'Nature (Color Film)',
466 12 => 'Smooth (Color Film) or Pure (My Color)',
467 17 => 'Dynamic (B&W Film)',
468 22 => 'Smooth (B&W Film)',
469 27 => 'Dynamic (Color Film)',
470 32 => 'Vibrant (Color Film) or Expressive (My Color)',
471 33 => 'Elegant (My Color)',
472 37 => 'Nostalgic (Color Film)',
473 41 => 'Dynamic Art (My Color)',
474 42 => 'Retro (My Color)',
475 },
476 },{
477 Name => 'ContrastMode',
478 Condition => '$$self{Model} =~ /^DMC-(TZ10|ZS7)$/',
479 Notes => 'these values are used by the TZ10 and ZS7',
480 Writable => 'int16u',
481 PrintConv => {
482 0 => 'Normal',
483 1 => '-2',
484 2 => '+2',
485 5 => '-1',
486 6 => '+1',
487 },
488 },{
489 Name => 'ContrastMode',
490 Writable => 'int16u',
491 },
492 ],
493 0x2d => {
494 Name => 'NoiseReduction',
495 Writable => 'int16u',
496 PrintConv => {
497 0 => 'Standard',
498 1 => 'Low (-1)',
499 2 => 'High (+1)',
500 3 => 'Lowest (-2)', #JD
501 4 => 'Highest (+2)', #JD
502 },
503 },
504 0x2e => { #4
505 Name => 'SelfTimer',
506 Writable => 'int16u',
507 PrintConv => {
508 1 => 'Off',
509 2 => '10 s',
510 3 => '2 s',
511 },
512 },
513 # 0x2f - values: 1 (LZ6,FX10K)
514 0x30 => { #7
515 Name => 'Rotation',
516 Writable => 'int16u',
517 PrintConv => {
518 1 => 'Horizontal (normal)',
519 3 => 'Rotate 180', #PH
520 6 => 'Rotate 90 CW', #PH (ref 7 gives 270 CW)
521 8 => 'Rotate 270 CW', #PH (ref 7 gives 90 CW)
522 },
523 },
524 0x31 => { #PH (FS7)
525 Name => 'AFAssistLamp',
526 Writable => 'int16u',
527 PrintConv => {
528 1 => 'Fired',
529 2 => 'Enabled but Not Used',
530 3 => 'Disabled but Required',
531 4 => 'Disabled and Not Required',
532 # have seen a value of 5 - PH
533 # values possibly related to FOC-L? - JD
534 },
535 },
536 0x32 => { #7
537 Name => 'ColorMode',
538 Writable => 'int16u',
539 PrintConv => {
540 0 => 'Normal',
541 1 => 'Natural',
542 2 => 'Vivid',
543 # have seen 3 for GF2 - PH
544 },
545 },
546 0x33 => { #JD
547 Name => 'BabyAge',
548 Writable => 'string',
549 Notes => 'or pet age', #PH
550 PrintConv => '$val eq "9999:99:99 00:00:00" ? "(not set)" : $val',
551 PrintConvInv => '$val =~ /^\d/ ? $val : "9999:99:99 00:00:00"',
552 },
553 0x34 => { #7/PH
554 Name => 'OpticalZoomMode',
555 Writable => 'int16u',
556 PrintConv => {
557 1 => 'Standard',
558 2 => 'Extended',
559 },
560 },
561 0x35 => { #9
562 Name => 'ConversionLens',
563 Writable => 'int16u',
564 PrintConv => { #PH (unconfirmed)
565 1 => 'Off',
566 2 => 'Wide',
567 3 => 'Telephoto',
568 4 => 'Macro',
569 },
570 },
571 0x36 => { #8
572 Name => 'TravelDay',
573 Writable => 'int16u',
574 PrintConv => '$val == 65535 ? "n/a" : $val',
575 PrintConvInv => '$val =~ /(\d+)/ ? $1 : $val',
576 },
577 # 0x37 - values: 0,1,2 (LZ6, 0 for movie preview); 257 (FX10K); 0,256 (TZ5, 0 for movie preview)
578 # 0x38 - values: 0,1,2 (LZ6, same as 0x37); 1,2 (FX10K); 0,256 (TZ5, 0 for movie preview)
579 0x39 => { #7 (L1/L10)
580 Name => 'Contrast',
581 Format => 'int16s',
582 Writable => 'int16u',
583 %Image::ExifTool::Exif::printParameter,
584 },
585 0x3a => {
586 Name => 'WorldTimeLocation',
587 Writable => 'int16u',
588 PrintConv => {
589 1 => 'Home',
590 2 => 'Destination',
591 },
592 },
593 0x3b => { #PH (TZ5/FS7)
594 # (tags 0x3b, 0x3e, 0x8008 and 0x8009 have the same values in all my samples - PH)
595 Name => 'TextStamp',
596 Writable => 'int16u',
597 PrintConv => { 1 => 'Off', 2 => 'On' },
598 },
599 0x3c => { #PH
600 Name => 'ProgramISO', # (maybe should rename this ISOSetting?)
601 Writable => 'int16u',
602 PrintConv => {
603 OTHER => sub { return shift },
604 65534 => 'Intelligent ISO', #PH (FS7)
605 65535 => 'n/a',
606 },
607 },
608 0x3d => { #PH
609 Name => 'AdvancedSceneMode',
610 Writable => 'int16u',
611 # values for the FZ28 (SceneMode/AdvancedSceneMode, "*"=add mode name) - PH:
612 # Portrait: 2/1=Normal*, 24/1=Soft Skin, 2/2=Outdoor*, 2/3=Indoor*, 2/4=Creative*
613 # Scenery: 3/1=Normal*, 3/2=Nature, 3/3=Architecture, 3/4=Creative*
614 # Sports: 4/1=Normal*, 4/2=Outdoor*, 4/3=Indoor*, 4/4=Creative*
615 # Night Scenery: 5/1=Night Portrait, 21/1=*, 21/2=Illuminations, 21/4=Creative*
616 # Macro (Close-up): 9/2=Flower, 22/1=Food, 9/3=Objects, 9/4=Creative*
617 # - have seen value of 5 for TZ5 (Macro) and FS20 (Scenery and Intelligent Auto)
618 # --> I'm guessing this is "Auto" - PH
619 # - values for HDR mode (ref 12): 1=Standard, 2=Art, 3=B&W
620 PrintConv => {
621 1 => 'Normal',
622 2 => 'Outdoor/Illuminations/Flower/HDR Art',
623 3 => 'Indoor/Architecture/Objects/HDR B&W',
624 4 => 'Creative',
625 5 => 'Auto',
626 7 => 'Expressive', #(GF1)
627 8 => 'Retro', #(GF1)
628 9 => 'Pure', #(GF1)
629 10 => 'Elegant', #(GF1)
630 12 => 'Monochrome', #(GF1)
631 13 => 'Dynamic Art', #(GF1)
632 14 => 'Silhouette', #(GF1)
633 },
634 },
635 0x3e => { #PH (TZ5/FS7)
636 # (tags 0x3b, 0x3e, 0x8008 and 0x8009 have the same values in all my samples - PH)
637 Name => 'TextStamp',
638 Writable => 'int16u',
639 PrintConv => { 1 => 'Off', 2 => 'On' },
640 },
641 0x3f => { #PH (TZ7)
642 Name => 'FacesDetected',
643 Writable => 'int16u',
644 },
645 0x40 => { #7 (L1/L10)
646 Name => 'Saturation',
647 Format => 'int16s',
648 Writable => 'int16u',
649 %Image::ExifTool::Exif::printParameter,
650 },
651 0x41 => { #7 (L1/L10)
652 Name => 'Sharpness',
653 Format => 'int16s',
654 Writable => 'int16u',
655 %Image::ExifTool::Exif::printParameter,
656 },
657 0x42 => { #7 (DMC-L1)
658 Name => 'FilmMode',
659 Writable => 'int16u',
660 PrintConv => {
661 0 => 'n/a', #PH (ie. FZ100 "Photo Frame" ShootingMode)
662 1 => 'Standard (color)',
663 2 => 'Dynamic (color)',
664 3 => 'Nature (color)',
665 4 => 'Smooth (color)',
666 5 => 'Standard (B&W)',
667 6 => 'Dynamic (B&W)',
668 7 => 'Smooth (B&W)',
669 # 8 => 'My Film 1'? (from owner manual)
670 # 9 => 'My Film 2'?
671 10 => 'Nostalgic', # GH1
672 11 => 'Vibrant', # GH1
673 # 12 => 'Multi Film'? (in the GH1 specs)
674 },
675 },
676 # 0x43 - int16u: 2,3
677 # 0x44 - int16u: 0,2500
678 # 0x45 - int16u: 0
679 0x46 => { #PH/JD
680 Name => 'WBAdjustAB',
681 Format => 'int16s',
682 Writable => 'int16u',
683 Notes => 'positive is a shift toward blue',
684 },
685 0x47 => { #PH/JD
686 Name => 'WBAdjustGM',
687 Format => 'int16s',
688 Writable => 'int16u',
689 Notes => 'positive is a shift toward green',
690 },
691 # 0x48 - int16u: 0
692 # 0x49 - int16u: 2
693 # 0x4a - int16u: 0
694 0x4b => { #PH
695 Name => 'PanasonicImageWidth',
696 Writable => 'int32u',
697 },
698 0x4c => { #PH
699 Name => 'PanasonicImageHeight',
700 Writable => 'int32u',
701 },
702 0x4d => { #PH (FS7)
703 Name => 'AFPointPosition',
704 Writable => 'rational64u',
705 Count => 2,
706 Notes => 'X Y coordinates of primary AF area center, in the range 0.0 to 1.0',
707 PrintConv => q{
708 return 'none' if $val eq '16777216 16777216';
709 my @a = split ' ', $val;
710 sprintf("%.2g %.2g",@a);
711 },
712 PrintConvInv => '$val eq "none" ? "16777216 16777216" : $val',
713 },
714 0x4e => { #PH
715 Name => 'FaceDetInfo',
716 PrintConv => 'length $val',
717 SubDirectory => {
718 TagTable => 'Image::ExifTool::Panasonic::FaceDetInfo',
719 },
720 },
721 # 0x4f,0x50 - int16u: 0
722 0x51 => {
723 Name => 'LensType',
724 Writable => 'string',
725 },
726 0x52 => { #7 (DMC-L1)
727 Name => 'LensSerialNumber',
728 Writable => 'string',
729 },
730 0x53 => { #7 (DMC-L1)
731 Name => 'AccessoryType',
732 Writable => 'string',
733 },
734 # 0x54 - string[14]: "0000000"
735 # 0x55 - int16u: 1
736 # 0x57 - int16u: 0
737 0x59 => { #PH (FS7)
738 Name => 'Transform',
739 Writable => 'undef',
740 Notes => 'decoded as two 16-bit signed integers',
741 Format => 'int16s',
742 Count => 2,
743 PrintConv => {
744 '-3 2' => 'Slim High',
745 '-1 1' => 'Slim Low',
746 '0 0' => 'Off',
747 '1 1' => 'Stretch Low',
748 '3 2' => 'Stretch High',
749 },
750 },
751 # 0x5a - int16u: 0,2
752 # 0x5b - int16u: 0
753 # 0x5c - int16u: 0,2
754 0x5d => { #PH (GF1, FZ35)
755 Name => 'IntelligentExposure',
756 Notes => 'not valid for some models', # (doesn't change in ZS7 and GH1 images)
757 Writable => 'int16u',
758 PrintConv => {
759 0 => 'Off',
760 1 => 'Low',
761 2 => 'Standard',
762 3 => 'High',
763 },
764 },
765 # 0x5e,0x5f,0x60 - undef[4]
766 0x61 => { #PH
767 Name => 'FaceRecInfo',
768 SubDirectory => {
769 TagTable => 'Image::ExifTool::Panasonic::FaceRecInfo',
770 },
771 },
772 0x62 => { #PH (FS7)
773 Name => 'FlashWarning',
774 Writable => 'int16u',
775 PrintConv => { 0 => 'No', 1 => 'Yes (flash required but disabled)' },
776 },
777 0x63 => { #PH
778 # not sure exactly what this means, but in my samples this is
779 # FacesRecognized bytes of 0x01, padded with 0x00 to a length of 4 - PH
780 Name => 'RecognizedFaceFlags',
781 Format => 'int8u',
782 Count => 4,
783 Writable => 'undef',
784 Unknown => 1,
785 },
786 0x65 => { #15
787 Name => 'Title',
788 Format => 'string',
789 Writable => 'undef', # (Count 64)
790 },
791 0x66 => { #15
792 Name => 'BabyName',
793 Notes => 'or pet name',
794 Format => 'string',
795 Writable => 'undef', # (Count 64)
796 },
797 0x67 => { #15
798 Name => 'Location',
799 Groups => { 2 => 'Location' },
800 Format => 'string',
801 Writable => 'undef', # (Count 64)
802 },
803 # 0x68 - int8u: 1
804 0x69 => { #PH (ZS7)
805 Name => 'Country', # (Country/Region)
806 Groups => { 2 => 'Location' },
807 Format => 'string',
808 Writable => 'undef', # (Count 72)
809 },
810 # 0x6a - int8u: 1
811 0x6b => { #PH (ZS7)
812 Name => 'State', # (State/Province/Count -- what is Count?)
813 Groups => { 2 => 'Location' },
814 Format => 'string',
815 Writable => 'undef', # (Count 72)
816 },
817 # 0x6c - int8u: 1
818 0x6d => { #PH (ZS7)
819 Name => 'City', # (City/Town)
820 Groups => { 2 => 'Location' },
821 Format => 'string',
822 Writable => 'undef', # (Count 72)
823 },
824 # 0x6e - int8u: 1
825 0x6f => { #PH (ZS7)
826 Name => 'Landmark', # (Landmark)
827 Groups => { 2 => 'Location' },
828 Format => 'string',
829 Writable => 'undef', # (Count 128)
830 },
831 0x70 => { #PH (ZS7)
832 Name => 'IntelligentResolution',
833 Writable => 'int8u',
834 PrintConv => {
835 0 => 'Off',
836 # Note: I think these values make sense for the GH2, but meanings
837 # may be different for other models
838 1 => 'Low',
839 2 => 'Standard',
840 3 => 'High',
841 4 => 'Extended',
842 },
843 },
844 # 0x71 - undef[128] (maybe text stamp text?)
845 # 0x72,0x73,0x74,0x75,0x76,0x77,0x78: 0
846 0x79 => { #PH (GH2)
847 Name => 'IntelligentD-Range',
848 Writable => 'int16u',
849 PrintConv => {
850 0 => 'Off',
851 1 => 'Low',
852 2 => 'Standard',
853 3 => 'High',
854 },
855 },
856 # 0x7a,0x7b: 0
857 0x0e00 => {
858 Name => 'PrintIM',
859 Description => 'Print Image Matching',
860 Writable => 0,
861 SubDirectory => {
862 TagTable => 'Image::ExifTool::PrintIM::Main',
863 },
864 },
865 0x8000 => { #PH
866 Name => 'MakerNoteVersion',
867 Format => 'undef',
868 },
869 0x8001 => { #7/PH/JD
870 Name => 'SceneMode',
871 Writable => 'int16u',
872 PrintConvColumns => 2,
873 PrintConv => {
874 0 => 'Off',
875 %shootingMode,
876 },
877 },
878 # 0x8002 - values: 1,2 related to focus? (PH/JD)
879 # 1 for HDR modes, 2 for Portrait (ref 12)
880 # 0x8003 - values: 1,2 related to focus? (PH/JD)
881 0x8004 => { #PH/JD
882 Name => 'WBRedLevel',
883 Writable => 'int16u',
884 },
885 0x8005 => { #PH/JD
886 Name => 'WBGreenLevel',
887 Writable => 'int16u',
888 },
889 0x8006 => { #PH/JD
890 Name => 'WBBlueLevel',
891 Writable => 'int16u',
892 },
893 0x8007 => { #PH
894 Name => 'FlashFired',
895 Writable => 'int16u',
896 PrintConv => { 1 => 'No', 2 => 'Yes' },
897 },
898 0x8008 => { #PH (TZ5/FS7)
899 # (tags 0x3b, 0x3e, 0x8008 and 0x8009 have the same values in all my samples - PH)
900 Name => 'TextStamp',
901 Writable => 'int16u',
902 PrintConv => { 1 => 'Off', 2 => 'On' },
903 },
904 0x8009 => { #PH (TZ5/FS7)
905 # (tags 0x3b, 0x3e, 0x8008 and 0x8009 have the same values in all my samples - PH)
906 Name => 'TextStamp',
907 Writable => 'int16u',
908 PrintConv => { 1 => 'Off', 2 => 'On' },
909 },
910 0x8010 => { #PH
911 Name => 'BabyAge',
912 Writable => 'string',
913 Notes => 'or pet age',
914 PrintConv => '$val eq "9999:99:99 00:00:00" ? "(not set)" : $val',
915 PrintConvInv => '$val =~ /^\d/ ? $val : "9999:99:99 00:00:00"',
916 },
917 0x8012 => { #PH (FS7)
918 Name => 'Transform',
919 Writable => 'undef',
920 Notes => 'decoded as two 16-bit signed integers',
921 Format => 'int16s',
922 Count => 2,
923 PrintConv => {
924 '-3 2' => 'Slim High',
925 '-1 1' => 'Slim Low',
926 '0 0' => 'Off',
927 '1 1' => 'Stretch Low',
928 '3 2' => 'Stretch High',
929 },
930 },
931);
932
933# Leica type2 maker notes (ref 10)
934%Image::ExifTool::Panasonic::Leica2 = (
935 WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
936 CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
937 GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
938 WRITABLE => 1,
939 NOTES => 'These tags are used by the Leica M8.',
940 0x300 => {
941 Name => 'Quality',
942 Writable => 'int16u',
943 PrintConv => {
944 1 => 'Fine',
945 2 => 'Basic',
946 },
947 },
948 0x302 => {
949 Name => 'UserProfile',
950 Writable => 'int32u',
951 PrintConv => {
952 1 => 'User Profile 1',
953 2 => 'User Profile 2',
954 3 => 'User Profile 3',
955 4 => 'User Profile 0 (Dynamic)',
956 },
957 },
958 0x303 => {
959 Name => 'SerialNumber',
960 Writable => 'int32u',
961 PrintConv => 'sprintf("%.7d", $val)',
962 PrintConvInv => '$val',
963 },
964 0x304 => {
965 Name => 'WhiteBalance',
966 Writable => 'int16u',
967 Notes => 'values above 0x8000 are converted to Kelvin color temperatures',
968 PrintConv => {
969 0 => 'Auto or Manual',
970 1 => 'Daylight',
971 2 => 'Fluorescent',
972 3 => 'Tungsten',
973 4 => 'Flash',
974 10 => 'Cloudy',
975 11 => 'Shade',
976 OTHER => \&WhiteBalanceConv,
977 },
978 },
979 0x310 => {
980 Name => 'LensInfo',
981 SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::LensInfo' },
982 },
983 0x311 => {
984 Name => 'ExternalSensorBrightnessValue',
985 Format => 'rational64s', # (incorrectly unsigned in JPEG images)
986 Writable => 'rational64s',
987 Notes => '"blue dot" measurement',
988 PrintConv => 'sprintf("%.2f", $val)',
989 PrintConvInv => '$val',
990 },
991 0x312 => {
992 Name => 'MeasuredLV',
993 Format => 'rational64s', # (incorrectly unsigned in JPEG images)
994 Writable => 'rational64s',
995 Notes => 'imaging sensor or TTL exposure meter measurement',
996 PrintConv => 'sprintf("%.2f", $val)',
997 PrintConvInv => '$val',
998 },
999 0x313 => {
1000 Name => 'ApproximateFNumber',
1001 Writable => 'rational64u',
1002 PrintConv => 'sprintf("%.1f", $val)',
1003 PrintConvInv => '$val',
1004 },
1005 0x320 => {
1006 Name => 'CameraTemperature',
1007 Writable => 'int32s',
1008 PrintConv => '"$val C"',
1009 PrintConvInv => '$val=~s/ ?C//; $val',
1010 },
1011 0x321 => { Name => 'ColorTemperature', Writable => 'int32u' },
1012 0x322 => { Name => 'WBRedLevel', Writable => 'rational64u' },
1013 0x323 => { Name => 'WBGreenLevel', Writable => 'rational64u' },
1014 0x324 => { Name => 'WBBlueLevel', Writable => 'rational64u' },
1015 0x325 => {
1016 Name => 'UV-IRFilterCorrection',
1017 Description => 'UV/IR Filter Correction',
1018 Writable => 'int32u',
1019 PrintConv => {
1020 0 => 'Not Active',
1021 1 => 'Active',
1022 },
1023 },
1024 0x330 => { Name => 'CCDVersion', Writable => 'int32u' },
1025 0x331 => { Name => 'CCDBoardVersion', Writable => 'int32u' },
1026 0x332 => { Name => 'ControllerBoardVersion', Writable => 'int32u' },
1027 0x333 => { Name => 'M16CVersion', Writable => 'int32u' },
1028 0x340 => { Name => 'ImageIDNumber', Writable => 'int32u' },
1029);
1030
1031# Leica type3 maker notes (ref PH)
1032%Image::ExifTool::Panasonic::Leica3 = (
1033 WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
1034 CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
1035 GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1036 WRITABLE => 1,
1037 NOTES => 'These tags are used by the Leica R8 and R9 digital backs.',
1038 0x0d => {
1039 Name => 'WB_RGBLevels',
1040 Writable => 'int16u',
1041 Count => 3,
1042 },
1043);
1044
1045# Leica type4 maker notes (ref PH) (M9)
1046%Image::ExifTool::Panasonic::Leica4 = (
1047 WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
1048 CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
1049 GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1050 WRITABLE => 1,
1051 NOTES => 'This information is written by the M9.',
1052 0x3000 => {
1053 Name => 'Subdir3000',
1054 SubDirectory => {
1055 TagTable => 'Image::ExifTool::Panasonic::Subdir',
1056 ByteOrder => 'Unknown',
1057 },
1058 },
1059 0x3100 => {
1060 Name => 'Subdir3100',
1061 SubDirectory => {
1062 TagTable => 'Image::ExifTool::Panasonic::Subdir',
1063 ByteOrder => 'Unknown',
1064 },
1065 },
1066 0x3400 => {
1067 Name => 'Subdir3400',
1068 SubDirectory => {
1069 TagTable => 'Image::ExifTool::Panasonic::Subdir',
1070 ByteOrder => 'Unknown',
1071 },
1072 },
1073 0x3900 => {
1074 Name => 'Subdir3900',
1075 SubDirectory => {
1076 TagTable => 'Image::ExifTool::Panasonic::Subdir',
1077 ByteOrder => 'Unknown',
1078 },
1079 },
1080);
1081
1082# Leica M9 SubDirectory tags (ref PH)
1083%Image::ExifTool::Panasonic::Subdir = (
1084 WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
1085 CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
1086 GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1087 TAG_PREFIX => 'Leica_Subdir',
1088 WRITABLE => 1,
1089 # 0x3001 - normally 0 but value of 2 when manual coding is used
1090 # with a coded lens (but only tested with Elmar-M 50mm f/2.8) - PH
1091 0x300a => {
1092 Name => 'Contrast',
1093 Writable => 'int32u',
1094 PrintConv => {
1095 0 => 'Low',
1096 1 => 'Medium Low',
1097 2 => 'Normal',
1098 3 => 'Medium High',
1099 4 => 'High',
1100 },
1101 },
1102 0x300b => {
1103 Name => 'Sharpening',
1104 Writable => 'int32u',
1105 PrintConv => {
1106 0 => 'Off',
1107 1 => 'Low',
1108 2 => 'Normal',
1109 3 => 'Medium High',
1110 4 => 'High',
1111 },
1112 },
1113 0x300d => {
1114 Name => 'Saturation',
1115 Writable => 'int32u',
1116 PrintConv => {
1117 0 => 'Low',
1118 1 => 'Medium Low',
1119 2 => 'Normal',
1120 3 => 'Medium High',
1121 4 => 'High',
1122 5 => 'Black & White',
1123 6 => 'Vintage B&W',
1124 },
1125 },
1126 # 0x3032 - some sort of RGB coefficients? (zeros unless Kelvin WB, but same for all Color Temps)
1127 0x3033 => {
1128 Name => 'WhiteBalance',
1129 Writable => 'int32u',
1130 PrintConv => { #13
1131 0 => 'Auto',
1132 1 => 'Tungsten',
1133 2 => 'Fluorescent',
1134 3 => 'Daylight Fluorescent',
1135 4 => 'Daylight',
1136 5 => 'Flash',
1137 6 => 'Cloudy',
1138 7 => 'Shade',
1139 8 => 'Manual',
1140 9 => 'Kelvin',
1141 },
1142 },
1143 0x3034 => {
1144 Name => 'JPEGQuality',
1145 Writable => 'int32u',
1146 PrintConv => {
1147 94 => 'Basic',
1148 97 => 'Fine',
1149 },
1150 },
1151 # 0x3035 (int32u): -1 unless Manual WB (2 in my Manual sample)
1152 0x3036 => {
1153 Name => 'WB_RGBLevels',
1154 Writable => 'rational64u',
1155 Count => 3,
1156 },
1157 0x3038 => {
1158 Name => 'UserProfile', # (CameraProfile according to ref 14)
1159 Writable => 'string',
1160 },
1161 0x303a => {
1162 Name => 'JPEGSize',
1163 Writable => 'int32u',
1164 PrintConv => {
1165 0 => '5216x3472',
1166 1 => '3840x2592',
1167 2 => '2592x1728',
1168 3 => '1728x1152',
1169 4 => '1280x864',
1170 },
1171 },
1172 0x3103 => { #13 (valid for FW 1.116 and later)
1173 Name => 'SerialNumber',
1174 Writable => 'string',
1175 },
1176 # 0x3104 body-dependent string ("00012905000000") (not serial number)
1177 # 0x3105 body-dependent string ("00012905000000")
1178 # 0x3107 - body-dependent string ("4H205800116800") (not serial number)
1179 0x3109 => {
1180 Name => 'FirmwareVersion',
1181 Writable => 'string',
1182 },
1183 0x312a => { #14 (NC)
1184 Name => 'BaseISO',
1185 Writable => 'int32u',
1186 },
1187 0x312b => {
1188 Name => 'SensorWidth',
1189 Writable => 'int32u',
1190 },
1191 0x312c => {
1192 Name => 'SensorHeight',
1193 Writable => 'int32u',
1194 },
1195 0x312d => { #14 (NC)
1196 Name => 'SensorBitDepth',
1197 Writable => 'int32u',
1198 },
1199 0x3402 => { #PH/13
1200 Name => 'CameraTemperature',
1201 Writable => 'int32s',
1202 PrintConv => '"$val C"',
1203 PrintConvInv => '$val=~s/ ?C//; $val',
1204 },
1205 0x3405 => {
1206 Name => 'LensType',
1207 Writable => 'int32u',
1208 SeparateTable => 1,
1209 ValueConv => '($val >> 2) . " " . ($val & 0x3)',
1210 ValueConvInv => \&LensTypeConvInv,
1211 PrintConv => \%leicaLensType,
1212 },
1213 0x3406 => { #PH/13
1214 Name => 'ApproximateFNumber',
1215 Writable => 'rational64u',
1216 PrintConv => 'sprintf("%.1f", $val)',
1217 PrintConvInv => '$val',
1218 },
1219 0x3407 => { #14
1220 Name => 'MeasuredLV',
1221 Writable => 'int32s',
1222 Notes => 'imaging sensor or TTL exposure meter measurement',
1223 ValueConv => '$val / 1e5', #PH (NC)
1224 ValueConvInv => '$val * 1e5', #PH (NC)
1225 PrintConv => 'sprintf("%.2f", $val)',
1226 PrintConvInv => '$val',
1227 },
1228 0x3408 => { #14
1229 Name => 'ExternalSensorBrightnessValue',
1230 Writable => 'int32s',
1231 Notes => '"blue dot" measurement',
1232 ValueConv => '$val / 1e5', #PH (NC)
1233 ValueConvInv => '$val * 1e5', #PH (NC)
1234 PrintConv => 'sprintf("%.2f", $val)',
1235 PrintConvInv => '$val',
1236 },
1237 0x3901 => {
1238 Name => 'Data1',
1239 SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::Data1' },
1240 },
1241 0x3902 => {
1242 Name => 'Data2',
1243 SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::Data2' },
1244 },
1245 # 0x3903 - larger binary data block
1246);
1247
1248%Image::ExifTool::Panasonic::Data1 = (
1249 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1250 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
1251 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
1252 GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1253 WRITABLE => 1,
1254 TAG_PREFIX => 'Leica_Data1',
1255 FIRST_ENTRY => 0,
1256 0x0016 => {
1257 Name => 'LensType',
1258 Writable => 'int32u',
1259 Priority => 0,
1260 SeparateTable => 1,
1261 ValueConv => '($val >> 2) . " " . ($val & 0x3)',
1262 ValueConvInv => \&LensTypeConvInv,
1263 PrintConv => \%leicaLensType,
1264 },
1265);
1266
1267%Image::ExifTool::Panasonic::Data2 = (
1268 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1269 GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1270 TAG_PREFIX => 'Leica_Data2',
1271 FIRST_ENTRY => 0,
1272);
1273
1274# Leica type5 maker notes (ref PH) (X1)
1275%Image::ExifTool::Panasonic::Leica5 = (
1276 WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
1277 CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
1278 GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1279 WRITABLE => 1,
1280 NOTES => 'This information is written by the X1.',
1281 # 0x0406 - saturation or sharpness
1282 0x0407 => { Name => 'OriginalFileName', Writable => 'string' },
1283 0x0408 => { Name => 'OriginalDirectory',Writable => 'string' },
1284 # 0x040b - related to white balance
1285 0x040d => {
1286 Name => 'ExposureMode',
1287 Format => 'int8u',
1288 Count => 4,
1289 PrintConv => {
1290 '0 0 0 0' => 'Program AE',
1291 '1 0 0 0' => 'Aperture-priority AE',
1292 '2 0 0 0' => 'Shutter speed priority AE', #(guess)
1293 '3 0 0 0' => 'Manual',
1294 },
1295 },
1296 # 0x0411 - saturation or sharpness
1297 0x0412 => { Name => 'FilmMode', Writable => 'string' },
1298 0x0413 => { Name => 'WB_RGBLevels', Writable => 'rational64u', Count => 3 },
1299);
1300
1301# Leica type6 maker notes (ref PH) (S2)
1302%Image::ExifTool::Panasonic::Leica6 = (
1303 WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
1304 CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
1305 GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1306 NOTES => 'This information is written by the S2 (as a trailer in JPEG images).',
1307 0x300 => {
1308 Name => 'PreviewImage',
1309 Writable => 'undef',
1310 Notes => 'S2',
1311 DataTag => 'PreviewImage',
1312 RawConv => q{
1313 return \$val if $val =~ /^Binary/;
1314 return \$val if $val =~ /^\xff\xd8\xff/;
1315 $$self{PreviewError} = 1 unless $val eq 'none';
1316 return undef;
1317 },
1318 ValueConvInv => '$val || "none"',
1319 WriteCheck => 'return $val=~/^(none|\xff\xd8\xff)/s ? undef : "Not a valid image"',
1320 ChangeBase => '$dirStart + $dataPos - 8',
1321 },
1322 0x301 => {
1323 Name => 'UnknownBlock',
1324 Notes => 'unknown 320kB block, not copied to JPEG images',
1325 Flags => [ 'Unknown', 'Binary', 'Drop' ],
1326 },
1327 # 0x302 - same value as 4 unknown bytes at the end of JPEG or after the DNG TIFF header
1328 0x303 => {
1329 Name => 'LensType',
1330 Writable => 'string',
1331 },
1332 # 0x340 - same as 0x302
1333);
1334
1335# Type 2 tags (ref PH)
1336%Image::ExifTool::Panasonic::Type2 = (
1337 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1338 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
1339 FIRST_ENTRY => 0,
1340 FORMAT => 'int16u',
1341 NOTES => q{
1342 This type of maker notes is used by models such as the NV-DS65, PV-D2002,
1343 PV-DC3000, PV-DV203, PV-DV401, PV-DV702, PV-L2001, PV-SD4090, PV-SD5000 and
1344 iPalm.
1345 },
1346 0 => {
1347 Name => 'MakerNoteType',
1348 Format => 'string[4]',
1349 },
1350 # seems to vary inversely with amount of light, so I'll call it 'Gain' - PH
1351 # (minimum is 16, maximum is 136. Value is 0 for pictures captured from video)
1352 3 => 'Gain',
1353);
1354
1355# lens information (ref 10)
1356%Image::ExifTool::Panasonic::LensInfo = (
1357 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1358 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
1359 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
1360 GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1361 WRITABLE => 1,
1362 FORMAT => 'int32u',
1363 FIRST_ENTRY => 0,
1364 0 => {
1365 Name => 'LensType',
1366 Mask => 0xfffffffc,
1367 PrintHex => 0,
1368 SeparateTable => 1,
1369 ValueConv => '$val >> 2',
1370 ValueConvInv => '$val << 2',
1371 PrintConv => \%leicaLensType,
1372 },
1373 0.1 => { # lower 2 bits give frame selector position
1374 Name => 'FrameSelector',
1375 Mask => 0x03,
1376 PrintConv => {
1377 1 => '28/90mm frame lines engaged',
1378 2 => '24/35mm frame lines engaged',
1379 3 => '50/75mm frame lines engaged',
1380 },
1381 },
1382);
1383
1384# Face detection position information (ref PH)
1385%Image::ExifTool::Panasonic::FaceDetInfo = (
1386 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1387 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
1388 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
1389 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
1390 WRITABLE => 1,
1391 FORMAT => 'int16u',
1392 FIRST_ENTRY => 0,
1393 DATAMEMBER => [ 0 ],
1394 NOTES => 'Face detection position information.',
1395 0 => {
1396 Name => 'NumFacePositions',
1397 Format => 'int16u',
1398 DataMember => 'NumFacePositions',
1399 RawConv => '$$self{NumFacePositions} = $val',
1400 Notes => q{
1401 number of detected face positions stored in this record. May be less than
1402 FacesDetected
1403 },
1404 },
1405 1 => {
1406 Name => 'Face1Position',
1407 Format => 'int16u[4]',
1408 RawConv => '$$self{NumFacePositions} < 1 ? undef : $val',
1409 Notes => q{
1410 4 numbers: X/Y coordinates of the face center and width/height of face.
1411 Coordinates are relative to an image twice the size of the thumbnail, or 320
1412 pixels wide
1413 },
1414 },
1415 5 => {
1416 Name => 'Face2Position',
1417 Format => 'int16u[4]',
1418 RawConv => '$$self{NumFacePositions} < 2 ? undef : $val',
1419 },
1420 9 => {
1421 Name => 'Face3Position',
1422 Format => 'int16u[4]',
1423 RawConv => '$$self{NumFacePositions} < 3 ? undef : $val',
1424 },
1425 13 => {
1426 Name => 'Face4Position',
1427 Format => 'int16u[4]',
1428 RawConv => '$$self{NumFacePositions} < 4 ? undef : $val',
1429 },
1430 17 => {
1431 Name => 'Face5Position',
1432 Format => 'int16u[4]',
1433 RawConv => '$$self{NumFacePositions} < 5 ? undef : $val',
1434 },
1435);
1436
1437# Face recognition information from DMC-TZ7 (ref PH)
1438%Image::ExifTool::Panasonic::FaceRecInfo = (
1439 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1440 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
1441 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
1442 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
1443 WRITABLE => 1,
1444 FIRST_ENTRY => 0,
1445 DATAMEMBER => [ 0 ],
1446 NOTES => q{
1447 Tags written by cameras with facial recognition. These cameras not only
1448 detect faces in an image, but also recognize specific people based a
1449 user-supplied set of known faces.
1450 },
1451 0 => {
1452 Name => 'FacesRecognized',
1453 Format => 'int16u',
1454 DataMember => 'FacesRecognized',
1455 RawConv => '$$self{FacesRecognized} = $val',
1456 },
1457 4 => {
1458 Name => 'RecognizedFace1Name',
1459 Format => 'string[20]',
1460 RawConv => '$$self{FacesRecognized} < 1 ? undef : $val',
1461 },
1462 24 => {
1463 Name => 'RecognizedFace1Position',
1464 Format => 'int16u[4]',
1465 RawConv => '$$self{FacesRecognized} < 1 ? undef : $val',
1466 Notes => 'coordinates in same format as face detection tags above',
1467 },
1468 32 => {
1469 Name => 'RecognizedFace1Age',
1470 Format => 'string[20]',
1471 RawConv => '$$self{FacesRecognized} < 1 ? undef : $val',
1472 },
1473 52 => {
1474 Name => 'RecognizedFace2Name',
1475 Format => 'string[20]',
1476 RawConv => '$$self{FacesRecognized} < 2 ? undef : $val',
1477 },
1478 72 => {
1479 Name => 'RecognizedFace2Position',
1480 Format => 'int16u[4]',
1481 RawConv => '$$self{FacesRecognized} < 2 ? undef : $val',
1482 },
1483 80 => {
1484 Name => 'RecognizedFace2Age',
1485 Format => 'string[20]',
1486 RawConv => '$$self{FacesRecognized} < 2 ? undef : $val',
1487 },
1488 100 => {
1489 Name => 'RecognizedFace3Name',
1490 Format => 'string[20]',
1491 RawConv => '$$self{FacesRecognized} < 3 ? undef : $val',
1492 },
1493 120 => {
1494 Name => 'RecognizedFace3Position',
1495 Format => 'int16u[4]',
1496 RawConv => '$$self{FacesRecognized} < 3 ? undef : $val',
1497 },
1498 128 => {
1499 Name => 'RecognizedFace3Age',
1500 Format => 'string[20]',
1501 RawConv => '$$self{FacesRecognized} < 3 ? undef : $val',
1502 },
1503);
1504
1505#------------------------------------------------------------------------------
1506# Inverse conversion for Leica M9 lens codes
1507# Inputs: 0) value
1508# Returns: Converted value, or undef on error
1509sub LensTypeConvInv($)
1510{
1511 my $val = shift;
1512 if ($val =~ /^(\d+) (\d+)$/) {
1513 return ($1 << 2) + ($2 & 0x03);
1514 } elsif ($val =~ /^\d+$/) {
1515 my $bits = $frameSelectorBits{$val};
1516 return undef unless defined $bits;
1517 return ($val << 2) | $bits;
1518 } else {
1519 return undef;
1520 }
1521}
1522
1523#------------------------------------------------------------------------------
1524# Convert Leica Kelvin white balance
1525# Inputs: 0) value, 1) flag to perform inverse conversion
1526# Returns: Converted value, or undef on error
1527sub WhiteBalanceConv($;$$)
1528{
1529 my ($val, $inv) = @_;
1530 if ($inv) {
1531 return $1 + 0x8000 if $val =~ /(\d+)/;
1532 } else {
1533 return ($val - 0x8000) . ' Kelvin' if $val > 0x8000;
1534 }
1535 return undef;
1536}
1537
1538#------------------------------------------------------------------------------
1539# Process MakerNote trailer written by Leica S2
1540# Inputs: 0) ExifTool object ref, 1) new absolute position of Leica trailer when writing
1541# Returns: On success: 1 when reading, directory data when writing; othewise undef
1542# Notes:
1543# - may be called twice for a file if the first call doesn't succeed
1544# - must leave RAF position unchanged
1545# - uses information from LeicaTrailer member:
1546# TagInfo = tag info ref for MakerNote SubDirectory
1547# Offset/Size = value offset/size from MakerNote IFD
1548# TrailStart/TrailLen = actual JPEG trailer position/size (2nd call only)
1549# - deletes LeicaTrailer member and sets LeicaTrailerPos when successful
1550sub ProcessLeicaTrailer($;$)
1551{
1552 my ($exifTool, $newPos) = @_;
1553 my $trail = $$exifTool{LeicaTrailer};
1554 my $raf = $$exifTool{RAF};
1555 my $trailPos = $$trail{TrailPos};
1556 my $pos = $trailPos || $$trail{Offset};
1557 my $len = $$trail{TrailLen} || $$trail{Size};
1558 my ($buff, $result, %tagPtr);
1559
1560 delete $$exifTool{LeicaTrailer} if $trailPos; # done after this
1561 unless ($len > 0) {
1562 $exifTool->Warn('Missing Leica MakerNote trailer', 1) if $trailPos;
1563 undef $$exifTool{LeicaTrailer};
1564 return undef;
1565 }
1566 my $oldPos = $raf->Tell();
1567 my $ok = ($raf->Seek($pos, 0) and $raf->Read($buff, $len) == $len);
1568 $raf->Seek($oldPos, 0);
1569 unless ($ok) {
1570 $exifTool->Warn('Error reading Leica MakerNote trailer', 1) if $trailPos;
1571 return undef;
1572 }
1573 # look for Leica MakerNote header (should be at start of
1574 # trailer, but allow up to 256 bytes of garbage just in case)
1575 if ($buff !~ /^(.{0,256})LEICA\0..../sg) {
1576 my $what = $trailPos ? 'trailer' : 'offset';
1577 $exifTool->Warn("Invalid Leica MakerNote $what", 1);
1578 return undef;
1579 }
1580 my $junk = $1;
1581 my $start = pos($buff) - 10;
1582 if ($start and not $trailPos) {
1583 $exifTool->Warn('Invalid Leica MakerNote offset', 1);
1584 return undef;
1585 }
1586#
1587# all checks passed -- go ahead and process the trailer now
1588#
1589 my $hdrLen = 8;
1590 my $dirStart = $start + $hdrLen;
1591 my $tagInfo = $$trail{TagInfo};
1592 if ($$exifTool{HTML_DUMP}) {
1593 my $name = $$tagInfo{Name};
1594 $exifTool->HDump($pos+$start, $len-$start, "$name value", 'Leica MakerNote trailer', 4);
1595 $exifTool->HDump($pos+$start, $hdrLen, "MakerNotes header", $name);
1596 } elsif ($exifTool->Options('Verbose')) {
1597 my $where = sprintf('at offset 0x%x', $pos);
1598 $exifTool->VPrint(0, "Leica MakerNote trailer ($len bytes $where):\n");
1599 }
1600 # delete LeicaTrailer member so we don't try to process it again
1601 delete $$exifTool{LeicaTrailer};
1602 $$exifTool{LeicaTrailerPos} = $pos + $start; # return actual start position of Leica trailer
1603
1604 my $oldOrder = GetByteOrder();
1605 my $num = Get16u(\$buff, $dirStart); # get entry count
1606 ToggleByteOrder() if ($num>>8) > ($num&0xff); # set byte order
1607
1608 # use specialized algorithm to automatically fix offsets
1609 my $valStart = $dirStart + 2 + 12 * $num + 4;
1610 my $fix = 0;
1611 if ($valStart < $len) {
1612 my $valBlock = Image::ExifTool::MakerNotes::GetValueBlocks(\$buff, $dirStart, \%tagPtr);
1613 # find the minimum offset (excluding the PreviewImage tag 0x300)
1614 my $minPtr;
1615 foreach (keys %tagPtr) {
1616 my $ptr = $tagPtr{$_};
1617 next if $_ == 0x300 or not $ptr;
1618 $minPtr = $ptr if not defined $minPtr or $minPtr > $ptr;
1619 }
1620 if ($minPtr) {
1621 my $diff = $minPtr - ($valStart + $pos);
1622 # scan value data for the first non-zero byte
1623 pos($buff) = $valStart;
1624 if ($buff =~ /[^\0]/g) {
1625 my $n = pos($buff) - 1 - $valStart; # number of zero bytes
1626 # S2 writes 282 bytes of zeros, exiftool writes none
1627 my $expect = $n >= 282 ? 282 : 0;
1628 my $fixBase = $exifTool->Options('FixBase');
1629 if ($diff != $expect or defined $fixBase) {
1630 $fix = $expect - $diff;
1631 if (defined $fixBase) {
1632 $fix = $fixBase if $fixBase ne '';
1633 $exifTool->Warn("Adjusted MakerNotes base by $fix",1);
1634 } else {
1635 $exifTool->Warn("Possibly incorrect maker notes offsets (fixed by $fix)",1);
1636 }
1637 }
1638 }
1639 }
1640 }
1641 # generate dirInfo for Leica MakerNote directory
1642 my %dirInfo = (
1643 Name => $$tagInfo{Name},
1644 Base => $fix,
1645 DataPt => \$buff,
1646 DataPos => $pos - $fix,
1647 DataLen => $len,
1648 DirStart => $dirStart,
1649 DirLen => $len - $dirStart,
1650 DirName => 'MakerNotes',
1651 Parent => 'ExifIFD',
1652 TagInfo => $tagInfo,
1653 );
1654 my $tagTablePtr = GetTagTable($$tagInfo{SubDirectory}{TagTable});
1655 if ($newPos) { # are we writing?
1656 # set position of new MakerNote IFD (+ 8 for Leica MakerNote header)
1657 $dirInfo{NewDataPos} = $newPos + $start + 8;
1658 $result = $exifTool->WriteDirectory(\%dirInfo, $tagTablePtr);
1659 # write preview image last if necessary and fix up the preview offsets
1660 my $previewInfo = $$exifTool{PREVIEW_INFO};
1661 delete $$exifTool{PREVIEW_INFO};
1662 if ($result) {
1663 if ($previewInfo) {
1664 my $fixup = $previewInfo->{Fixup};
1665 # set preview offset (relative to start of makernotes, + 8 for makernote header)
1666 $fixup->SetMarkerPointers(\$result, 'PreviewImage', length($result) + 8);
1667 $result .= $$previewInfo{Data};
1668 }
1669 return $junk . substr($buff, $start, $hdrLen) . $result;
1670 }
1671 } else {
1672 # extract information
1673 $result = $exifTool->ProcessDirectory(\%dirInfo, $tagTablePtr);
1674 # also extract as a block if necessary
1675 if ($exifTool->Options('MakerNotes') or
1676 $exifTool->{REQ_TAG_LOOKUP}{lc($$tagInfo{Name})})
1677 {
1678 # makernote header must be included in RebuildMakerNotes call
1679 $dirInfo{DirStart} -= 8;
1680 $dirInfo{DirLen} += 8;
1681 $exifTool->{MAKER_NOTE_BYTE_ORDER} = GetByteOrder();
1682 # rebuild maker notes (creates $exifTool->{MAKER_NOTE_FIXUP})
1683 my $val = Image::ExifTool::Exif::RebuildMakerNotes($exifTool, $tagTablePtr, \%dirInfo);
1684 unless (defined $val) {
1685 $exifTool->Warn('Error rebuilding maker notes (may be corrupt)');
1686 $val = $buff,
1687 }
1688 my $key = $exifTool->FoundTag($tagInfo, $val);
1689 $exifTool->SetGroup($key, 'ExifIFD');
1690 }
1691 }
1692 SetByteOrder($oldOrder);
1693 return $result;
1694}
1695
16961; # end
1697
1698__END__
1699
1700=head1 NAME
1701
1702Image::ExifTool::Panasonic - Panasonic/Leica maker notes tags
1703
1704=head1 SYNOPSIS
1705
1706This module is loaded automatically by Image::ExifTool when required.
1707
1708=head1 DESCRIPTION
1709
1710This module contains definitions required by Image::ExifTool to interpret
1711Panasonic and Leica maker notes in EXIF information.
1712
1713=head1 AUTHOR
1714
1715Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
1716
1717This library is free software; you can redistribute it and/or modify it
1718under the same terms as Perl itself.
1719
1720=head1 REFERENCES
1721
1722=over 4
1723
1724=item L<http://www.compton.nu/panasonic.html>
1725
1726=item L<http://johnst.org/sw/exiftags/>
1727
1728=item L<http://homepage3.nifty.com/kamisaka/makernote/makernote_pana.htm>
1729
1730=item L<http://bretteville.com/pdfs/M8Metadata_v2.pdf>
1731
1732=item L<http://www.digital-leica.com/lens_codes/index.html>
1733
1734=item (...plus lots of testing with store demos and my wife's DMC-FS7!)
1735
1736=back
1737
1738=head1 ACKNOWLEDGEMENTS
1739
1740Thanks to Tels for the information he provided on decoding some tags, and to
1741Marcel Coenen, Jens Duttke and Michael Byczkowski for their contributions.
1742
1743=head1 SEE ALSO
1744
1745L<Image::ExifTool::TagNames/Panasonic Tags>,
1746L<Image::ExifTool(3pm)|Image::ExifTool>
1747
1748=cut
Note: See TracBrowser for help on using the repository browser.