mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-31 16:07:30 +03:00 
			
		
		
		
	Merge branch 'main' into winbuild-update
This commit is contained in:
		
						commit
						147c52f92f
					
				
							
								
								
									
										24
									
								
								CHANGES.rst
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								CHANGES.rst
									
									
									
									
									
								
							|  | @ -5,6 +5,30 @@ Changelog (Pillow) | |||
| 9.3.0 (unreleased) | ||||
| ------------------ | ||||
| 
 | ||||
| - Don't reassign crc on ChunkStream close #6627 | ||||
|   [wiredfool, radarhere] | ||||
| 
 | ||||
| - Raise a warning if NumPy failed to raise an error during conversion #6594 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - Show all frames in ImageShow #6611 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - Allow FLI palette chunk to not be first #6626 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - If first GIF frame has transparency for RGB_ALWAYS loading strategy, use RGBA mode #6592 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - Round box position to integer when pasting embedded color #6517 | ||||
|   [radarhere, nulano] | ||||
| 
 | ||||
| - Removed EXIF prefix when saving WebP #6582 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - Pad IM palette to 768 bytes when saving #6579 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - Added DDS BC6 reading #6449 | ||||
|   [ShadelessFox, REDxEYE, radarhere] | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										
											BIN
										
									
								
								Tests/images/bw_gradient.imt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Tests/images/bw_gradient.imt
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Tests/images/hopper_palette_chunk_second.fli
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Tests/images/hopper_palette_chunk_second.fli
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Tests/images/text_float_coord.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Tests/images/text_float_coord.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 2.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/text_float_coord_1_alt.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Tests/images/text_float_coord_1_alt.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 807 B | 
|  | @ -4,7 +4,7 @@ import pytest | |||
| 
 | ||||
| from PIL import FliImagePlugin, Image | ||||
| 
 | ||||
| from .helper import assert_image_equal_tofile, is_pypy | ||||
| from .helper import assert_image_equal, assert_image_equal_tofile, is_pypy | ||||
| 
 | ||||
| # created as an export of a palette image from Gimp2.6 | ||||
| # save as...-> hopper.fli, default options. | ||||
|  | @ -79,6 +79,12 @@ def test_invalid_file(): | |||
|         FliImagePlugin.FliImageFile(invalid_file) | ||||
| 
 | ||||
| 
 | ||||
| def test_palette_chunk_second(): | ||||
|     with Image.open("Tests/images/hopper_palette_chunk_second.fli") as im: | ||||
|         with Image.open(static_test_file) as expected: | ||||
|             assert_image_equal(im.convert("RGB"), expected.convert("RGB")) | ||||
| 
 | ||||
| 
 | ||||
| def test_n_frames(): | ||||
|     with Image.open(static_test_file) as im: | ||||
|         assert im.n_frames == 1 | ||||
|  |  | |||
|  | @ -84,17 +84,24 @@ def test_l_mode_transparency(): | |||
| 
 | ||||
| 
 | ||||
| def test_strategy(): | ||||
|     with Image.open("Tests/images/iss634.gif") as im: | ||||
|         expected_rgb_always = im.convert("RGB") | ||||
| 
 | ||||
|     with Image.open("Tests/images/chi.gif") as im: | ||||
|         expected_zero = im.convert("RGB") | ||||
|         expected_rgb_always_rgba = im.convert("RGBA") | ||||
| 
 | ||||
|         im.seek(1) | ||||
|         expected_one = im.convert("RGB") | ||||
|         expected_different = im.convert("RGB") | ||||
| 
 | ||||
|     try: | ||||
|         GifImagePlugin.LOADING_STRATEGY = GifImagePlugin.LoadingStrategy.RGB_ALWAYS | ||||
|         with Image.open("Tests/images/chi.gif") as im: | ||||
|         with Image.open("Tests/images/iss634.gif") as im: | ||||
|             assert im.mode == "RGB" | ||||
|             assert_image_equal(im, expected_zero) | ||||
|             assert_image_equal(im, expected_rgb_always) | ||||
| 
 | ||||
|         with Image.open("Tests/images/chi.gif") as im: | ||||
|             assert im.mode == "RGBA" | ||||
|             assert_image_equal(im, expected_rgb_always_rgba) | ||||
| 
 | ||||
