Index: main/trunk/greenstone2/perllib/cpan/Image/ExifTool/Panasonic.pm
===================================================================
--- main/trunk/greenstone2/perllib/cpan/Image/ExifTool/Panasonic.pm	(revision 24107)
+++ main/trunk/greenstone2/perllib/cpan/Image/ExifTool/Panasonic.pm	(revision 34921)
@@ -15,8 +15,17 @@
 #              10) http://bretteville.com/pdfs/M8Metadata_v2.pdf
 #              11) http://www.digital-leica.com/lens_codes/index.html
+#                  (now https://www.l-camera-forum.com/leica-news/leica-lens-codes/)
 #              12) Joerg - http://www.cpanforum.com/threads/11602 (LX3 firmware 2.0)
 #              13) Michael Byczkowski private communication (Leica M9)
 #              14) Carl Bretteville private communication (M9)
 #              15) Zdenek Mihula private communication (TZ8)
+#              16) Olaf Ulrich private communication
+#              17) https://exiftool.org/forum/index.php/topic,4922.0.html
+#              18) Thomas Modes private communication (G6)
+#              19) https://exiftool.org/forum/index.php/topic,5533.0.html
+#              20) Bernd-Michael Kemper private communication (DMC-GX80/85)
+#              21) Klaus Homeister forum post
+#              22) Daniel Beichl private communication (G9)
+#              23) Tim Gray private communication (M10 Monochrom)
 #              JD) Jens Duttke private communication (TZ3,FZ30,FZ50)
 #------------------------------------------------------------------------------
@@ -25,15 +34,15 @@
 
 use strict;
-use vars qw($VERSION);
+use vars qw($VERSION %leicaLensTypes);
 use Image::ExifTool qw(:DataAccess :Utils);
 use Image::ExifTool::Exif;
 
-$VERSION = '1.59';
-
-sub ProcessPanasonicType2($$$);
+$VERSION = '2.14';
+
+sub ProcessLeicaLEIC($$$);
 sub WhiteBalanceConv($;$$);
 
 # Leica lens types (ref 10)
-my %leicaLensType = (
+%leicaLensTypes = (
     OTHER => sub {
         my ($val, $inv, $conv) = @_;
@@ -42,7 +51,8 @@
     },
     Notes => q{
-        Entries with 2 numbers give the lower 2 bits of the LensType value which are
-        used to identify certain manually coded lenses on the M9, or the focal
-        length of some multi-focal lenses.
+        the LensType value is obtained by splitting the stored value into 2
+        integers:  The stored value divided by 4, and its lower 2 bits.  The second
+        number is used only if necessary to identify certain manually coded lenses
+        on the M9, or the focal length of some multi-focal lenses.
     },
     # All M9 codes (two numbers: first the LensID then the lower 2 bits)
@@ -55,4 +65,8 @@
     # frame selector.  The bits are zero for uncoded lenses when manually coding
     # from the menu on the M9. - PH
+    # Frame selector bits (from ref 10, M8):
+    #   1 => '28/90mm frame lines engaged',
+    #   2 => '24/35mm frame lines engaged',
+    #   3 => '50/75mm frame lines engaged',
     '0 0' => 'Uncoded lens',
 #
@@ -69,4 +83,6 @@
     9 => 'Elmarit-M 135mm f/2.8 (I/II)',    # 11829
     '9 0' => 'Apo-Telyt-M 135mm f/3.4',     # 11889
+    11 => 'Summaron-M 28mm f/5.6',          # ? (ref IB)
+    12 => 'Thambar-M 90mm f/2.2',           # ? (ref IB)
     16 => 'Tri-Elmar-M 16-18-21mm f/4 ASPH.',# 11626
     '16 1' => 'Tri-Elmar-M 16-18-21mm f/4 ASPH. (at 16mm)',
@@ -94,4 +110,6 @@
     '39 0' => 'Tele-Elmar-M 135mm f/4 (II)',# 11861
     40 => 'Macro-Adapter M',                # 14409
+    41 => 'Apo-Summicron-M 50mm f/2 ASPH.', #IB
+    '41 3' => 'Apo-Summicron-M 50mm f/2 ASPH.', #16
     42 => 'Tri-Elmar-M 28-35-50mm f/4 ASPH.',# 11625
     '42 1' => 'Tri-Elmar-M 28-35-50mm f/4 ASPH. (at 28mm)',
@@ -106,5 +124,11 @@
     49 => 'Noctilux-M 50mm f/0.95 ASPH.',   # ? (ref 11)
     50 => 'Elmar-M 24mm f/3.8 ASPH.',       # ? (ref 11)
-    52 => 'Super-Elmar-M 18mm f/3.8 ASPH.', # ? (ref PH/11)
+    51 => 'Super-Elmar-M 21mm f/3.4 Asph',  # ? (ref 16, frameSelectorBits=1)
+    '51 2' => 'Super-Elmar-M 14mm f/3.8 Asph', # ? (ref 16)
+    52 => 'Apo-Telyt-M 18mm f/3.8 ASPH.', # ? (ref PH/11)
+    53 => 'Apo-Telyt-M 135mm f/3.4',        #IB
+    '53 2' => 'Apo-Telyt-M 135mm f/3.4',    #16
+    '53 3' => 'Apo-Summicron-M 50mm f/2 (VI)', #LR
+    58 => 'Noctilux-M 75mm f/1.25 ASPH.',   # ? (ref IB)
 );
 
@@ -149,5 +173,7 @@
     49 => 3, # (NC)
     50 => 2, # (NC)
+    51 => 1, # or 2 (ref 16)
     52 => 3,
+    53 => 2, #16
 );
 
@@ -198,5 +224,41 @@
     45 => 'My Color', #PH (GF1)
     46 => 'Photo Frame', #PH (FS7)
+    48 => 'Movie', #PH (GM1)
+    # 49 - seen for FS4 (snow?)
     51 => 'HDR', #12
+    52 => 'Peripheral Defocus', #Horst Wandres
+    55 => 'Handheld Night Shot', #PH (FZ47)
+    57 => '3D', #PH (3D1)
+    59 => 'Creative Control', #PH (FZ47)
+    60 => 'Intelligent Auto Plus', #20
+    62 => 'Panorama', #17
+    63 => 'Glass Through', #17
+    64 => 'HDR', #17
+    66 => 'Digital Filter', #PH (GF5 "Impressive Art", "Cross Process", "Color Select", "Star")
+    67 => 'Clear Portrait', #18
+    68 => 'Silky Skin', #18
+    69 => 'Backlit Softness', #18
+    70 => 'Clear in Backlight', #18
+    71 => 'Relaxing Tone', #18
+    72 => "Sweet Child's Face", #18
+    73 => 'Distinct Scenery', #18
+    74 => 'Bright Blue Sky', #18
+    75 => 'Romantic Sunset Glow', #18
+    76 => 'Vivid Sunset Glow', #18
+    77 => 'Glistening Water', #18
+    78 => 'Clear Nightscape', #18
+    79 => 'Cool Night Sky', #18
+    80 => 'Warm Glowing Nightscape', #18
+    81 => 'Artistic Nightscape', #18
+    82 => 'Glittering Illuminations', #18
+    83 => 'Clear Night Portrait', #18
+    84 => 'Soft Image of a Flower', #18
+    85 => 'Appetizing Food', #18
+    86 => 'Cute Dessert', #18
+    87 => 'Freeze Animal Motion', #18
+    88 => 'Clear Sports Shot', #18
+    89 => 'Monochrome', #18
+    90 => 'Creative Control', #18
+    92 => 'Handheld Night Shot', #forum11523
 );
 
@@ -209,10 +271,15 @@
         Name => 'ImageQuality',
         Writable => 'int16u',
-        PrintConv => {
+        Notes => 'quality of the main image, which may be in a different file',
+        PrintConv => {
+            1 => 'TIFF', #PH (FZ20)
             2 => 'High',
             3 => 'Normal',
+            # 5 - seen this for 1920x1080, 30fps SZ7 video - PH
             6 => 'Very High', #3 (Leica)
-            7 => 'Raw', #3 (Leica)
+            7 => 'RAW', #3 (Leica)
             9 => 'Motion Picture', #PH (LZ6)
+            11 => 'Full HD Movie', #PH (V-LUX)
+            12 => '4k Movie', #PH (V-LUX)
         },
     },
@@ -245,6 +312,11 @@
             8 => 'Flash',
             10 => 'Black & White', #3 (Leica)
-            11 => 'Manual', #PH (FZ8)
+            11 => 'Manual 2', #PH (FZ8)
             12 => 'Shade', #PH (FS7)
+            13 => 'Kelvin', #PeterK (NC)
+            14 => 'Manual 3', #forum9296
+            15 => 'Manual 4', #forum9296
+            # also seen 18,26 (forum9296)
+            19 => 'Auto (cool)', #PH (Leica C-Lux)
         },
     },
@@ -257,5 +329,7 @@
             4 => 'Auto, Focus button', #4
             5 => 'Auto, Continuous', #4
-            # have seens 6 for GF1 - PH
+            6 => 'AF-S', #18 (also seen for GF1 - PH)
+            7 => 'AF-C', #18
+            8 => 'AF-F', #18 (auto-focus flexible)
         },
     },
@@ -279,4 +353,7 @@
                 '0 1'   => '9-area', # (FS7)
                 '0 16'  => '3-area (high speed)', # (FZ8)
+                '0 23'  => '23-area', #PH (FZ47,NC)
+                '0 49'  => '49-area', #20
+                '0 225' => '225-area', #22
                 '1 0'   => 'Spot Focusing', # (FZ8)
                 '1 1'   => '5-area', # (FZ8)
@@ -284,9 +361,15 @@
                 '16 0'  => '1-area', # (FZ8)
                 '16 16' => '1-area (high speed)', # (FZ8)
-                '32 0'  => 'Auto or Face Detect', # (Face Detect for FS7, Auto is DMC-L1 guess)
+                # '32 0' is Face Detect for FS7, and Face Detect or Focus Tracking
+                # for the DMC-FZ200 (ref 17), and Auto is DMC-L1 guess,
+                '32 0'  => 'Tracking',
                 '32 1'  => '3-area (left)?', # (DMC-L1 guess)
                 '32 2'  => '3-area (center)?', # (DMC-L1 guess)
                 '32 3'  => '3-area (right)?', # (DMC-L1 guess)
                 '64 0'  => 'Face Detect',
