mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 09:57:43 +03:00 
			
		
		
		
	Merge pull request #2902 from wiredfool/pr_2388
Add disposal option when saving GIFs
This commit is contained in:
		
						commit
						ff13d184d8
					
				| 
						 | 
				
			
			@ -392,6 +392,7 @@ def _write_single_frame(im, fp, palette):
 | 
			
		|||
def _write_multiple_frames(im, fp, palette):
 | 
			
		||||
 | 
			
		||||
    duration = im.encoderinfo.get("duration", None)
 | 
			
		||||
    disposal = im.encoderinfo.get('disposal', None)
 | 
			
		||||
 | 
			
		||||
    im_frames = []
 | 
			
		||||
    frame_count = 0
 | 
			
		||||
| 
						 | 
				
			
			@ -404,6 +405,8 @@ def _write_multiple_frames(im, fp, palette):
 | 
			
		|||
            encoderinfo = im.encoderinfo.copy()
 | 
			
		||||
            if isinstance(duration, (list, tuple)):
 | 
			
		||||
                encoderinfo['duration'] = duration[frame_count]
 | 
			
		||||
            if isinstance(disposal, (list, tuple)):
 | 
			
		||||
                encoderinfo["disposal"] = disposal[frame_count]
 | 
			
		||||
            frame_count += 1
 | 
			
		||||
 | 
			
		||||
            if im_frames:
 | 
			
		||||
| 
						 | 
				
			
			@ -503,15 +506,19 @@ def _write_local_header(fp, im, offset, flags):
 | 
			
		|||
        duration = int(im.encoderinfo["duration"] / 10)
 | 
			
		||||
    else:
 | 
			
		||||
        duration = 0
 | 
			
		||||
    if transparent_color_exists or duration != 0:
 | 
			
		||||
        transparency_flag = 1 if transparent_color_exists else 0
 | 
			
		||||
 | 
			
		||||
    disposal = int(im.encoderinfo.get('disposal', 0))
 | 
			
		||||
 | 
			
		||||
    if transparent_color_exists or duration != 0 or disposal:
 | 
			
		||||
        packed_flag = 1 if transparent_color_exists else 0
 | 
			
		||||
        packed_flag |= disposal << 2
 | 
			
		||||
        if not transparent_color_exists:
 | 
			
		||||
            transparency = 0
 | 
			
		||||
 | 
			
		||||
        fp.write(b"!" +
 | 
			
		||||
                 o8(249) +                # extension intro
 | 
			
		||||
                 o8(4) +                  # length
 | 
			
		||||
                 o8(transparency_flag) +  # packed fields
 | 
			
		||||
                 o8(packed_flag) +        # packed fields
 | 
			
		||||
                 o16(duration) +          # duration
 | 
			
		||||
                 o8(transparency) +       # transparency index
 | 
			
		||||
                 o8(0))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -259,6 +259,40 @@ class TestFileGif(PillowTestCase):
 | 
			
		|||
        except EOFError:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    def test_save_dispose(self):
 | 
			
		||||
        out = self.tempfile('temp.gif')
 | 
			
		||||
        im_list = [
 | 
			
		||||
            Image.new('L', (100, 100), '#000'),
 | 
			
		||||
            Image.new('L', (100, 100), '#111'),
 | 
			
		||||
            Image.new('L', (100, 100), '#222'),
 | 
			
		||||
        ]
 | 
			
		||||
        for method in range(0,4):
 | 
			
		||||
            im_list[0].save(
 | 
			
		||||
                out,
 | 
			
		||||
                save_all=True,
 | 
			
		||||
                append_images=im_list[1:],
 | 
			
		||||
                disposal=method
 | 
			
		||||
            )
 | 
			
		||||
            img = Image.open(out)
 | 
			
		||||
            for _ in range(2):
 | 
			
		||||
                img.seek(img.tell() + 1)
 | 
			
		||||
                self.assertEqual(img.disposal_method, method)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        # check per frame disposal
 | 
			
		||||
        im_list[0].save(
 | 
			
		||||
            out,
 | 
			
		||||
            save_all=True,
 | 
			
		||||
            append_images=im_list[1:],
 | 
			
		||||
            disposal=tuple(range(len(im_list)))
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        img = Image.open(out)
 | 
			
		||||
 | 
			
		||||
        for i in range(2):
 | 
			
		||||
            img.seek(img.tell() + 1)
 | 
			
		||||
            self.assertEqual(img.disposal_method, i+1)
 | 
			
		||||
 | 
			
		||||
    def test_iss634(self):
 | 
			
		||||
        img = Image.open("Tests/images/iss634.gif")
 | 
			
		||||
        # seek to the second frame
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -132,6 +132,17 @@ are available::
 | 
			
		|||
    the palette can be passed in as an
 | 
			
		||||
    :py:class:`PIL.ImagePalette.ImagePalette` object.
 | 
			
		||||
 | 
			
		||||
**disposal**
 | 
			
		||||
    Indicates the way in which the graphic is to be treated after being displayed.
 | 
			
		||||
 | 
			
		||||
    * 0 - No disposal specified.
 | 
			
		||||
    * 1 - Do not dispose.
 | 
			
		||||
    * 2 - Restore to background color.
 | 
			
		||||
    * 3 - Restore to previous content.
 | 
			
		||||
 | 
			
		||||
     Pass a single integer for a constant disposal, or a list or tuple
 | 
			
		||||
     to set the disposal for each frame separately. 
 | 
			
		||||
 | 
			
		||||
Reading local images
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user