|         GifImagePlugin.LOADING_STRATEGY = ( | ||||
|             GifImagePlugin.LoadingStrategy.RGB_AFTER_DIFFERENT_PALETTE_ONLY | ||||
|  | @ -105,7 +112,7 @@ def test_strategy(): | |||
| 
 | ||||
|             im.seek(1) | ||||
|             assert im.mode == "P" | ||||
|             assert_image_equal(im.convert("RGB"), expected_one) | ||||
|             assert_image_equal(im.convert("RGB"), expected_different) | ||||
| 
 | ||||
|         # Change to RGB mode when a frame has an individual palette | ||||
|         with Image.open("Tests/images/iss634.gif") as im: | ||||
|  |  | |||
|  | @ -86,6 +86,18 @@ def test_roundtrip(mode, tmp_path): | |||
|     assert_image_equal_tofile(im, out) | ||||
| 
 | ||||
| 
 | ||||
| def test_small_palette(tmp_path): | ||||
|     im = Image.new("P", (1, 1)) | ||||
|     colors = [0, 1, 2] | ||||
|     im.putpalette(colors) | ||||
| 
 | ||||
|     out = str(tmp_path / "temp.im") | ||||
|     im.save(out) | ||||
| 
 | ||||
|     with Image.open(out) as reloaded: | ||||
|         assert reloaded.getpalette() == colors + [0] * 765 | ||||
| 
 | ||||
| 
 | ||||
| def test_save_unsupported_mode(tmp_path): | ||||
|     out = str(tmp_path / "temp.im") | ||||
|     im = hopper("HSV") | ||||
|  |  | |||
							
								
								
									
										19
									
								
								Tests/test_file_imt.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								Tests/test_file_imt.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| import io | ||||
| 
 | ||||
| import pytest | ||||
| 
 | ||||
| from PIL import Image, ImtImagePlugin | ||||
| 
 | ||||
| from .helper import assert_image_equal_tofile | ||||
| 
 | ||||
| 
 | ||||
| def test_sanity(): | ||||
|     with Image.open("Tests/images/bw_gradient.imt") as im: | ||||
|         assert_image_equal_tofile(im, "Tests/images/bw_gradient.png") | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.parametrize("data", (b"\n", b"\n-", b"width 1\n")) | ||||
| def test_invalid_file(data): | ||||
|     with io.BytesIO(data) as fp: | ||||
|         with pytest.raises(SyntaxError): | ||||
|             ImtImagePlugin.ImtImageFile(fp) | ||||
|  | @ -55,9 +55,7 @@ def test_write_exif_metadata(): | |||
|     test_buffer.seek(0) | ||||
|     with Image.open(test_buffer) as webp_image: | ||||
|         webp_exif = webp_image.info.get("exif", None) | ||||
|     assert webp_exif | ||||
|     if webp_exif: | ||||
|         assert webp_exif == expected_exif, "WebP EXIF didn't match" | ||||
|     assert webp_exif == expected_exif[6:], "WebP EXIF didn't match" | ||||
| 
 | ||||
| 
 | ||||
| def test_read_icc_profile(): | ||||
|  |  | |||
|  | @ -35,10 +35,13 @@ def test_toarray(): | |||
|     test_with_dtype(numpy.float64) | ||||
|     test_with_dtype(numpy.uint8) | ||||
| 
 | ||||
|     if parse_version(numpy.__version__) >= parse_version("1.23"): | ||||
|     with Image.open("Tests/images/truncated_jpeg.jpg") as im_truncated: | ||||
|         if parse_version(numpy.__version__) >= parse_version("1.23"): | ||||
|             with pytest.raises(OSError): | ||||
|                 numpy.array(im_truncated) | ||||
|         else: | ||||
|             with pytest.warns(UserWarning): | ||||
|                 numpy.array(im_truncated) | ||||
| 
 | ||||
| 
 | ||||
| def test_fromarray(): | ||||
|  |  | |||
|  | @ -935,7 +935,30 @@ def test_standard_embedded_color(layout_engine): | |||
|     d = ImageDraw.Draw(im) | ||||
|     d.text((10, 10), txt, font=ttf, fill="#fa6", embedded_color=True) | ||||
| 
 | ||||
|     assert_image_similar_tofile(im, "Tests/images/standard_embedded.png", 6.2) | ||||
|     assert_image_similar_tofile(im, "Tests/images/standard_embedded.png", 3.1) | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.parametrize("fontmode", ("1", "L", "RGBA")) | ||||
| def test_float_coord(layout_engine, fontmode): | ||||
|     txt = "Hello World!" | ||||
|     ttf = ImageFont.truetype(FONT_PATH, 40, layout_engine=layout_engine) | ||||
| 
 | ||||
|     im = Image.new("RGB", (300, 64), "white") | ||||
|     d = ImageDraw.Draw(im) | ||||
|     if fontmode == "1": | ||||
|         d.fontmode = "1" | ||||
| 
 | ||||
|     embedded_color = fontmode == "RGBA" | ||||
|     d.text((9.5, 9.5), txt, font=ttf, fill="#fa6", embedded_color=embedded_color) | ||||
|     try: | ||||
|         assert_image_similar_tofile(im, "Tests/images/text_float_coord.png", 3.9) | ||||
|     except AssertionError: | ||||
|         if fontmode == "1" and layout_engine == ImageFont.Layout.BASIC: | ||||
|             assert_image_similar_tofile( | ||||
|                 im, "Tests/images/text_float_coord_1_alt.png", 1 | ||||
|             ) | ||||
|         else: | ||||
|             raise | ||||
| 
 | ||||
| 
 | ||||
| def test_cbdt(layout_engine): | ||||
|  |  | |||
|  | @ -6,10 +6,8 @@ from PIL import Image, ImageMath | |||
| def pixel(im): | ||||
|     if hasattr(im, "im"): | ||||
|         return f"{im.mode} {repr(im.getpixel((0, 0)))}" | ||||
|     else: | ||||
|         if isinstance(im, int): | ||||
|     elif isinstance(im, int): | ||||
|         return int(im)  # hack to deal with booleans | ||||
|         print(im) | ||||
| 
 | ||||
| 
 | ||||
| A = Image.new("L", (1, 1), 1) | ||||
|  |  | |||
|  | @ -60,7 +60,10 @@ Pillow also provides limited support for a few additional modes, including: | |||
|     * ``BGR;24`` (24-bit reversed true colour) | ||||
|     * ``BGR;32`` (32-bit reversed true colour) | ||||
| 
 | ||||
| However, Pillow doesn’t support user-defined modes; if you need to handle band | ||||
| Apart from these additional modes, Pillow doesn't yet support multichannel | ||||
| images with a depth of more than 8 bits per channel. | ||||
| 
 | ||||
| Pillow also doesn’t support user-defined modes; if you need to handle band | ||||
| combinations that are not listed above, use a sequence of Image objects. | ||||
| 
 | ||||
| You can read the mode of an image through the :py:attr:`~PIL.Image.Image.mode` | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ | |||
| # See the README file for information on usage and redistribution. | ||||
| # | ||||
| 
 | ||||
| import os | ||||
| 
 | ||||
| from . import Image, ImageFile, ImagePalette | ||||
| from ._binary import i16le as i16 | ||||
|  | @ -80,11 +81,19 @@ class FliImageFile(ImageFile.ImageFile): | |||
| 
 | ||||
|         if i16(s, 4) == 0xF1FA: | ||||
|             # look for palette chunk | ||||
|             number_of_subchunks = i16(s, 6) | ||||
|             chunk_size = None | ||||
|             for _ in range(number_of_subchunks): | ||||
|                 if chunk_size is not None: | ||||
|                     self.fp.seek(chunk_size - 6, os.SEEK_CUR) | ||||
|                 s = self.fp.read(6) | ||||
|             if i16(s, 4) == 11: | ||||
|                 self._palette(palette, 2) | ||||
|             elif i16(s, 4) == 4: | ||||
|                 self._palette(palette, 0) | ||||
|                 chunk_type = i16(s, 4) | ||||
|                 if chunk_type in (4, 11): | ||||
|                     self._palette(palette, 2 if chunk_type == 11 else 0) | ||||
|                     break | ||||
|                 chunk_size = i32(s) | ||||
|                 if not chunk_size: | ||||
|                     break | ||||
| 
 | ||||
|         palette = [o8(r) + o8(g) + o8(b) for (r, g, b) in palette] | ||||
|         self.palette = ImagePalette.raw("RGB", b"".join(palette)) | ||||
|  |  | |||
|  | @ -299,11 +299,13 @@ class GifImageFile(ImageFile.ImageFile): | |||
|             self.im.paste(self.dispose, self.dispose_extent) | ||||
| 
 | ||||
|         self._frame_palette = palette or self.global_palette | ||||
|         self._frame_transparency = frame_transparency | ||||
|         if frame == 0: | ||||
|             if self._frame_palette: | ||||
|                 self.mode = ( | ||||
|                     "RGB" if LOADING_STRATEGY == LoadingStrategy.RGB_ALWAYS else "P" | ||||
|                 ) | ||||
|                 if LOADING_STRATEGY == LoadingStrategy.RGB_ALWAYS: | ||||
|                     self.mode = "RGBA" if frame_transparency is not None else "RGB" | ||||
|                 else: | ||||
|                     self.mode = "P" | ||||
|             else: | ||||
|                 self.mode = "L" | ||||
| 
 | ||||
|  | @ -313,7 +315,6 @@ class GifImageFile(ImageFile.ImageFile): | |||
|                 palette = copy(self.global_palette) | ||||
|             self.palette = palette | ||||
|         else: | ||||
|             self._frame_transparency = frame_transparency | ||||
|             if self.mode == "P": | ||||
|                 if ( | ||||
|                     LOADING_STRATEGY != LoadingStrategy.RGB_AFTER_DIFFERENT_PALETTE_ONLY | ||||
|  | @ -386,6 +387,7 @@ class GifImageFile(ImageFile.ImageFile): | |||
|             transparency = -1 | ||||
|             if frame_transparency is not None: | ||||
|                 if frame == 0: | ||||
|                     if LOADING_STRATEGY != LoadingStrategy.RGB_ALWAYS: | ||||
|                         self.info["transparency"] = frame_transparency | ||||
|                 elif self.mode not in ("RGB", "RGBA"): | ||||
|                     transparency = frame_transparency | ||||
|  | @ -410,9 +412,9 @@ class GifImageFile(ImageFile.ImageFile): | |||
|         temp_mode = "P" if self._frame_palette else "L" | ||||
|         self._prev_im = None | ||||
|         if self.__frame == 0: | ||||
|             if "transparency" in self.info: | ||||
|             if self._frame_transparency is not None: | ||||
|                 self.im = Image.core.fill( | ||||
|                     temp_mode, self.size, self.info["transparency"] | ||||
|                     temp_mode, self.size, self._frame_transparency | ||||
|                 ) | ||||
|         elif self.mode in ("RGB", "RGBA"): | ||||
|             self._prev_im = self.im | ||||
|  | @ -429,8 +431,12 @@ class GifImageFile(ImageFile.ImageFile): | |||
|     def load_end(self): | ||||
|         if self.__frame == 0: | ||||
|             if self.mode == "P" and LOADING_STRATEGY == LoadingStrategy.RGB_ALWAYS: | ||||
|                 if self._frame_transparency is not None: | ||||
|                     self.im.putpalettealpha(self._frame_transparency, 0) | ||||
|                     self.mode = "RGBA" | ||||
|                 else: | ||||
|                     self.mode = "RGB" | ||||
|                 self.im = self.im.convert("RGB", Image.Dither.FLOYDSTEINBERG) | ||||
|                 self.im = self.im.convert(self.mode, Image.Dither.FLOYDSTEINBERG) | ||||
|             return | ||||
|         if self.mode == "P" and self._prev_im: | ||||
|             if self._frame_transparency is not None: | ||||
|  |  | |||
|  | @ -352,7 +352,13 @@ def _save(im, fp, filename): | |||
|         fp.write(b"Lut: 1\r\n") | ||||
|     fp.write(b"\000" * (511 - fp.tell()) + b"\032") | ||||
|     if im.mode in ["P", "PA"]: | ||||
|         fp.write(im.im.getpalette("RGB", "RGB;L"))  # 768 bytes | ||||
|         im_palette = im.im.getpalette("RGB", "RGB;L") | ||||
|         colors = len(im_palette) // 3 | ||||
|         palette = b"" | ||||
|         for i in range(3): | ||||
|             palette += im_palette[colors * i : colors * (i + 1)] | ||||
|             palette += b"\x00" * (256 - colors) | ||||
|         fp.write(palette)  # 768 bytes | ||||
|     ImageFile._save(im, fp, [("raw", (0, 0) + im.size, 0, (rawmode, 0, -1))]) | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -679,12 +679,24 @@ class Image: | |||
|         new["shape"] = shape | ||||
|         new["typestr"] = typestr | ||||
|         new["version"] = 3 | ||||
|         try: | ||||
|             if self.mode == "1": | ||||
|                 # Binary images need to be extended from bits to bytes | ||||
|                 # See: https://github.com/python-pillow/Pillow/issues/350 | ||||
|                 new["data"] = self.tobytes("raw", "L") | ||||
|             else: | ||||
|                 new["data"] = self.tobytes() | ||||
|         except Exception as e: | ||||
|             if not isinstance(e, (MemoryError, RecursionError)): | ||||
|                 try: | ||||
|                     import numpy | ||||
|                     from packaging.version import parse as parse_version | ||||
|                 except ImportError: | ||||
|                     pass | ||||
|                 else: | ||||
|                     if parse_version(numpy.__version__) < parse_version("1.23"): | ||||
|                         warnings.warn(e) | ||||
|             raise | ||||
|         return new | ||||
| 
 | ||||
|     def __getstate__(self): | ||||
|  |  | |||
|  | @ -482,8 +482,8 @@ class ImageDraw: | |||
|                 # extract mask and set text alpha | ||||
|                 color, mask = mask, mask.getband(3) | ||||
|                 color.fillband(3, (ink >> 24) & 0xFF) | ||||
|                 coord2 = coord[0] + mask.size[0], coord[1] + mask.size[1] | ||||
|                 self.im.paste(color, coord + coord2, mask) | ||||
|                 x, y = (int(c) for c in coord) | ||||
|                 self.im.paste(color, (x, y, x + mask.size[0], y + mask.size[1]), mask) | ||||
|             else: | ||||
|                 self.draw.draw_bitmap(coord, mask, ink) | ||||
| 
 | ||||
|  |  | |||
|  | @ -136,7 +136,7 @@ class WindowsViewer(Viewer): | |||
|     """The default viewer on Windows is the default system application for PNG files.""" | ||||
| 
 | ||||
|     format = "PNG" | ||||
|     options = {"compress_level": 1} | ||||
|     options = {"compress_level": 1, "save_all": True} | ||||
| 
 | ||||
|     def get_command(self, file, **options): | ||||
|         return ( | ||||
|  | @ -154,7 +154,7 @@ class MacViewer(Viewer): | |||
|     """The default viewer on macOS using ``Preview.app``.""" | ||||
| 
 | ||||
|     format = "PNG" | ||||
|     options = {"compress_level": 1} | ||||
|     options = {"compress_level": 1, "save_all": True} | ||||
| 
 | ||||
|     def get_command(self, file, **options): | ||||
|         # on darwin open returns immediately resulting in the temp | ||||
|  | @ -197,7 +197,7 @@ if sys.platform == "darwin": | |||
| 
 | ||||
| class UnixViewer(Viewer): | ||||
|     format = "PNG" | ||||
|     options = {"compress_level": 1} | ||||
|     options = {"compress_level": 1, "save_all": True} | ||||
| 
 | ||||
|     def get_command(self, file, **options): | ||||
|         command = self.get_command_ex(file, **options)[0] | ||||
|  |  | |||
|  | @ -39,14 +39,18 @@ class ImtImageFile(ImageFile.ImageFile): | |||
|         # Quick rejection: if there's not a LF among the first | ||||
|         # 100 bytes, this is (probably) not a text header. | ||||
| 
 | ||||
|         if b"\n" not in self.fp.read(100): | ||||
|         buffer = self.fp.read(100) | ||||
|         if b"\n" not in buffer: | ||||
|             raise SyntaxError("not an IM file") | ||||
|         self.fp.seek(0) | ||||
| 
 | ||||
|         xsize = ysize = 0 | ||||
| 
 | ||||
|         while True: | ||||
| 
 | ||||
|             if buffer: | ||||
|                 s = buffer[:1] | ||||
|                 buffer = buffer[1:] | ||||
|             else: | ||||
|                 s = self.fp.read(1) | ||||
|             if not s: | ||||
|                 break | ||||
|  | @ -55,7 +59,12 @@ class ImtImageFile(ImageFile.ImageFile): | |||
| 
 | ||||
|                 # image data begins | ||||
|                 self.tile = [ | ||||
|                     ("raw", (0, 0) + self.size, self.fp.tell(), (self.mode, 0, 1)) | ||||
|                     ( | ||||
|                         "raw", | ||||
|                         (0, 0) + self.size, | ||||
|                         self.fp.tell() - len(buffer), | ||||
|                         (self.mode, 0, 1), | ||||
|                     ) | ||||
|                 ] | ||||
| 
 | ||||
|                 break | ||||
|  | @ -63,8 +72,11 @@ class ImtImageFile(ImageFile.ImageFile): | |||
|             else: | ||||
| 
 | ||||
|                 # read key/value pair | ||||
|                 # FIXME: dangerous, may read whole file | ||||
|                 s = s + self.fp.readline() | ||||
|                 if b"\n" not in buffer: | ||||
|                     buffer += self.fp.read(100) | ||||
|                 lines = buffer.split(b"\n") | ||||
|                 s += lines.pop(0) | ||||
|                 buffer = b"\n".join(lines) | ||||
|                 if len(s) == 1 or len(s) > 100: | ||||
|                     break | ||||
|                 if s[0] == ord(b"*"): | ||||
|  | @ -74,13 +86,13 @@ class ImtImageFile(ImageFile.ImageFile): | |||
|                 if not m: | ||||
|                     break | ||||
|                 k, v = m.group(1, 2) | ||||
|                 if k == "width": | ||||
|                 if k == b"width": | ||||
|                     xsize = int(v) | ||||
|                     self._size = xsize, ysize | ||||
|                 elif k == "height": | ||||
|                 elif k == b"height": | ||||
|                     ysize = int(v) | ||||
|                     self._size = xsize, ysize | ||||
|                 elif k == "pixel" and v == "n8": | ||||
|                 elif k == b"pixel" and v == b"n8": | ||||
|                     self.mode = "L" | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -189,7 +189,7 @@ class ChunkStream: | |||
|         self.close() | ||||
| 
 | ||||
|     def close(self): | ||||
|         self.queue = self.crc = self.fp = None | ||||
|         self.queue = self.fp = None | ||||
| 
 | ||||
|     def push(self, cid, pos, length): | ||||
| 
 | ||||
|  | @ -224,7 +224,7 @@ class ChunkStream: | |||
|             ) from e | ||||
| 
 | ||||
|     def crc_skip(self, cid, data): | ||||
|         """Read checksum.  Used if the C module is not present""" | ||||
|         """Read checksum""" | ||||
| 
 | ||||
|         self.fp.read(4) | ||||
| 
 | ||||
|  |  | |||
|  | @ -311,9 +311,11 @@ def _save(im, fp, filename): | |||
|     lossless = im.encoderinfo.get("lossless", False) | ||||
|     quality = im.encoderinfo.get("quality", 80) | ||||
|     icc_profile = im.encoderinfo.get("icc_profile") or "" | ||||
|     exif = im.encoderinfo.get("exif", "") | ||||
|     exif = im.encoderinfo.get("exif", b"") | ||||
|     if isinstance(exif, Image.Exif): | ||||
|         exif = exif.tobytes() | ||||
|     if exif.startswith(b"Exif\x00\x00"): | ||||
|         exif = exif[6:] | ||||
|     xmp = im.encoderinfo.get("xmp", "") | ||||
|     method = im.encoderinfo.get("method", 4) | ||||
| 
 | ||||
|  |  | |||
|  | @ -138,9 +138,9 @@ deps = { | |||
|         "bins": ["cjpeg.exe", "djpeg.exe"], | ||||
|     }, | ||||
|     "zlib": { | ||||
|         "url": "https://zlib.net/zlib1212.zip", | ||||
|         "filename": "zlib1212.zip", | ||||
|         "dir": "zlib-1.2.12", | ||||
|         "url": "https://zlib.net/zlib1213.zip", | ||||
|         "filename": "zlib1213.zip", | ||||
|         "dir": "zlib-1.2.13", | ||||
|         "license": "README", | ||||
|         "license_pattern": "Copyright notice:\n\n(.+)$", | ||||
|         "build": [ | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user