Repository: python-pillow/Pillow

Issue:
Alpha channel ignored in tkinter using PIL.Image.open and PIL.ImageTk.PhotoImage for PNGs in palette mode
### What did you do?

I opened a PNG image (palette mode with alpha channel) using pillow and passed it to tkinter.

### What did you expect to happen?

It should work just like using tkinter.PhotoImage.

### What actually happened?

The alpha channel is ignored.

### What are your OS, Python and Pillow versions?

* OS: `5.10.0-17-amd64 #1 SMP Debian 5.10.136-1 (2022-08-13) x86_64 GNU/Linux`
* Python: `Python 3.9.2`
* Pillow: `9.0.1`

I noticed an error when I wanted to include a PNG image in palette mode with alpha channel into a tkinter application.
Since I wanted to resize it before displaying it, I used Pillow.
However if I execute the code below ([reproduce.zip](https://github.com/python-pillow/Pillow/files/9483016/reproduce.zip)) I see this:
![Bildschirmfoto 2022-09-03 18:53:25](https://user-images.githubusercontent.com/4997642/188280682-638eb8c4-8711-409a-9eab-b844a1f71526.png)

It shows the following 3 images:

- The first image is created using `Image.open` and `ImageTk.PhotoImage`, the transparent part is black.
- The second image shows the same image which has been converted to RGBA mode and then saved (also with Pillow), which works.
- The third image shows the `tkinter.PhotoImage` version which also works fine.

Uncommenting the explicit conversion to RGBA also fixes the problem, which is my current workaround.
However I think this should not be necessary.


```python
from tkinter import Tk, Label, PhotoImage

from PIL import Image, ImageTk


root = Tk()
# via Pillow
pil_image = Image.open('loading.png')
print(pil_image.mode)
#pil_image = pil_image.convert('RGBA')
image1 = ImageTk.PhotoImage(pil_image)
Label(root, image=image1).grid(row=0, column=0, padx=5, pady=5)

# using RGBA mode
pil_image_rgba = Image.open('loading_RGBA.png')
print(pil_image_rgba.mode)
image2 = ImageTk.PhotoImage(pil_image_rgba)
Label(root, image=image2).grid(row=0, column=1, padx=5, pady=5)

# using tkinter.PhotoImage
image3 = PhotoImage(file='loading.png')
Label(root, image=image3).grid(row=0, column=2, padx=5, pady=5)
root.mainloop()
```



Discussion:
Looking at `ImageTk.PhotoImage`, if it is passed an image with a palette, it automatically converts the image to the mode of the palette before passing it to tkinter:
https://github.com/python-pillow/Pillow/blob/b6348d9b2d14d17c28da769d0483b8d486274efb/src/PIL/ImageTk.py#L108-L112

However, your first image is loaded with a palette with mode RGB, not RGBA as you might expect.
This was discussed in #6348, and #6352 added a new function [`image.apply_transparency()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.apply_transparency) to convert the palette of PNG images from RGB to RGBA in [Pillow 9.2.0](https://pillow.readthedocs.io/en/stable/releasenotes/9.2.0.html?highlight=apply_transparency%20#image-apply-transparency).


```python
from tkinter import Tk, Label, PhotoImage

from PIL import Image, ImageTk


root = Tk()
pil_image = Image.open('loading.png')
print(pil_image.mode, pil_image.palette.mode)  # P RGB
pil_image.apply_transparency()
print(pil_image.mode, pil_image.palette.mode)  # P RGBA
image1 = ImageTk.PhotoImage(pil_image)
Label(root, image=image1).grid(row=0, column=0, padx=5, pady=5)
```

![image](https://user-images.githubusercontent.com/3819630/188332319-30f78481-4542-4092-be3e-a9b0775d17d0.png)


Resolving patch:
diff --git a/src/PIL/ImageTk.py b/src/PIL/ImageTk.py
--- a/src/PIL/ImageTk.py
+++ b/src/PIL/ImageTk.py
@@ -107,6 +107,7 @@ def __init__(self, image=None, size=None, **kw):
             mode = image.mode
             if mode == "P":
                 # palette mapped data
+                image.apply_transparency()
                 image.load()
                 try:
                     mode = image.palette.mode


Test patch:
diff --git a/Tests/test_imagetk.py b/Tests/test_imagetk.py
--- a/Tests/test_imagetk.py
+++ b/Tests/test_imagetk.py
@@ -69,6 +69,13 @@ def test_photoimage():
         assert_image_equal(reloaded, im.convert("RGBA"))
 
 
+def test_photoimage_apply_transparency():
+    with Image.open("Tests/images/pil123p.png") as im:
+        im_tk = ImageTk.PhotoImage(im)
+        reloaded = ImageTk.getimage(im_tk)
+        assert_image_equal(reloaded, im.convert("RGBA"))
+
+
 def test_photoimage_blank():
     # test a image using mode/size:
     for mode in TK_MODES: