Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

f.info['duration'] changes don't stick #4052

Closed
knaik95 opened this issue Sep 7, 2019 · 7 comments
Closed

f.info['duration'] changes don't stick #4052

knaik95 opened this issue Sep 7, 2019 · 7 comments
Labels

Comments

@knaik95
Copy link

knaik95 commented Sep 7, 2019

This might have something to do with #4002 .

I'm trying to set 'duration' to '[1, 1, 1, 1, 1, 1, 1000, 1, 1, 1, 1, 1, 1]' but once it hits 1000, it stays at 1000, meaning all the frames after that point are slower than I want them to be.
This is the code I have.

frames[0].save(end_f, save_all=True, loop=0, append_images=frames[1:], duration=durations)
f = Image.open(end_f)
f.info['duration'] = durations
f.save("out.gif", save_all=True)
print f.info

print f.info doesn't even show a 'duration' key so I'm not exactly sure what's going on.

@radarhere
Copy link
Member

Could you provide the values for frames? Without that, there is a key piece of information missing when trying to replicate your problem. For example, the following works fine for me -

from PIL import Image
frames = [Image.new("RGB", (100, 100), color) for color in ["#000", "#001", "#002", "#003", "#004", "#005", "#006", "#007", "#008", "#009", "#00a", "#00b", "#00c"]]
end_f = "out.gif"
durations = [1, 1, 1, 1, 1, 1, 1000, 1, 1, 1, 1, 1, 1]

frames[0].save(end_f, save_all=True, loop=0, append_images=frames[1:], duration=durations)
f = Image.open(end_f)
f.info['duration'] = durations
f.save("out.gif", save_all=True)
print(f.info)

Also, what version of Pillow are you using?

While not related to your question, you are using Python 2 - be aware that in 2020, Pillow will drop support for Python 2, as part of https://python3statement.org/

@knaik95
Copy link
Author

knaik95 commented Sep 7, 2019

I'm using Pillow 6.1.0

sublime_text_2019-09-07_17-56-01
^the testFunction() is me running a nuanced version of your code. I get the error in the right window. At the top of the error, I've printed out len(frames), len(durations) and under that is print durations

out
^this is the GIF generated by actionsToFrames(), which I told to return the frames and durations lists and localized them in testFunction(). As you can see, the first 6 frames play out smoothly, but once the 7th frame, which has duration = 1000, plays out, all succeeding frames are slowed down as well.

And yeah, I know the version of Python I'm using is ancient, it's just the one I learned with so I've stuck with it until now. I'll deal with it's EOL when it happens :'D

@knaik95
Copy link
Author

knaik95 commented Sep 7, 2019

Okay, this is weird. The GIF slows down on my machine, but looking at it in my above response, it's normal. Is it an Internet Explorer (the default program to open GIFs) issue?

@radarhere radarhere added the GIF label Sep 7, 2019
@radarhere
Copy link
Member

The error that you are receiving does look like #4002. So if you would like that fixed, you can wait for Pillow 6.2.0 on October 1, or build from Pillow master now.

As for the rest of your problem, I am confused - that error should only occur if all of the frames that you are saving are identical. I'm also not sure how you have an image output by the code when there is an error in the middle. Would you be able to provide a simple, self-contained version of your code that demonstrates the problem? Something that can be run from start to end to show the bug. You are welcome to attach images to be included as the input.

@knaik95
Copy link
Author

knaik95 commented Sep 7, 2019

Running this code should produce an example GIF. On my machine, re-running the code with the last 4 lines uncommented raises the TypeError.

from PIL import Image
import urllib2 as urlib
import io

img_name_list = ["idle_down", "idle_left", "idle_right", "idle_up", "left_left", "left_right", "up_right", "up_left"]

url_list = ["https://i.imgur.com/JwLDvjj.png", "https://i.imgur.com/TaKxt4b.png", "https://i.imgur.com/6TLvOcH.png", "https://i.imgur.com/sdfxto0.png", "https://i.imgur.com/XlOnNEs.png", "https://i.imgur.com/mEkXLph.png", "https://i.imgur.com/Ub0zx5t.png", "https://i.imgur.com/hQ0yh4c.png"]

img_list = []

img_dict = {}

#print len(img_name_list), len(url_list)

for url in url_list:
	fd = urlib.urlopen(url)
	img_fetch = io.BytesIO(fd.read())
	img = Image.open(img_fetch)
	img_list.append(img)

for name, img in zip(img_name_list, img_list):
	img_dict[name] = img

actions = ["left 3", "up 2"]

a_list = [a.split() for a in actions]

frames, durations = [], []

for a in a_list:
	direction, reps = a[0], int(a[1])
	for x in range(reps):
		steps = (direction + "_right",  "idle_" + direction, direction + "_left")
		for step in steps:
			frames.append(img_dict[step])
			durations.append(1)

print len(frames), len(durations)

end_f = "out.gif"

frames[0].save(end_f, save_all=True, loop=0, append_images=frames[1:], duration=durations)

#f = Image.open(end_f)
#f.info['duration'] = durations
#f.save("out.gif", save_all=True)
#print(f.info)

Also, the reason the GIF generated with my previous code even though there was that error in the middle is because I reran the code after commenting the faulty lines out to show you the result of a clean run.

@radarhere
Copy link
Member

Okay, so I think essential problem is this - in those last few lines, you are opening a file and saving back to the same file.

from PIL import Image
f = Image.open("out.gif")
f.save("out.gif", save_all=True)

I find that this code turns a multiframe GIF into a single frame GIF. The TypeError happens because of that, so we can set the raised error aside.

If you do want to open a file and save it back to the same file, I can offer this for an immediate workaround -

from PIL import Image, ImageSequence
f = Image.open("out.gif")
frames = ImageSequence.all_frames(f)
frames[0].save("out.gif", save_all=True, append_images=frames[1:])

Just to avoid confusion, I'll also point out that in your last code sample, all durations are set to 1, instead of one of them being set to 1000.

@knaik95
Copy link
Author

knaik95 commented Sep 8, 2019

Yep, that was the problem. Thanks!

@knaik95 knaik95 closed this as completed Sep 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants