0

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 : )

ItzTheDodo
  • 100
  • 8
  • 2
    Those Labels you're adding to your Canvas are going to be opaque rectangles, regardless of what the image is. You might have better luck adding the images directly to the Canvas, via `cv.create_image()`. – jasonharper Apr 01 '21 at 16:19
  • @jasonharper These are procedurally generated images, adding them via ````cv.create_image()```` means the variable used would be moved to garbage by python because Tkinter doesn't use image handling very well, rendering it useless when Tkinter uses it for display. I need an object like a Label to use the variable image in ````Label.image = image```` so it is not rendered useless by python. TL;DR: python will move the image variable to garbage meaning Tkinter can't use it. – ItzTheDodo Apr 01 '21 at 16:51
  • You fix that by keeping a reference to the image somewhere - append them all to a list, perhaps. – jasonharper Apr 01 '21 at 16:53
  • @jasonharper I tried this method and it seems to add unneeded complexity to something that should be very simple. Aside from the small flaws in my code, do you have an idea for resizing an image with a transparent background? – ItzTheDodo Apr 01 '21 at 16:58

1 Answers1

0

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.

ItzTheDodo
  • 100
  • 8