File Coverage

blib/lib/Image/ExifTool/Panasonic.pm
Criterion Covered Total %
statement 16 139 11.5
branch 2 78 2.5
condition 0 44 0.0
subroutine 5 8 62.5
pod 0 4 0.0
total 23 273 8.4


line stmt bran cond sub pod time code
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             # (now https://www.l-camera-forum.com/leica-news/leica-lens-codes/)
18             # 12) Joerg - http://www.cpanforum.com/threads/11602 (LX3 firmware 2.0)
19             # 13) Michael Byczkowski private communication (Leica M9)
20             # 14) Carl Bretteville private communication (M9)
21             # 15) Zdenek Mihula private communication (TZ8)
22             # 16) Olaf Ulrich private communication
23             # 17) https://exiftool.org/forum/index.php/topic,4922.0.html
24             # 18) Thomas Modes private communication (G6)
25             # 19) https://exiftool.org/forum/index.php/topic,5533.0.html
26             # 20) Bernd-Michael Kemper private communication (DMC-GX80/85)
27             # 21) Klaus Homeister forum post
28             # 22) Daniel Beichl private communication (G9)
29             # 23) Tim Gray private communication (M10 Monochrom)
30             # JD) Jens Duttke private communication (TZ3,FZ30,FZ50)
31             #------------------------------------------------------------------------------
32              
33             package Image::ExifTool::Panasonic;
34              
35 29     29   4509 use strict;
  29         76  
  29         1018  
36 29     29   149 use vars qw($VERSION %leicaLensTypes);
  29         70  
  29         1472  
37 29     29   170 use Image::ExifTool qw(:DataAccess :Utils);
  29         64  
  29         5430  
38 29     29   1258 use Image::ExifTool::Exif;
  29         109  
  29         152370  
