File Coverage

blib/lib/Image/ExifTool/Panasonic.pm
Criterion Covered Total %
statement 16 142 11.2
branch 2 80 2.5
condition 0 44 0.0
subroutine 5 8 62.5
pod 0 4 0.0
total 23 278 8.2


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