+                '64 1' => 'Face Detect (animal detect on)', #forum11194
+                '64 2' => 'Face Detect (animal detect off)', #forum11194
+                '128 0' => 'Pinpoint focus', #18/forum11194
+                '240 0' => 'Tracking', #22
             },
         },
@@ -296,8 +379,15 @@
         Writable => 'int16u',
         PrintConv => {
-            2 => 'On, Mode 1',
+            2 => 'On, Optical',
             3 => 'Off',
             4 => 'On, Mode 2',
-            # GF1 also has a mode 3
+            5 => 'On, Optical Panning', #18
+            # GF1 also has a "Mode 3" - PH
+            6 => 'On, Body-only', #PH (GX7, sensor shift?)
+            7 => 'On, Body-only Panning', #forum11194
+            9 => 'Dual IS', #20
+            10 => 'Dual IS Panning', #forum11194
+            11 => 'Dual2 IS', #forum9298
+            12 => 'Dual2 IS Panning', #forum11194
         },
     },
@@ -321,5 +411,9 @@
         Name => 'Audio',
         Writable => 'int16u',
-        PrintConv => { 1 => 'Yes', 2 => 'No' },
+        PrintConv => {
+            1 => 'Yes',
+            2 => 'No',
+            3 => 'Stereo', #PH (NC)
+        },
     },
     0x21 => { #2
@@ -342,4 +436,8 @@
         Format => 'int16s',
         Writable => 'int16s',
+        ValueConv => '$val / 3', #17 (older models may not have factor of 3? - PH)
+        ValueConvInv => '$val * 3',
+        PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)',
+        PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)',
     },
     0x25 => { #PH
@@ -362,5 +460,13 @@
         Writable => 'undef',
     },
-    # 0x27 - values: 0 (LZ6,FX10K)
+    0x27 => {
+        Name => 'VideoFrameRate',
+        Writable => 'int16u',
+        Notes => 'only valid for older models',
+        PrintConv => {
+            OTHER => sub { shift },
+            0 => 'n/a',
+        },
+    },
     0x28 => {
         Name => 'ColorEffect',
@@ -374,4 +480,5 @@
             5 => 'Sepia',
             6 => 'Happy', #PH (FX70) (yes, really. you wouldn't want sad colors now would you?)
+            8 => 'Vivid', #PH (SZ3)
         },
     },
@@ -397,7 +504,10 @@
             my $m = int($val / 60);
             $val -= $m * 60;
-            my $s = int($val);
-            my $f = 100 * ($val - int($val));
-            return sprintf("%s%.2d:%.2d:%.2d.%.2d",$str,$h,$m,$s,$f);
+            my $ss = sprintf('%05.2f', $val);
+            if ($ss >= 60) {
+                $ss = '00.00';
+                ++$m >= 60 and $m -= 60, ++$h;
+            }
+            return sprintf("%s%.2d:%.2d:%s",$str,$h,$m,$ss);
         },
         PrintConvInv => sub {
@@ -419,6 +529,10 @@
             0 => 'Off',
             1 => 'On', #PH (TZ5) [was "Low/High Quality" from ref 4]
-            2 => 'Infinite',
+            2 => 'Auto Exposure Bracketing (AEB)', #17
+            3 => 'Focus Bracketing', #forum11194
             4 => 'Unlimited', #PH (TZ5)
+            8 => 'White Balance Bracketing', #18
+            17 => 'On (with flash)', #forum5597
+            18 => 'Aperture Bracketing', #forum11194
         },
     },
@@ -430,5 +544,5 @@
         {
             Name => 'ContrastMode',
-            Condition => '$$self{Model} !~ /^DMC-(FX10|G1|L1|L10|LC80|GF1|TZ10|ZS7)$/',
+            Condition => '$$self{Model} !~ /^DMC-(FX10|G1|L1|L10|LC80|GF\d+|G2|TZ10|ZS7)$/',
             Flags => 'PrintHex',
             Writable => 'int16u',
@@ -439,11 +553,19 @@
             },
             PrintConv => {
-                0 => 'Normal',
-                1 => 'Low',
-                2 => 'High',
-                # 3 - observed with LZ6 and TZ5 in Fireworks mode - PH
-                # 5 - observed with FX01, FX40 and FP8 (EXIF contrast "Normal") - PH
-                6 => 'Medium Low', #PH (FZ18)
-                7 => 'Medium High', #PH (FZ18)
+                0x00 => 'Normal',
+                0x01 => 'Low',
+                0x02 => 'High',
+                # 0x03 - observed with LZ6 and TZ5 in Fireworks mode
+                #        and GX7 in Fantasy/Retro/OldDays/HighKey - PH
+                # 0x04 - observed in MP4 movie with GM1 (EXIF and 0x39 Contrast "Normal") - PH
+                0x05 => 'Normal 2', #forum1194
+                0x06 => 'Medium Low', #PH (FZ18)
+                0x07 => 'Medium High', #PH (FZ18)
+                # 0x08 - GX7 in DynamicMonochrome mode
+                0x0d => 'High Dynamic', #PH (FZ47 in ?)
+                # 0x13 - seen for LX100 (PH)
+                0x18 => 'Dynamic Range (film-like)', #forum11194
+                0x2e => 'Match Filter Effects Toy', #forum11194
+                0x37 => 'Match Photo Style L. Monochrome', #forum11194
                 # DMC-LC1 values:
                 0x100 => 'Low',
@@ -453,8 +575,8 @@
         },{
             Name => 'ContrastMode',
-            Condition => '$$self{Model} eq "DMC-GF1"',
-            Notes => 'these values are used by the GF1',
+            Condition => '$$self{Model} =~ /^DMC-(GF\d+|G2)$/',
+            Notes => 'these values are used by the G2, GF1, GF2, GF3, GF5 and GF6',
             Writable => 'int16u',
-            PrintConv => {
+            PrintConv => { # (decoded for GF1 unless otherwise noted)
                 0 => '-2',
                 1 => '-1',
@@ -463,14 +585,50 @@
                 4 => '+2',
                 # Note: Other Contrast tags will be "Normal" in any of these modes:
-                7 => 'Nature (Color Film)',
-                12 => 'Smooth (Color Film) or Pure (My Color)',
-                17 => 'Dynamic (B&W Film)',
-                22 => 'Smooth (B&W Film)',
-                27 => 'Dynamic (Color Film)',
-                32 => 'Vibrant (Color Film) or Expressive (My Color)',
+                5 => 'Normal 2', # 5 - seen for Portrait (FX80) and Normal (GF6)
+                7 => 'Nature (Color Film)', # (GF1,G2; GF3 "Miniature")
+                9 => 'Expressive', #(GF3)
+                12 => 'Smooth (Color Film) or Pure (My Color)', #(GF1,G2 "Smooth Color")
+                17 => 'Dynamic (B&W Film)', #(GF1,G2)
+                22 => 'Smooth (B&W Film)', #(GF1,G2)
+                25 => 'High Dynamic', #(GF5)
+                26 => 'Retro', #(GF5)
+                27 => 'Dynamic (Color Film)', #(GF1,G2) (GF3 "High Key")
+                28 => 'Low Key', #(GF5)
+                29 => 'Toy Effect', #(GF5)
+                32 => 'Vibrant (Color Film) or Expressive (My Color)', # (GF1; G2 "Vibrant"; GF2,GF5 "Expressive")
                 33 => 'Elegant (My Color)',
-                37 => 'Nostalgic (Color Film)',
-                41 => 'Dynamic Art (My Color)',
+                37 => 'Nostalgic (Color Film)', # (GF1,G2; GF5 "Sepia")
+                41 => 'Dynamic Art (My Color)', # (GF5 "High Key")
                 42 => 'Retro (My Color)',
+                45 => 'Cinema', #(GF2)
+                47 => 'Dynamic Mono', #(GF5)
+                50 => 'Impressive Art', #(GF5)
+                51 => 'Cross Process', #(GF5)
+                100 => 'High Dynamic 2', #Exiv2 (G6)
+                101 => 'Retro 2', #Exiv2 (G6)
+                102 => 'High Key 2', #Exiv2 (G6)
+                103 => 'Low Key 2', #Exiv2 (G6)
+                104 => 'Toy Effect 2', #Exiv2 (G6)
+                107 => 'Expressive 2', #(GF6)
+                112 => 'Sepia', #Exiv2 (G6)
+                117 => 'Miniature', #Exiv2 (G6)
+                122 => 'Dynamic Monochrome', #(GF6)
+                127 => 'Old Days', #Exiv2 (G6)
+                132 => 'Dynamic Monochrome 2', #Exiv2 (G6)
+                135 => 'Impressive Art 2', #Exiv2 (G6)
+                136 => 'Cross Process 2', #Exiv2 (G6)
+                137 => 'Toy Pop', #Exiv2 (G6)
+                138 => 'Fantasy', #Exiv2 (G6)
+                256 => 'Normal 3', #Exiv2 (G6)
+                272 => 'Standard', #Exiv2 (G6)
+                288 => 'High', #Exiv2 (G6)
+                # more new modes for GF6:
+                # ? => 'Old Days',
+                # ? => 'Toy Pop',
+                # ? => 'Bleach Bypass',
+                # ? => 'Fantasy',
+                # ? => 'Star Filter',
+                # ? => 'One Point Color',
+                # ? => 'Sunshine',
             },
         },{
@@ -494,4 +652,5 @@
         Name => 'NoiseReduction',
         Writable => 'int16u',
+        Notes => 'the encoding for this value is not consistent between models',
         PrintConv => {
             0 => 'Standard',
@@ -500,4 +659,11 @@
             3 => 'Lowest (-2)', #JD
             4 => 'Highest (+2)', #JD
+            5 => '+5', #PH (NC)
+            6 => '+6', # (NC) seen for DC-S1/S1R (IB)
+            65531 => '-5', # LX100/FZ2500 "NR1" test shots at imaging-resource (PH)
+            65532 => '-4',
+            65533 => '-3',
+            65534 => '-2',
+            65535 => '-1',
         },
     },
@@ -506,7 +672,12 @@
         Writable => 'int16u',
         PrintConv => {
+            0 => 'Off (0)', #forum11529
             1 => 'Off',
             2 => '10 s',
             3 => '2 s',
+            4 => '10 s / 3 pictures', #17
+            258 => '2 s after shutter pressed', #forum11194
+            266 => '10 s after shutter pressed', #forum11194
+            778 => '3 photos after 10 s', #forum11194
         },
     },
