-
[Continuing a discussion that started in [issue #5278], where @smccombie reports having trouble with PIL-generated animated GIFs not animating in Microsoft Teams, and also being larger than necessary. He suspected the LZW encoding had something to do with the problem, but that's not likely. Since we don't know how PIL causes the problem yet, I thought it better to be a discussion than an issue for now.] @smccombie, this is still a mystery. Addressing first the size differences: in your latest four files, the LZW-encoded data amounts to not much difference. The first two files (from PIL) each have a total of 966 bytes of LZW data; the GIMP file has 729 bytes, and the ezgif file has 973 bytes total LZW data. Nearly all the difference in file size comes from the PIL files having a 768-byte GCT (global color table) and five 768-byte LCTs (local color tables), while the GIMP-ified file has an 8-slot 24-byte GCT and no LCTs, and the ezgif file has a 2-slot 6-byte GCT and four 6-byte LCTs (its first image has no LCT). In your second bad file today, how did you remove the extra animation-looping (NETSCAPE2.0) application extension blocks? Can you use the same technique to remove the extra comment blocks? And, does the ezgif file work in Teams? I looked at the second bad file for anything anomalous that could explain its not working in Teams. Nothing jumps out except the excess comments, and the "color resolution" field having a value of 0 (2 colors) while the GCT size field has a value of 7 (256 colors). I would like you to try this patched version of your second (bad) file: It's patched to change the color resolution to 7. If that fails, see if you can generate the GIFs from PIL without comments. The GIMP-ified version has no comment blocks. Keep me posted, and feel free to email me directly: raygard at gmail dot com. |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 21 replies
-
@raygard -- thanks for continuing to help me out, been a bit busy today to get back to you until just now. Unfortunately, that patched file also doesn't work, so the issue must be elsewhere. I'm going to try to remove the extra comment blocks, I didn't notice that earlier. I removed the extra application extensions through a home-brew script, shouldn't take me long to do the same for the comments. I'll keep you posted, thank you for checking the LZW sizes, that alleviates many of my concerns. Also I didn't realize each frame had a LCT, I thought the graphic extension had the flag set to no LCT (but I only checked the first frame). I see it is indeed set after the first frame (whoops!), going to try to strip out the LCT and see if that's the source of the problem. Shouldn't be necessary to have LCT in any of my graphics, and I thought there was a PIL patch to use just the GCT. This file is still broken, but I've removed the LCTs: Ok, so I also removed all of the comments and the problem went away!!! So really the major issue was the LCT and comments (also not sure if this matters but I have a single application extension before everything), not sure if it works with a single comment though as I believe I've shown that working with GIMP before, will investigate further, but from a PIL perspective, probably just need a mechanism to disallow LCT, also I'll raise these findings with Microsoft, although I doubt they're going to do anything about it... In the mean-time, putting together some python hackery to fix things and I'll post the code here. Once again thank you for your help and everyone on the PIL team! |
Beta Was this translation helpful? Give feedback.
-
@smccombie, At this point it seems more likely that Teams does not like extra (or maybe any) comments. The first file from yesterday (from GIMP) did have LCTs on all but the first image, and you said it worked, so LCTs are not necessarily the problem. I'm not sure how you can get PIL to generate animated GIFs without LCTs. If you just delete LCTs you may (and probably will) get a defective file. You can really only eliminate all the LCTs if they all match the GCT, I believe. Removing LCTs is an optimization that some GIF optimizers can do, by finding all the colors in all the images, reducing to 256 or fewer if there are more, and then rearranging the pixel data to use the new GCT generated from the reduced colors. That will usually alter the appearance, but not perceptibly in many or most cases. If you can demonstrate that Teams can work with a single comment block and also use disposal=1 to get consistent a disposal method, then maybe PIL can be fixed to only write a single comment block. I would like to see the script you use to remove extra animation application extension blocks and/or comment blocks. If we can be sure that extraneous comment blocks and/or application extension blocks are a problem, then we can make that an issue and maybe get it resolved. Another thought: maybe you can use pygifsicle to optimize them when you generate them. I think it can remove LCTs and do other optimizations, but I haven't looked into it. |
Beta Was this translation helpful? Give feedback.
-
Okay so I've narrowed down the 2 problems. You were correct, the LCT is not causing any problems and can be left alone (although it would be nice to have an option to use just the GCT to help reduce size, but that's not an immediate concern of mine). The multiple application extensions and comment extensions causes Teams to break. You can however have 1 comment extension without it breaking, which is the preferred behavior. The following is the code I used, which is just for debugging purposes, but helped me prove the problem. Please let me know if you're going to submit a request to have PIL remove the extraneous comments and application extensions. Thanks again for everything! fh = open("original.gif", "rb")
bad = fh.read()
fh.close()
#REMOVE EXTRA COMMENTS (KEEPS FIRST)
ct = 0
xx = []
for i in range(0, len(bad)):
if hex(bad[i])[2:] == "21" and hex(bad[i + 1])[2:] == "fe":
ct = ct + 1
xx.append(i)
print("----")
print(ct, xx)
fh = open("step-1.gif", "wb")
fh.write(bad[:xx[1]])
fh.write(bad[xx[1]+30:xx[2]])
fh.write(bad[xx[2]+30:xx[3]])
fh.write(bad[xx[3]+30:xx[4]])
fh.write(bad[xx[4]+30:])
fh.close()
#REMOVE EXTRA APPLICATIONS (KEEPS FIRST)
fh = open("step-1.gif", "rb")
bad = fh.read()
fh.close()
ct = 0
xx = []
for i in range(0, len(bad)):
if hex(bad[i])[2:] == "21" and hex(bad[i + 1])[2:] == "ff":
ct = ct + 1
xx.append(i)
print("----")
print(ct, xx)
fh = open("step-2.gif", "wb")
fh.write(bad[:xx[1]])
fh.write(bad[xx[1]+19:xx[2]])
fh.write(bad[xx[2]+19:xx[3]])
fh.write(bad[xx[3]+19:xx[4]])
fh.write(bad[xx[4]+19:])
fh.close() |
Beta Was this translation helpful? Give feedback.
-
For anyone who needs a quick and dirty fix that is compatible with the Pyodide runtime: buf = io.BytesIO() #! NEW BINARY BUFFER
buf.seek(0) #! REWIND OLD BINARY BUFFER
#img[0].save(buf, append_images = img[1:], comment = str(datetime.datetime.now()), #AWAITING PIL PATCH...
# duration = 1000, loop = 0x0, format = "GIF", optimize = False, save_all = True) #AWAITING PIL PATCH...
img[0].save(buf, append_images = img[1:], comment = "", duration = 1000, format = "GIF", loop = 0, save_all = True)
tmp = buf.getvalue().split(b'NETSCAPE2.0')
buf = tmp[0] + (b'NETSCAPE2.0') + tmp[1][:5]
for i in range(1, len(tmp)):
buf = buf + tmp[i][5:-3]
buf = buf + tmp[-1][-3:] |
Beta Was this translation helpful? Give feedback.
-
@smccombie Scott, I have written a program (uploaded as a gist), I'd like you to try it on some of the GIFs that are giving you trouble in Teams. Please let me know if this helps. If so, I'd like to get Also, can you please tell me what version of Pillow you are using? |
Beta Was this translation helpful? Give feedback.
@smccombie Scott, I have written a program (uploaded as a gist),
fix_gif.py
. It will "Re-order GIF file sections if needed, so "NETSCAPE2.0" animation loop extension is immediately after header and global color table (if latter is present), followed by all other application extensions, then all comment sections (with duplicates removed), then all other sections in original order. The code may be modified easily to put comment sections and other application extensions at the end, but Pillow 9.1.0 does not work well with sections after the last image data section."I'd like you to try it on some of the GIFs that are giving you trouble in Teams. Please let me know if this helps. If so, I'd l…