pythontkinterpython-imaging-libraryimage-editing

Python tkinter, resizing transparent image on canvas


I am making an isometric game using python and the Tkinter library. I ran into a problem though when rendering my schematics to the screen. I can't seem to keep the transparent background even though the images (.png) are being stored as rgba in pil. When I save the images, as they are, just before being loaded; they still have a transparent background so it's something to do with the way I'm resizing the image. I have looked around and most answers to this that I have seen say to edit the pil plugin or aren't actually resizing the image. Is there a relatively simple way to resize an image and keep transparency that doesn't include messing around with the pil plugin??

My code:

    def renderToTkCanvas(self, x_axis, y_axis, cv, block_width=50, block_height=50):
        cur_schem = self._map_schematic.getSchematic()
        cur_y = 0
        for y in cur_schem:
            cur_x = 0
            for x in y:
                if x != 0:
                    image = ImageTk.PhotoImage(x.resize((block_width, block_height)))
                    cur_label = Label(image=image)
                    cv.create_window(x_axis + (block_width * cur_x), y_axis + (block_height * cur_y), window=cur_label, anchor="nw", tag="map")
                    cur_label.image = image
                cur_x += 1
            cur_y += 1

Schematic being used (1x4):

[[<PIL.Image.Image image mode=RGBA size=1170x1240 at 0x12F5AFC9C10>], [<PIL.Image.Image image mode=RGBA size=1170x1240 at 0x12F5AFC9C10>], [<PIL.Image.Image image mode=RGBA size=1169x1240 at 0x12F5AFDED60>], [<PIL.Image.Image image mode=RGBA size=1170x1240 at 0x12F5AFC9C10>]]

Thx for any help : )


Solution

  • Ok, so I managed to find the issue. The problem was not with the resizing but with the label as @jasonharper had stated. The working way is very unclean and creates unused labels to store the variable to prevent movement to the python garbage. I have tried with an array/list however it doesn't seem to work, that code is below. I don't see many people having this issue in the future because it's so small but I'll put the working code below as well.

    Code using list that doesn't work:

        def renderToTkCanvas(self, x_axis, y_axis, cv, block_width=50, block_height=50):
            cur_schem = self._map_schematic.getSchematic()
            img_matrix = []
            cur_y = 0
            for y in cur_schem:
                cur_x = 0
                img_matrix.append([])
                for x in y:
                    if x != 0:
                        image = ImageTk.PhotoImage(image=x.resize((block_width, block_height)))
                        img_matrix[cur_y].append(image)
                        cv.create_image(x_axis + (block_width * cur_x / 2), y_axis + (block_height * cur_y / 2), image=img_matrix[cur_y][cur_x], anchor="nw", tag="map")
                    else:
                        img_matrix[cur_y].append(0)
                    cur_x += 1
                cur_y += 1
    

    Working code but very unclean:

        def renderToTkCanvas(self, x_axis, y_axis, cv, block_width=50, block_height=50):
            cur_schem = self._map_schematic.getSchematic()
            cur_y = 0
            for y in cur_schem:
                cur_x = 0
                for x in y:
                    if x != 0:
                        image = ImageTk.PhotoImage(image=x.resize((block_width, block_height)))
                        cur_label = Label(image=image)
                        cv.create_image(x_axis + (block_width * cur_x / 2), y_axis + (block_height * cur_y / 2), image=image, anchor="nw", tag="map")
                        cur_label.image = image
                        del cur_label  # attempt to clean up the code slightly
                    cur_x += 1
                cur_y += 1
    

    Thx for the help.