@@ -576,5 +747,18 @@
     },
     # 0x37 - values: 0,1,2 (LZ6, 0 for movie preview); 257 (FX10K); 0,256 (TZ5, 0 for movie preview)
-    # 0x38 - values: 0,1,2 (LZ6, same as 0x37); 1,2 (FX10K); 0,256 (TZ5, 0 for movie preview)
+    #        --> may indicate battery power (forum11388)
+    0x38 => { #forum11388
+        Name => 'BatteryLevel',
+        Writable => 'int16u',
+        PrintConv => {
+            1 => 'Full',
+            2 => 'Medium',
+            3 => 'Low',
+            4 => 'Near Empty',
+            7 => 'Near Full',
+            8 => 'Medium Low',
+            256 => 'n/a',
+        },
+    },
     0x39 => { #7 (L1/L10)
         Name => 'Contrast',
@@ -599,37 +783,17 @@
     0x3c => { #PH
         Name => 'ProgramISO', # (maybe should rename this ISOSetting?)
-        Writable => 'int16u',
-        PrintConv => {
-            OTHER => sub { return shift },
+        Writable => 'int16u', # (new models store a long here)
+        PrintConv => {
+            OTHER => sub { shift },
             65534 => 'Intelligent ISO', #PH (FS7)
             65535 => 'n/a',
+            -1 => 'n/a',
         },
     },
     0x3d => { #PH
-        Name => 'AdvancedSceneMode',
-        Writable => 'int16u',
-        # values for the FZ28 (SceneMode/AdvancedSceneMode, "*"=add mode name) - PH:
-        # Portrait: 2/1=Normal*, 24/1=Soft Skin, 2/2=Outdoor*, 2/3=Indoor*, 2/4=Creative*
-        # Scenery: 3/1=Normal*, 3/2=Nature, 3/3=Architecture, 3/4=Creative*
-        # Sports: 4/1=Normal*, 4/2=Outdoor*, 4/3=Indoor*, 4/4=Creative*
-        # Night Scenery: 5/1=Night Portrait, 21/1=*, 21/2=Illuminations, 21/4=Creative*
-        # Macro (Close-up): 9/2=Flower, 22/1=Food, 9/3=Objects, 9/4=Creative*
-        # - have seen value of 5 for TZ5 (Macro) and FS20 (Scenery and Intelligent Auto)
-        #   --> I'm guessing this is "Auto" - PH
-        # - values for HDR mode (ref 12): 1=Standard, 2=Art, 3=B&W
-        PrintConv => {
-            1 => 'Normal',
-            2 => 'Outdoor/Illuminations/Flower/HDR Art',
-            3 => 'Indoor/Architecture/Objects/HDR B&W',
-            4 => 'Creative',
-            5 => 'Auto',
-            7 => 'Expressive', #(GF1)
-            8 => 'Retro', #(GF1)
-            9 => 'Pure', #(GF1)
-            10 => 'Elegant', #(GF1)
-            12 => 'Monochrome', #(GF1)
-            13 => 'Dynamic Art', #(GF1)
-            14 => 'Silhouette', #(GF1)
-        },
+        Name => 'AdvancedSceneType',
+        Writable => 'int16u',
+        Notes => 'used together with SceneMode to derive Composite AdvancedSceneMode',
+        # see forum11194 for more info
     },
     0x3e => { #PH (TZ5/FS7)
@@ -659,5 +823,5 @@
         Writable => 'int16u',
         PrintConv => {
-            0 => 'n/a', #PH (ie. FZ100 "Photo Frame" ShootingMode)
+            0 => 'n/a', #PH (eg. FZ100 "Photo Frame" ShootingMode)
             1 => 'Standard (color)',
             2 => 'Dynamic (color)',
@@ -669,14 +833,39 @@
             # 8 => 'My Film 1'? (from owner manual)
             # 9 => 'My Film 2'?
-            10 => 'Nostalgic', # GH1
-            11 => 'Vibrant', # GH1
+            10 => 'Nostalgic', #(GH1)
+            11 => 'Vibrant', #(GH1)
             # 12 => 'Multi Film'? (in the GH1 specs)
         },
     },
-    # 0x43 - int16u: 2,3
-    # 0x44 - int16u: 0,2500
-    # 0x45 - int16u: 0
+    0x43 => { #forum9369
+        Name => 'JPEGQuality',
+        Writable => 'int16u',
+        PrintConv => {
+            0 => 'n/a (Movie)',
+            2 => 'High',
+            3 => 'Standard',
+            6 => 'Very High',
+            255 => 'n/a (RAW only)',
+        },
+    },
+    0x44 => {
+        Name => 'ColorTempKelvin',
+        Format => 'int16u',
+    },
+    0x45 => { #19
+        Name => 'BracketSettings',
+        Writable => 'int16u',
+        PrintConv => {
+            0 => 'No Bracket',
+            1 => '3 Images, Sequence 0/-/+',
+            2 => '3 Images, Sequence -/0/+',
+            3 => '5 Images, Sequence 0/-/+',
+            4 => '5 Images, Sequence -/0/+',
+            5 => '7 Images, Sequence 0/-/+',
+            6 => '7 Images, Sequence -/0/+',
+        },
+    },
     0x46 => { #PH/JD
-        Name => 'WBAdjustAB',
+        Name => 'WBShiftAB',
         Format => 'int16s',
         Writable => 'int16u',
@@ -684,11 +873,26 @@
     },
     0x47 => { #PH/JD
-        Name => 'WBAdjustGM',
+        Name => 'WBShiftGM',
         Format => 'int16s',
         Writable => 'int16u',
         Notes => 'positive is a shift toward green',
     },
-    # 0x48 - int16u: 0
-    # 0x49 - int16u: 2
+    0x48 => { #17
+        Name => 'FlashCurtain',
+        Writable => 'int16u',
+        PrintConv => {
+            0 => 'n/a',
+            1 => '1st',
+            2 => '2nd',
+        },
+    },
+    0x49 => { #19
+        Name => 'LongExposureNoiseReduction', # (indicates availability, forum11194)
+        Writable => 'int16u',
+        PrintConv => {
+            1 => 'Off',
+            2 => 'On'
+        }
+    },
     # 0x4a - int16u: 0
     0x4b => { #PH
@@ -723,15 +927,26 @@
         Name => 'LensType',
         Writable => 'string',
+        ValueConv => '$val=~s/ +$//; $val', # trim trailing spaces
+        ValueConvInv => '$val',
     },
     0x52 => { #7 (DMC-L1)
         Name => 'LensSerialNumber',
         Writable => 'string',
+        ValueConv => '$val=~s/ +$//; $val', # trim trailing spaces
+        ValueConvInv => '$val',
     },
     0x53 => { #7 (DMC-L1)
         Name => 'AccessoryType',
         Writable => 'string',
-    },
-    # 0x54 - string[14]: "0000000"
-    # 0x55 - int16u: 1
+        ValueConv => '$val=~s/ +$//; $val', # trim trailing spaces
+        ValueConvInv => '$val',
+    },
+    0x54 => { #19
+        Name => 'AccessorySerialNumber',
+        Writable => 'string',
+        ValueConv => '$val=~s/ +$//; $val', # trim trailing spaces
+        ValueConvInv => '$val',
+    },
+    # 0x55 - int16u: 1 (see forum9372)
     # 0x57 - int16u: 0
     0x59 => { #PH (FS7)
@@ -763,5 +978,13 @@
         },
     },
-    # 0x5e,0x5f,0x60 - undef[4]
+    # 0x5e,0x5f - undef[4]
+    0x60 => { #18
+        Name => 'LensFirmwareVersion',
+        Writable => 'undef',
+        Format => 'int8u',
+        Count => 4,
+        PrintConv => '$val=~tr/ /./; $val',
+        PrintConvInv => '$val=~tr/./ /; $val',
+    },
     0x61 => { #PH
         Name => 'FaceRecInfo',
@@ -816,9 +1039,10 @@
     },
     # 0x6c - int8u: 1
-    0x6d => { #PH (ZS7)
+    0x6d => { #PH (ZS7) (also see forum5997)
         Name => 'City', # (City/Town)
         Groups => { 2 => 'Location' },
         Format => 'string',
         Writable => 'undef', # (Count 72)
+        Notes => 'City/Town as stored by some models, or County/Township for others',
     },
     # 0x6e - int8u: 1
@@ -843,5 +1067,16 @@
     },
     # 0x71 - undef[128] (maybe text stamp text?)
-    # 0x72,0x73,0x74,0x75,0x76,0x77,0x78: 0
+    0x77 => { #18
+        Name => 'BurstSpeed',
+        Writable => 'int16u',
+        Notes => 'images per second',
+    },
+    # 0x72,0x73,0x74,0x75,0x77,0x78: 0
+    # 0x76: 0, (3 for G6 with HDR on, ref 18)
+    0x76 => { #18/21
+        Name => 'HDRShot',
+        Writable => 'int16u',
+        PrintConv => { 0 => 'Off', 3 => 'On' },
+    },
     0x79 => { #PH (GH2)
         Name => 'IntelligentD-Range',
@@ -855,11 +1090,347 @@
     },
     # 0x7a,0x7b: 0
