2

I made a custom image viewing program in python since I couldn't find one that worked how I wanted it to, and I know it at least USED to work with transparent gifs but now it doesn't. The effects seem to vary from gif to gif to gif but it always is an issue with the transparency. Doing some testing with .save I found that the PIL image is completely fine and I can export it as a png with absolutely no issues and perfect transparency. With that said, despite making the program I never really learned Tkinter since I just didn't need to use it beyond simple canvas clearing and updating, so I have no clue how to test beyond PIL. I believe the issue should be in these lines :

image = ImageTk.PhotoImage(GifFrameSized) #GifFrameSized is the resized GIF
imagesprite = canvas.create_image(show.w/2,show.h/2,image=image) #w and h are the width and height of the monitor
root.update_idletasks()
root.update()
canvas.pack()

I genuinely have no idea how the issue could be coming from any of these but I was able to use PIL to save a png of the frame in the line immediately above "image = ImageTk.PhotoImage(GifFrameSized)" and it looked fine so I have to imagine its somewhere in those lines.

Church.exe
  • 99
  • 4
  • 1
    You refering about an issue you never explained to us and havent given the code to reproduce it, nor you have showed exampels in your question. How is this question solvable at this state? Please review your question and add information that is needed to solve the question. – Thingamabobs Dec 29 '21 at 14:53
  • I literally can't explain it because as I said it varies from gif to gif depending on how they are encoded. I gave the code segment which is causing the issue, and every sinlge gif with transparency I have tested has had an issue. – Church.exe Dec 29 '21 at 15:25
  • 1
    A look into my magic glass ball tells me you overlay your pictures with new ones and dont update the images. Also see [When should I use root.update() in tkInter for python](https://stackoverflow.com/questions/66781579/when-should-i-use-root-update-in-tkinter-for-python/66781785#66781785) – Thingamabobs Dec 29 '21 at 15:54
  • 1
    seems like an issue with the gif then, just because you can export it as png doesn't mean that it is transparent or the issue above – Matiiss Dec 29 '21 at 16:50
  • Try to convert the mode of the GIF image to "RGBA" using `GifFrameSized = GifFrameSized.convert("RGBA")`. – acw1668 Dec 30 '21 at 07:56
  • @acw1668 I tried adding that and it didn't seem to have an effect – Church.exe Jan 08 '22 at 01:16
  • @Matiiss the gif is transparent, the png I export has normal transparency and I can open the gif in another image viewer such as window's build in "photos" and it displays fine. (I will say I do think the gif has something to do with it, when I try different gifs the transparency behaves differently for each one, like the bug in my code somewhere is failing a different way based on how they were each encoded but no matter how they are made it always breaks the transparency in some way) – Church.exe Jan 08 '22 at 01:17
  • @Thingamabobs Quite possibly since I don't use tkinter, is there a reason that would cause transparency to be really strangely bugged? How would I go about just updating the images? I won't lie I do not understand tkinter at all so I've kind of just been running with what I found and it had worked perfectly fine until now. The link you sent did say something along the lines that if you use root.update your code might not work going forward so that sounds about right but I tried removing all uses of root.update and the image still displays fine, windows says its not responding though. – Church.exe Jan 08 '22 at 01:18

1 Answers1

-2

So I used this gif file and it works as expected. There seems no magic in achieving it. I just get a image reference to each frame of the animated image and make a itertools.cycle out of it with:

frames = []
im = Image.open('52O8.gif')
for frame in range(im.n_frames):
    im.seek(frame)
    frames.append(ImageTk.PhotoImage(im.copy()))
frames_cycle=cycle(frames)

and later I just iterate every 100ms over the cycle to show a different frame in my canvas with:

DELAY = 100

def animate():
    canvas.itemconfig(img,image=next(frames_cycle))
    root.after(DELAY,animate)

Full Code

import tkinter as tk
from PIL import Image, ImageTk
from itertools import cycle

DELAY = 100

def animate():
    canvas.itemconfig(img,image=next(frames_cycle))
    root.after(DELAY,animate)

root = tk.Tk()
root.config(background='black')

frames = []
im = Image.open('52O8.gif')
for frame in range(im.n_frames):
    im.seek(frame)
    frames.append(ImageTk.PhotoImage(im.copy()))
frames_cycle=cycle(frames)

canvas = tk.Canvas(root,bg='black',width=400,height=400)
img = canvas.create_image(0,0,anchor=tk.NW,image=next(frames_cycle))
canvas.pack()
animate()
root.mainloop()
Thingamabobs
  • 4,666
  • 3
  • 8
  • 33
  • @Church.exe tkinter as a toolkit can satisfy all your needs, you just have to write the code for it. I never was forced to us another. – Thingamabobs Jan 15 '22 at 19:07
  • Turns out it looks like 99% of the issue was actually a bug in Pillow. I just ran it again, got annoyed by the issue, but this time when I searched it I was able to find a few obscure references to a bug in pillow that got fixed jan 2nd this year, when I updated now its almost entirely fixed. I still get a brief flash of issues on what I think is the first frame of any given gif, but if it's an issue with PIL I just have to wait for a fix for that too. (besides I'll take "just 99% better" any day) (P.S. sorry for taking so long, personal reasons that I cant fit in character limit) – Church.exe Apr 16 '22 at 10:07
  • @Church.exe While I cant reproduce the issue and the code I posted works just fine for me, I'm unable to help you out here. You may set a bounty on it. – Thingamabobs Apr 17 '22 at 07:09