diff --git a/easy_thumbnails/processors.py b/easy_thumbnails/processors.py index 7f7ba20c..223e93d7 100644 --- a/easy_thumbnails/processors.py +++ b/easy_thumbnails/processors.py @@ -52,8 +52,9 @@ def apply_to_frames(self, method, *args, **kwargs): self.im.seek(i) new_frames.append(method(*args, **kwargs)) write_to = BytesIO() + loop = self.im.info.get('loop', 0) new_frames[0].save( - write_to, format=self.im.format, save_all=True, append_images=new_frames[1:] + write_to, format=self.im.format, save_all=True, append_images=new_frames[1:], loop=loop ) return Image.open(write_to) @@ -104,6 +105,7 @@ def colorspace(im, bw=False, replace_alpha=False, **kwargs): im = base else: frames = [] + loop = im.info.get('loop', 0) for i in range(im.n_frames): im.seek(i) if im.mode != 'RGBA': @@ -113,7 +115,7 @@ def colorspace(im, bw=False, replace_alpha=False, **kwargs): frames.append(base) write_to = BytesIO() frames[0].save( - write_to, format=im.format, save_all=True, append_images=frames[1:] + write_to, format=im.format, save_all=True, append_images=frames[1:], loop=loop ) return Image.open(write_to) else: @@ -376,6 +378,7 @@ def background(im, size, background=None, **kwargs): return new_im else: frames = [] + loop = im.info.get('loop', 0) for i in range(im.n_frames): im.seek(i) copied_new_im = new_im.copy() @@ -383,6 +386,6 @@ def background(im, size, background=None, **kwargs): frames.append(copied_new_im) write_to = BytesIO() frames[0].save( - write_to, format=im.format, save_all=True, append_images=frames[1:] + write_to, format=im.format, save_all=True, append_images=frames[1:], loop=loop ) return Image.open(write_to) diff --git a/easy_thumbnails/tests/test_animated_formats.py b/easy_thumbnails/tests/test_animated_formats.py index f3cf81b9..ee720218 100644 --- a/easy_thumbnails/tests/test_animated_formats.py +++ b/easy_thumbnails/tests/test_animated_formats.py @@ -4,7 +4,7 @@ from unittest import TestCase -def create_animated_image(mode='RGB', format="gif", size=(1000, 1000), no_frames=6): +def create_animated_image(mode='RGB', format="gif", size=(1000, 1000), no_frames=6, loop=None): frames = [] for i in range(no_frames): image = Image.new(mode, size, (255, 255, 255)) @@ -14,9 +14,10 @@ def create_animated_image(mode='RGB', format="gif", size=(1000, 1000), no_frames draw.rectangle((x_bit * 2, y_bit, x_bit * 3, y_bit * 8), 'yellow') frames.append(image) write_to = BytesIO() - frames[0].save( - write_to, format=format, save_all=True, append_images=frames[1:] - ) + save_kwargs = {'format': format, 'save_all': True, 'append_images': frames[1:]} + if loop is not None: + save_kwargs['loop'] = loop + frames[0].save(write_to, **save_kwargs) im = Image.open(write_to) # for debugging # with open(f"animated{no_frames}.{format}", "wb") as f: @@ -81,3 +82,17 @@ def test_background(self): # indeed processed? self.assertEqual(frames_count, processed_frames_count) self.assertEqual(processed.size, (1000, 1800)) + + def test_background_loop_preserved(self): + no_frames = 5 + loop_value = 3 + im = create_animated_image(format="gif", no_frames=no_frames, loop=loop_value) + + original_loop = im.info.get('loop', 0) + self.assertEqual(original_loop, loop_value) + + processed = processors.background(im, background="#00ff00", size=(1200, 1200)) + + processed_loop = processed.info.get('loop', 0) + self.assertEqual(processed_loop, original_loop) + self.assertEqual(processed_loop, loop_value)