+    0x7c => { #18
+        Name => 'ClearRetouch',
+        Writable => 'int16u',
+        PrintConv => { 0 => 'Off', 1 => 'On' },
+    },
+    0x80 => { #forum5997 (seen garbage here for SZ5 - PH)
+        Name => 'City2', # (City/Town/Village)
+        Groups => { 2 => 'Location' },
+        Format => 'string',
+        Writable => 'undef', # (Count 72)
+        Notes => 'City/Town/Village as stored by some models',
+    },
+    # 0x81 - undef[72]: "---"
+    # 0x82 - undef[72]: "---"
+    # 0x83 - undef[72]: "---"
+    # 0x84 - undef[72]: "---"
+    # 0x85 - undef[128]: "---"
+    0x86 => { #http://dev.exiv2.org/issues/825
+        Name => 'ManometerPressure',
+        Writable => 'int16u',
+        RawConv => '$val==65535 ? undef : $val',
+        ValueConv => '$val / 10',
+        ValueConvInv => '$val * 10',
+        PrintConv => 'sprintf("%.1f kPa",$val)',
+        PrintConvInv => '$val=~s/ ?kPa//i; $val',
+    },
+    0x89 => {
+        Name => 'PhotoStyle',
+        Writable => 'int16u',
+        PrintConv => {
+            0 => 'Auto',
+            1 => 'Standard or Custom',
+            2 => 'Vivid',
+            3 => 'Natural',
+            4 => 'Monochrome',
+            5 => 'Scenery',
+            6 => 'Portrait',
+            8 => 'Cinelike D', #forum11194
+            9 => 'Cinelike V', #forum11194
+            11 => 'L. Monochrome', #forum11194
+            15 => 'L. Monochrome D', #forum11194
+        },
+    },
+    0x8a => { #18
+        Name => 'ShadingCompensation',
+        Writable => 'int16u',
+        PrintConv => {
+            0 => 'Off',
+            1 => 'On'
+        }
+    },
+    0x8b => { #21
+        Name => 'WBShiftIntelligentAuto',
+        Writable => 'int16u',
+        Format => 'int16s',
+        Notes => 'value is -9 for blue to +9 for amber.  Valid for Intelligent-Auto modes',
+    },
+    0x8c => {
+        Name => 'AccelerometerZ',
+        Writable => 'int16u',
+        Format => 'int16s',
+        Notes => 'positive is acceleration upwards',
+    },
+    0x8d => {
+        Name => 'AccelerometerX',
+        Writable => 'int16u',
+        Format => 'int16s',
+        Notes => 'positive is acceleration to the left',
+    },
+    0x8e => {
+        Name => 'AccelerometerY',
+        Writable => 'int16u',
+        Format => 'int16s',
+        Notes => 'positive is acceleration backwards',
+    },
+    0x8f => { #18
+        Name => 'CameraOrientation',
+        Writable => 'int8u',
+        PrintConv => {
+            0 => 'Normal',
+            1 => 'Rotate CW',
+            2 => 'Rotate 180',
+            3 => 'Rotate CCW',
+            4 => 'Tilt Upwards',
+            5 => 'Tilt Downwards'
+        }
+    },
+    0x90 => {
+        Name => 'RollAngle',
+        Writable => 'int16u',
+        Format => 'int16s',
+        Notes => 'converted to degrees of clockwise camera rotation',
+        ValueConv => '$val / 10',
+        ValueConvInv => '$val * 10',
+    },
+    0x91 => {
+        Name => 'PitchAngle',
+        Writable => 'int16u',
+        Format => 'int16s',
+        Notes => 'converted to degrees of upward camera tilt',
+        ValueConv => '-$val / 10',
+        ValueConvInv => '-$val * 10',
+    },
+    0x92 => { #21 (forum9453) (more to decode in forum11194)
+        Name => 'WBShiftCreativeControl',
+        Writable => 'int8u',
+        Format => 'int8s',
+        Notes => 'WB shift or style strength.  Valid for Creative-Control modes',
+    },
+    0x93 => { #18
+        Name => 'SweepPanoramaDirection',
+        Writable => 'int8u',
+        PrintConv => {
+            0 => 'Off',
+            1 => 'Left to Right',
+            2 => 'Right to Left',
+            3 => 'Top to Bottom',
+            4 => 'Bottom to Top'
+        }
+    },
+    0x94 => { #18
+        Name => 'SweepPanoramaFieldOfView',
+        Writable => 'int16u'
+    },
+    0x96 => { #18
+        Name => 'TimerRecording',
+        Writable => 'int8u',
+        PrintConv => {
+            0 => 'Off',
+            1 => 'Time Lapse',
+            2 => 'Stop-motion Animation',
+            3 => 'Focus Bracketing', #forum11194
+        },
+    },
+    0x9d => { #18
+        Name => 'InternalNDFilter',
+        Writable => 'rational64u'
+    },
+    0x9e => { #18
+        Name => 'HDR',
+        Writable => 'int16u',
+        PrintConv => {
+            0 => 'Off',
+            100 => '1 EV',
+            200 => '2 EV',
+            300 => '3 EV',
+            32868 => '1 EV (Auto)',
+            32968 => '2 EV (Auto)',
+            33068 => '3 EV (Auto)',
+        },
+    },
+    0x9f => { #18
+        Name => 'ShutterType',
+        Writable => 'int16u',
+        PrintConv => {
+            0 => 'Mechanical',
+            1 => 'Electronic',
+            2 => 'Hybrid', #PH (GM1, 1st curtain electronic, 2nd curtain mechanical)
+        },
+    },
+    # 0xa0 - undef[32]: AWB gains and black levels (ref forum9303)
+    0xa1 => { #forum11194
+        Name => 'FilterEffect',
+        Writable => 'rational64u',
+        Format => 'int32u',
+        PrintConv => {
+            '0 0' => 'Expressive',
+            # '0 1' => have seen this for XS1 (PH)
+            '0 2' => 'Retro',
+            '0 4' => 'High Key',
+            '0 8' => 'Sepia',
+            '0 16' => 'High Dynamic',
+            '0 32' => 'Miniature Effect',
+            '0 256' => 'Low Key',
+            '0 512' => 'Toy Effect',
+            '0 1024' => 'Dynamic Monochrome',
+            '0 2048' => 'Soft Focus',
+            '0 4096' => 'Impressive Art',
+            '0 8192' => 'Cross Process',
+            '0 16384' => 'One Point Color',
+            '0 32768' => 'Star Filter',
+            '0 524288' => 'Old Days',
+            '0 1048576' => 'Sunshine',
+            '0 2097152' => 'Bleach Bypass',
+            '0 4194304' => 'Toy Pop',
+            '0 8388608' => 'Fantasy',
+            '0 33554432' => 'Monochrome',
+            '0 67108864' => 'Rough Monochrome',
+            '0 134217728' => 'Silky Monochrome',
+        },
+    },
+    0xa3 => { #18
+        Name => 'ClearRetouchValue',
+        Writable => 'rational64u',
+        # undef if ClearRetouch is off, 0 if it is on
+    },
+    0xa7 => { #forum9374 (conversion table for 14- to 16-bit mapping)
+        Name => 'OutputLUT',
+        Binary => 1,
+        Notes => q{
+            2-column by 432-row binary lookup table of unsigned short values for
+            converting to 16-bit output (1st column) from 14 bits (2nd column) with
+            camera contrast
+        },
+    },
+    0xab => { #18
+        Name => 'TouchAE',
+        Writable => 'int16u',
+        PrintConv => { 0 => 'Off', 1 => 'On' },
+    },
+    0xac => { #forum11194
+        Name => 'MonochromeFilterEffect',
+        Writable => 'int16u',
+        PrintConv => { 0 => 'Off', 1 => 'Yellow', 2 => 'Orange', 3 => 'Red', 4 => 'Green' },
+    },
+    0xad => { #forum9360
+        Name => 'HighlightShadow',
+        Writable => 'int16u',
+        Format => 'int16s', #forum11194
+        Count => 2,
+    },
+    0xaf => { #PH (is this in UTC maybe? -- sometimes different time zone other times)
+        Name => 'TimeStamp',
+        Writable => 'string',
+        Groups => { 2 => 'Time' },
+        Shift => 'Time',
+        PrintConv => '$self->ConvertDateTime($val)',
+        PrintConvInv => '$self->InverseDateTime($val)',
+    },
+    0xb3 => { #forum11194
+        Name => 'VideoBurstResolution',
+        Writable => 'int16u',
+        PrintConv => { 1 => 'Off or 4K', 4 => '6K' },
+    },
+    0xb4 => { #forum9429
+        Name => 'MultiExposure',
+        Writable => 'int16u',
+        PrintConv => { 0 => 'n/a', 1 => 'Off', 2 => 'On' },
+    },
+    0xb9 => { #forum9425
+        Name => 'RedEyeRemoval',
+        Writable => 'int16u',
+        PrintConv => { 0 => 'Off', 1 => 'On' },
+    },
+    0xbb => { #forum9282
+        Name => 'VideoBurstMode',
+        Writable => 'int32u',
+        PrintHex => 1,
+        PrintConv => {
+            0x01 => 'Off',
+            0x04 => 'Post Focus',
+            0x18 => '4K Burst',
+            0x28 => '4K Burst (Start/Stop)',
+            0x48 => '4K Pre-burst',
+            0x108 => 'Loop Recording',
+            0x810 => '6K Burst',
+            0x820 => '6K Burst (Start/Stop)',
+            0x408 => 'Focus Stacking', #forum11563
+            0x1001 => 'High Resolution Mode',
+        },
+    },
+    0xbc => { #forum9282
+        Name => 'DiffractionCorrection',
+        Writable => 'int16u',
+        PrintConv => { 0 => 'Off', 1 => 'Auto' },
+    },
+    0xbd => { #forum11194
+        Name => 'FocusBracket',
+        Notes => 'positive is further, negative is closer',
+        Writable => 'int16u',
+        Format => 'int16s',
+    },
+    0xbe => { #forum11194
+        Name => 'LongExposureNRUsed',
+        Writable => 'int16u',
+        PrintConv => { 0 => 'No', 1 => 'Yes' },
+    },
+    0xbf => { #forum11194
+        Name => 'PostFocusMerging',
+        Format => 'int32u',
+        Count => 2,
+        PrintConv => { '0 0' => 'Post Focus Auto Merging or None' },
+    },
+    0xc1 => { #forum11194
+        Name => 'VideoPreburst',
+        Writable => 'int16u',
+        PrintConv => { 0 => 'No', 1 => '4K or 6K' },
+    },
+    0xca => { #forum11459
+        Name => 'SensorType',
+        Writable => 'int16u',
+        PrintConv => {
+            0 => 'Multi-aspect',
+            1 => 'Standard',
+        },
+    },
+    # Note: LensTypeMake and LensTypeModel are combined into a Composite LensType tag
+    # defined in Olympus.pm which has the same values as Olympus:LensType
+    0xc4 => { #PH
+        Name => 'LensTypeMake',
+        Condition => '$format eq "int16u" and $$valPt ne "\xff\xff"',   # (ignore make 65535 for now)
+        Writable => 'int16u',
+    },
+    0xc5 => { #PH
+        Name => 'LensTypeModel',
+        Condition => '$format eq "int16u"',
+        Writable => 'int16u',
+        RawConv => q{
+            return undef unless $val;
+            require Image::ExifTool::Olympus; # (to load Composite LensID)
+            return $val;
+        },
+        ValueConv => '$_=sprintf("%.4x",$val); s/(..)(..)/$2 $1/; $_',
+        ValueConvInv => '$val =~ s/(..) (..)/$2$1/; hex($val)',
+    },
+    0xd1 => { #PH
+        Name => 'ISO',
+        RawConv => '$val > 0xfffffff0 ? undef : $val',
+        Writable => 'int32u',
+    },
+    0xd2 => { #forum11194
+        Name => 'MonochromeGrainEffect',
+        Writable => 'int16u',
+        PrintConv => {
+            0 => 'Off',
+            1 => 'Low',
+            2 => 'Standard',
+            3 => 'High',
+        },
+    },
+    0xd6 => { #PH (DC-S1)
+        Name => 'NoiseReductionStrength',
+        Writable => 'rational64s',
+    },
     0x0e00 => {
         Name => 'PrintIM',
         Description => 'Print Image Matching',
         Writable => 0,
-        SubDirectory => {
-            TagTable => 'Image::ExifTool::PrintIM::Main',
-        },
+        SubDirectory => { TagTable => 'Image::ExifTool::PrintIM::Main' },
+    },
+    0x2003 => { #21
+        Name => 'TimeInfo',
+        SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::TimeInfo' },
     },
     0x8000 => { #PH
@@ -876,7 +1447,14 @@
         },
     },
-    # 0x8002 - values: 1,2 related to focus? (PH/JD)
-    #          1 for HDR modes, 2 for Portrait (ref 12)
-    # 0x8003 - values: 1,2 related to focus? (PH/JD)
+    0x8002 => { #21
+        Name => 'HighlightWarning',
+        Writable => 'int16u',
+        PrintConv => { 0 => 'Disabled', 1 => 'No', 2 => 'Yes' },
+    },
+    0x8003 => { #21
+        Name => 'DarkFocusEnvironment',
+        Writable => 'int16u',
+        PrintConv => { 1 => 'No', 2 => 'Yes' },
+    },
     0x8004 => { #PH/JD
         Name => 'WBRedLevel',
@@ -891,9 +1469,9 @@
         Writable => 'int16u',
     },
-    0x8007 => { #PH
-        Name => 'FlashFired',
-        Writable => 'int16u',
-        PrintConv => { 1 => 'No', 2 => 'Yes' },
-    },
+    #0x8007 => { #PH - questionable [disabled because it conflicts with EXIF in too many samples]
+    #    Name => 'FlashFired',
+    #    Writable => 'int16u',
+    #    PrintConv => { 0 => 'Yes', 1 => 'No' },
+    #},
     0x8008 => { #PH (TZ5/FS7)
         # (tags 0x3b, 0x3e, 0x8008 and 0x8009 have the same values in all my samples - PH)
@@ -978,6 +1556,10 @@
     },
     0x310 => {
-        Name => 'LensInfo',
-        SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::LensInfo' },
+        Name => 'LensType',
+        Writable => 'int32u',
+        SeparateTable => 1,
+        ValueConv => '($val >> 2) . " " . ($val & 0x3)',
+        ValueConvInv => \&LensTypeConvInv,
+        PrintConv => \%leicaLensTypes,
     },
     0x311 => {
@@ -1036,4 +1618,8 @@
     WRITABLE => 1,
     NOTES => 'These tags are used by the Leica R8 and R9 digital backs.',
+    0x0b => { #IB
+        Name => 'SerialInfo',
+        SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::SerialInfo' },
+    },
     0x0d => {
         Name => 'WB_RGBLevels',
@@ -1041,4 +1627,16 @@
         Count => 3,
     },
+);
+
+# Leica serial number info (ref IB)
+%Image::ExifTool::Panasonic::SerialInfo = (
+    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
+    GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
+    TAG_PREFIX => 'Leica_SerialInfo',
+    FIRST_ENTRY => 0,
+    4 => {
+        Name => 'SerialNumber',
+        Format => 'string[8]',
+    }
 );
 
@@ -1209,5 +1807,5 @@
         ValueConv => '($val >> 2) . " " . ($val & 0x3)',
         ValueConvInv => \&LensTypeConvInv,
-        PrintConv => \%leicaLensType,
+        PrintConv => \%leicaLensTypes,
     },
     0x3406 => { #PH/13
@@ -1244,4 +1842,36 @@
     },
     # 0x3903 - larger binary data block
+);
+
+# time stamp information (ref 21)
+%Image::ExifTool::Panasonic::TimeInfo = (
+    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
+    WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
+    CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
+    GROUPS => { 0 => 'MakerNotes', 1 => 'Panasonic', 2 => 'Image' },
+    FIRST_ENTRY => 0,
+    WRITABLE => 1,
+    0 => {
+        Name => 'PanasonicDateTime',
+        Groups => { 2 => 'Time' },
+        Shift => 'Time',
+        Format => 'undef[8]',
+        RawConv => '$val =~ /^\0/ ? undef : $val',
+        ValueConv => 'sprintf("%s:%s:%s %s:%s:%s.%s", unpack "H4H2H2H2H2H2H2", $val)',
+        ValueConvInv => q{
+            $val =~ s/[-+].*//;     # remove time zone
+            $val =~ tr/0-9//dc;     # remove non-digits
+            $val = pack("H*",$val);
+            $val .= "\0" while length $val < 8;
+            return $val;
+        },
+        PrintConv => '$self->ConvertDateTime($val)',
+        PrintConvInv => '$self->InverseDateTime($val)',
+    },
+    # 8 - 8 bytes usually 8 x 0xff (spot for another date/time?)
+    16 => {
+        Name => 'TimeLapseShotNumber',
+        Format => 'int32u',
+    },
 );
 
@@ -1256,10 +1886,10 @@
     0x0016 => {
         Name => 'LensType',
-        Writable => 'int32u',
+        Format => 'int32u',
         Priority => 0,
         SeparateTable => 1,
-        ValueConv => '($val >> 2) . " " . ($val & 0x3)',
+        ValueConv => '(($val >> 2) & 0xffff) . " " . ($val & 0x3)',
         ValueConvInv => \&LensTypeConvInv,
-        PrintConv => \%leicaLensType,
+        PrintConv => \%leicaLensTypes,
     },
 );
@@ -1278,8 +1908,27 @@
     GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
     WRITABLE => 1,
-    NOTES => 'This information is written by the X1.',
+    PRIORITY => 0,
+    NOTES => 'This information is written by the X1, X2, X VARIO and T.',
+    0x0303 => {
+        Name => 'LensType',
+        Condition => '$format eq "string"',
+        Notes => 'Leica T only',
+        Writable => 'string',
+    },
+    # 0x0304 - int8u[1]: may be M-lens ID for Leica SL, mounted through "M-adapter L" (ref IB)
+    #          --> int8u[4] for some models (maybe not lens ID for these?) - PH
+    #          (see http://us.leica-camera.com/Photography/Leica-APS-C/Lenses-for-Leica-TL/L-Adapters/M-Adapter-L)
+    #          58 = 'Leica Noctilux-M 75mm F1.25 ASPH (Typ 601) on Leica SL
+    0x0305 => { #IB
+        Name => 'SerialNumber',
+        Writable => 'int32u',
+    },
     # 0x0406 - saturation or sharpness
     0x0407 => { Name => 'OriginalFileName', Writable => 'string' },
     0x0408 => { Name => 'OriginalDirectory',Writable => 'string' },
+    0x040a => { #IB
+        Name => 'FocusInfo',
+        SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::FocusInfo' },
+    },
     # 0x040b - related to white balance
     0x040d => {
@@ -1289,12 +1938,72 @@
         PrintConv => {
             '0 0 0 0' => 'Program AE',
+          # '0 1 0 0' - seen for X (Typ 113) - PH
             '1 0 0 0' => 'Aperture-priority AE',
+            '1 1 0 0' => 'Aperture-priority AE (1)', # (see for Leica T)
             '2 0 0 0' => 'Shutter speed priority AE', #(guess)
             '3 0 0 0' => 'Manual',
         },
     },
-    # 0x0411 - saturation or sharpness
+    0x0410 => {
+        Name => 'ShotInfo',
+        SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::ShotInfo' },
+    },
+    # 0x0410 - int8u[16]: first byte is FileNumber
+    # 0x0411 - int8u[4]: first number is FilmMode (1=Standard,2=Vivid,3=Natural,4=BW Natural,5=BW High Contrast)
     0x0412 => { Name => 'FilmMode',         Writable => 'string' },
     0x0413 => { Name => 'WB_RGBLevels',     Writable => 'rational64u', Count => 3 },
+    0x0500 => {
+        Name => 'InternalSerialNumber',
+        Writable => 'undef',
+        PrintConv => q{
+            return $val unless $val=~/^(.{3})(\d{2})(\d{2})(\d{2})(\d{4})/;
+            my $yr = $2 + ($2 < 70 ? 2000 : 1900);
+            return "($1) $yr:$3:$4 no. $5";
+        },
+        PrintConvInv => '$_=$val; tr/A-Z0-9//dc; s/(.{3})(19|20)/$1/; $_',
+    },
+);
+
+# Leica type5 ShotInfo (ref PH) (X2)
+%Image::ExifTool::Panasonic::ShotInfo = (
+    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
+    WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
+    CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
+    GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
+    TAG_PREFIX => 'Leica_ShotInfo',
+    FIRST_ENTRY => 0,
+    WRITABLE => 1,
+    0 => {
+        Name => 'FileIndex',
+        Format => 'int16u',
+    },
+);
+
+# Leica type5 FocusInfo (ref IB)
+%Image::ExifTool::Panasonic::FocusInfo = (
+    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
+    WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
+    CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
+    GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
+    TAG_PREFIX => 'Leica_FocusInfo',
+    FIRST_ENTRY => 0,
+    WRITABLE => 1,
+    FORMAT => 'int16u',
+    0 => {
+        Name => 'FocusDistance',
+        ValueConv => '$val / 1000',
+        ValueConvInv => '$val * 1000',
+        PrintConv => '$val < 65535 ? "$val m" : "inf"',
+        PrintConvInv => '$val =~ s/ ?m$//; IsFloat($val) ? $val : 65535',
+    },
+    1 => {
+        Name => 'FocalLength',
+        Priority => 0,
+        RawConv => '$val ? $val : undef',
+        ValueConv => '$val / 1000',
+        ValueConvInv => '$val * 1000',
+        PrintConv => 'sprintf("%.1f mm",$val)',
+        PrintConvInv => '$val=~s/\s*mm$//;$val',
+    },
 );
 
