Search code examples
pythontkinterpython-imaging-librarypngpython-3.9

Some transparent images on labels have black backgrounds when using PIL


I have a frame where I put multiple labels on. All of these labels contain png images, some that fill the whole background, and others that don't; have transparent backgrounds. I want to get 16x16 px images and resize them to 32x32 for visibility. I noticed that the original images work fine when resized, but when I add a new image to the assets directory and use it, its background turns black. I have an assets folder where I store my png images. I am sure that every one of them should have transparent backgrounds, atleast according to my photo editor.

This is the minimal code:

from tkinter import *
from PIL import Image, ImageTk
import os
project_path = os.path.dirname(os.path.abspath(__file__))
root = Tk()

button_frame1 = Frame(root)
button_frame1.pack(side=TOP)
Label(button_frame1, text="Hotbar",padx=8).grid(row=0,column=2)
hotbarFrame = Frame(button_frame1, bg="white", width=288, height=32, highlightbackground="black", highlightthickness=1)
hotbarFrame.grid(row=0,column=3,padx=10)
hotbarItems = ["dirt", "grass_block_side", "grass", "stone", "cobblestone", "oak_planks", "oak_log", "oak_leaves2", "glass"]
hotbarImages, hotbarSlots = {}, []

for slot in range(len(hotbarItems)):
    item = hotbarItems[slot]
    item_file = open(project_path + "\\assets\\blocks\\" + item + ".png", "rb")
    hotbarImages[item] = ImageTk.PhotoImage(Image.open(item_file).resize((32,32), Image.NONE))
    hotbarSlots.append(Label(hotbarFrame, image=hotbarImages[item], width=32, height=32, highlightthickness=1))
    hotbarSlots[slot].grid(row=0,column=slot)

root.mainloop()

Output: Notice that the eighth icon has a black background, even though it's transparent.

Click here to see the original eighth icon.


Solution

  • The problem is your PNG image not in RGBA mode, but in P mode.

    P mode 8-bit pixels, mapped to any other mode using a color palette

    from PIL import Image
    
    im = Image.open("D:/oak_leaves2.png")
    print(im.mode)        # P
    im.show()
    

    Following simple script show the result

    from PIL import Image, ImageTk
    import tkinter as tk
    
    root = tk.Tk()
    
    frame = tk.Frame(root, bg='blue')
    frame.pack(fill='both', expand=1)
    
    im = Image.open("D:/oak_leaves2.png").resize((80, 80), Image.BICUBIC)
    image = ImageTk.PhotoImage(im)
    
    label = tk.Label(frame, text='Hello', image=image)
    label.pack()
    
    root.mainloop()
    

    So, actually, it look like this

    enter image description here