39              
40             $VERSION = '2.17';
41              
42             sub ProcessLeicaLEIC($$$);
43             sub WhiteBalanceConv($;$$);
44              
45             # Leica lens types (ref 10)
46             %leicaLensTypes = (
47             OTHER => sub {
48             my ($val, $inv, $conv) = @_;
49             return undef if $inv or not $val =~ s/ .*//;
50             return $$conv{$val};
51             },
52             Notes => q{
53             the LensType value is obtained by splitting the stored value into 2
54             integers: The stored value divided by 4, and its lower 2 bits. The second
55             number is used only if necessary to identify certain manually coded lenses
56             on the M9, or the focal length of some multi-focal lenses.
57             },
58             # All M9 codes (two numbers: first the LensID then the lower 2 bits)
59             # are ref PH with samples from ref 13. From ref 10, the lower 2 bits of
60             # the LensType value give the frame selector position for most lenses,
61             # although for the 28-35-50mm (at least) it gives the focal length selection.
62             # The M9 also gives the focal length selection but for other lenses the
63             # lower 3 bits don't change with frame selector position except for the lens
64             # shows as uncoded for certain lenses and some incorrect positions of the
65             # frame selector. The bits are zero for uncoded lenses when manually coding
66             # from the menu on the M9. - PH
67             # Frame selector bits (from ref 10, M8):
68             # 1 => '28/90mm frame lines engaged',
69             # 2 => '24/35mm frame lines engaged',
70             # 3 => '50/75mm frame lines engaged',
71             '0 0' => 'Uncoded lens',
72             #
73             # NOTE: MUST ADD ENTRY TO %frameSelectorBits below when a new lens is added!!!!
74             #
75             # model number(s):
76             1 => 'Elmarit-M 21mm f/2.8', # 11134
77             3 => 'Elmarit-M 28mm f/2.8 (III)', # 11804
78             4 => 'Tele-Elmarit-M 90mm f/2.8 (II)', # 11800
79             5 => 'Summilux-M 50mm f/1.4 (II)', # 11868/11856/11114
80             6 => 'Summicron-M 35mm f/2 (IV)', # 11310/11311
81             '6 0' => 'Summilux-M 35mm f/1.4', # 11869/11870/11860
82             7 => 'Summicron-M 90mm f/2 (II)', # 11136/11137
83             9 => 'Elmarit-M 135mm f/2.8 (I/II)', # 11829
84             '9 0' => 'Apo-Telyt-M 135mm f/3.4', # 11889
85             11 => 'Summaron-M 28mm f/5.6', # ? (ref IB)
86             12 => 'Thambar-M 90mm f/2.2', # ? (ref IB)
87             16 => 'Tri-Elmar-M 16-18-21mm f/4 ASPH.',# 11626
88             '16 1' => 'Tri-Elmar-M 16-18-21mm f/4 ASPH. (at 16mm)',
89             '16 2' => 'Tri-Elmar-M 16-18-21mm f/4 ASPH. (at 18mm)',
90             '16 3' => 'Tri-Elmar-M 16-18-21mm f/4 ASPH. (at 21mm)',
91             23 => 'Summicron-M 50mm f/2 (III)', # 11817, version (I) in camera menu
92             24 => 'Elmarit-M 21mm f/2.8 ASPH.', # 11135/11897
93             25 => 'Elmarit-M 24mm f/2.8 ASPH.', # 11878/11898
94             26 => 'Summicron-M 28mm f/2 ASPH.', # 11604
95             27 => 'Elmarit-M 28mm f/2.8 (IV)', # 11809
96             28 => 'Elmarit-M 28mm f/2.8 ASPH.', # 11606
97             29 => 'Summilux-M 35mm f/1.4 ASPH.', # 11874/11883
98             '29 0' => 'Summilux-M 35mm f/1.4 ASPHERICAL', # 11873 (different from "ASPH." model!)
99             30 => 'Summicron-M 35mm f/2 ASPH.', # 11879/11882
100             31 => 'Noctilux-M 50mm f/1', # 11821/11822
101             '31 0' => 'Noctilux-M 50mm f/1.2', # 11820
102             32 => 'Summilux-M 50mm f/1.4 ASPH.', # 11891/11892
103             33 => 'Summicron-M 50mm f/2 (IV, V)', # 11819/11825/11826/11816, version (II,III) in camera menu
104             34 => 'Elmar-M 50mm f/2.8', # 11831/11823/11825
105             35 => 'Summilux-M 75mm f/1.4', # 11814/11815/11810
106             36 => 'Apo-Summicron-M 75mm f/2 ASPH.', # 11637
107             37 => 'Apo-Summicron-M 90mm f/2 ASPH.', # 11884/11885
108             38 => 'Elmarit-M 90mm f/2.8', # 11807/11808, version (II) in camera menu
109             39 => 'Macro-Elmar-M 90mm f/4', # 11633/11634
110             '39 0' => 'Tele-Elmar-M 135mm f/4 (II)',# 11861
111             40 => 'Macro-Adapter M', # 14409
112             41 => 'Apo-Summicron-M 50mm f/2 ASPH.', #IB
113             '41 3' => 'Apo-Summicron-M 50mm f/2 ASPH.', #16
114             42 => 'Tri-Elmar-M 28-35-50mm f/4 ASPH.',# 11625
115             '42 1' => 'Tri-Elmar-M 28-35-50mm f/4 ASPH. (at 28mm)',
116             '42 2' => 'Tri-Elmar-M 28-35-50mm f/4 ASPH. (at 35mm)',
117             '42 3' => 'Tri-Elmar-M 28-35-50mm f/4 ASPH. (at 50mm)',
118             43 => 'Summarit-M 35mm f/2.5', # ? (ref PH)
119             44 => 'Summarit-M 50mm f/2.5', # ? (ref PH)
120             45 => 'Summarit-M 75mm f/2.5', # ? (ref PH)
121             46 => 'Summarit-M 90mm f/2.5', # ?
122             47 => 'Summilux-M 21mm f/1.4 ASPH.', # ? (ref 11)
123             48 => 'Summilux-M 24mm f/1.4 ASPH.', # ? (ref 11)
124             49 => 'Noctilux-M 50mm f/0.95 ASPH.', # ? (ref 11)
125             50 => 'Elmar-M 24mm f/3.8 ASPH.', # ? (ref 11)
126             51 => 'Super-Elmar-M 21mm f/3.4 Asph', # ? (ref 16, frameSelectorBits=1)
127             '51 2' => 'Super-Elmar-M 14mm f/3.8 Asph', # ? (ref 16)
128             52 => 'Apo-Telyt-M 18mm f/3.8 ASPH.', # ? (ref PH/11)
129             53 => 'Apo-Telyt-M 135mm f/3.4', #IB
130             '53 2' => 'Apo-Telyt-M 135mm f/3.4', #16
131             '53 3' => 'Apo-Summicron-M 50mm f/2 (VI)', #LR
132             58 => 'Noctilux-M 75mm f/1.25 ASPH.', # ? (ref IB)
133             );
134              
135             # M9 frame selector bits for each lens
136             # 1 = towards lens = 28/90mm or 21mm or Adapter (or Elmarit-M 135mm f/2.8)
137             # 2 = away from lens = 24/35mm (or 35/135mm on the M9)
138             # 3 = middle position = 50/75mm or 18mm
139             my %frameSelectorBits = (
140             1 => 1,
141             3 => 1,
142             4 => 1,
143             5 => 3,
144             6 => 2,
145             7 => 1,
146             9 => 1, # (because lens has special magnifier for the rangefinder)
147             16 => 1, # or 2 or 3
148             23 => 3,
149             24 => 1,
150             25 => 2,
151             26 => 1,
152             27 => 1,
153             28 => 1,
154             29 => 2,
155             30 => 2,
156             31 => 3,
157             32 => 3,
158             33 => 3,
159             34 => 3,
160             35 => 3,
161             36 => 3,
162             37 => 1,
163             38 => 1,
164             39 => 1,
165             40 => 1,
166             42 => 1, # or 2 or 3
167             43 => 2, # (NC)
168             44 => 3, # (NC)
169             45 => 3,
170             46 => 1, # (NC)
171             47 => 1, # (NC)
172             48 => 2, # (NC)
173             49 => 3, # (NC)
174             50 => 2, # (NC)
175             51 => 1, # or 2 (ref 16)
176             52 => 3,
177             53 => 2, #16
178             );
179              
180             # conversions for ShootingMode and SceneMode
181             my %shootingMode = (
182             1 => 'Normal',
183             2 => 'Portrait',
184             3 => 'Scenery',
185             4 => 'Sports',
186             5 => 'Night Portrait',
187             6 => 'Program',
188             7 => 'Aperture Priority',
189             8 => 'Shutter Priority',
190             9 => 'Macro',
191             10 => 'Spot', #7
192             11 => 'Manual',
193             12 => 'Movie Preview', #PH (LZ6)
194             13 => 'Panning',
195             14 => 'Simple', #PH (LZ6)
196             15 => 'Color Effects', #7
197             16 => 'Self Portrait', #PH (TZ5)
198             17 => 'Economy', #7
199             18 => 'Fireworks',
200             19 => 'Party',
201             20 => 'Snow',
202             21 => 'Night Scenery',
203             22 => 'Food', #7
204             23 => 'Baby', #JD
205             24 => 'Soft Skin', #PH (LZ6)
206             25 => 'Candlelight', #PH (LZ6)
207             26 => 'Starry Night', #PH (LZ6)
208             27 => 'High Sensitivity', #7 (LZ6)
209             28 => 'Panorama Assist', #7
210             29 => 'Underwater', #7
211             30 => 'Beach', #PH (LZ6)
212             31 => 'Aerial Photo', #PH (LZ6)
213             32 => 'Sunset', #PH (LZ6)
214             33 => 'Pet', #JD
215             34 => 'Intelligent ISO', #PH (LZ6)
216             35 => 'Clipboard', #7
217             36 => 'High Speed Continuous Shooting', #7
218             37 => 'Intelligent Auto', #7
219             39 => 'Multi-aspect', #PH (TZ5)
220             41 => 'Transform', #PH (FS7)
221             42 => 'Flash Burst', #PH (FZ28)
222             43 => 'Pin Hole', #PH (FZ28)
223             44 => 'Film Grain', #PH (FZ28)
224             45 => 'My Color', #PH (GF1)
225             46 => 'Photo Frame', #PH (FS7)
226             48 => 'Movie', #PH (GM1)
227             # 49 - seen for FS4 (snow?)
228             51 => 'HDR', #12
229             52 => 'Peripheral Defocus', #Horst Wandres
230             55 => 'Handheld Night Shot', #PH (FZ47)
231             57 => '3D', #PH (3D1)
232             59 => 'Creative Control', #PH (FZ47)
233             60 => 'Intelligent Auto Plus', #20
234             62 => 'Panorama', #17
235             63 => 'Glass Through', #17
236             64 => 'HDR', #17
237             66 => 'Digital Filter', #PH (GF5 "Impressive Art", "Cross Process", "Color Select", "Star")
238             67 => 'Clear Portrait', #18
239             68 => 'Silky Skin', #18
240             69 => 'Backlit Softness', #18
241             70 => 'Clear in Backlight', #18
242             71 => 'Relaxing Tone', #18
243             72 => "Sweet Child's Face", #18
244             73 => 'Distinct Scenery', #18
245             74 => 'Bright Blue Sky', #18
246             75 => 'Romantic Sunset Glow', #18
247             76 => 'Vivid Sunset Glow', #18
248             77 => 'Glistening Water', #18
249             78 => 'Clear Nightscape', #18
250             79 => 'Cool Night Sky', #18
251             80 => 'Warm Glowing Nightscape', #18
252             81 => 'Artistic Nightscape', #18
253             82 => 'Glittering Illuminations', #18
254             83 => 'Clear Night Portrait', #18
255             84 => 'Soft Image of a Flower', #18
256             85 => 'Appetizing Food', #18
257             86 => 'Cute Dessert', #18
258             87 => 'Freeze Animal Motion', #18
259             88 => 'Clear Sports Shot', #18
260             89 => 'Monochrome', #18
261             90 => 'Creative Control', #18
262             92 => 'Handheld Night Shot', #forum11523
263             );
264              
265             %Image::ExifTool::Panasonic::Main = (
266             WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
267             CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
268             GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
269             WRITABLE => 1,
270             0x01 => {
271             Name => 'ImageQuality',
272             Writable => 'int16u',
273             Notes => 'quality of the main image, which may be in a different file',
274             PrintConv => {
275             1 => 'TIFF', #PH (FZ20)
276             2 => 'High',
277             3 => 'Normal',
278             # 5 - seen this for 1920x1080, 30fps SZ7 video - PH
279             6 => 'Very High', #3 (Leica)
280             7 => 'RAW', #3 (Leica)
281             9 => 'Motion Picture', #PH (LZ6)
282             11 => 'Full HD Movie', #PH (V-LUX)
283             12 => '4k Movie', #PH (V-LUX)
284             },
285             },
286             0x02 => {
287             Name => 'FirmwareVersion',
288             Writable => 'undef',
289             Notes => q{
290             for some camera models such as the FZ30 this may be an internal production
291             reference number and not the actual firmware version
292             }, # (ref http://www.stevesforums.com/forums/view_topic.php?id=87764&forum_id=23&)
293             # (can be either binary or ascii -- add decimal points if binary)
294             ValueConv => '$val=~/[\0-\x2f]/ ? join(" ",unpack("C*",$val)) : $val',
295             ValueConvInv => q{
296             $val =~ /(\d+ ){3}\d+/ and $val = pack('C*',split(' ', $val));
297             length($val) == 4 or warn "Version must be 4 numbers\n";
298             return $val;
299             },
300             PrintConv => '$val=~tr/ /./; $val',
301             PrintConvInv => '$val=~tr/./ /; $val',
302             },
303             0x03 => {
304             Name => 'WhiteBalance',
305             Writable => 'int16u',
306             PrintConv => {
307             1 => 'Auto',
308             2 => 'Daylight',
309             3 => 'Cloudy',
310             4 => 'Incandescent', #PH
311             5 => 'Manual',
312             8 => 'Flash',
313             10 => 'Black & White', #3 (Leica)
314             11 => 'Manual 2', #PH (FZ8)
315             12 => 'Shade', #PH (FS7)
316             13 => 'Kelvin', #PeterK (NC)
317             14 => 'Manual 3', #forum9296
318             15 => 'Manual 4', #forum9296
319             # also seen 18,26 (forum9296)
320             19 => 'Auto (cool)', #PH (Leica C-Lux)
321             },
322             },
323             0x07 => {
324             Name => 'FocusMode',
325             Writable => 'int16u',
326             PrintConv => {
327             1 => 'Auto',
328             2 => 'Manual',
329             4 => 'Auto, Focus button', #4
330             5 => 'Auto, Continuous', #4
331             6 => 'AF-S', #18 (also seen for GF1 - PH)
332             7 => 'AF-C', #18
333             8 => 'AF-F', #18 (auto-focus flexible)
334             },
335             },
336             0x0f => [
337             {
338             Name => 'AFAreaMode',
339             Condition => '$$self{Model} =~ /DMC-FZ10\b/', #JD
340             Writable => 'int8u',
341             Count => 2,
342             Notes => 'DMC-FZ10',
343             PrintConv => {
344             '0 1' => 'Spot Mode On',
345             '0 16' => 'Spot Mode Off',
346             },
347             },{
348             Name => 'AFAreaMode',
349             Writable => 'int8u',
350             Count => 2,
351             Notes => 'other models',
352             PrintConv => { #PH
353             '0 1' => '9-area', # (FS7)
354             '0 16' => '3-area (high speed)', # (FZ8)
355             '0 23' => '23-area', #PH (FZ47,NC)
356             '0 49' => '49-area', #20
357             '0 225' => '225-area', #22
358             '1 0' => 'Spot Focusing', # (FZ8)
359             '1 1' => '5-area', # (FZ8)
360             '16' => 'Normal?', # (only mode for DMC-LC20)
361             '16 0' => '1-area', # (FZ8)
362             '16 16' => '1-area (high speed)', # (FZ8)
363             # '32 0' is Face Detect for FS7, and Face Detect or Focus Tracking
364             # for the DMC-FZ200 (ref 17), and Auto is DMC-L1 guess,
365             '32 0' => 'Tracking',
366             '32 1' => '3-area (left)?', # (DMC-L1 guess)
367             '32 2' => '3-area (center)?', # (DMC-L1 guess)
368             '32 3' => '3-area (right)?', # (DMC-L1 guess)
369             '64 0' => 'Face Detect',
370             '64 1' => 'Face Detect (animal detect on)', #forum11194
371             '64 2' => 'Face Detect (animal detect off)', #forum11194
372             '128 0' => 'Pinpoint focus', #18/forum11194
373             '240 0' => 'Tracking', #22
374             },
375             },
376             ],
377             0x1a => {
378             Name => 'ImageStabilization',
379             Writable => 'int16u',
380             PrintConv => {
381             2 => 'On, Optical',
382             3 => 'Off',
383             4 => 'On, Mode 2',
384             5 => 'On, Optical Panning', #18
385             # GF1 also has a "Mode 3" - PH
386             6 => 'On, Body-only', #PH (GX7, sensor shift?)
387             7 => 'On, Body-only Panning', #forum11194
388             9 => 'Dual IS', #20
389             10 => 'Dual IS Panning', #forum11194
390             11 => 'Dual2 IS', #forum9298
391             12 => 'Dual2 IS Panning', #forum11194
392             },
393             },
394             0x1c => {
395             Name => 'MacroMode',
396             Writable => 'int16u',
397             PrintConv => {
398             1 => 'On',
399             2 => 'Off',
400             0x101 => 'Tele-Macro', #7
401             0x201 => 'Macro Zoom', #PH (FS7)
402             },
403             },
404             0x1f => {
405             Name => 'ShootingMode',
406             Writable => 'int16u',
407             PrintConvColumns => 2,
408             PrintConv => \%shootingMode,
409             },
410             0x20 => {
411             Name => 'Audio',
412             Writable => 'int16u',
413             PrintConv => {
414             1 => 'Yes',
415             2 => 'No',
416             3 => 'Stereo', #PH (NC)
417             },
418             },
419             0x21 => { #2
420             Name => 'DataDump',
421             Writable => 0,
422             Binary => 1,
423             },
424             # 0x22 - normally 0, but 2 for 'Simple' ShootingMode in LZ6 sample - PH
425             0x23 => {
426             Name => 'WhiteBalanceBias',
427             Format => 'int16s',
428             Writable => 'int16s',
429             ValueConv => '$val / 3',
430             ValueConvInv => '$val * 3',
431             PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)',
432             PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)',
433             },
434             0x24 => {
435             Name => 'FlashBias',
436             Format => 'int16s',
437             Writable => 'int16s',
438             ValueConv => '$val / 3', #17 (older models may not have factor of 3? - PH)
439             ValueConvInv => '$val * 3',
440             PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)',
441             PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)',
442             },
443             0x25 => { #PH
444             Name => 'InternalSerialNumber',
445             Writable => 'undef',
446             Count => 16,
447             Notes => q{
448             this number is unique, and contains the date of manufacture, but is not the
449             same as the number printed on the camera body
450             },
451             PrintConv => q{
452             return $val unless $val=~/^([A-Z][0-9A-Z]{2})(\d{2})(\d{2})(\d{2})(\d{4})/;
453             my $yr = $2 + ($2 < 70 ? 2000 : 1900);
454             return "($1) $yr:$3:$4 no. $5";
455             },
456             PrintConvInv => '$_=$val; tr/A-Z0-9//dc; s/(.{3})(19|20)/$1/; $_',
457             },
458             0x26 => { #PH
459             Name => 'PanasonicExifVersion',
460             Writable => 'undef',
461             },
462             0x27 => {
463             Name => 'VideoFrameRate',
464             Writable => 'int16u',
465             Notes => 'only valid for older models',
466             PrintConv => {
467             OTHER => sub { shift },
468             0 => 'n/a',
469             },
470             },
471             0x28 => {
472             Name => 'ColorEffect',
473             Writable => 'int16u',
474             # FX30 manual: (ColorMode) natural, vivid, cool, warm, b/w, sepia
475             PrintConv => {
476             1 => 'Off',
477             2 => 'Warm',
478             3 => 'Cool',
479             4 => 'Black & White',
480             5 => 'Sepia',
481             6 => 'Happy', #PH (FX70) (yes, really. you wouldn't want sad colors now would you?)
482             8 => 'Vivid', #PH (SZ3)
483             },
484             },
485             0x29 => { #JD
486             Name => 'TimeSincePowerOn',
487             Writable => 'int32u',
488             Notes => q{
489             time in 1/100 s from when the camera was powered on to when the image is
490             written to memory card
491             },
492             ValueConv => '$val / 100',
493             ValueConvInv => '$val * 100',
494             PrintConv => sub { # convert to format "[DD days ]HH:MM:SS.ss"
495             my $val = shift;
496             my $str = '';
497             if ($val >= 24 * 3600) {
498             my $d = int($val / (24 * 3600));
499             $str .= "$d days ";
500             $val -= $d * 24 * 3600;
501             }
502             my $h = int($val / 3600);
503             $val -= $h * 3600;
504             my $m = int($val / 60);
505             $val -= $m * 60;
506             my $ss = sprintf('%05.2f', $val);
507             if ($ss >= 60) {
508             $ss = '00.00';
509             ++$m >= 60 and $m -= 60, ++$h;
510             }
511             return sprintf("%s%.2d:%.2d:%s",$str,$h,$m,$ss);
512             },
513             PrintConvInv => sub {
514             my $val = shift;
515             my @vals = ($val =~ /\d+(?:\.\d*)?/g);
516             my $sec = 0;
517             $sec += 24 * 3600 * shift(@vals) if @vals > 3;
518             $sec += 3600 * shift(@vals) if @vals > 2;
519             $sec += 60 * shift(@vals) if @vals > 1;
520             $sec += shift(@vals) if @vals;
521             return $sec;
522             },
523             },
524             0x2a => { #4
525             Name => 'BurstMode',
526             Writable => 'int16u',
527             Notes => 'decoding may be different for some models',
528             PrintConv => {
529             0 => 'Off',
530             1 => 'On', #PH (TZ5) [was "Low/High Quality" from ref 4]
531             2 => 'Auto Exposure Bracketing (AEB)', #17
532             3 => 'Focus Bracketing', #forum11194
533             4 => 'Unlimited', #PH (TZ5)
534             8 => 'White Balance Bracketing', #18
535             17 => 'On (with flash)', #forum5597
536             18 => 'Aperture Bracketing', #forum11194
537             },
538             },
539             0x2b => { #4
540             Name => 'SequenceNumber',
541             Writable => 'int32u',
542             },
543             0x2c => [
544             {
545             Name => 'ContrastMode',
546             Condition => '$$self{Model} !~ /^DMC-(FX10|G1|L1|L10|LC80|GF\d+|G2|TZ10|ZS7)$/',
547             Flags => 'PrintHex',
548             Writable => 'int16u',
549             Notes => q{
550             this decoding seems to work for some models such as the LC1, LX2, FZ7, FZ8,
551             FZ18 and FZ50, but may not be correct for other models such as the FX10, G1, L1,
552             L10 and LC80
553             },
554             PrintConv => {
555             0x00 => 'Normal',
556             0x01 => 'Low',
557             0x02 => 'High',
558             # 0x03 - observed with LZ6 and TZ5 in Fireworks mode
559             # and GX7 in Fantasy/Retro/OldDays/HighKey - PH
560             # 0x04 - observed in MP4 movie with GM1 (EXIF and 0x39 Contrast "Normal") - PH
561             0x05 => 'Normal 2', #forum1194
562             0x06 => 'Medium Low', #PH (FZ18)
563             0x07 => 'Medium High', #PH (FZ18)
564             # 0x08 - GX7 in DynamicMonochrome mode
565             0x0d => 'High Dynamic', #PH (FZ47 in ?)
566             # 0x13 - seen for LX100 (PH)
567             0x18 => 'Dynamic Range (film-like)', #forum11194
568             0x2e => 'Match Filter Effects Toy', #forum11194
569             0x37 => 'Match Photo Style L. Monochrome', #forum11194
570             # DMC-LC1 values:
571             0x100 => 'Low',
572             0x110 => 'Normal',
573             0x120 => 'High',
574             }
575             },{
576             Name => 'ContrastMode',
577             Condition => '$$self{Model} =~ /^DMC-(GF\d+|G2)$/',
578             Notes => 'these values are used by the G2, GF1, GF2, GF3, GF5 and GF6',
579             Writable => 'int16u',
580             PrintConv => { # (decoded for GF1 unless otherwise noted)
581             0 => '-2',
582             1 => '-1',
583             2 => 'Normal',
584             3 => '+1',
585             4 => '+2',
586             # Note: Other Contrast tags will be "Normal" in any of these modes:
587             5 => 'Normal 2', # 5 - seen for Portrait (FX80) and Normal (GF6)
588             7 => 'Nature (Color Film)', # (GF1,G2; GF3 "Miniature")
589             9 => 'Expressive', #(GF3)
590             12 => 'Smooth (Color Film) or Pure (My Color)', #(GF1,G2 "Smooth Color")
591             17 => 'Dynamic (B&W Film)', #(GF1,G2)
592             22 => 'Smooth (B&W Film)', #(GF1,G2)
593             25 => 'High Dynamic', #(GF5)
594             26 => 'Retro', #(GF5)
595             27 => 'Dynamic (Color Film)', #(GF1,G2) (GF3 "High Key")
596             28 => 'Low Key', #(GF5)
597             29 => 'Toy Effect', #(GF5)
598             32 => 'Vibrant (Color Film) or Expressive (My Color)', # (GF1; G2 "Vibrant"; GF2,GF5 "Expressive")
599             33 => 'Elegant (My Color)',
600             37 => 'Nostalgic (Color Film)', # (GF1,G2; GF5 "Sepia")
601             41 => 'Dynamic Art (My Color)', # (GF5 "High Key")
602             42 => 'Retro (My Color)',
603             45 => 'Cinema', #(GF2)
604             47 => 'Dynamic Mono', #(GF5)
605             50 => 'Impressive Art', #(GF5)
606             51 => 'Cross Process', #(GF5)
607             100 => 'High Dynamic 2', #Exiv2 (G6)
608             101 => 'Retro 2', #Exiv2 (G6)
609             102 => 'High Key 2', #Exiv2 (G6)
610             103 => 'Low Key 2', #Exiv2 (G6)
611             104 => 'Toy Effect 2', #Exiv2 (G6)
612             107 => 'Expressive 2', #(GF6)
613             112 => 'Sepia', #Exiv2 (G6)
614             117 => 'Miniature', #Exiv2 (G6)
615             122 => 'Dynamic Monochrome', #(GF6)
616             127 => 'Old Days', #Exiv2 (G6)
617             132 => 'Dynamic Monochrome 2', #Exiv2 (G6)
618             135 => 'Impressive Art 2', #Exiv2 (G6)
619             136 => 'Cross Process 2', #Exiv2 (G6)
620             137 => 'Toy Pop', #Exiv2 (G6)
621             138 => 'Fantasy', #Exiv2 (G6)
622             256 => 'Normal 3', #Exiv2 (G6)
623             272 => 'Standard', #Exiv2 (G6)
624             288 => 'High', #Exiv2 (G6)
625             # more new modes for GF6:
626             # ? => 'Old Days',
627             # ? => 'Toy Pop',
628             # ? => 'Bleach Bypass',
629             # ? => 'Fantasy',
630             # ? => 'Star Filter',
631             # ? => 'One Point Color',
632             # ? => 'Sunshine',
633             },
634             },{
635             Name => 'ContrastMode',
636             Condition => '$$self{Model} =~ /^DMC-(TZ10|ZS7)$/',
637             Notes => 'these values are used by the TZ10 and ZS7',
638             Writable => 'int16u',
639             PrintConv => {
640             0 => 'Normal',
641             1 => '-2',
642             2 => '+2',
643             5 => '-1',
644             6 => '+1',
645             },
646             },{
647             Name => 'ContrastMode',
648             Writable => 'int16u',
649             },
650             ],
651             0x2d => {
652             Name => 'NoiseReduction',
653             Writable => 'int16u',
654             Notes => 'the encoding for this value is not consistent between models',
655             PrintConv => {
656             0 => 'Standard',
657             1 => 'Low (-1)',
658             2 => 'High (+1)',
659             3 => 'Lowest (-2)', #JD
660             4 => 'Highest (+2)', #JD
661             5 => '+5', #PH (NC)
662             6 => '+6', # (NC) seen for DC-S1/S1R (IB)
663             65531 => '-5', # LX100/FZ2500 "NR1" test shots at imaging-resource (PH)
664             65532 => '-4',
665             65533 => '-3',
666             65534 => '-2',
667             65535 => '-1',
668             },
669             },
670             0x2e => { #4
671             Name => 'SelfTimer',
672             Writable => 'int16u',
673             PrintConv => {
674             0 => 'Off (0)', #forum11529
675             1 => 'Off',
676             2 => '10 s',
677             3 => '2 s',
678             4 => '10 s / 3 pictures', #17
679             258 => '2 s after shutter pressed', #forum11194
680             266 => '10 s after shutter pressed', #forum11194
681             778 => '3 photos after 10 s', #forum11194
682             },
683             },
684             # 0x2f - values: 1 (LZ6,FX10K)
685             0x30 => { #7
686             Name => 'Rotation',
687             Writable => 'int16u',
688             PrintConv => {
689             1 => 'Horizontal (normal)',
690             3 => 'Rotate 180', #PH
691             6 => 'Rotate 90 CW', #PH (ref 7 gives 270 CW)
692             8 => 'Rotate 270 CW', #PH (ref 7 gives 90 CW)
693             },
694             },
695             0x31 => { #PH (FS7)
696             Name => 'AFAssistLamp',
697             Writable => 'int16u',
698             PrintConv => {
699             1 => 'Fired',
700             2 => 'Enabled but Not Used',
701             3 => 'Disabled but Required',
702             4 => 'Disabled and Not Required',
703             # have seen a value of 5 - PH
704             # values possibly related to FOC-L? - JD
705             },
706             },
707             0x32 => { #7
708             Name => 'ColorMode',
709             Writable => 'int16u',
710             PrintConv => {
711             0 => 'Normal',
712             1 => 'Natural',
713             2 => 'Vivid',
714             # have seen 3 for GF2 - PH
715             },
716             },
717             0x33 => { #JD
718             Name => 'BabyAge',
719             Writable => 'string',
720             Notes => 'or pet age', #PH
721             PrintConv => '$val eq "9999:99:99 00:00:00" ? "(not set)" : $val',
722             PrintConvInv => '$val =~ /^\d/ ? $val : "9999:99:99 00:00:00"',
723             },
724             0x34 => { #7/PH
725             Name => 'OpticalZoomMode',
726             Writable => 'int16u',
727             PrintConv => {
728             1 => 'Standard',
729             2 => 'Extended',
730             },
731             },
732             0x35 => { #9
733             Name => 'ConversionLens',
734             Writable => 'int16u',
735             PrintConv => { #PH (unconfirmed)
736             1 => 'Off',
737             2 => 'Wide',
738             3 => 'Telephoto',
739             4 => 'Macro',
740             },
741             },
742             0x36 => { #8
743             Name => 'TravelDay',
744             Writable => 'int16u',
745             PrintConv => '$val == 65535 ? "n/a" : $val',
746             PrintConvInv => '$val =~ /(\d+)/ ? $1 : $val',
747             },
748             # 0x37 - values: 0,1,2 (LZ6, 0 for movie preview); 257 (FX10K); 0,256 (TZ5, 0 for movie preview)
749             # --> may indicate battery power (forum11388)
750             0x38 => { #forum11388
751             Name => 'BatteryLevel',
752             Writable => 'int16u',
753             PrintConv => {
754             1 => 'Full',
755             2 => 'Medium',
756             3 => 'Low',
757             4 => 'Near Empty',
758             7 => 'Near Full',
759             8 => 'Medium Low',
760             256 => 'n/a',
761             },
762             },
763             0x39 => { #7 (L1/L10)
764             Name => 'Contrast',
765             Format => 'int16s',
766             Writable => 'int16u',
767             %Image::ExifTool::Exif::printParameter,
768             },
769             0x3a => {
770             Name => 'WorldTimeLocation',
771             Writable => 'int16u',
772             PrintConv => {
773             1 => 'Home',
774             2 => 'Destination',
775             },
776             },
777             0x3b => { #PH (TZ5/FS7)
778             # (tags 0x3b, 0x3e, 0x8008 and 0x8009 have the same values in all my samples - PH)
779             Name => 'TextStamp',
780             Writable => 'int16u',
781             PrintConv => { 1 => 'Off', 2 => 'On' },
782             },
783             0x3c => { #PH
784             Name => 'ProgramISO', # (maybe should rename this ISOSetting?)
785             Writable => 'int16u', # (new models store a long here)
786             PrintConv => {
787             OTHER => sub { shift },
788             65534 => 'Intelligent ISO', #PH (FS7)
789             65535 => 'n/a',
790             -1 => 'n/a',
791             },
792             },
793             0x3d => { #PH
794             Name => 'AdvancedSceneType',
795             Writable => 'int16u',
796             Notes => 'used together with SceneMode to derive Composite AdvancedSceneMode',
797             # see forum11194 for more info
798             },
799             0x3e => { #PH (TZ5/FS7)
800             # (tags 0x3b, 0x3e, 0x8008 and 0x8009 have the same values in all my samples - PH)
801             Name => 'TextStamp',
802             Writable => 'int16u',
803             PrintConv => { 1 => 'Off', 2 => 'On' },
804             },
805             0x3f => { #PH (TZ7)
806             Name => 'FacesDetected',
807             Writable => 'int16u',
808             },
809             0x40 => { #7 (L1/L10)
810             Name => 'Saturation',
811             Format => 'int16s',
812             Writable => 'int16u',
813             %Image::ExifTool::Exif::printParameter,
814             },
815             0x41 => { #7 (L1/L10)
816             Name => 'Sharpness',
817             Format => 'int16s',
818             Writable => 'int16u',
819             %Image::ExifTool::Exif::printParameter,
820             },
821             0x42 => { #7 (DMC-L1)
822             Name => 'FilmMode',
823             Writable => 'int16u',
824             PrintConv => {
825             0 => 'n/a', #PH (eg. FZ100 "Photo Frame" ShootingMode)
826             1 => 'Standard (color)',
827             2 => 'Dynamic (color)',
828             3 => 'Nature (color)',
829             4 => 'Smooth (color)',
830             5 => 'Standard (B&W)',
831             6 => 'Dynamic (B&W)',
832             7 => 'Smooth (B&W)',
833             # 8 => 'My Film 1'? (from owner manual)
834             # 9 => 'My Film 2'?
835             10 => 'Nostalgic', #(GH1)
836             11 => 'Vibrant', #(GH1)
837             # 12 => 'Multi Film'? (in the GH1 specs)
838             },
839             },
840             0x43 => { #forum9369
841             Name => 'JPEGQuality',
842             Writable => 'int16u',
843             PrintConv => {
844             0 => 'n/a (Movie)',
845             2 => 'High',
846             3 => 'Standard',
847             6 => 'Very High',
848             255 => 'n/a (RAW only)',
849             },
850             },
851             0x44 => {
852             Name => 'ColorTempKelvin',
853             Format => 'int16u',
854             },
855             0x45 => { #19
856             Name => 'BracketSettings',
857             Writable => 'int16u',
858             PrintConv => {
859             0 => 'No Bracket',
860             1 => '3 Images, Sequence 0/-/+',
861             2 => '3 Images, Sequence -/0/+',
862             3 => '5 Images, Sequence 0/-/+',
863             4 => '5 Images, Sequence -/0/+',
864             5 => '7 Images, Sequence 0/-/+',
865             6 => '7 Images, Sequence -/0/+',
866             },
867             },
868             0x46 => { #PH/JD
869             Name => 'WBShiftAB',
870             Format => 'int16s',
871             Writable => 'int16u',
872             Notes => 'positive is a shift toward blue',
873             },
874             0x47 => { #PH/JD
875             Name => 'WBShiftGM',
876             Format => 'int16s',
877             Writable => 'int16u',
878             Notes => 'positive is a shift toward green',
879             },
880             0x48 => { #17
881             Name => 'FlashCurtain',
882             Writable => 'int16u',
883             PrintConv => {
884             0 => 'n/a',
885             1 => '1st',
886             2 => '2nd',
887             },
888             },
889             0x49 => { #19
890             Name => 'LongExposureNoiseReduction', # (indicates availability, forum11194)
891             Writable => 'int16u',
892             PrintConv => {
893             1 => 'Off',
894             2 => 'On'
895             }
896             },
897             # 0x4a - int16u: 0
898             0x4b => { #PH
899             Name => 'PanasonicImageWidth',
900             Writable => 'int32u',
901             },
902             0x4c => { #PH
903             Name => 'PanasonicImageHeight',
904             Writable => 'int32u',
905             },
906             0x4d => { #PH (FS7)
907             Name => 'AFPointPosition',
908             Writable => 'rational64u',
909             Count => 2,
910             Notes => 'X Y coordinates of primary AF area center, in the range 0.0 to 1.0',
911             PrintConv => q{
912             return 'none' if $val eq '16777216 16777216';
913             my @a = split ' ', $val;
914             sprintf("%.2g %.2g",@a);
915             },
916             PrintConvInv => '$val eq "none" ? "16777216 16777216" : $val',
917             },
918             0x4e => { #PH
919             Name => 'FaceDetInfo',
920             PrintConv => 'length $val',
921             SubDirectory => {
922             TagTable => 'Image::ExifTool::Panasonic::FaceDetInfo',
923             },
924             },
925             # 0x4f,0x50 - int16u: 0
926             0x51 => {
927             Name => 'LensType',
928             Writable => 'string',
929             ValueConv => '$val=~s/ +$//; $val', # trim trailing spaces
930             ValueConvInv => '$val',
931             },
932             0x52 => { #7 (DMC-L1)
933             Name => 'LensSerialNumber',
934             Writable => 'string',
935             ValueConv => '$val=~s/ +$//; $val', # trim trailing spaces
936             ValueConvInv => '$val',
937             },
938             0x53 => { #7 (DMC-L1)
939             Name => 'AccessoryType',
940             Writable => 'string',
941             ValueConv => '$val=~s/ +$//; $val', # trim trailing spaces
942             ValueConvInv => '$val',
943             },
944             0x54 => { #19
945             Name => 'AccessorySerialNumber',
946             Writable => 'string',
947             ValueConv => '$val=~s/ +$//; $val', # trim trailing spaces
948             ValueConvInv => '$val',
949             },
950             # 0x55 - int16u: 1 (see forum9372)
951             # 0x57 - int16u: 0
952             0x59 => { #PH (FS7)
953             Name => 'Transform',
954             Writable => 'undef',
955             Notes => 'decoded as two 16-bit signed integers',
956             Format => 'int16s',
957             Count => 2,
958             PrintConv => {
959             '-3 2' => 'Slim High',
960             '-1 1' => 'Slim Low',
961             '0 0' => 'Off',
962             '1 1' => 'Stretch Low',
963             '3 2' => 'Stretch High',
964             },
965             },
966             # 0x5a - int16u: 0,2
967             # 0x5b - int16u: 0
968             # 0x5c - int16u: 0,2
969             0x5d => { #PH (GF1, FZ35)
970             Name => 'IntelligentExposure',
971             Notes => 'not valid for some models', # (doesn't change in ZS7 and GH1 images)
972             Writable => 'int16u',
973             PrintConv => {
974             0 => 'Off',
975             1 => 'Low',
976             2 => 'Standard',
977             3 => 'High',
978             },
979             },
980             # 0x5e,0x5f - undef[4]
981             0x60 => { #18
982             Name => 'LensFirmwareVersion',
983             Writable => 'undef',
984             Format => 'int8u',
985             Count => 4,
986             PrintConv => '$val=~tr/ /./; $val',
987             PrintConvInv => '$val=~tr/./ /; $val',
988             },
989             0x61 => { #PH
990             Name => 'FaceRecInfo',
991             SubDirectory => {
992             TagTable => 'Image::ExifTool::Panasonic::FaceRecInfo',
993             },
994             },
995             0x62 => { #PH (FS7)
996             Name => 'FlashWarning',
997             Writable => 'int16u',
998             PrintConv => { 0 => 'No', 1 => 'Yes (flash required but disabled)' },
999             },
1000             0x63 => { #PH
1001             # not sure exactly what this means, but in my samples this is
1002             # FacesRecognized bytes of 0x01, padded with 0x00 to a length of 4 - PH
1003             Name => 'RecognizedFaceFlags',
1004             Format => 'int8u',
1005             Count => 4,
1006             Writable => 'undef',
1007             Unknown => 1,
1008             },
1009             0x65 => { #15
1010             Name => 'Title',
1011             Format => 'string',
1012             Writable => 'undef', # (Count 64)
1013             },
1014             0x66 => { #15
1015             Name => 'BabyName',
1016             Notes => 'or pet name',
1017             Format => 'string',
1018             Writable => 'undef', # (Count 64)
1019             },
1020             0x67 => { #15
1021             Name => 'Location',
1022             Groups => { 2 => 'Location' },
1023             Format => 'string',
1024             Writable => 'undef', # (Count 64)
1025             },
1026             # 0x68 - int8u: 1
1027             0x69 => { #PH (ZS7)
1028             Name => 'Country', # (Country/Region)
1029             Groups => { 2 => 'Location' },
1030             Format => 'string',
1031             Writable => 'undef', # (Count 72)
1032             },
1033             # 0x6a - int8u: 1
1034             0x6b => { #PH (ZS7)
1035             Name => 'State', # (State/Province/Count -- what is Count?)
1036             Groups => { 2 => 'Location' },
1037             Format => 'string',
1038             Writable => 'undef', # (Count 72)
1039             },
1040             # 0x6c - int8u: 1
1041             0x6d => { #PH (ZS7) (also see forum5997)
1042             Name => 'City', # (City/Town)
1043             Groups => { 2 => 'Location' },
1044             Format => 'string',
1045             Writable => 'undef', # (Count 72)
1046             Notes => 'City/Town as stored by some models, or County/Township for others',
1047             },
1048             # 0x6e - int8u: 1
1049             0x6f => { #PH (ZS7)
1050             Name => 'Landmark', # (Landmark)
1051             Groups => { 2 => 'Location' },
1052             Format => 'string',
1053             Writable => 'undef', # (Count 128)
1054             },
1055             0x70 => { #PH (ZS7)
1056             Name => 'IntelligentResolution',
1057             Writable => 'int8u',
1058             PrintConv => {
1059             0 => 'Off',
1060             # Note: I think these values make sense for the GH2, but meanings
1061             # may be different for other models
1062             1 => 'Low',
1063             2 => 'Standard',
1064             3 => 'High',
1065             4 => 'Extended',
1066             },
1067             },
1068             # 0x71 - undef[128] (maybe text stamp text?)
1069             0x77 => { #18
1070             Name => 'BurstSpeed',
1071             Writable => 'int16u',
1072             Notes => 'images per second',
1073             },
1074             # 0x72,0x73,0x74,0x75,0x77,0x78: 0
1075             # 0x76: 0, (3 for G6 with HDR on, ref 18)
1076             0x76 => { #18/21
1077             Name => 'HDRShot',
1078             Writable => 'int16u',
1079             PrintConv => { 0 => 'Off', 3 => 'On' },
1080             },
1081             0x79 => { #PH (GH2)
1082             Name => 'IntelligentD-Range',
1083             Writable => 'int16u',
1084             PrintConv => {
1085             0 => 'Off',
1086             1 => 'Low',
1087             2 => 'Standard',
1088             3 => 'High',
1089             },
1090             },
1091             # 0x7a,0x7b: 0
1092             0x7c => { #18
1093             Name => 'ClearRetouch',
1094             Writable => 'int16u',
1095             PrintConv => { 0 => 'Off', 1 => 'On' },
1096             },
1097             0x80 => { #forum5997 (seen garbage here for SZ5 - PH)
1098             Name => 'City2', # (City/Town/Village)
1099             Groups => { 2 => 'Location' },
1100             Format => 'string',
1101             Writable => 'undef', # (Count 72)
1102             Notes => 'City/Town/Village as stored by some models',
1103             },
1104             # 0x81 - undef[72]: "---"
1105             # 0x82 - undef[72]: "---"
1106             # 0x83 - undef[72]: "---"
1107             # 0x84 - undef[72]: "---"
1108             # 0x85 - undef[128]: "---"
1109             0x86 => { #http://dev.exiv2.org/issues/825
1110             Name => 'ManometerPressure',
1111             Writable => 'int16u',
1112             RawConv => '$val==65535 ? undef : $val',
1113             ValueConv => '$val / 10',
1114             ValueConvInv => '$val * 10',
1115             PrintConv => 'sprintf("%.1f kPa",$val)',
1116             PrintConvInv => '$val=~s/ ?kPa//i; $val',
1117             },
1118             0x89 => {
1119             Name => 'PhotoStyle',
1120             Writable => 'int16u',
1121             PrintConv => {
1122             0 => 'Auto',
1123             1 => 'Standard or Custom',
1124             2 => 'Vivid',
1125             3 => 'Natural',
1126             4 => 'Monochrome',
1127             5 => 'Scenery',
1128             6 => 'Portrait',
1129             8 => 'Cinelike D', #forum11194
1130             9 => 'Cinelike V', #forum11194
1131             11 => 'L. Monochrome', #forum11194
1132             15 => 'L. Monochrome D', #forum11194
1133             },
1134             },
1135             0x8a => { #18
1136             Name => 'ShadingCompensation',
1137             Writable => 'int16u',
1138             PrintConv => {
1139             0 => 'Off',
1140             1 => 'On'
1141             }
1142             },
1143             0x8b => { #21
1144             Name => 'WBShiftIntelligentAuto',
1145             Writable => 'int16u',
1146             Format => 'int16s',
1147             Notes => 'value is -9 for blue to +9 for amber. Valid for Intelligent-Auto modes',
1148             },
1149             0x8c => {
1150             Name => 'AccelerometerZ',
1151             Writable => 'int16u',
1152             Format => 'int16s',
1153             Notes => 'positive is acceleration upwards',
1154             },
1155             0x8d => {
1156             Name => 'AccelerometerX',
1157             Writable => 'int16u',
1158             Format => 'int16s',
1159             Notes => 'positive is acceleration to the left',
1160             },
1161             0x8e => {
1162             Name => 'AccelerometerY',
1163             Writable => 'int16u',
1164             Format => 'int16s',
1165             Notes => 'positive is acceleration backwards',
1166             },
1167             0x8f => { #18
1168             Name => 'CameraOrientation',
1169             Writable => 'int8u',
1170             PrintConv => {
1171             0 => 'Normal',
1172             1 => 'Rotate CW',
1173             2 => 'Rotate 180',
1174             3 => 'Rotate CCW',
1175             4 => 'Tilt Upwards',
1176             5 => 'Tilt Downwards'
1177             }
1178             },
1179             0x90 => {
1180             Name => 'RollAngle',
1181             Writable => 'int16u',
1182             Format => 'int16s',
1183             Notes => 'converted to degrees of clockwise camera rotation',
1184             ValueConv => '$val / 10',
1185             ValueConvInv => '$val * 10',
1186             },
1187             0x91 => {
1188             Name => 'PitchAngle',
1189             Writable => 'int16u',
1190             Format => 'int16s',
1191             Notes => 'converted to degrees of upward camera tilt',
1192             ValueConv => '-$val / 10',
1193             ValueConvInv => '-$val * 10',
1194             },
1195             0x92 => { #21 (forum9453) (more to decode in forum11194)
1196             Name => 'WBShiftCreativeControl',
1197             Writable => 'int8u',
1198             Format => 'int8s',
1199             Notes => 'WB shift or style strength. Valid for Creative-Control modes',
1200             },
1201             0x93 => { #18
1202             Name => 'SweepPanoramaDirection',
1203             Writable => 'int8u',
1204             PrintConv => {
1205             0 => 'Off',
1206             1 => 'Left to Right',
1207             2 => 'Right to Left',
1208             3 => 'Top to Bottom',
1209             4 => 'Bottom to Top'
1210             }
1211             },
1212             0x94 => { #18
1213             Name => 'SweepPanoramaFieldOfView',
1214             Writable => 'int16u'
1215             },
1216             0x96 => { #18
1217             Name => 'TimerRecording',
1218             Writable => 'int8u',
1219             PrintConv => {
1220             0 => 'Off',
1221             1 => 'Time Lapse',
1222             2 => 'Stop-motion Animation',
1223             3 => 'Focus Bracketing', #forum11194
1224             },
1225             },
1226             0x9d => { #18
1227             Name => 'InternalNDFilter',
1228             Writable => 'rational64u'
1229             },
1230             0x9e => { #18
1231             Name => 'HDR',
1232             Writable => 'int16u',
1233             PrintConv => {
1234             0 => 'Off',
1235             100 => '1 EV',
1236             200 => '2 EV',
1237             300 => '3 EV',
1238             32868 => '1 EV (Auto)',
1239             32968 => '2 EV (Auto)',
1240             33068 => '3 EV (Auto)',
1241             },
1242             },
1243             0x9f => { #18
1244             Name => 'ShutterType',
1245             Writable => 'int16u',
1246             PrintConv => {
1247             0 => 'Mechanical',
1248             1 => 'Electronic',
1249             2 => 'Hybrid', #PH (GM1, 1st curtain electronic, 2nd curtain mechanical)
1250             },
1251             },
1252             # 0xa0 - undef[32]: AWB gains and black levels (ref forum9303)
1253             0xa1 => { #forum11194
1254             Name => 'FilterEffect',
1255             Writable => 'rational64u',
1256             Format => 'int32u',
1257             PrintConv => {
1258             '0 0' => 'Expressive',
1259             # '0 1' => have seen this for XS1 (PH)
1260             '0 2' => 'Retro',
1261             '0 4' => 'High Key',
1262             '0 8' => 'Sepia',
1263             '0 16' => 'High Dynamic',
1264             '0 32' => 'Miniature Effect',
1265             '0 256' => 'Low Key',
1266             '0 512' => 'Toy Effect',
1267             '0 1024' => 'Dynamic Monochrome',
1268             '0 2048' => 'Soft Focus',
1269             '0 4096' => 'Impressive Art',
1270             '0 8192' => 'Cross Process',
1271             '0 16384' => 'One Point Color',
1272             '0 32768' => 'Star Filter',
1273             '0 524288' => 'Old Days',
1274             '0 1048576' => 'Sunshine',
1275             '0 2097152' => 'Bleach Bypass',
1276             '0 4194304' => 'Toy Pop',
1277             '0 8388608' => 'Fantasy',
1278             '0 33554432' => 'Monochrome',
1279             '0 67108864' => 'Rough Monochrome',
1280             '0 134217728' => 'Silky Monochrome',
1281             },
1282             },
1283             0xa3 => { #18
1284             Name => 'ClearRetouchValue',
1285             Writable => 'rational64u',
1286             # undef if ClearRetouch is off, 0 if it is on
1287             },
1288             0xa7 => { #forum9374 (conversion table for 14- to 16-bit mapping)
1289             Name => 'OutputLUT',
1290             Binary => 1,
1291             Notes => q{
1292             2-column by 432-row binary lookup table of unsigned short values for
1293             converting to 16-bit output (1st column) from 14 bits (2nd column) with
1294             camera contrast
1295             },
1296             },
1297             0xab => { #18
1298             Name => 'TouchAE',
1299             Writable => 'int16u',
1300             PrintConv => { 0 => 'Off', 1 => 'On' },
1301             },
1302             0xac => { #forum11194
1303             Name => 'MonochromeFilterEffect',
1304             Writable => 'int16u',
1305             PrintConv => { 0 => 'Off', 1 => 'Yellow', 2 => 'Orange', 3 => 'Red', 4 => 'Green' },
1306             },
1307             0xad => { #forum9360
1308             Name => 'HighlightShadow',
1309             Writable => 'int16u',
1310             Format => 'int16s', #forum11194
1311             Count => 2,
1312             },
1313             0xaf => { #PH (is this in UTC maybe? -- sometimes different time zone other times)
1314             Name => 'TimeStamp',
1315             Writable => 'string',
1316             Groups => { 2 => 'Time' },
1317             Shift => 'Time',
1318             PrintConv => '$self->ConvertDateTime($val)',
1319             PrintConvInv => '$self->InverseDateTime($val)',
1320             },
1321             0xb3 => { #forum11194
1322             Name => 'VideoBurstResolution',
1323             Writable => 'int16u',
1324             PrintConv => { 1 => 'Off or 4K', 4 => '6K' },
1325             },
1326             0xb4 => { #forum9429
1327             Name => 'MultiExposure',
1328             Writable => 'int16u',
1329             PrintConv => { 0 => 'n/a', 1 => 'Off', 2 => 'On' },
1330             },
1331             0xb9 => { #forum9425
1332             Name => 'RedEyeRemoval',
1333             Writable => 'int16u',
1334             PrintConv => { 0 => 'Off', 1 => 'On' },
1335             },
1336             0xbb => { #forum9282
1337             Name => 'VideoBurstMode',
1338             Writable => 'int32u',
1339             PrintHex => 1,
1340             PrintConv => {
1341             0x01 => 'Off',
1342             0x04 => 'Post Focus',
1343             0x18 => '4K Burst',
1344             0x28 => '4K Burst (Start/Stop)',
1345             0x48 => '4K Pre-burst',
1346             0x108 => 'Loop Recording',
1347             0x810 => '6K Burst',
1348             0x820 => '6K Burst (Start/Stop)',
1349             0x408 => 'Focus Stacking', #forum11563
1350             0x1001 => 'High Resolution Mode',
1351             },
1352             },
1353             0xbc => { #forum9282
1354             Name => 'DiffractionCorrection',
1355             Writable => 'int16u',
1356             PrintConv => { 0 => 'Off', 1 => 'Auto' },
1357             },
1358             0xbd => { #forum11194
1359             Name => 'FocusBracket',
1360             Notes => 'positive is further, negative is closer',
1361             Writable => 'int16u',
1362             Format => 'int16s',
1363             },
1364             0xbe => { #forum11194
1365             Name => 'LongExposureNRUsed',
1366             Writable => 'int16u',
1367             PrintConv => { 0 => 'No', 1 => 'Yes' },
1368             },
1369             0xbf => { #forum11194
1370             Name => 'PostFocusMerging',
1371             Format => 'int32u',
1372             Count => 2,
1373             PrintConv => { '0 0' => 'Post Focus Auto Merging or None' },
1374             },
1375             0xc1 => { #forum11194
1376             Name => 'VideoPreburst',
1377             Writable => 'int16u',
1378             PrintConv => { 0 => 'No', 1 => '4K or 6K' },
1379             },
1380             0xca => { #forum11459
1381             Name => 'SensorType',
1382             Writable => 'int16u',
1383             PrintConv => {
1384             0 => 'Multi-aspect',
1385             1 => 'Standard',
1386             },
1387             },
1388             # Note: LensTypeMake and LensTypeModel are combined into a Composite LensType tag
1389             # defined in Olympus.pm which has the same values as Olympus:LensType
1390             0xc4 => { #PH
1391             Name => 'LensTypeMake',
1392             Condition => '$format eq "int16u" and $$valPt ne "\xff\xff"', # (ignore make 65535 for now)
1393             Writable => 'int16u',
1394             },
1395             0xc5 => { #PH
1396             Name => 'LensTypeModel',
1397             Condition => '$format eq "int16u"',
1398             Writable => 'int16u',
1399             RawConv => q{
1400             return undef unless $val;
1401             require Image::ExifTool::Olympus; # (to load Composite LensID)
1402             return $val;
1403             },
1404             ValueConv => '$_=sprintf("%.4x",$val); s/(..)(..)/$2 $1/; $_',
1405             ValueConvInv => '$val =~ s/(..) (..)/$2$1/; hex($val)',
1406             },
1407             0xd1 => { #PH
1408             Name => 'ISO',
1409             RawConv => '$val > 0xfffffff0 ? undef : $val',
1410             Writable => 'int32u',
1411             },
1412             0xd2 => { #forum11194
1413             Name => 'MonochromeGrainEffect',
1414             Writable => 'int16u',
1415             PrintConv => {
1416             0 => 'Off',
1417             1 => 'Low',
1418             2 => 'Standard',
1419             3 => 'High',
1420             },
1421             },
1422             0xd6 => { #PH (DC-S1)
1423             Name => 'NoiseReductionStrength',
1424             Writable => 'rational64s',
1425             },
1426             0xe4 => { #IB
1427             Name => 'LensTypeModel',
1428             Condition => '$format eq "int16u"',
1429             Writable => 'int16u',
1430             RawConv => q{
1431             return undef unless $val;
1432             require Image::ExifTool::Olympus; # (to load Composite LensID)
1433             return $val;
1434             },
1435             ValueConv => '$_=sprintf("%.4x",$val); s/(..)(..)/$2 $1/; $_',
1436             ValueConvInv => '$val =~ s/(..) (..)/$2$1/; hex($val)',
1437             },
1438             0x0e00 => {
1439             Name => 'PrintIM',
1440             Description => 'Print Image Matching',
1441             Writable => 0,
1442             SubDirectory => { TagTable => 'Image::ExifTool::PrintIM::Main' },
1443             },
1444             0x2003 => { #21
1445             Name => 'TimeInfo',
1446             SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::TimeInfo' },
1447             },
1448             0x8000 => { #PH
1449             Name => 'MakerNoteVersion',
1450             Format => 'undef',
1451             },
1452             0x8001 => { #7/PH/JD
1453             Name => 'SceneMode',
1454             Writable => 'int16u',
1455             PrintConvColumns => 2,
1456             PrintConv => {
1457             0 => 'Off',
1458             %shootingMode,
1459             },
1460             },
1461             0x8002 => { #21
1462             Name => 'HighlightWarning',
1463             Writable => 'int16u',
1464             PrintConv => { 0 => 'Disabled', 1 => 'No', 2 => 'Yes' },
1465             },
1466             0x8003 => { #21
1467             Name => 'DarkFocusEnvironment',
1468             Writable => 'int16u',
1469             PrintConv => { 1 => 'No', 2 => 'Yes' },
1470             },
1471             0x8004 => { #PH/JD
1472             Name => 'WBRedLevel',
1473             Writable => 'int16u',
1474             },
1475             0x8005 => { #PH/JD
1476             Name => 'WBGreenLevel',
1477             Writable => 'int16u',
1478             },
1479             0x8006 => { #PH/JD
1480             Name => 'WBBlueLevel',
1481             Writable => 'int16u',
1482             },
1483             #0x8007 => { #PH - questionable [disabled because it conflicts with EXIF in too many samples]
1484             # Name => 'FlashFired',
1485             # Writable => 'int16u',
1486             # PrintConv => { 0 => 'Yes', 1 => 'No' },
1487             #},
1488             0x8008 => { #PH (TZ5/FS7)
1489             # (tags 0x3b, 0x3e, 0x8008 and 0x8009 have the same values in all my samples - PH)
1490             Name => 'TextStamp',
1491             Writable => 'int16u',
1492             PrintConv => { 1 => 'Off', 2 => 'On' },
1493             },
1494             0x8009 => { #PH (TZ5/FS7)
1495             # (tags 0x3b, 0x3e, 0x8008 and 0x8009 have the same values in all my samples - PH)
1496             Name => 'TextStamp',
1497             Writable => 'int16u',
1498             PrintConv => { 1 => 'Off', 2 => 'On' },
1499             },
1500             0x8010 => { #PH
1501             Name => 'BabyAge',
1502             Writable => 'string',
1503             Notes => 'or pet age',
1504             PrintConv => '$val eq "9999:99:99 00:00:00" ? "(not set)" : $val',
1505             PrintConvInv => '$val =~ /^\d/ ? $val : "9999:99:99 00:00:00"',
1506             },
1507             0x8012 => { #PH (FS7)
1508             Name => 'Transform',
1509             Writable => 'undef',
1510             Notes => 'decoded as two 16-bit signed integers',
1511             Format => 'int16s',
1512             Count => 2,
1513             PrintConv => {
1514             '-3 2' => 'Slim High',
1515             '-1 1' => 'Slim Low',
1516             '0 0' => 'Off',
1517             '1 1' => 'Stretch Low',
1518             '3 2' => 'Stretch High',
1519             },
1520             },
1521             );
1522              
1523             # Leica type2 maker notes (ref 10)
1524             %Image::ExifTool::Panasonic::Leica2 = (
1525             WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
1526             CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
1527             GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1528             WRITABLE => 1,
1529             NOTES => 'These tags are used by the Leica M8.',
1530             0x300 => {
1531             Name => 'Quality',
1532             Writable => 'int16u',
1533             PrintConv => {
1534             1 => 'Fine',
1535             2 => 'Basic',
1536             },
1537             },
1538             0x302 => {
1539             Name => 'UserProfile',
1540             Writable => 'int32u',
1541             PrintConv => {
1542             1 => 'User Profile 1',
1543             2 => 'User Profile 2',
1544             3 => 'User Profile 3',
1545             4 => 'User Profile 0 (Dynamic)',
1546             },
1547             },
1548             0x303 => {
1549             Name => 'SerialNumber',
1550             Writable => 'int32u',
1551             PrintConv => 'sprintf("%.7d", $val)',
1552             PrintConvInv => '$val',
1553             },
1554             0x304 => {
1555             Name => 'WhiteBalance',
1556             Writable => 'int16u',
1557             Notes => 'values above 0x8000 are converted to Kelvin color temperatures',
1558             PrintConv => {
1559             0 => 'Auto or Manual',
1560             1 => 'Daylight',
1561             2 => 'Fluorescent',
1562             3 => 'Tungsten',
1563             4 => 'Flash',
1564             10 => 'Cloudy',
1565             11 => 'Shade',
1566             OTHER => \&WhiteBalanceConv,
1567             },
1568             },
1569             0x310 => {
1570             Name => 'LensType',
1571             Writable => 'int32u',
1572             SeparateTable => 1,
1573             ValueConv => '($val >> 2) . " " . ($val & 0x3)',
1574             ValueConvInv => \&LensTypeConvInv,
1575             PrintConv => \%leicaLensTypes,
1576             },
1577             0x311 => {
1578             Name => 'ExternalSensorBrightnessValue',
1579             Format => 'rational64s', # (incorrectly unsigned in JPEG images)
1580             Writable => 'rational64s',
1581             Notes => '"blue dot" measurement',
1582             PrintConv => 'sprintf("%.2f", $val)',
1583             PrintConvInv => '$val',
1584             },
1585             0x312 => {
1586             Name => 'MeasuredLV',
1587             Format => 'rational64s', # (incorrectly unsigned in JPEG images)
1588             Writable => 'rational64s',
1589             Notes => 'imaging sensor or TTL exposure meter measurement',
1590             PrintConv => 'sprintf("%.2f", $val)',
1591             PrintConvInv => '$val',
1592             },
1593             0x313 => {
1594             Name => 'ApproximateFNumber',
1595             Writable => 'rational64u',
1596             PrintConv => 'sprintf("%.1f", $val)',
1597             PrintConvInv => '$val',
1598             },
1599             0x320 => {
1600             Name => 'CameraTemperature',
1601             Writable => 'int32s',
1602             PrintConv => '"$val C"',
1603             PrintConvInv => '$val=~s/ ?C//; $val',
1604             },
1605             0x321 => { Name => 'ColorTemperature', Writable => 'int32u' },
1606             0x322 => { Name => 'WBRedLevel', Writable => 'rational64u' },
1607             0x323 => { Name => 'WBGreenLevel', Writable => 'rational64u' },
1608             0x324 => { Name => 'WBBlueLevel', Writable => 'rational64u' },
1609             0x325 => {
1610             Name => 'UV-IRFilterCorrection',
1611             Description => 'UV/IR Filter Correction',
1612             Writable => 'int32u',
1613             PrintConv => {
1614             0 => 'Not Active',
1615             1 => 'Active',
1616             },
1617             },
1618             0x330 => { Name => 'CCDVersion', Writable => 'int32u' },
1619             0x331 => { Name => 'CCDBoardVersion', Writable => 'int32u' },
1620             0x332 => { Name => 'ControllerBoardVersion', Writable => 'int32u' },
1621             0x333 => { Name => 'M16CVersion', Writable => 'int32u' },
1622             0x340 => { Name => 'ImageIDNumber', Writable => 'int32u' },
1623             );
1624              
1625             # Leica type3 maker notes (ref PH)
1626             %Image::ExifTool::Panasonic::Leica3 = (
1627             WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
1628             CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
1629             GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1630             WRITABLE => 1,
1631             NOTES => 'These tags are used by the Leica R8 and R9 digital backs.',
1632             0x0b => { #IB
1633             Name => 'SerialInfo',
1634             SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::SerialInfo' },
1635             },
1636             0x0d => {
1637             Name => 'WB_RGBLevels',
1638             Writable => 'int16u',
1639             Count => 3,
1640             },
1641             );
1642              
1643             # Leica serial number info (ref IB)
1644             %Image::ExifTool::Panasonic::SerialInfo = (
1645             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1646             GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1647             TAG_PREFIX => 'Leica_SerialInfo',
1648             FIRST_ENTRY => 0,
1649             4 => {
1650             Name => 'SerialNumber',
1651             Format => 'string[8]',
1652             }
1653             );
1654              
1655             # Leica type4 maker notes (ref PH) (M9)
1656             %Image::ExifTool::Panasonic::Leica4 = (
1657             WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
1658             CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
1659             GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1660             WRITABLE => 1,
1661             NOTES => 'This information is written by the M9.',
1662             0x3000 => {
1663             Name => 'Subdir3000',
1664             SubDirectory => {
1665             TagTable => 'Image::ExifTool::Panasonic::Subdir',
1666             ByteOrder => 'Unknown',
1667             },
1668             },
1669             0x3100 => {
1670             Name => 'Subdir3100',
1671             SubDirectory => {
1672             TagTable => 'Image::ExifTool::Panasonic::Subdir',
1673             ByteOrder => 'Unknown',
1674             },
1675             },
1676             0x3400 => {
1677             Name => 'Subdir3400',
1678             SubDirectory => {
1679             TagTable => 'Image::ExifTool::Panasonic::Subdir',
1680             ByteOrder => 'Unknown',
1681             },
1682             },
1683             0x3900 => {
1684             Name => 'Subdir3900',
1685             SubDirectory => {
1686             TagTable => 'Image::ExifTool::Panasonic::Subdir',
1687             ByteOrder => 'Unknown',
1688             },
1689             },
1690             );
1691              
1692             # Leica M9 SubDirectory tags (ref PH)
1693             %Image::ExifTool::Panasonic::Subdir = (
1694             WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
1695             CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
1696             GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1697             TAG_PREFIX => 'Leica_Subdir',
1698             WRITABLE => 1,
1699             # 0x3001 - normally 0 but value of 2 when manual coding is used
1700             # with a coded lens (but only tested with Elmar-M 50mm f/2.8) - PH
1701             0x300a => {
1702             Name => 'Contrast',
1703             Writable => 'int32u',
1704             PrintConv => {
1705             0 => 'Low',
1706             1 => 'Medium Low',
1707             2 => 'Normal',
1708             3 => 'Medium High',
1709             4 => 'High',
1710             },
1711             },
1712             0x300b => {
1713             Name => 'Sharpening',
1714             Writable => 'int32u',
1715             PrintConv => {
1716             0 => 'Off',
1717             1 => 'Low',
1718             2 => 'Normal',
1719             3 => 'Medium High',
1720             4 => 'High',
1721             },
1722             },
1723             0x300d => {
1724             Name => 'Saturation',
1725             Writable => 'int32u',
1726             PrintConv => {
1727             0 => 'Low',
1728             1 => 'Medium Low',
1729             2 => 'Normal',
1730             3 => 'Medium High',
1731             4 => 'High',
1732             5 => 'Black & White',
1733             6 => 'Vintage B&W',
1734             },
1735             },
1736             # 0x3032 - some sort of RGB coefficients? (zeros unless Kelvin WB, but same for all Color Temps)
1737             0x3033 => {
1738             Name => 'WhiteBalance',
1739             Writable => 'int32u',
1740             PrintConv => { #13
1741             0 => 'Auto',
1742             1 => 'Tungsten',
1743             2 => 'Fluorescent',
1744             3 => 'Daylight Fluorescent',
1745             4 => 'Daylight',
1746             5 => 'Flash',
1747             6 => 'Cloudy',
1748             7 => 'Shade',
1749             8 => 'Manual',
1750             9 => 'Kelvin',
1751             },
1752             },
1753             0x3034 => {
1754             Name => 'JPEGQuality',
1755             Writable => 'int32u',
1756             PrintConv => {
1757             94 => 'Basic',
1758             97 => 'Fine',
1759             },
1760             },
1761             # 0x3035 (int32u): -1 unless Manual WB (2 in my Manual sample)
1762             0x3036 => {
1763             Name => 'WB_RGBLevels',
1764             Writable => 'rational64u',
1765             Count => 3,
1766             },
1767             0x3038 => {
1768             Name => 'UserProfile', # (CameraProfile according to ref 14)
1769             Writable => 'string',
1770             },
1771             0x303a => {
1772             Name => 'JPEGSize',
1773             Writable => 'int32u',
1774             PrintConv => {
1775             0 => '5216x3472',
1776             1 => '3840x2592',
1777             2 => '2592x1728',
1778             3 => '1728x1152',
1779             4 => '1280x864',
1780             },
1781             },
1782             0x3103 => { #13 (valid for FW 1.116 and later)
1783             Name => 'SerialNumber',
1784             Writable => 'string',
1785             },
1786             # 0x3104 body-dependent string ("00012905000000") (not serial number)
1787             # 0x3105 body-dependent string ("00012905000000")
1788             # 0x3107 - body-dependent string ("4H205800116800") (not serial number)
1789             0x3109 => {
1790             Name => 'FirmwareVersion',
1791             Writable => 'string',
1792             },
1793             0x312a => { #14 (NC)
1794             Name => 'BaseISO',
1795             Writable => 'int32u',
1796             },
1797             0x312b => {
1798             Name => 'SensorWidth',
1799             Writable => 'int32u',
1800             },
1801             0x312c => {
1802             Name => 'SensorHeight',
1803             Writable => 'int32u',
1804             },
1805             0x312d => { #14 (NC)
1806             Name => 'SensorBitDepth',
1807             Writable => 'int32u',
1808             },
1809             0x3402 => { #PH/13
1810             Name => 'CameraTemperature',
1811             Writable => 'int32s',
1812             PrintConv => '"$val C"',
1813             PrintConvInv => '$val=~s/ ?C//; $val',
1814             },
1815             0x3405 => {
1816             Name => 'LensType',
1817             Writable => 'int32u',
1818             SeparateTable => 1,
1819             ValueConv => '($val >> 2) . " " . ($val & 0x3)',
1820             ValueConvInv => \&LensTypeConvInv,
1821             PrintConv => \%leicaLensTypes,
1822             },
1823             0x3406 => { #PH/13
1824             Name => 'ApproximateFNumber',
1825             Writable => 'rational64u',
1826             PrintConv => 'sprintf("%.1f", $val)',
1827             PrintConvInv => '$val',
1828             },
1829             0x3407 => { #14
1830             Name => 'MeasuredLV',
1831             Writable => 'int32s',
1832             Notes => 'imaging sensor or TTL exposure meter measurement',
1833             ValueConv => '$val / 1e5', #PH (NC)
1834             ValueConvInv => '$val * 1e5', #PH (NC)
1835             PrintConv => 'sprintf("%.2f", $val)',
1836             PrintConvInv => '$val',
1837             },
1838             0x3408 => { #14
1839             Name => 'ExternalSensorBrightnessValue',
1840             Writable => 'int32s',
1841             Notes => '"blue dot" measurement',
1842             ValueConv => '$val / 1e5', #PH (NC)
1843             ValueConvInv => '$val * 1e5', #PH (NC)
1844             PrintConv => 'sprintf("%.2f", $val)',
1845             PrintConvInv => '$val',
1846             },
1847             0x3901 => {
1848             Name => 'Data1',
1849             SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::Data1' },
1850             },
1851             0x3902 => {
1852             Name => 'Data2',
1853             SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::Data2' },
1854             },
1855             # 0x3903 - larger binary data block
1856             );
1857              
1858             # time stamp information (ref 21)
1859             %Image::ExifTool::Panasonic::TimeInfo = (
1860             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1861             WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
1862             CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
1863             GROUPS => { 0 => 'MakerNotes', 1 => 'Panasonic', 2 => 'Image' },
1864             FIRST_ENTRY => 0,
1865             WRITABLE => 1,
1866             0 => {
1867             Name => 'PanasonicDateTime',
1868             Groups => { 2 => 'Time' },
1869             Shift => 'Time',
1870             Format => 'undef[8]',
1871             RawConv => '$val =~ /^\0/ ? undef : $val',
1872             ValueConv => 'sprintf("%s:%s:%s %s:%s:%s.%s", unpack "H4H2H2H2H2H2H2", $val)',
1873             ValueConvInv => q{
1874             $val =~ s/[-+].*//; # remove time zone
1875             $val =~ tr/0-9//dc; # remove non-digits
1876             $val = pack("H*",$val);
1877             $val .= "\0" while length $val < 8;
1878             return $val;
1879             },
1880             PrintConv => '$self->ConvertDateTime($val)',
1881             PrintConvInv => '$self->InverseDateTime($val)',
1882             },
1883             # 8 - 8 bytes usually 8 x 0xff (spot for another date/time?)
1884             16 => {
1885             Name => 'TimeLapseShotNumber',
1886             Format => 'int32u',
1887             },
1888             );
1889              
1890             %Image::ExifTool::Panasonic::Data1 = (
1891             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1892             WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
1893             CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
1894             GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1895             WRITABLE => 1,
1896             TAG_PREFIX => 'Leica_Data1',
1897             FIRST_ENTRY => 0,
1898             0x0016 => {
1899             Name => 'LensType',
1900             Format => 'int32u',
1901             Priority => 0,
1902             SeparateTable => 1,
1903             ValueConv => '(($val >> 2) & 0xffff) . " " . ($val & 0x3)',
1904             ValueConvInv => \&LensTypeConvInv,
1905             PrintConv => \%leicaLensTypes,
1906             },
1907             );
1908              
1909             %Image::ExifTool::Panasonic::Data2 = (
1910             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1911             GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1912             TAG_PREFIX => 'Leica_Data2',
1913             FIRST_ENTRY => 0,
1914             );
1915              
1916             # Leica type5 maker notes (ref PH) (X1)
1917             %Image::ExifTool::Panasonic::Leica5 = (
1918             WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
1919             CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
1920             GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1921             WRITABLE => 1,
1922             PRIORITY => 0,
1923             NOTES => 'This information is written by the X1, X2, X VARIO and T.',
1924             0x0303 => {
1925             Name => 'LensType',
1926             Condition => '$format eq "string"',
1927             Notes => 'Leica T only',
1928             Writable => 'string',
1929             },
1930             # 0x0304 - int8u[1]: may be M-lens ID for Leica SL, mounted through "M-adapter L" (ref IB)
1931             # --> int8u[4] for some models (maybe not lens ID for these?) - PH
1932             # (see http://us.leica-camera.com/Photography/Leica-APS-C/Lenses-for-Leica-TL/L-Adapters/M-Adapter-L)
1933             # 58 = 'Leica Noctilux-M 75mm F1.25 ASPH (Typ 601) on Leica SL
1934             0x0305 => { #IB
1935             Name => 'SerialNumber',
1936             Writable => 'int32u',
1937             },
1938             # 0x0406 - saturation or sharpness
1939             0x0407 => { Name => 'OriginalFileName', Writable => 'string' },
1940             0x0408 => { Name => 'OriginalDirectory',Writable => 'string' },
1941             0x040a => { #IB
1942             Name => 'FocusInfo',
1943             SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::FocusInfo' },
1944             },
1945             # 0x040b - related to white balance
1946             0x040d => {
1947             Name => 'ExposureMode',
1948             Format => 'int8u',
1949             Count => 4,
1950             PrintConv => {
1951             '0 0 0 0' => 'Program AE',
1952             # '0 1 0 0' - seen for X (Typ 113) - PH
1953             '1 0 0 0' => 'Aperture-priority AE',
1954             '1 1 0 0' => 'Aperture-priority AE (1)', # (see for Leica T)
1955             '2 0 0 0' => 'Shutter speed priority AE', #(guess)
1956             '3 0 0 0' => 'Manual',
1957             },
1958             },
1959             0x0410 => {
1960             Name => 'ShotInfo',
1961             SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::ShotInfo' },
1962             },
1963             # 0x0410 - int8u[16]: first byte is FileNumber
1964             # 0x0411 - int8u[4]: first number is FilmMode (1=Standard,2=Vivid,3=Natural,4=BW Natural,5=BW High Contrast)
1965             0x0412 => { Name => 'FilmMode', Writable => 'string' },
1966             0x0413 => { Name => 'WB_RGBLevels', Writable => 'rational64u', Count => 3 },
1967             0x0500 => {
1968             Name => 'InternalSerialNumber',
1969             Writable => 'undef',
1970             PrintConv => q{
1971             return $val unless $val=~/^(.{3})(\d{2})(\d{2})(\d{2})(\d{4})/;
1972             my $yr = $2 + ($2 < 70 ? 2000 : 1900);
1973             return "($1) $yr:$3:$4 no. $5";
1974             },
1975             PrintConvInv => '$_=$val; tr/A-Z0-9//dc; s/(.{3})(19|20)/$1/; $_',
1976             },
1977             );
1978              
1979             # Leica type5 ShotInfo (ref PH) (X2)
1980             %Image::ExifTool::Panasonic::ShotInfo = (
1981             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1982             WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
1983             CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
1984             GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
1985             TAG_PREFIX => 'Leica_ShotInfo',
1986             FIRST_ENTRY => 0,
1987             WRITABLE => 1,
1988             0 => {
1989             Name => 'FileIndex',
1990             Format => 'int16u',
1991             },
1992             );
1993              
1994             # Leica type5 FocusInfo (ref IB)
1995             %Image::ExifTool::Panasonic::FocusInfo = (
1996             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1997             WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
1998             CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
1999             GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
2000             TAG_PREFIX => 'Leica_FocusInfo',
2001             FIRST_ENTRY => 0,
2002             WRITABLE => 1,
2003             FORMAT => 'int16u',
2004             0 => {
2005             Name => 'FocusDistance',
2006             ValueConv => '$val / 1000',
2007             ValueConvInv => '$val * 1000',
2008             PrintConv => '$val < 65535 ? "$val m" : "inf"',
2009             PrintConvInv => '$val =~ s/ ?m$//; IsFloat($val) ? $val : 65535',
2010             },
2011             1 => {
2012             Name => 'FocalLength',
2013             Priority => 0,
2014             RawConv => '$val ? $val : undef',
2015             ValueConv => '$val / 1000',
2016             ValueConvInv => '$val * 1000',
2017             PrintConv => 'sprintf("%.1f mm",$val)',
2018             PrintConvInv => '$val=~s/\s*mm$//;$val',
2019             },
2020             );
2021              
2022             # Leica type6 maker notes (ref PH) (S2)
2023             %Image::ExifTool::Panasonic::Leica6 = (
2024             WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
2025             CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
2026             GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
2027             NOTES => q{
2028             This information is written by the S2 and M (Typ 240), as a trailer in JPEG
2029             images.
2030             },
2031             0x300 => {
2032             Name => 'PreviewImage',
2033             Groups => { 2 => 'Preview' },
2034             Writable => 'undef',
2035             Notes => 'S2 and M (Typ 240)',
2036             DataTag => 'PreviewImage',
2037             RawConv => q{
2038             return \$val if $val =~ /^Binary/;
2039             return \$val if $val =~ /^\xff\xd8\xff/;
2040             $$self{PreviewError} = 1 unless $val eq 'none';
2041             return undef;
2042             },
2043             ValueConvInv => '$val || "none"',
2044             WriteCheck => 'return $val=~/^(none|\xff\xd8\xff)/s ? undef : "Not a valid image"',
2045             ChangeBase => '$dirStart + $dataPos - 8',
2046             },
2047             0x301 => {
2048             Name => 'UnknownBlock',
2049             Notes => 'unknown 320kB block, not copied to JPEG images',
2050             Flags => [ 'Unknown', 'Binary', 'Drop' ],
2051             },
2052             # 0x302 - same value as 4 unknown bytes at the end of JPEG or after the DNG TIFF header (ImageID, ref IB)
2053             0x303 => {
2054             Name => 'LensType',
2055             Writable => 'string',
2056             ValueConv => '$val=~s/ +$//; $val', # trim trailing spaces
2057             ValueConvInv => '$val',
2058             },
2059             0x304 => { #IB
2060             Name => 'FocusDistance',
2061             Notes => 'focus distance in mm for most models, but cm for others',
2062             Writable => 'int32u',
2063             },
2064             0x311 => {
2065             Name => 'ExternalSensorBrightnessValue',
2066             Condition => '$$self{Model} =~ /Typ 006/',
2067             Notes => 'Leica S only',
2068             Format => 'rational64s', # (may be incorrectly unsigned in JPEG images)
2069             Writable => 'rational64s',
2070             PrintConv => 'sprintf("%.2f", $val)',
2071             PrintConvInv => '$val',
2072             },
2073             0x312 => {
2074             Name => 'MeasuredLV',
2075             Condition => '$$self{Model} =~ /Typ 006/',
2076             Notes => 'Leica S only',
2077             Format => 'rational64s', # (may be incorrectly unsigned in JPEG images)
2078             Writable => 'rational64s',
2079             PrintConv => 'sprintf("%.2f", $val)',
2080             PrintConvInv => '$val',
2081             },
2082             0x320 => {
2083             Name => 'FirmwareVersion',
2084             Condition => '$$self{Model} =~ /Typ 006/',
2085             Notes => 'Leica S only',
2086             Writable => 'int8u',
2087             Count => 4,
2088             PrintConv => '$val=~tr/ /./; $val',
2089             PrintConvInv => '$val=~tr/./ /; $val',
2090             },
2091             0x321 => { #IB
2092             Name => 'LensSerialNumber',
2093             Condition => '$$self{Model} =~ /Typ 006/',
2094             Notes => 'Leica S only',
2095             Writable => 'int32u',
2096             PrintConv => 'sprintf("%.10d",$val)',
2097             PrintConvInv => '$val',
2098             },
2099             # 0x321 - SerialNumber for Leica S? (ref IB)
2100             # 0x340 - same as 0x302 (ImageID, ref IB)
2101             );
2102              
2103             # Leica type9 maker notes (ref IB) (S)
2104             %Image::ExifTool::Panasonic::Leica9 = (
2105             WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
2106             CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
2107             GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
2108             NOTES => 'This information is written by the Leica S (Typ 007) and M10 models.',
2109             0x304 => {
2110             Name => 'FocusDistance',
2111             Notes => 'focus distance in mm for most models, but cm for others',
2112             Writable => 'int32u',
2113             },
2114             0x311 => {
2115             Name => 'ExternalSensorBrightnessValue',
2116             Format => 'rational64s', # (may be incorrectly unsigned in JPEG images)
2117             Writable => 'rational64s',
2118             PrintConv => 'sprintf("%.2f", $val)',
2119             PrintConvInv => '$val',
2120             },
2121             0x312 => {
2122             Name => 'MeasuredLV',
2123             Format => 'rational64s', # (may be incorrectly unsigned in JPEG images)
2124             Writable => 'rational64s',
2125             PrintConv => 'sprintf("%.2f", $val)',
2126             PrintConvInv => '$val',
2127             },
2128             # 0x340 - ImageUniqueID
2129             0x34c => { #23
2130             Name => 'UserProfile',
2131             Writable => 'string',
2132             },
2133             # 0x357 int32u - 0=DNG, 3162=JPG (ref 23)
2134             0x359 => { #23
2135             Name => 'ISOSelected',
2136             Writable => 'int32s',
2137             PrintConv => {
2138             0 => 'Auto',
2139             OTHER => sub { return shift; },
2140             },
2141             },
2142             0x35a => { #23
2143             Name => 'FNumber',
2144             Writable => 'int32s',
2145             ValueConv => '$val / 1000',
2146             ValueConvInv => '$val * 1000',
2147             PrintConv => 'sprintf("%.1f", $val)',
2148             PrintConvInv => '$val',
2149             },
2150             0x035b => { #IB
2151             Name => 'CorrelatedColorTemp', # (in Kelvin)
2152             Writable => 'int16u',
2153             },
2154             0x035c => { #IB
2155             Name => 'ColorTint', # (same units as Adobe is using)
2156             Writable => 'int16s',
2157             },
2158             0x035d => { #IB
2159             Name => 'WhitePoint', # (x/y)
2160             Writable => 'rational64u',
2161             Count => 2,
2162             },
2163             );
2164              
2165             # Type 2 tags (ref PH)
2166             %Image::ExifTool::Panasonic::Type2 = (
2167             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
2168             GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
2169             FIRST_ENTRY => 0,
2170             FORMAT => 'int16u',
2171             NOTES => q{
2172             This type of maker notes is used by models such as the NV-DS65, PV-D2002,
2173             PV-DC3000, PV-DV203, PV-DV401, PV-DV702, PV-L2001, PV-SD4090, PV-SD5000 and
2174             iPalm.
2175             },
2176             0 => {
2177             Name => 'MakerNoteType',
2178             Format => 'string[4]',
2179             },
2180             # seems to vary inversely with amount of light, so I'll call it 'Gain' - PH
2181             # (minimum is 16, maximum is 136. Value is 0 for pictures captured from video)
2182             3 => 'Gain',
2183             );
2184              
2185             # Face detection position information (ref PH)
2186             %Image::ExifTool::Panasonic::FaceDetInfo = (
2187             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
2188             WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
2189             CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
2190             GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
2191             WRITABLE => 1,
2192             FORMAT => 'int16u',
2193             FIRST_ENTRY => 0,
2194             DATAMEMBER => [ 0 ],
2195             NOTES => 'Face detection position information.',
2196             0 => {
2197             Name => 'NumFacePositions',
2198             Format => 'int16u',
2199             DataMember => 'NumFacePositions',
2200             RawConv => '$$self{NumFacePositions} = $val',
2201             Notes => q{
2202             number of detected face positions stored in this record. May be less than
2203             FacesDetected
2204             },
2205             },
2206             1 => {
2207             Name => 'Face1Position',
2208             Format => 'int16u[4]',
2209             RawConv => '$$self{NumFacePositions} < 1 ? undef : $val',
2210             Notes => q{
2211             4 numbers: X/Y coordinates of the face center and width/height of face.
2212             Coordinates are relative to an image twice the size of the thumbnail, or 320
2213             pixels wide
2214             },
2215             },
2216             5 => {
2217             Name => 'Face2Position',
2218             Format => 'int16u[4]',
2219             RawConv => '$$self{NumFacePositions} < 2 ? undef : $val',
2220             },
2221             9 => {
2222             Name => 'Face3Position',
2223             Format => 'int16u[4]',
2224             RawConv => '$$self{NumFacePositions} < 3 ? undef : $val',
2225             },
2226             13 => {
2227             Name => 'Face4Position',
2228             Format => 'int16u[4]',
2229             RawConv => '$$self{NumFacePositions} < 4 ? undef : $val',
2230             },
2231             17 => {
2232             Name => 'Face5Position',
2233             Format => 'int16u[4]',
2234             RawConv => '$$self{NumFacePositions} < 5 ? undef : $val',
2235             },
2236             );
2237              
2238             # Face recognition information from DMC-TZ7 (ref PH)
2239             %Image::ExifTool::Panasonic::FaceRecInfo = (
2240             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
2241             WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
2242             CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
2243             GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
2244             WRITABLE => 1,
2245             FIRST_ENTRY => 0,
2246             DATAMEMBER => [ 0 ],
2247             NOTES => q{
2248             Tags written by cameras with facial recognition. These cameras not only
2249             detect faces in an image, but also recognize specific people based a
2250             user-supplied set of known faces.
2251             },
2252             0 => {
2253             Name => 'FacesRecognized',
2254             Format => 'int16u',
2255             DataMember => 'FacesRecognized',
2256             RawConv => '$$self{FacesRecognized} = $val',
2257             },
2258             4 => {
2259             Name => 'RecognizedFace1Name',
2260             Format => 'string[20]',
2261             RawConv => '$$self{FacesRecognized} < 1 ? undef : $val',
2262             },
2263             24 => {
2264             Name => 'RecognizedFace1Position',
2265             Format => 'int16u[4]',
2266             RawConv => '$$self{FacesRecognized} < 1 ? undef : $val',
2267             Notes => 'coordinates in same format as face detection tags above',
2268             },
2269             32 => {
2270             Name => 'RecognizedFace1Age',
2271             Format => 'string[20]',
2272             RawConv => '$$self{FacesRecognized} < 1 ? undef : $val',
2273             },
2274             52 => {
2275             Name => 'RecognizedFace2Name',
2276             Format => 'string[20]',
2277             RawConv => '$$self{FacesRecognized} < 2 ? undef : $val',
2278             },
2279             72 => {
2280             Name => 'RecognizedFace2Position',
2281             Format => 'int16u[4]',
2282             RawConv => '$$self{FacesRecognized} < 2 ? undef : $val',
2283             },
2284             80 => {
2285             Name => 'RecognizedFace2Age',
2286             Format => 'string[20]',
2287             RawConv => '$$self{FacesRecognized} < 2 ? undef : $val',
2288             },
2289             100 => {
2290             Name => 'RecognizedFace3Name',
2291             Format => 'string[20]',
2292             RawConv => '$$self{FacesRecognized} < 3 ? undef : $val',
2293             },
2294             120 => {
2295             Name => 'RecognizedFace3Position',
2296             Format => 'int16u[4]',
2297             RawConv => '$$self{FacesRecognized} < 3 ? undef : $val',
2298             },
2299             128 => {
2300             Name => 'RecognizedFace3Age',
2301             Format => 'string[20]',
2302             RawConv => '$$self{FacesRecognized} < 3 ? undef : $val',
2303             },
2304             );
2305              
2306             # PANA atom found in user data of MP4 videos (ref PH)
2307             %Image::ExifTool::Panasonic::PANA = (
2308             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
2309             GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
2310             NOTES => q{
2311             Tags extracted from the PANA and LEIC user data found in MP4 videos from
2312             various Panasonic and Leica models.
2313             },
2314             0x00 => {
2315             Name => 'Make',
2316             Condition => '$$valPt =~ /^(LEICA|Panasonic)/', # (only seen "LEICA")
2317             Groups => { 2 => 'Camera' },
2318             Format => 'string[22]',
2319             RawConv => '$$self{LeicaLEIC} = 1;$$self{Make} = $val',
2320             },
2321             0x04 => {
2322             Name => 'Model',
2323             Condition => '$$valPt =~ /^[^\0]{6}/ and not $$self{LeicaLEIC}',
2324             Description => 'Camera Model Name',
2325             Groups => { 2 => 'Camera' },
2326             Format => 'string[16]',
2327             RawConv => '$$self{Model} = $val',
2328             },
2329             0x0c => { # (FZ1000)
2330             Name => 'Model',
2331             Condition => '$$valPt =~ /^[^\0]{6}/ and not $$self{LeicaLEIC} and not $$self{Model}',
2332             Description => 'Camera Model Name',
2333             Groups => { 2 => 'Camera' },
2334             Format => 'string[16]',
2335             RawConv => '$$self{Model} = $val',
2336             },
2337             0x10 => { # (DC-FT7)
2338             Name => 'JPEG-likeData',
2339             # looks like a JPEG preview, but not a well-formed JPEG file
2340             Condition => '$$valPt =~ /^\xff\xd8\xff\xe1..Exif\0\0/s',
2341             Format => 'undef[$size-0x10]',
2342             SubDirectory => {
2343             TagTable => 'Image::ExifTool::Exif::Main',
2344             ProcessProc => \&Image::ExifTool::ProcessTIFF,
2345             Start => 12,
2346             },
2347             },
2348             0x16 => {
2349             Name => 'Model',
2350             Condition => '$$self{LeicaLEIC}',
2351             Description => 'Camera Model Name',
2352             Groups => { 2 => 'Camera' },
2353             Format => 'string[30]',
2354             RawConv => '$$self{Model} = $val',
2355             },
2356             0x40 => {
2357             Name => 'ThumbnailTest',
2358             Format => 'undef[0x600]',
2359             Hidden => 1,
2360             RawConv => q{
2361             if (substr($val,0x1c,3) eq "\xff\xd8\xff") { # offset 0x5c
2362             $$self{ThumbType} = 1;
2363             } elsif (substr($val,0x506,3) eq "\xff\xd8\xff") { # offset 0x546
2364             $$self{ThumbType} = 2;
2365             } elsif (substr($val,0x51e,3) eq "\xff\xd8\xff") { # offset 0x55e (Leica T)
2366             $$self{ThumbType} = 3;
2367             } else {
2368             $$self{ThumbType} = 0;
2369             }
2370             return undef;
2371             },
2372             },
2373             0x34 => {
2374             Name => 'Version1',
2375             Condition => '$$self{LeicaLEIC}',
2376             Format => 'string[14]',
2377             },
2378             0x3e => {
2379             Name => 'Version2',
2380             Condition => '$$self{LeicaLEIC}',
2381             Format => 'string[14]',
2382             },
2383             0x50 => {
2384             Name => 'MakerNoteLeica5',
2385             Condition => '$$self{LeicaLEIC}',
2386             SubDirectory => {
2387             TagTable => 'Image::ExifTool::Panasonic::Leica5',
2388             ProcessProc => \&ProcessLeicaLEIC,
2389             },
2390             },
2391             0x58 => {
2392             Name => 'ThumbnailWidth',
2393             Condition => '$$self{ThumbType} == 1',
2394             Notes => 'Panasonic models',
2395             Format => 'int16u',
2396             },
2397             0x5a => {
2398             Name => 'ThumbnailHeight',
2399             Condition => '$$self{ThumbType} == 1',
2400             Format => 'int16u',
2401             },
2402             0x5c => {
2403             Name => 'ThumbnailImage',
2404             Condition => '$$self{ThumbType} == 1',
2405             Groups => { 2 => 'Preview' },
2406             Format => 'undef[16384]',
2407             ValueConv => '$val=~s/\0*$//; \$val', # remove trailing zeros
2408             },
2409             # 0x5c - there is some messed-up EXIF-IFD-looking data starting here in
2410             # Leica X VARIO MP4 videos, but it doesn't quite make sense
2411             0x536 => { # (Leica X VARIO)
2412             Name => 'ThumbnailWidth',
2413             Condition => '$$self{ThumbType} == 2',
2414             Notes => 'Leica X Vario',
2415             Format => 'int32uRev', # (little-endian)
2416             },
2417             0x53a => { # (Leica X VARIO)
2418             Name => 'ThumbnailHeight',
2419             Condition => '$$self{ThumbType} == 2',
2420             Format => 'int32uRev', # (little-endian)
2421             },
2422             0x53e => { # (Leica X VARIO)
2423             Name => 'ThumbnailLength',
2424             Condition => '$$self{ThumbType} == 2',
2425             Format => 'int32uRev', # (little-endian)
2426             },
2427             0x546 => { # (Leica X VARIO)
2428             Name => 'ThumbnailImage',
2429             Condition => '$$self{ThumbType} == 2',
2430             Groups => { 2 => 'Preview' },
2431             Format => 'undef[$val{0x53e}]',
2432             Binary => 1,
2433             },
2434             0x54e => { # (Leica T)
2435             Name => 'ThumbnailWidth',
2436             Condition => '$$self{ThumbType} == 3',
2437             Notes => 'Leica X Vario',
2438             Format => 'int32uRev', # (little-endian)
2439             },
2440             0x552 => { # (Leica T)
2441             Name => 'ThumbnailHeight',
2442             Condition => '$$self{ThumbType} == 3',
2443             Format => 'int32uRev', # (little-endian)
2444             },
2445             0x556 => { # (Leica T)
2446             Name => 'ThumbnailLength',
2447             Condition => '$$self{ThumbType} == 3',
2448             Format => 'int32uRev', # (little-endian)
2449             },
2450             0x55e => { # (Leica T)
2451             Name => 'ThumbnailImage',
2452             Condition => '$$self{ThumbType} == 3',
2453             Groups => { 2 => 'Preview' },
2454             Format => 'undef[$val{0x556}]',
2455             Binary => 1,
2456             },
2457             0x4068 => {
2458             Name => 'ExifData',
2459             Condition => '$$valPt =~ /^\xff\xd8\xff\xe1..Exif\0\0/s',
2460             SubDirectory => {
2461             TagTable => 'Image::ExifTool::Exif::Main',
2462             ProcessProc => \&Image::ExifTool::ProcessTIFF,
2463             Start => 12,
2464             },
2465             },
2466             0x4080 => { # (FZ1000)
2467             Name => 'ExifData',
2468             Condition => '$$valPt =~ /^\xff\xd8\xff\xe1..Exif\0\0/s',
2469             SubDirectory => {
2470             TagTable => 'Image::ExifTool::Exif::Main',
2471             ProcessProc => \&Image::ExifTool::ProcessTIFF,
2472             Start => 12,
2473             },
2474             },
2475             0x200080 => { # (GH6)
2476             Name => 'ExifData',
2477             Condition => '$$valPt =~ /^\xff\xd8\xff\xe1..Exif\0\0/s',
2478             SubDirectory => {
2479             TagTable => 'Image::ExifTool::Exif::Main',
2480             ProcessProc => \&Image::ExifTool::ProcessTIFF,
2481             Start => 12,
2482             },
2483             },
2484             );
2485              
2486             # Panasonic Composite tags
2487             %Image::ExifTool::Panasonic::Composite = (
2488             GROUPS => { 2 => 'Camera' },
2489             AdvancedSceneMode => {
2490             SeparateTable => 'Panasonic AdvancedSceneMode', # print values in a separate table
2491             Require => {
2492             0 => 'Model',
2493             1 => 'SceneMode',
2494             2 => 'AdvancedSceneType',
2495             },
2496             ValueConv => '"$val[0] $val[1] $val[2]"',
2497             PrintConv => { #PH
2498             OTHER => sub {
2499             my ($val,$flag,$conv) = @_;
2500             $val =~ s/.* (\d+ \d+)/$1/; # drop model name
2501             return $$conv{$val} if $$conv{$val};
2502             my @v = split ' ', $val;
2503             my $prt = $shootingMode{$v[0]};
2504             # AdvancedSceneType=1 for non-automatic modes P,A,S,SCN (ref 19)
2505             # AdvancedSceneType=5 for automatic mode iA (ref 19)
2506             if ($prt) {
2507             return $prt if $v[1] == 1;
2508             return "$prt (intelligent auto)" if $v[1] == 5; #forum11523
2509             return "$prt (intelligent auto plus)" if $v[1] == 7; #forum11523
2510             return "$prt ($v[1])";
2511             }
2512             return "Unknown ($val)";
2513             },
2514             Notes => 'A Composite tag derived from Model, SceneMode and AdvancedSceneType.',
2515             '0 1' => 'Off',
2516             # '0 7' - seen this for V-LUX movies (PH)
2517             # '0 8' - seen for D-LUX(Typ104) movies (PH)
2518             '2 2' => 'Outdoor Portrait', #(FZ28)
2519             '2 3' => 'Indoor Portrait', #(FZ28)
2520             '2 4' => 'Creative Portrait', #(FZ28)
2521             '3 2' => 'Nature', #(FZ28)
2522             '3 3' => 'Architecture', #(FZ28)
2523             '3 4' => 'Creative Scenery', #(FZ28)
2524             #'3 5' - ? (FT1)
2525             '4 2' => 'Outdoor Sports', #(FZ28)
2526             '4 3' => 'Indoor Sports', #(FZ28)
2527             '4 4' => 'Creative Sports', #(FZ28)
2528             '9 2' => 'Flower', #(FZ28)
2529             '9 3' => 'Objects', #(FZ28)
2530             '9 4' => 'Creative Macro', #(FZ28)
2531             #'9 5' - ? (GF3)
2532             '18 1' => 'High Sensitivity', #forum11523 (TZ5)
2533             '20 1' => 'Fireworks', #forum11523 (TZ5)
2534             '21 2' => 'Illuminations', #(FZ28)
2535             '21 4' => 'Creative Night Scenery', #(FZ28)
2536             #'21 5' - ? (LX3)
2537             '26 1' => 'High-speed Burst (shot 1)', #forum11523 (TZ5)
2538             '27 1' => 'High-speed Burst (shot 2)', #forum11523 (TZ5)
2539             '29 1' => 'Snow', #forum11523 (TZ5)
2540             '30 1' => 'Starry Sky', #forum11523 (TZ5)
2541             '31 1' => 'Beach', #forum11523 (TZ5)
2542             '36 1' => 'High-speed Burst (shot 3)', #forum11523 (TZ5)
2543             #'37 5' - ? (various)
2544             '39 1' => 'Aerial Photo / Underwater / Multi-aspect', #forum11523 (TZ5)
2545             '45 2' => 'Cinema', #(GF2)
2546             '45 7' => 'Expressive', #(GF1,GF2)
2547             '45 8' => 'Retro', #(GF1,GF2)
2548             '45 9' => 'Pure', #(GF1,GF2)
2549             '45 10' => 'Elegant', #(GF1,GF2)
2550             '45 12' => 'Monochrome', #(GF1,GF2)
2551             '45 13' => 'Dynamic Art', #(GF1,GF2)
2552             '45 14' => 'Silhouette', #(GF1,GF2)
2553             '51 2' => 'HDR Art', #12
2554             '51 3' => 'HDR B&W', #12
2555             '59 1' => 'Expressive', #(GF5)
2556             '59 2' => 'Retro', #(GF5)
2557             '59 3' => 'High Key', #(GF5)
2558             '59 4' => 'Sepia', #(GF3,GF5)
2559             '59 5' => 'High Dynamic', #(GF3,GF5)
2560             '59 6' => 'Miniature', #(GF3)
2561             '59 9' => 'Low Key', #(GF5)
2562             '59 10' => 'Toy Effect', #(GF5)
2563             '59 11' => 'Dynamic Monochrome', #(GF5)
2564             '59 12' => 'Soft', #(GF5)
2565             '66 1' => 'Impressive Art', #19
2566             '66 2' => 'Cross Process', #(GF5)
2567             '66 3' => 'Color Select', #(GF5) (called "One Point Color" by some other models - PH)
2568             '66 4' => 'Star', #(GF5)
2569             '90 3' => 'Old Days', #18
2570             '90 4' => 'Sunshine', #18
2571             '90 5' => 'Bleach Bypass', #18
2572             '90 6' => 'Toy Pop', #18
2573             '90 7' => 'Fantasy', #18
2574             '90 8' => 'Monochrome', #PH (GX7)
2575             '90 9' => 'Rough Monochrome', #PH (GX7)
2576             '90 10' => 'Silky Monochrome', #PH (GX7)
2577             '92 1' => 'Handheld Night Shot', #Horst Wandres (FZ1000)
2578             # TZ40 Creative Control modes (ref 19)
2579             'DMC-TZ40 90 1' => 'Expressive',
2580             'DMC-TZ40 90 2' => 'Retro',
2581             'DMC-TZ40 90 3' => 'High Key',
2582             'DMC-TZ40 90 4' => 'Sepia',
2583             'DMC-TZ40 90 5' => 'High Dynamic',
2584             'DMC-TZ40 90 6' => 'Miniature',
2585             'DMC-TZ40 90 9' => 'Low Key',
2586             'DMC-TZ40 90 10' => 'Toy Effect',
2587             'DMC-TZ40 90 11' => 'Dynamic Monochrome',
2588             'DMC-TZ40 90 12' => 'Soft',
2589             },
2590             },
2591             );
2592              
2593             # add our composite tags
2594             Image::ExifTool::AddCompositeTags('Image::ExifTool::Panasonic');
2595              
2596             #------------------------------------------------------------------------------
2597             # Inverse conversion for Leica M9 lens codes
2598             # Inputs: 0) value
2599             # Returns: Converted value, or undef on error
2600             sub LensTypeConvInv($)
2601             {
2602 0     0 0 0 my $val = shift;
2603 0 0       0 if ($val =~ /^(\d+) (\d+)$/) {
    0          
2604 0         0 return ($1 << 2) + ($2 & 0x03);
2605             } elsif ($val =~ /^\d+$/) {
2606 0         0 my $bits = $frameSelectorBits{$val};
2607 0 0       0 return undef unless defined $bits;
2608 0         0 return ($val << 2) | $bits;
2609             } else {
2610 0         0 return undef;
2611             }
2612             }
2613              
2614             #------------------------------------------------------------------------------
2615             # Convert Leica Kelvin white balance
2616             # Inputs: 0) value, 1) flag to perform inverse conversion
2617             # Returns: Converted value, or undef on error
2618             sub WhiteBalanceConv($;$$)
2619             {
2620 2     2 0 8 my ($val, $inv) = @_;
2621 2 50       19 if ($inv) {
2622 2 50       13 return $1 + 0x8000 if $val =~ /(\d+)/;
2623             } else {
2624 0 0       0 return ($val - 0x8000) . ' Kelvin' if $val > 0x8000;
2625             }
2626 2         10 return undef;
2627             }
2628              
2629             #------------------------------------------------------------------------------
2630             # Process Leica makernotes in LEIC atom of MP4 videos (Leica T and X Vario)
2631             # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
2632             # Returns: 1 on success
2633             sub ProcessLeicaLEIC($$$)
2634             {
2635 0     0 0   my ($et, $dirInfo, $tagTablePtr) = @_;
2636 0           my $dataPt = $$dirInfo{DataPt};
2637 0   0       my $dirStart = $$dirInfo{DirStart} || 0;
2638 0   0       my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $dirStart);
2639 0 0         return 0 if $dirLen < 6;
2640 0           SetByteOrder('II');
2641 0           my $numEntries = Get16u($dataPt, $dirStart);
2642 0 0 0       return 0 if $numEntries < 1 or $numEntries > 255;
2643 0           my $size = Get32u($dataPt, $dirStart + 2);
2644 0 0 0       return 0 if $size < $numEntries * 12 or $size + 6 > $dirLen;
2645             # the Leica programmers want to make things difficult, so they store
2646             # the entry count before the directory size, making it impossible to
2647             # process as a standard TIFF IFD without a bit of reorganization...
2648 0           Set16u($numEntries, $dataPt, $dirStart + 4);
2649 0           my %dirInfo = %$dirInfo;
2650 0           $dirInfo{DirStart} = $dirStart + 4;
2651 0           $dirInfo{DirLen} = $size - 4;
2652 0           $dirInfo{DataPos} -= $dirStart;
2653 0           $dirInfo{Base} += $dirStart;
2654 0           return Image::ExifTool::Exif::ProcessExif($et, \%dirInfo, $tagTablePtr);
2655 0           return 1;
2656             }
2657              
2658             #------------------------------------------------------------------------------
2659             # Process MakerNote trailer written by Leica S2
2660             # Inputs: 0) ExifTool object ref, 1) new absolute position of Leica trailer when writing
2661             # Returns: On success: 1 when reading, directory data when writing; otherwise undef
2662             # Notes:
2663             # - may be called twice for a file if the first call doesn't succeed
2664             # - must leave RAF position unchanged
2665             # - uses information from LeicaTrailer member:
2666             # TagInfo = tag info ref for MakerNote SubDirectory
2667             # Offset/Size = value offset/size from MakerNote IFD
2668             # TrailStart/TrailLen = actual JPEG trailer position/size (2nd call only)
2669             # - deletes LeicaTrailer member and sets LeicaTrailerPos when successful
2670             sub ProcessLeicaTrailer($;$)
2671             {
2672 0     0 0   my ($et, $newPos) = @_;
2673 0           my $trail = $$et{LeicaTrailer};
2674 0           my $raf = $$et{RAF};
2675 0           my $trailPos = $$trail{TrailPos};
2676 0   0       my $pos = $trailPos || $$trail{Offset};
2677 0   0       my $len = $$trail{TrailLen} || $$trail{Size};
2678 0           my ($buff, $result, %tagPtr);
2679              
2680 0 0         delete $$et{LeicaTrailer} if $trailPos; # done after this
2681 0 0         unless ($len > 0) {
2682 0 0         $et->Warn('Missing Leica MakerNote trailer', 1) if $trailPos;
2683 0           delete $$et{LeicaTrailer};
2684 0           return undef;
2685             }
2686 0           my $oldPos = $raf->Tell();
2687 0   0       my $ok = ($raf->Seek($pos, 0) and $raf->Read($buff, $len) == $len);
2688 0           $raf->Seek($oldPos, 0);
2689 0 0         unless ($ok) {
2690 0 0         $et->Warn('Error reading Leica MakerNote trailer', 1) if $trailPos;
2691 0           return undef;
2692             }
2693             # look for Leica MakerNote header (should be at start of
2694             # trailer, but allow up to 256 bytes of garbage just in case)
2695 0 0         if ($buff !~ /^(.{0,256})LEICA\0..../sg) {
2696 0 0         my $what = $trailPos ? 'trailer' : 'offset';
2697 0           $et->Warn("Invalid Leica MakerNote $what", 1);
2698 0           return undef;
2699             }
2700 0           my $junk = $1;
2701 0           my $start = pos($buff) - 10;
2702 0 0 0       if ($start and not $trailPos) {
2703 0           $et->Warn('Invalid Leica MakerNote offset', 1);
2704 0           return undef;
2705             }
2706             #
2707             # all checks passed -- go ahead and process the trailer now
2708             #
2709 0           my $hdrLen = 8;
2710 0           my $dirStart = $start + $hdrLen;
2711 0           my $tagInfo = $$trail{TagInfo};
2712 0 0         if ($$et{HTML_DUMP}) {
    0          
2713 0           my $name = $$tagInfo{Name};
2714 0           $et->HDump($pos+$start, $len-$start, "$name value", 'Leica MakerNote trailer', 4);
2715 0           $et->HDump($pos+$start, $hdrLen, "MakerNotes header", $name);
2716             } elsif ($et->Options('Verbose')) {
2717 0           my $where = sprintf('at offset 0x%x', $pos);
2718 0           $et->VPrint(0, "Leica MakerNote trailer ($len bytes $where):\n");
2719             }
2720             # delete LeicaTrailer member so we don't try to process it again
2721 0           delete $$et{LeicaTrailer};
2722 0           $$et{LeicaTrailerPos} = $pos + $start; # return actual start position of Leica trailer
2723              
2724 0           my $oldOrder = GetByteOrder();
2725 0           my $num = Get16u(\$buff, $dirStart); # get entry count
2726 0 0         ToggleByteOrder() if ($num>>8) > ($num&0xff); # set byte order
2727              
2728             # use specialized algorithm to automatically fix offsets
2729 0           my $valStart = $dirStart + 2 + 12 * $num + 4;
2730 0           my $fix = 0;
2731 0 0         if ($valStart < $len) {
2732 0           my $valBlock = Image::ExifTool::MakerNotes::GetValueBlocks(\$buff, $dirStart, \%tagPtr);
2733             # find the minimum offset (excluding the PreviewImage tag 0x300 and 0x301)
2734 0           my $minPtr;
2735 0           foreach (keys %tagPtr) {
2736 0           my $ptr = $tagPtr{$_};
2737 0 0 0       next if $_ == 0x300 or $_ == 0x301 or not $ptr or $ptr == 0xffffffff;
      0        
      0        
2738 0 0 0       $minPtr = $ptr if not defined $minPtr or $minPtr > $ptr;
2739             }
2740 0 0         if ($minPtr) {
2741 0           my $diff = $minPtr - ($valStart + $pos);
2742 0           pos($buff) = $valStart;
2743 0           my $expect;
2744 0 0         if ($$et{Model} eq 'S2') {
2745             # scan value data for the first non-zero byte
2746 0 0         if ($buff =~ /[^\0]/g) {
2747 0           my $n = pos($buff) - 1 - $valStart; # number of zero bytes
2748             # S2 writes 282 bytes of zeros, exiftool writes none
2749 0 0         $expect = $n >= 282 ? 282 : 0;
2750             }
2751             } else { # M (Type 240)
2752             # scan for the lens type (M writes 114 bytes of garbage first)
2753 0 0 0       if ($buff =~ /\G.{114}([\x20-\x7f]*\0*)/sg and length($1) >= 50) {
2754 0           $expect = 114;
2755             }
2756             }
2757 0           my $fixBase = $et->Options('FixBase');
2758 0 0 0       if (not defined $expect) {
    0          
2759 0           $et->Warn('Unrecognized Leica trailer structure');
2760             } elsif ($diff != $expect or defined $fixBase) {
2761 0           $fix = $expect - $diff;
2762 0 0         if (defined $fixBase) {
2763 0 0         $fix = $fixBase if $fixBase ne '';
2764 0           $et->Warn("Adjusted MakerNotes base by $fix",1);
2765             } else {
2766 0           $et->Warn("Possibly incorrect maker notes offsets (fixed by $fix)",1);
2767             }
2768             }
2769             }
2770             }
2771             # generate dirInfo for Leica MakerNote directory
2772             my %dirInfo = (
2773             Name => $$tagInfo{Name},
2774 0           Base => $fix,
2775             DataPt => \$buff,
2776             DataPos => $pos - $fix,
2777             DataLen => $len,
2778             DirStart => $dirStart,
2779             DirLen => $len - $dirStart,
2780             DirName => 'MakerNotes',
2781             Parent => 'ExifIFD',
2782             TagInfo => $tagInfo,
2783             );
2784 0           my $tagTablePtr = GetTagTable($$tagInfo{SubDirectory}{TagTable});
2785 0 0         if ($newPos) { # are we writing?
2786 0 0         if ($$et{Model} ne 'S2') {
2787 0           $et->Warn('Leica MakerNote trailer too messed up to edit. Copying as a block', 1);
2788 0           return $buff;
2789             }
2790             # set position of new MakerNote IFD (+ 8 for Leica MakerNote header)
2791 0           $dirInfo{NewDataPos} = $newPos + $start + 8;
2792 0           $result = $et->WriteDirectory(\%dirInfo, $tagTablePtr);
2793             # write preview image last if necessary and fix up the preview offsets
2794 0           my $previewInfo = $$et{PREVIEW_INFO};
2795 0           delete $$et{PREVIEW_INFO};
2796 0 0         if ($result) {
2797 0 0         if ($previewInfo) {
2798 0           my $fixup = $previewInfo->{Fixup};
2799             # set preview offset (relative to start of makernotes, + 8 for makernote header)
2800 0           $fixup->SetMarkerPointers(\$result, 'PreviewImage', length($result) + 8);
2801 0           $result .= $$previewInfo{Data};
2802             }
2803 0           return $junk . substr($buff, $start, $hdrLen) . $result;
2804             }
2805             } else {
2806             # extract information
2807 0           $result = $et->ProcessDirectory(\%dirInfo, $tagTablePtr);
2808             # also extract as a block if necessary
2809 0 0 0       if ($et->Options('MakerNotes') or
2810             $$et{REQ_TAG_LOOKUP}{lc($$tagInfo{Name})})
2811             {
2812             # makernote header must be included in RebuildMakerNotes call
2813 0           $dirInfo{DirStart} -= 8;
2814 0           $dirInfo{DirLen} += 8;
2815 0           $$et{MAKER_NOTE_BYTE_ORDER} = GetByteOrder();
2816             # rebuild maker notes (creates $$et{MAKER_NOTE_FIXUP})
2817 0           my $val = Image::ExifTool::Exif::RebuildMakerNotes($et, \%dirInfo, $tagTablePtr);
2818 0 0         unless (defined $val) {
2819 0 0         $et->Warn('Error rebuilding maker notes (may be corrupt)') if $len > 4;
2820 0           $val = $buff,
2821             }
2822 0           my $key = $et->FoundTag($tagInfo, $val);
2823 0           $et->SetGroup($key, 'ExifIFD');
2824             }
2825             }
2826 0           SetByteOrder($oldOrder);
2827 0           return $result;
2828             }
2829              
2830             1; # end
2831              
2832             __END__