@@ -1304,9 +2013,13 @@
     CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
     GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
-    NOTES => 'This information is written by the S2 (as a trailer in JPEG images).',
+    NOTES => q{
+        This information is written by the S2 and M (Typ 240), as a trailer in JPEG
+        images.
+    },
     0x300 => {
         Name => 'PreviewImage',
+        Groups => { 2 => 'Preview' },
         Writable => 'undef',
-        Notes => 'S2',
+        Notes => 'S2 and M (Typ 240)',
         DataTag => 'PreviewImage',
         RawConv => q{
@@ -1325,10 +2038,102 @@
         Flags => [ 'Unknown', 'Binary', 'Drop' ],
     },
-    # 0x302 - same value as 4 unknown bytes at the end of JPEG or after the DNG TIFF header
+    # 0x302 - same value as 4 unknown bytes at the end of JPEG or after the DNG TIFF header (ImageID, ref IB)
     0x303 => {
         Name => 'LensType',
         Writable => 'string',
-    },
-    # 0x340 - same as 0x302
+        ValueConv => '$val=~s/ +$//; $val', # trim trailing spaces
+        ValueConvInv => '$val',
+    },
+    0x304 => { #IB
+        Name => 'FocusDistance',
+        Notes => 'focus distance in mm for most models, but cm for others',
+        Writable => 'int32u',
+    },
+    0x311 => {
+        Name => 'ExternalSensorBrightnessValue',
+        Condition => '$$self{Model} =~ /Typ 006/',
+        Notes => 'Leica S only',
+        Format => 'rational64s', # (may be incorrectly unsigned in JPEG images)
+        Writable => 'rational64s',
+        PrintConv => 'sprintf("%.2f", $val)',
+        PrintConvInv => '$val',
+    },
+    0x312 => {
+        Name => 'MeasuredLV',
+        Condition => '$$self{Model} =~ /Typ 006/',
+        Notes => 'Leica S only',
+        Format => 'rational64s', # (may be incorrectly unsigned in JPEG images)
+        Writable => 'rational64s',
+        PrintConv => 'sprintf("%.2f", $val)',
+        PrintConvInv => '$val',
+    },
+    0x320 => {
+        Name => 'FirmwareVersion',
+        Condition => '$$self{Model} =~ /Typ 006/',
+        Notes => 'Leica S only',
+        Writable => 'int8u',
+        Count => 4,
+        PrintConv => '$val=~tr/ /./; $val',
+        PrintConvInv => '$val=~tr/./ /; $val',
+    },
+    0x321 => { #IB
+        Name => 'LensSerialNumber',
+        Condition => '$$self{Model} =~ /Typ 006/',
+        Notes => 'Leica S only',
+        Writable => 'int32u',
+        PrintConv => 'sprintf("%.10d",$val)',
+        PrintConvInv => '$val',
+    },
+    # 0x321 - SerialNumber for Leica S? (ref IB)
+    # 0x340 - same as 0x302 (ImageID, ref IB)
+);
+
+# Leica type9 maker notes (ref IB) (S)
+%Image::ExifTool::Panasonic::Leica9 = (
+    WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
+    CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
+    GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
+    NOTES => 'This information is written by the Leica S (Typ 007) and M10 models.',
+    0x304 => {
+        Name => 'FocusDistance',
+        Notes => 'focus distance in mm for most models, but cm for others',
+        Writable => 'int32u',
+    },
+    0x311 => {
+        Name => 'ExternalSensorBrightnessValue',
+        Format => 'rational64s', # (may be incorrectly unsigned in JPEG images)
+        Writable => 'rational64s',
+        PrintConv => 'sprintf("%.2f", $val)',
+        PrintConvInv => '$val',
+    },
+    0x312 => {
+        Name => 'MeasuredLV',
+        Format => 'rational64s', # (may be incorrectly unsigned in JPEG images)
+        Writable => 'rational64s',
+        PrintConv => 'sprintf("%.2f", $val)',
+        PrintConvInv => '$val',
+    },
+    # 0x340 - ImageUniqueID
+    0x34c => { #23
+        Name => 'UserProfile',
+        Writable => 'string',
+    },
+    0x359 => { #23
+        Name => 'ISOSelected',
+        Writable => 'int32s',
+        PrintConv => {
+            0 => 'Auto',
+            OTHER => sub { return shift; },
+        },
+    },
+    0x35a => { #23
+        Name => 'FNumber',
+        Writable => 'int32s',
+        ValueConv => '$val / 1000',
+        ValueConvInv => '$val * 1000',
+        PrintConv => 'sprintf("%.1f", $val)',
+        PrintConvInv => '$val',
+    },
+    # 0x357 int32u - 0=DNG, 3162=JPG (ref 23)
 );
 
@@ -1351,33 +2156,4 @@
     # (minimum is 16, maximum is 136.  Value is 0 for pictures captured from video)
     3 => 'Gain',
-);
-
-# lens information (ref 10)
-%Image::ExifTool::Panasonic::LensInfo = (
-    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
-    WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
-    CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
-    GROUPS => { 0 => 'MakerNotes', 1 => 'Leica', 2 => 'Camera' },
-    WRITABLE => 1,
-    FORMAT => 'int32u',
-    FIRST_ENTRY => 0,
-    0 => {
-        Name => 'LensType',
-        Mask => 0xfffffffc,
-        PrintHex => 0,
-        SeparateTable => 1,
-        ValueConv => '$val >> 2',
-        ValueConvInv => '$val << 2',
-        PrintConv => \%leicaLensType,
-    },
-    0.1 => { # lower 2 bits give frame selector position
-        Name => 'FrameSelector',
-        Mask => 0x03,
-        PrintConv => {
-            1 => '28/90mm frame lines engaged',
-            2 => '24/35mm frame lines engaged',
-            3 => '50/75mm frame lines engaged',
-        },
-    },
 );
 
@@ -1503,4 +2279,285 @@
 );
 
