Skip to content

Commit

Permalink
Merge pull request #6211 from radarhere/gif_loop
Browse files Browse the repository at this point in the history
Netscape GIF extension belongs after the global color table
  • Loading branch information
hugovk committed May 27, 2022
2 parents c34d789 + 2457eaf commit 69f1b4a
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 16 deletions.
Binary file added Tests/images/duplicate_number_of_loops.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 8 additions & 1 deletion Tests/test_file_gif.py
Expand Up @@ -772,9 +772,16 @@ def test_number_of_loops(tmp_path):
im = Image.new("L", (100, 100), "#000")
im.save(out, loop=number_of_loops)
with Image.open(out) as reread:

assert reread.info["loop"] == number_of_loops

# Check that even if a subsequent GIF frame has the number of loops specified,
# only the value from the first frame is used
with Image.open("Tests/images/duplicate_number_of_loops.gif") as im:
assert im.info["loop"] == 2

im.seek(1)
assert im.info["loop"] == 2


def test_background(tmp_path):
out = str(tmp_path / "temp.gif")
Expand Down
29 changes: 14 additions & 15 deletions src/PIL/GifImagePlugin.py
Expand Up @@ -244,15 +244,15 @@ def _seek(self, frame, update_image=True):
info["comment"] = comment
s = None
continue
elif s[0] == 255:
elif s[0] == 255 and frame == 0:
#
# application extension
#
info["extension"] = block, self.fp.tell()
if block[:11] == b"NETSCAPE2.0":
block = self.data()
if len(block) >= 3 and block[0] == 1:
info["loop"] = i16(block, 1)
self.info["loop"] = i16(block, 1)
while self.data():
pass

Expand Down Expand Up @@ -399,7 +399,7 @@ def _rgb(color):

if info.get("comment"):
self.info["comment"] = info["comment"]
for k in ["duration", "extension", "loop"]:
for k in ["duration", "extension"]:
if k in info:
self.info[k] = info[k]
elif k in self.info:
Expand Down Expand Up @@ -716,18 +716,6 @@ def _write_local_header(fp, im, offset, flags):
+ o8(0)
)

if "loop" in im.encoderinfo:
number_of_loops = im.encoderinfo["loop"]
fp.write(
b"!"
+ o8(255) # extension intro
+ o8(11)
+ b"NETSCAPE2.0"
+ o8(3)
+ o8(1)
+ o16(number_of_loops) # number of loops
+ o8(0)
)
include_color_table = im.encoderinfo.get("include_color_table")
if include_color_table:
palette_bytes = _get_palette_bytes(im)
Expand Down Expand Up @@ -933,6 +921,17 @@ def _get_global_header(im, info):
# Global Color Table
_get_header_palette(palette_bytes),
]
if "loop" in info:
header.append(
b"!"
+ o8(255) # extension intro
+ o8(11)
+ b"NETSCAPE2.0"
+ o8(3)
+ o8(1)
+ o16(info["loop"]) # number of loops
+ o8(0)
)
if info.get("comment"):
comment_block = b"!" + o8(254) # extension intro

Expand Down

0 comments on commit 69f1b4a

Please sign in to comment.