Repository: python-pillow/Pillow

Issue:
Image.show() on image with mode LA does not show transparency
When I use `Image.show()` on an image with mode `LA`, transparency is not shown.  When I use `.save(...)`, the resulting image has transparency included correctly.  With mode `RGBA`, transparency is correctly displayed on `.show()` (and correctly written on `.save(...)`).

### What did you do?

I used `.show()` on an image with mode `LA`.

### What did you expect to happen?

I expected it to display an image with transparency:

![im1](https://user-images.githubusercontent.com/500246/58331700-faf35f00-7e39-11e9-973a-d1d2dd1414cf.png)

### What actually happened?

It showed an image without transparency:

![tmplevyr9u2](https://user-images.githubusercontent.com/500246/58331737-0fcff280-7e3a-11e9-9179-baf3a324f971.PNG)

### What are your OS, Python and Pillow versions?

* OS: openSUSE 15.0
* Python: 3.7.3
* Pillow: 6.0.0

```python
from numpy import linspace, block, concatenate, zeros, full
from PIL import Image

L = linspace(0, 255, 200*200, dtype="u1").reshape(200, 200, 1)
A = block([[zeros((100, 100), "u1"),             full((100, 100), 255, "u1")],
            [full((100, 100), 255, "u1"),
            zeros((100, 100), "u1")]]).reshape(200, 200, 1)
im1 = Image.fromarray((concatenate((L, A), 2)), mode="LA")
im2 = Image.fromarray((concatenate((L, L, L, A), 2)), mode="RGBA")
im1.show()
im2.show()
```



Discussion:

Resolving patch:
diff --git a/src/PIL/ImageMode.py b/src/PIL/ImageMode.py
--- a/src/PIL/ImageMode.py
+++ b/src/PIL/ImageMode.py
@@ -48,9 +48,17 @@ def getmode(mode):
         modes["La"] = ModeDescriptor("La", ("L", "a"), "L", "L")
         modes["PA"] = ModeDescriptor("PA", ("P", "A"), "RGB", "L")
         # mapping modes
-        modes["I;16"] = ModeDescriptor("I;16", "I", "L", "L")
-        modes["I;16L"] = ModeDescriptor("I;16L", "I", "L", "L")
-        modes["I;16B"] = ModeDescriptor("I;16B", "I", "L", "L")
+        for i16mode in (
+            "I;16",
+            "I;16S",
+            "I;16L",
+            "I;16LS",
+            "I;16B",
+            "I;16BS",
+            "I;16N",
+            "I;16NS",
+        ):
+            modes[i16mode] = ModeDescriptor(i16mode, ("I",), "L", "L")
         # set global mode cache atomically
         _modes = modes
     return _modes[mode]
diff --git a/src/PIL/ImageShow.py b/src/PIL/ImageShow.py
--- a/src/PIL/ImageShow.py
+++ b/src/PIL/ImageShow.py
@@ -63,16 +63,12 @@ class Viewer(object):
     def show(self, image, **options):
 
         # save temporary image to disk
-        if image.mode[:4] == "I;16":
-            # @PIL88 @PIL101
-            # "I;16" isn't an 'official' mode, but we still want to
-            # provide a simple way to show 16-bit images.
-            base = "L"
-            # FIXME: auto-contrast if max() > 255?
-        else:
+        if not (
+            image.mode in ("1", "RGBA") or (self.format == "PNG" and image.mode == "LA")
+        ):
             base = Image.getmodebase(image.mode)
-        if base != image.mode and image.mode != "1" and image.mode != "RGBA":
-            image = image.convert(base)
+            if image.mode != base:
+                image = image.convert(base)
 
         return self.show_image(image, **options)
 


Test patch:
diff --git a/Tests/test_image_mode.py b/Tests/test_image_mode.py
--- a/Tests/test_image_mode.py
+++ b/Tests/test_image_mode.py
@@ -26,6 +26,17 @@ def test_sanity(self):
         self.assertEqual(m.basemode, "L")
         self.assertEqual(m.basetype, "L")
 
+        for mode in ("I;16", "I;16S",
+                     "I;16L", "I;16LS",
+                     "I;16B", "I;16BS",
+                     "I;16N", "I;16NS"):
+            m = ImageMode.getmode(mode)
+            self.assertEqual(m.mode, mode)
+            self.assertEqual(str(m), mode)
+            self.assertEqual(m.bands, ("I",))
+            self.assertEqual(m.basemode, "L")
+            self.assertEqual(m.basetype, "L")
+
         m = ImageMode.getmode("RGB")
         self.assertEqual(m.mode, "RGB")
         self.assertEqual(str(m), "RGB")
diff --git a/Tests/test_imageshow.py b/Tests/test_imageshow.py
--- a/Tests/test_imageshow.py
+++ b/Tests/test_imageshow.py
@@ -18,18 +18,19 @@ def test_register(self):
         ImageShow._viewers.pop()
 
     def test_show(self):
-        class TestViewer:
+        class TestViewer(ImageShow.Viewer):
             methodCalled = False
 
-            def show(self, image, title=None, **options):
+            def show_image(self, image, **options):
                 self.methodCalled = True
                 return True
         viewer = TestViewer()
         ImageShow.register(viewer, -1)
 
-        im = hopper()
-        self.assertTrue(ImageShow.show(im))
-        self.assertTrue(viewer.methodCalled)
+        for mode in ("1", "I;16", "LA", "RGB", "RGBA"):
+            im = hopper(mode)
+            self.assertTrue(ImageShow.show(im))
+            self.assertTrue(viewer.methodCalled)
 
         # Restore original state
         ImageShow._viewers.pop(0)