+# PANA atom found in user data of MP4 videos (ref PH)
+%Image::ExifTool::Panasonic::PANA = (
+    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
+    GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
+    NOTES => q{
+        Tags extracted from the PANA and LEIC user data found in MP4 videos from
+        various Panasonic and Leica models.
+    },
+    0x00 => {
+        Name => 'Make',
+        Condition => '$$valPt =~ /^(LEICA|Panasonic)/', # (only seen "LEICA")
+        Groups => { 2 => 'Camera' },
+        Format => 'string[22]',
+        RawConv => '$$self{LeicaLEIC} = 1;$$self{Make} = $val',
+    },
+    0x04 => {
+        Name => 'Model',
+        Condition => '$$valPt =~ /^[^\0]{6}/ and not $$self{LeicaLEIC}',
+        Description => 'Camera Model Name',
+        Groups => { 2 => 'Camera' },
+        Format => 'string[16]',
+        RawConv => '$$self{Model} = $val',
+    },
+    0x0c => { # (FZ1000)
+        Name => 'Model',
+        Condition => '$$valPt =~ /^[^\0]{6}/ and not $$self{LeicaLEIC} and not $$self{Model}',
+        Description => 'Camera Model Name',
+        Groups => { 2 => 'Camera' },
+        Format => 'string[16]',
+        RawConv => '$$self{Model} = $val',
+    },
+    0x10 => { # (DC-FT7)
+        Name => 'JPEG-likeData',
+        # looks like a JPEG preview, but not a well-formed JPEG file
+        Condition => '$$valPt =~ /^\xff\xd8\xff\xe1..Exif\0\0/s',
+        Format => 'undef[$size-0x10]',
+        SubDirectory => {
+            TagTable => 'Image::ExifTool::Exif::Main',
+            ProcessProc => \&Image::ExifTool::ProcessTIFF,
+            Start => 12,
+        },
+    },
+    0x16 => {
+        Name => 'Model',
+        Condition => '$$self{LeicaLEIC}',
+        Description => 'Camera Model Name',
+        Groups => { 2 => 'Camera' },
+        Format => 'string[30]',
+        RawConv => '$$self{Model} = $val',
+    },
+    0x40 => {
+        Name => 'ThumbnailTest',
+        Format => 'undef[0x600]',
+        Hidden => 1,
+        RawConv => q{
+            if (substr($val,0x1c,3) eq "\xff\xd8\xff") { # offset 0x5c
+                $$self{ThumbType} = 1;
+            } elsif (substr($val,0x506,3) eq "\xff\xd8\xff") { # offset 0x546
+                $$self{ThumbType} = 2;
+            } elsif (substr($val,0x51e,3) eq "\xff\xd8\xff") { # offset 0x55e (Leica T)
+                $$self{ThumbType} = 3;
+            } else {
+                $$self{ThumbType} = 0;
+            }
+            return undef;
+        },
+    },
+    0x34 => {
+        Name => 'Version1',
+        Condition => '$$self{LeicaLEIC}',
+        Format => 'string[14]',
+    },
+    0x3e => {
+        Name => 'Version2',
+        Condition => '$$self{LeicaLEIC}',
+        Format => 'string[14]',
+    },
+    0x50 => {
+        Name => 'MakerNoteLeica5',
+        Condition => '$$self{LeicaLEIC}',
+        SubDirectory => {
+            TagTable => 'Image::ExifTool::Panasonic::Leica5',
+            ProcessProc => \&ProcessLeicaLEIC,
+        },
+    },
+    0x58 => {
+        Name => 'ThumbnailWidth',
+        Condition => '$$self{ThumbType} == 1',
+        Notes => 'Panasonic models',
+        Format => 'int16u',
+    },
+    0x5a => {
+        Name => 'ThumbnailHeight',
+        Condition => '$$self{ThumbType} == 1',
+        Format => 'int16u',
+    },
+    0x5c => {
+        Name => 'ThumbnailImage',
+        Condition => '$$self{ThumbType} == 1',
+        Groups => { 2 => 'Preview' },
+        Format => 'undef[16384]',
+        ValueConv => '$val=~s/\0*$//; \$val',   # remove trailing zeros
+    },
+    # 0x5c - there is some messed-up EXIF-IFD-looking data starting here in
+    #        Leica X VARIO MP4 videos, but it doesn't quite make sense
+    0x536 => { # (Leica X VARIO)
+        Name => 'ThumbnailWidth',
+        Condition => '$$self{ThumbType} == 2',
+        Notes => 'Leica X Vario',
+        Format => 'int32uRev', # (little-endian)
+    },
+    0x53a => { # (Leica X VARIO)
+        Name => 'ThumbnailHeight',
+        Condition => '$$self{ThumbType} == 2',
+        Format => 'int32uRev', # (little-endian)
+    },
+    0x53e => { # (Leica X VARIO)
+        Name => 'ThumbnailLength',
+        Condition => '$$self{ThumbType} == 2',
+        Format => 'int32uRev', # (little-endian)
+    },
+    0x546 => { # (Leica X VARIO)
+        Name => 'ThumbnailImage',
+        Condition => '$$self{ThumbType} == 2',
+        Groups => { 2 => 'Preview' },
+        Format => 'undef[$val{0x53e}]',
+        Binary => 1,
+    },
+    0x54e => { # (Leica T)
+        Name => 'ThumbnailWidth',
+        Condition => '$$self{ThumbType} == 3',
+        Notes => 'Leica X Vario',
+        Format => 'int32uRev', # (little-endian)
+    },
+    0x552 => { # (Leica T)
+        Name => 'ThumbnailHeight',
+        Condition => '$$self{ThumbType} == 3',
+        Format => 'int32uRev', # (little-endian)
+    },
+    0x556 => { # (Leica T)
+        Name => 'ThumbnailLength',
+        Condition => '$$self{ThumbType} == 3',
+        Format => 'int32uRev', # (little-endian)
+    },
+    0x55e => { # (Leica T)
+        Name => 'ThumbnailImage',
+        Condition => '$$self{ThumbType} == 3',
+        Groups => { 2 => 'Preview' },
+        Format => 'undef[$val{0x556}]',
+        Binary => 1,
+    },
+    0x4068 => {
+        Name => 'ExifData',
+        Condition => '$$valPt =~ /^\xff\xd8\xff\xe1..Exif\0\0/s',
+        SubDirectory => {
+            TagTable => 'Image::ExifTool::Exif::Main',
+            ProcessProc => \&Image::ExifTool::ProcessTIFF,
+            Start => 12,
+        },
+    },
+    0x4080 => { # (FZ1000)
+        Name => 'ExifData',
+        Condition => '$$valPt =~ /^\xff\xd8\xff\xe1..Exif\0\0/s',
+        SubDirectory => {
+            TagTable => 'Image::ExifTool::Exif::Main',
+            ProcessProc => \&Image::ExifTool::ProcessTIFF,
+            Start => 12,
+        },
+    },
+);
+
+# Panasonic Composite tags
+%Image::ExifTool::Panasonic::Composite = (
+    GROUPS => { 2 => 'Camera' },
+    AdvancedSceneMode => {
+        SeparateTable => 'Panasonic AdvancedSceneMode',    # print values in a separate table
+        Require => {
+            0 => 'Model',
+            1 => 'SceneMode',
+            2 => 'AdvancedSceneType',
+        },
+        ValueConv => '"$val[0] $val[1] $val[2]"',
+        PrintConv => { #PH
+            OTHER => sub {
+                my ($val,$flag,$conv) = @_;
+                $val =~ s/.* (\d+ \d+)/$1/; # drop model name
+                return $$conv{$val} if $$conv{$val};
+                my @v = split ' ', $val;
+                my $prt = $shootingMode{$v[0]};
+                # AdvancedSceneType=1 for non-automatic modes P,A,S,SCN (ref 19)
+                # AdvancedSceneType=5 for automatic mode iA (ref 19)
+                if ($prt) {
+                    return $prt if $v[1] == 1;
+                    return "$prt (intelligent auto)" if $v[1] == 5; #forum11523
+                    return "$prt (intelligent auto plus)" if $v[1] == 7; #forum11523
+                    return "$prt ($v[1])";
+                }
+                return "Unknown ($val)";
+            },
+            Notes => 'A Composite tag derived from Model, SceneMode and AdvancedSceneType.',
+            '0 1' => 'Off',
+            # '0 7' - seen this for V-LUX movies (PH)
+            # '0 8' - seen for D-LUX(Typ104) movies (PH)
+            '2 2' => 'Outdoor Portrait', #(FZ28)
+            '2 3' => 'Indoor Portrait', #(FZ28)
+            '2 4' => 'Creative Portrait', #(FZ28)
+            '3 2' => 'Nature', #(FZ28)
+            '3 3' => 'Architecture', #(FZ28)
+            '3 4' => 'Creative Scenery', #(FZ28)
+            #'3 5' - ? (FT1)
+            '4 2' => 'Outdoor Sports', #(FZ28)
+            '4 3' => 'Indoor Sports', #(FZ28)
+            '4 4' => 'Creative Sports', #(FZ28)
+            '9 2' => 'Flower', #(FZ28)
+            '9 3' => 'Objects', #(FZ28)
+            '9 4' => 'Creative Macro', #(FZ28)
+            #'9 5' - ? (GF3)
+            '18 1' => 'High Sensitivity', #forum11523 (TZ5)
+            '20 1' => 'Fireworks', #forum11523 (TZ5)
+            '21 2' => 'Illuminations', #(FZ28)
+            '21 4' => 'Creative Night Scenery', #(FZ28)
+            #'21 5' - ? (LX3)
+            '26 1' => 'High-speed Burst (shot 1)', #forum11523 (TZ5)
+            '27 1' => 'High-speed Burst (shot 2)', #forum11523 (TZ5)
+            '29 1' => 'Snow', #forum11523 (TZ5)
+            '30 1' => 'Starry Sky', #forum11523 (TZ5)
+            '31 1' => 'Beach', #forum11523 (TZ5)
+            '36 1' => 'High-speed Burst (shot 3)', #forum11523 (TZ5)
+            #'37 5' - ? (various)
+            '39 1' => 'Aerial Photo / Underwater / Multi-aspect', #forum11523 (TZ5)
+            '45 2' => 'Cinema', #(GF2)
+            '45 7' => 'Expressive', #(GF1,GF2)
+            '45 8' => 'Retro', #(GF1,GF2)
+            '45 9' => 'Pure', #(GF1,GF2)
+            '45 10' => 'Elegant', #(GF1,GF2)
+            '45 12' => 'Monochrome', #(GF1,GF2)
+            '45 13' => 'Dynamic Art', #(GF1,GF2)
+            '45 14' => 'Silhouette', #(GF1,GF2)
+            '51 2' => 'HDR Art', #12
+            '51 3' => 'HDR B&W', #12
+            '59 1' => 'Expressive', #(GF5)
+            '59 2' => 'Retro', #(GF5)
+            '59 3' => 'High Key', #(GF5)
+            '59 4' => 'Sepia', #(GF3,GF5)
+            '59 5' => 'High Dynamic', #(GF3,GF5)
+            '59 6' => 'Miniature', #(GF3)
+            '59 9' => 'Low Key', #(GF5)
+            '59 10' => 'Toy Effect', #(GF5)
+            '59 11' => 'Dynamic Monochrome', #(GF5)
+            '59 12' => 'Soft', #(GF5)
+            '66 1' => 'Impressive Art', #19
+            '66 2' => 'Cross Process', #(GF5)
+            '66 3' => 'Color Select', #(GF5) (called "One Point Color" by some other models - PH)
+            '66 4' => 'Star', #(GF5)
+            '90 3' => 'Old Days', #18
+            '90 4' => 'Sunshine', #18
+            '90 5' => 'Bleach Bypass', #18
+            '90 6' => 'Toy Pop', #18
+            '90 7' => 'Fantasy', #18
+            '90 8' => 'Monochrome', #PH (GX7)
+            '90 9' => 'Rough Monochrome', #PH (GX7)
+            '90 10' => 'Silky Monochrome', #PH (GX7)
+            '92 1' => 'Handheld Night Shot', #Horst Wandres (FZ1000)
+            # TZ40 Creative Control modes (ref 19)
+            'DMC-TZ40 90 1' => 'Expressive',
+            'DMC-TZ40 90 2' => 'Retro',
+            'DMC-TZ40 90 3' => 'High Key',
+            'DMC-TZ40 90 4' => 'Sepia',
+            'DMC-TZ40 90 5' => 'High Dynamic',
+            'DMC-TZ40 90 6' => 'Miniature',
+            'DMC-TZ40 90 9' => 'Low Key',
+            'DMC-TZ40 90 10' => 'Toy Effect',
+            'DMC-TZ40 90 11' => 'Dynamic Monochrome',
+            'DMC-TZ40 90 12' => 'Soft',
+        },
+    },
+);
+
+# add our composite tags
+Image::ExifTool::AddCompositeTags('Image::ExifTool::Panasonic');
+
 #------------------------------------------------------------------------------
 # Inverse conversion for Leica M9 lens codes
@@ -1537,7 +2594,36 @@
 
 #------------------------------------------------------------------------------
+# Process Leica makernotes in LEIC atom of MP4 videos (Leica T and X Vario)
+# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
+# Returns: 1 on success
+sub ProcessLeicaLEIC($$$)
+{
+    my ($et, $dirInfo, $tagTablePtr) = @_;
+    my $dataPt = $$dirInfo{DataPt};
+    my $dirStart = $$dirInfo{DirStart} || 0;
+    my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $dirStart);
+    return 0 if $dirLen < 6;
+    SetByteOrder('II');
+    my $numEntries = Get16u($dataPt, $dirStart);
+    return 0 if $numEntries < 1 or $numEntries > 255;
+    my $size = Get32u($dataPt, $dirStart + 2);
+    return 0 if $size < $numEntries * 12 or $size + 6 > $dirLen;
+    # the Leica programmers want to make things difficult, so they store
+    # the entry count before the directory size, making it impossible to
+    # process as a standard TIFF IFD without a bit of reorganization...
+    Set16u($numEntries, $dataPt, $dirStart + 4);
+    my %dirInfo = %$dirInfo;
+    $dirInfo{DirStart} = $dirStart + 4;
+    $dirInfo{DirLen} = $size - 4;
+    $dirInfo{DataPos} -= $dirStart;
+    $dirInfo{Base} += $dirStart;
+    return Image::ExifTool::Exif::ProcessExif($et, \%dirInfo, $tagTablePtr);
+    return 1;
+}
+
+#------------------------------------------------------------------------------
 # Process MakerNote trailer written by Leica S2
 # Inputs: 0) ExifTool object ref, 1) new absolute position of Leica trailer when writing
-# Returns: On success: 1 when reading, directory data when writing; othewise undef
+# Returns: On success: 1 when reading, directory data when writing; otherwise undef
 # Notes:
 # - may be called twice for a file if the first call doesn't succeed
@@ -1550,7 +2636,7 @@
 sub ProcessLeicaTrailer($;$)
 {
-    my ($exifTool, $newPos) = @_;
-    my $trail = $$exifTool{LeicaTrailer};
-    my $raf = $$exifTool{RAF};
+    my ($et, $newPos) = @_;
+    my $trail = $$et{LeicaTrailer};
+    my $raf = $$et{RAF};
     my $trailPos = $$trail{TrailPos};
     my $pos = $trailPos || $$trail{Offset};
@@ -1558,8 +2644,8 @@
     my ($buff, $result, %tagPtr);
 
-    delete $$exifTool{LeicaTrailer} if $trailPos;   # done after this
+    delete $$et{LeicaTrailer} if $trailPos;   # done after this
     unless ($len > 0) {
-        $exifTool->Warn('Missing Leica MakerNote trailer', 1) if $trailPos;
-        undef $$exifTool{LeicaTrailer};
+        $et->Warn('Missing Leica MakerNote trailer', 1) if $trailPos;
+        delete $$et{LeicaTrailer};
         return undef;
     }
@@ -1568,5 +2654,5 @@
     $raf->Seek($oldPos, 0);
     unless ($ok) {
-        $exifTool->Warn('Error reading Leica MakerNote trailer', 1) if $trailPos;
+        $et->Warn('Error reading Leica MakerNote trailer', 1) if $trailPos;
         return undef;
     }
@@ -1575,5 +2661,5 @@
     if ($buff !~ /^(.{0,256})LEICA\0..../sg) {
         my $what = $trailPos ? 'trailer' : 'offset';
-        $exifTool->Warn("Invalid Leica MakerNote $what", 1);
+        $et->Warn("Invalid Leica MakerNote $what", 1);
         return undef;
     }
@@ -1581,5 +2667,5 @@
     my $start = pos($buff) - 10;
     if ($start and not $trailPos) {
-        $exifTool->Warn('Invalid Leica MakerNote offset', 1);
+        $et->Warn('Invalid Leica MakerNote offset', 1);
         return undef;
     }
@@ -1590,15 +2676,15 @@
     my $dirStart = $start + $hdrLen;
     my $tagInfo = $$trail{TagInfo};
-    if ($$exifTool{HTML_DUMP}) {
+    if ($$et{HTML_DUMP}) {
         my $name = $$tagInfo{Name};
-        $exifTool->HDump($pos+$start, $len-$start, "$name value", 'Leica MakerNote trailer', 4);
-        $exifTool->HDump($pos+$start, $hdrLen, "MakerNotes header", $name);
-    } elsif ($exifTool->Options('Verbose')) {
+        $et->HDump($pos+$start, $len-$start, "$name value", 'Leica MakerNote trailer', 4);
+        $et->HDump($pos+$start, $hdrLen, "MakerNotes header", $name);
+    } elsif ($et->Options('Verbose')) {
         my $where = sprintf('at offset 0x%x', $pos);
-        $exifTool->VPrint(0, "Leica MakerNote trailer ($len bytes $where):\n");
+        $et->VPrint(0, "Leica MakerNote trailer ($len bytes $where):\n");
     }
     # delete LeicaTrailer member so we don't try to process it again
-    delete $$exifTool{LeicaTrailer};
-    $$exifTool{LeicaTrailerPos} = $pos + $start;    # return actual start position of Leica trailer
+    delete $$et{LeicaTrailer};
+    $$et{LeicaTrailerPos} = $pos + $start;    # return actual start position of Leica trailer
 
     my $oldOrder = GetByteOrder();
@@ -1611,28 +2697,38 @@
     if ($valStart < $len) {
         my $valBlock = Image::ExifTool::MakerNotes::GetValueBlocks(\$buff, $dirStart, \%tagPtr);
-        # find the minimum offset (excluding the PreviewImage tag 0x300)
+        # find the minimum offset (excluding the PreviewImage tag 0x300 and 0x301)
         my $minPtr;
         foreach (keys %tagPtr) {
             my $ptr = $tagPtr{$_};
-            next if $_ == 0x300 or not $ptr;
+            next if $_ == 0x300 or $_ == 0x301 or not $ptr or $ptr == 0xffffffff;
             $minPtr = $ptr if not defined $minPtr or $minPtr > $ptr;
         }
         if ($minPtr) {
             my $diff = $minPtr - ($valStart + $pos);
-            # scan value data for the first non-zero byte
             pos($buff) = $valStart;
-            if ($buff =~ /[^\0]/g) {
-                my $n = pos($buff) - 1 - $valStart; # number of zero bytes
-                # S2 writes 282 bytes of zeros, exiftool writes none
-                my $expect = $n >= 282 ? 282 : 0;
-                my $fixBase = $exifTool->Options('FixBase');
-                if ($diff != $expect or defined $fixBase) {
-                    $fix = $expect - $diff;
-                    if (defined $fixBase) {
-                        $fix = $fixBase if $fixBase ne '';
-                        $exifTool->Warn("Adjusted MakerNotes base by $fix",1);
-                    } else {
-                        $exifTool->Warn("Possibly incorrect maker notes offsets (fixed by $fix)",1);
-                    }
+            my $expect;
+            if ($$et{Model} eq 'S2') {
+                # scan value data for the first non-zero byte
+                if ($buff =~ /[^\0]/g) {
+                    my $n = pos($buff) - 1 - $valStart; # number of zero bytes
+                    # S2 writes 282 bytes of zeros, exiftool writes none
+                    $expect = $n >= 282 ? 282 : 0;
+                }
+            } else { # M (Type 240)
+                # scan for the lens type (M writes 114 bytes of garbage first)
+                if ($buff =~ /\G.{114}([\x20-\x7f]*\0*)/sg and length($1) >= 50) {
+                    $expect = 114;
+                }
+            }
+            my $fixBase = $et->Options('FixBase');
+            if (not defined $expect) {
+                $et->Warn('Unrecognized Leica trailer structure');
+            } elsif ($diff != $expect or defined $fixBase) {
+                $fix = $expect - $diff;
+                if (defined $fixBase) {
+                    $fix = $fixBase if $fixBase ne '';
+                    $et->Warn("Adjusted MakerNotes base by $fix",1);
+                } else {
+                    $et->Warn("Possibly incorrect maker notes offsets (fixed by $fix)",1);
                 }
             }
@@ -1654,10 +2750,14 @@
     my $tagTablePtr = GetTagTable($$tagInfo{SubDirectory}{TagTable});
     if ($newPos) { # are we writing?
+        if ($$et{Model} ne 'S2') {
+            $et->Warn('Leica MakerNote trailer too messed up to edit.  Copying as a block', 1);
+            return $buff;
+        }
         # set position of new MakerNote IFD (+ 8 for Leica MakerNote header)
         $dirInfo{NewDataPos} = $newPos + $start + 8;
-        $result = $exifTool->WriteDirectory(\%dirInfo, $tagTablePtr);
+        $result = $et->WriteDirectory(\%dirInfo, $tagTablePtr);
         # write preview image last if necessary and fix up the preview offsets
-        my $previewInfo = $$exifTool{PREVIEW_INFO};
-        delete $$exifTool{PREVIEW_INFO};
+        my $previewInfo = $$et{PREVIEW_INFO};
+        delete $$et{PREVIEW_INFO};
         if ($result) {
             if ($previewInfo) {
@@ -1671,21 +2771,21 @@
     } else {
         # extract information
-        $result = $exifTool->ProcessDirectory(\%dirInfo, $tagTablePtr);
+        $result = $et->ProcessDirectory(\%dirInfo, $tagTablePtr);
         # also extract as a block if necessary
-        if ($exifTool->Options('MakerNotes') or
-            $exifTool->{REQ_TAG_LOOKUP}{lc($$tagInfo{Name})})
+        if ($et->Options('MakerNotes') or
+            $$et{REQ_TAG_LOOKUP}{lc($$tagInfo{Name})})
         {
             # makernote header must be included in RebuildMakerNotes call
             $dirInfo{DirStart} -= 8;
             $dirInfo{DirLen} += 8;
-            $exifTool->{MAKER_NOTE_BYTE_ORDER} = GetByteOrder();
-            # rebuild maker notes (creates $exifTool->{MAKER_NOTE_FIXUP})
-            my $val = Image::ExifTool::Exif::RebuildMakerNotes($exifTool, $tagTablePtr, \%dirInfo);
+            $$et{MAKER_NOTE_BYTE_ORDER} = GetByteOrder();
+            # rebuild maker notes (creates $$et{MAKER_NOTE_FIXUP})
+            my $val = Image::ExifTool::Exif::RebuildMakerNotes($et, \%dirInfo, $tagTablePtr);
             unless (defined $val) {
-                $exifTool->Warn('Error rebuilding maker notes (may be corrupt)');
+                $et->Warn('Error rebuilding maker notes (may be corrupt)') if $len > 4;
                 $val = $buff,
             }
-            my $key = $exifTool->FoundTag($tagInfo, $val);
-            $exifTool->SetGroup($key, 'ExifIFD');
+            my $key = $et->FoundTag($tagInfo, $val);
+            $et->SetGroup($key, 'ExifIFD');
         }
     }
@@ -1713,5 +2813,5 @@
 =head1 AUTHOR
 
-Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
+Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
 
 This library is free software; you can redistribute it and/or modify it
@@ -1738,6 +2838,6 @@
 =head1 ACKNOWLEDGEMENTS
 
-Thanks to Tels for the information he provided on decoding some tags, and to
-Marcel Coenen, Jens Duttke and Michael Byczkowski for their contributions.
+Thanks to Tels, Marcel Coenen, Jens Duttke, Joerg, Michael Byczkowski, Carl
+Bretteville, Zdenek Mihula and Olaf Ulrich for their contributions.
 
 =head1 SEE ALSO
