mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-31 07:57:27 +03:00 
			
		
		
		
	Merge branch 'master' into fast-merge
# Conflicts: # _imaging.c # libImaging/Bands.c # libImaging/Imaging.h
This commit is contained in:
		
						commit
						9cf8f93c64
					
				|  | @ -26,6 +26,8 @@ matrix: | |||
|     - env: DOCKER="debian-stretch-x86" | ||||
|     - env: DOCKER="centos-6-amd64" | ||||
|     - env: DOCKER="amazon-amd64" | ||||
|     - env: DOCKER="fedora-24-amd64" | ||||
|     - env: DOCKER="fedora-26-amd64" | ||||
| 
 | ||||
| dist: trusty | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										60
									
								
								CHANGES.rst
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								CHANGES.rst
									
									
									
									
									
								
							|  | @ -4,6 +4,66 @@ Changelog (Pillow) | |||
| 4.3.0 (unreleased) | ||||
| ------------------ | ||||
| 
 | ||||
| - CI: Add Fedora 24 and 26 to Docker tests | ||||
|   [wiredfool] | ||||
| 
 | ||||
| - JPEG: Fix ZeroDivisionError when EXIF contains invalid DPI (0/0). #2667 | ||||
|   [vytisb] | ||||
| 
 | ||||
| - Depends: Updated openjpeg to 2.2.0 #2669 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - Depends: Updated Tk Tcl to 8.6.7 #2668 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - Depends: Updated libimagequant to 2.10.2 #2660 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - Test: Added test for ImImagePlugin tell() #2675 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - Test: Additional tests for SGIImagePlugin #2659 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - New Image.getchannel method #2661 | ||||
|   [homm] | ||||
| 
 | ||||
| - Remove unused im.copy2 and core.copy methods #2657 | ||||
|   [homm] | ||||
| 
 | ||||
| - Fast Image.split() #2676 | ||||
|   [homm] | ||||
| 
 | ||||
| - Fast image allocation #2655 | ||||
|   [homm] | ||||
| 
 | ||||
| - Storage cleanup #2654 | ||||
|   [homm] | ||||
|    | ||||
| - FLI: Use frame count from FLI header #2674 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - Test: Test animated FLI file #2650 | ||||
|   [hugovk] | ||||
| 
 | ||||
| - Bug: Fixed uninitalized memory in bc5 decoding #2648 | ||||
|   [ifeherva] | ||||
| 
 | ||||
| - Moved SgiImagePlugin save error to before the start of write operations #2646 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - Move createfontdatachunk.py so isn't installed globally #2645 | ||||
|   [hugovk] | ||||
| 
 | ||||
| - Bug: Fix unexpected keyword argument 'align' #2641 | ||||
|   [hugovk] | ||||
| 
 | ||||
| - Add newlines to error message for clarity #2640 | ||||
|   [hugovk] | ||||
| 
 | ||||
| - Docs: Updated redirected URL #2637 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - Bug: Fix JPEG DPI when EXIF is invalid #2632 | ||||
|   [wiredfool] | ||||
| 
 | ||||
|  |  | |||
|  | @ -38,7 +38,7 @@ class FliImageFile(ImageFile.ImageFile): | |||
|     format = "FLI" | ||||
|     format_description = "Autodesk FLI/FLC Animation" | ||||
|     _close_exclusive_fp_after_loading = False | ||||
|      | ||||
| 
 | ||||
|     def _open(self): | ||||
| 
 | ||||
|         # HEAD | ||||
|  | @ -49,6 +49,9 @@ class FliImageFile(ImageFile.ImageFile): | |||
|                 s[20:22] == b"\x00\x00"):  # reserved | ||||
|             raise SyntaxError("not an FLI/FLC file") | ||||
| 
 | ||||
|         # frames | ||||
|         self.__framecount = i16(s[6:8]) | ||||
| 
 | ||||
|         # image characteristics | ||||
|         self.mode = "P" | ||||
|         self.size = i16(s[8:10]), i16(s[10:12]) | ||||
|  | @ -56,7 +59,7 @@ class FliImageFile(ImageFile.ImageFile): | |||
|         # animation speed | ||||
|         duration = i32(s[16:20]) | ||||
|         if magic == 0xAF11: | ||||
|             duration = (duration * 1000) / 70 | ||||
|             duration = (duration * 1000) // 70 | ||||
|         self.info["duration"] = duration | ||||
| 
 | ||||
|         # look for palette | ||||
|  | @ -86,8 +89,6 @@ class FliImageFile(ImageFile.ImageFile): | |||
|         self.__frame = -1 | ||||
|         self.__fp = self.fp | ||||
|         self.__rewind = self.fp.tell() | ||||
|         self._n_frames = None | ||||
|         self._is_animated = None | ||||
|         self.seek(0) | ||||
| 
 | ||||
|     def _palette(self, palette, shift): | ||||
|  | @ -110,43 +111,22 @@ class FliImageFile(ImageFile.ImageFile): | |||
| 
 | ||||
|     @property | ||||
|     def n_frames(self): | ||||
|         if self._n_frames is None: | ||||
|             current = self.tell() | ||||
|             try: | ||||
|                 while True: | ||||
|                     self.seek(self.tell() + 1) | ||||
|             except EOFError: | ||||
|                 self._n_frames = self.tell() + 1 | ||||
|             self.seek(current) | ||||
|         return self._n_frames | ||||
|         return self.__framecount | ||||
| 
 | ||||
|     @property | ||||
|     def is_animated(self): | ||||
|         if self._is_animated is None: | ||||
|             current = self.tell() | ||||
| 
 | ||||
|             try: | ||||
|                 self.seek(1) | ||||
|                 self._is_animated = True | ||||
|             except EOFError: | ||||
|                 self._is_animated = False | ||||
| 
 | ||||
|             self.seek(current) | ||||
|         return self._is_animated | ||||
|         return self.__framecount > 1 | ||||
| 
 | ||||
|     def seek(self, frame): | ||||
|         if frame == self.__frame: | ||||
|             return | ||||
|         if frame < self.__frame: | ||||
|             self._seek(0) | ||||
|         if frame >= self.__framecount: | ||||
|             raise EOFError("no more images in FLI file") | ||||
| 
 | ||||
|         last_frame = self.__frame | ||||
|         for f in range(self.__frame + 1, frame + 1): | ||||
|             try: | ||||
|                 self._seek(f) | ||||
|             except EOFError: | ||||
|                 self.seek(last_frame) | ||||
|                 raise EOFError("no more images in FLI file") | ||||
|             self._seek(f) | ||||
| 
 | ||||
|     def _seek(self, frame): | ||||
|         if frame == 0: | ||||
|  | @ -176,6 +156,7 @@ class FliImageFile(ImageFile.ImageFile): | |||
|     def tell(self): | ||||
|         return self.__frame | ||||
| 
 | ||||
| 
 | ||||
| # | ||||
| # registry | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										34
									
								
								PIL/Image.py
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								PIL/Image.py
									
									
									
									
									
								
							|  | @ -56,8 +56,9 @@ try: | |||
|     from . import _imaging as core | ||||
|     if PILLOW_VERSION != getattr(core, 'PILLOW_VERSION', None): | ||||
|         raise ImportError("The _imaging extension was built for another " | ||||
|                           "version of Pillow or PIL: Core Version: %s" | ||||
|                           "Pillow Version:  %s" % | ||||
|                           "version of Pillow or PIL:\n" | ||||
|                           "Core version: %s\n" | ||||
|                           "Pillow version: %s" % | ||||
|                           (getattr(core, 'PILLOW_VERSION', None), | ||||
|                            PILLOW_VERSION)) | ||||
| 
 | ||||
|  | @ -1947,6 +1948,9 @@ class Image(object): | |||
|         containing a copy of one of the original bands (red, green, | ||||
|         blue). | ||||
| 
 | ||||
|         If you need only one band, :py:meth:`~PIL.Image.Image.getchannel` | ||||
|         method can be more convenient and faster. | ||||
| 
 | ||||
|         :returns: A tuple containing bands. | ||||
|         """ | ||||
| 
 | ||||
|  | @ -1954,11 +1958,31 @@ class Image(object): | |||
|         if self.im.bands == 1: | ||||
|             ims = [self.copy()] | ||||
|         else: | ||||
|             ims = [] | ||||
|             for i in range(self.im.bands): | ||||
|                 ims.append(self._new(self.im.getband(i))) | ||||
|             ims = map(self._new, self.im.split()) | ||||
|         return tuple(ims) | ||||
| 
 | ||||
|     def getchannel(self, channel): | ||||
|         """ | ||||
|         Returns an image containing a single channel of the source image. | ||||
| 
 | ||||
|         :param channel: What channel to return. Could be index | ||||
|           (0 for "R" channel of "RGB") or channel name | ||||
|           ("A" for alpha channel of "RGBA"). | ||||
|         :returns: An image in "L" mode. | ||||
| 
 | ||||
|         .. versionadded:: 4.3.0 | ||||
|         """ | ||||
|         self.load() | ||||
| 
 | ||||
|         if isStringType(channel): | ||||
|             try: | ||||
|                 channel = self.getbands().index(channel) | ||||
|             except ValueError: | ||||
|                 raise ValueError( | ||||
|                     'The image has no channel "{}"'.format(channel)) | ||||
| 
 | ||||
|         return self._new(self.im.getband(channel)) | ||||
| 
 | ||||
|     def tell(self): | ||||
|         """ | ||||
|         Returns the current frame number. See :py:meth:`~PIL.Image.Image.seek`. | ||||
|  |  | |||
|  | @ -67,7 +67,7 @@ class Contrast(_Enhance): | |||
|         self.degenerate = Image.new("L", image.size, mean).convert(image.mode) | ||||
| 
 | ||||
|         if 'A' in image.getbands(): | ||||
|             self.degenerate.putalpha(image.split()[-1]) | ||||
|             self.degenerate.putalpha(image.getchannel('A')) | ||||
| 
 | ||||
| 
 | ||||
| class Brightness(_Enhance): | ||||
|  | @ -82,7 +82,7 @@ class Brightness(_Enhance): | |||
|         self.degenerate = Image.new(image.mode, image.size, 0) | ||||
| 
 | ||||
|         if 'A' in image.getbands(): | ||||
|             self.degenerate.putalpha(image.split()[-1]) | ||||
|             self.degenerate.putalpha(image.getchannel('A')) | ||||
| 
 | ||||
| 
 | ||||
| class Sharpness(_Enhance): | ||||
|  | @ -97,4 +97,4 @@ class Sharpness(_Enhance): | |||
|         self.degenerate = image.filter(ImageFilter.SMOOTH) | ||||
| 
 | ||||
|         if 'A' in image.getbands(): | ||||
|             self.degenerate.putalpha(image.split()[-1]) | ||||
|             self.degenerate.putalpha(image.getchannel('A')) | ||||
|  |  | |||
|  | @ -36,6 +36,7 @@ class _imagingft_not_installed(object): | |||
|     def __getattr__(self, id): | ||||
|         raise ImportError("The _imagingft C module is not installed") | ||||
| 
 | ||||
| 
 | ||||
| try: | ||||
|     from . import _imagingft as core | ||||
| except ImportError: | ||||
|  | @ -113,7 +114,6 @@ class ImageFont(object): | |||
|         return self.font.getmask(text, mode) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ## | ||||
| # Wrapper for FreeType fonts.  Application code should use the | ||||
| # <b>truetype</b> factory function to create font objects. | ||||
|  | @ -162,7 +162,7 @@ class FreeTypeFont(object): | |||
|     def getmask(self, text, mode="", direction=None, features=None): | ||||
|         return self.getmask2(text, mode, direction=direction, features=features)[0] | ||||
| 
 | ||||
|     def getmask2(self, text, mode="", fill=Image.core.fill, direction=None, features=None): | ||||
|     def getmask2(self, text, mode="", fill=Image.core.fill, direction=None, features=None, *args, **kwargs): | ||||
|         size, offset = self.font.getsize(text, direction, features) | ||||
|         im = fill("L", size, 0) | ||||
|         self.font.render(text, im.id, mode == "1", direction, features) | ||||
|  | @ -250,7 +250,7 @@ def truetype(font=None, size=10, index=0, encoding="", | |||
|                      and "armn" (Apple Roman). See the FreeType documentation | ||||
|                      for more information. | ||||
|     :param layout_engine: Which layout engine to use, if available: | ||||
|                      `ImageFont.LAYOUT_BASIC` or `ImageFont.LAYOUT_RAQM`.                   | ||||
|                      `ImageFont.LAYOUT_BASIC` or `ImageFont.LAYOUT_RAQM`. | ||||
|     :return: A font object. | ||||
|     :exception IOError: If the file could not be read. | ||||
|     """ | ||||
|  |  | |||
|  | @ -131,9 +131,10 @@ def APP(self, marker): | |||
|                 # 1 dpcm = 2.54 dpi | ||||
|                 dpi *= 2.54 | ||||
|             self.info["dpi"] = dpi, dpi | ||||
|         except (KeyError, SyntaxError): | ||||
|         except (KeyError, SyntaxError, ZeroDivisionError): | ||||
|             # SyntaxError for invalid/unreadable exif | ||||
|             # KeyError for dpi not included | ||||
|             # ZeroDivisionError for invalid dpi rational value | ||||
|             self.info["dpi"] = 72, 72 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -104,6 +104,11 @@ def _save(im, fp, filename): | |||
|     z = len(im.mode) | ||||
|     if dim == 1 or dim == 2: | ||||
|         z = 1 | ||||
|     # assert we've got the right number of bands. | ||||
|     if len(im.getbands()) != z: | ||||
|         raise ValueError("incorrect number of bands in SGI write: %s vs %s" % | ||||
|                          (z, len(im.getbands()))) | ||||
| 
 | ||||
|     # Minimum Byte value | ||||
|     pinmin = 0 | ||||
|     # Maximum Byte value (255 = 8bits per pixel) | ||||
|  | @ -131,11 +136,6 @@ def _save(im, fp, filename): | |||
| 
 | ||||
|     fp.write(struct.pack('404s', b''))  # dummy | ||||
| 
 | ||||
|     # assert we've got the right number of bands. | ||||
|     if len(im.getbands()) != z: | ||||
|         raise ValueError("incorrect number of bands in SGI write: %s vs %s" % | ||||
|                          (z, len(im.getbands()))) | ||||
| 
 | ||||
|     for channel in im.split(): | ||||
|         fp.write(channel.tobytes()) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										
											BIN
										
									
								
								Tests/images/a.fli
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Tests/images/a.fli
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Tests/images/exif-dpi-zerodivision.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Tests/images/exif-dpi-zerodivision.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 11 KiB | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/hopper_emboss.bmp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Tests/images/hopper_emboss.bmp
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 48 KiB | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/hopper_emboss_more.bmp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Tests/images/hopper_emboss_more.bmp
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 48 KiB | 
|  | @ -4,17 +4,38 @@ from PIL import Image, FliImagePlugin | |||
| 
 | ||||
| # created as an export of a palette image from Gimp2.6 | ||||
| # save as...-> hopper.fli, default options. | ||||
| test_file = "Tests/images/hopper.fli" | ||||
| static_test_file = "Tests/images/hopper.fli" | ||||
| 
 | ||||
| # From https://samples.libav.org/fli-flc/ | ||||
| animated_test_file = "Tests/images/a.fli" | ||||
| 
 | ||||
| 
 | ||||
| class TestFileFli(PillowTestCase): | ||||
| 
 | ||||
|     def test_sanity(self): | ||||
|         im = Image.open(test_file) | ||||
|         im = Image.open(static_test_file) | ||||
|         im.load() | ||||
|         self.assertEqual(im.mode, "P") | ||||
|         self.assertEqual(im.size, (128, 128)) | ||||
|         self.assertEqual(im.format, "FLI") | ||||
|         self.assertFalse(im.is_animated) | ||||
| 
 | ||||
|         im = Image.open(animated_test_file) | ||||
|         self.assertEqual(im.mode, "P") | ||||
|         self.assertEqual(im.size, (320, 200)) | ||||
|         self.assertEqual(im.format, "FLI") | ||||
|         self.assertEqual(im.info["duration"], 71) | ||||
|         self.assertTrue(im.is_animated) | ||||
| 
 | ||||
|     def test_tell(self): | ||||
|         # Arrange | ||||
|         im = Image.open(static_test_file) | ||||
| 
 | ||||
|         # Act | ||||
|         frame = im.tell() | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(frame, 0) | ||||
| 
 | ||||
|     def test_invalid_file(self): | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
|  | @ -23,12 +44,16 @@ class TestFileFli(PillowTestCase): | |||
|                           lambda: FliImagePlugin.FliImageFile(invalid_file)) | ||||
| 
 | ||||
|     def test_n_frames(self): | ||||
|         im = Image.open(test_file) | ||||
|         im = Image.open(static_test_file) | ||||
|         self.assertEqual(im.n_frames, 1) | ||||
|         self.assertFalse(im.is_animated) | ||||
| 
 | ||||
|         im = Image.open(animated_test_file) | ||||
|         self.assertEqual(im.n_frames, 384) | ||||
|         self.assertTrue(im.is_animated) | ||||
| 
 | ||||
|     def test_eoferror(self): | ||||
|         im = Image.open(test_file) | ||||
|         im = Image.open(animated_test_file) | ||||
| 
 | ||||
|         n_frames = im.n_frames | ||||
|         while True: | ||||
|  | @ -39,6 +64,33 @@ class TestFileFli(PillowTestCase): | |||
|             except EOFError: | ||||
|                 self.assertLess(im.tell(), n_frames) | ||||
| 
 | ||||
|     def test_seek_outside(self): | ||||
|         # Test negative seek | ||||
|         im = Image.open(static_test_file) | ||||
|         im.seek(-1) | ||||
|         self.assertEqual(im.tell(), 0) | ||||
| 
 | ||||
|         # Test seek past end of file | ||||
|         self.assertRaises(EOFError, lambda: im.seek(2)) | ||||
| 
 | ||||
|     def test_seek_tell(self): | ||||
|         im = Image.open(animated_test_file) | ||||
| 
 | ||||
|         layer_number = im.tell() | ||||
|         self.assertEqual(layer_number, 0) | ||||
| 
 | ||||
|         im.seek(0) | ||||
|         layer_number = im.tell() | ||||
|         self.assertEqual(layer_number, 0) | ||||
| 
 | ||||
|         im.seek(1) | ||||
|         layer_number = im.tell() | ||||
|         self.assertEqual(layer_number, 1) | ||||
| 
 | ||||
|         im.seek(2) | ||||
|         layer_number = im.tell() | ||||
|         self.assertEqual(layer_number, 2) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     unittest.main() | ||||
|  |  | |||
|  | @ -15,6 +15,16 @@ class TestFileIm(PillowTestCase): | |||
|         self.assertEqual(im.size, (128, 128)) | ||||
|         self.assertEqual(im.format, "IM") | ||||
| 
 | ||||
|     def test_tell(self): | ||||
|         # Arrange | ||||
|         im = Image.open(TEST_IM) | ||||
| 
 | ||||
|         # Act | ||||
|         frame = im.tell() | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(frame, 0) | ||||
| 
 | ||||
|     def test_n_frames(self): | ||||
|         im = Image.open(TEST_IM) | ||||
|         self.assertEqual(im.n_frames, 1) | ||||
|  |  | |||
|  | @ -535,6 +535,16 @@ class TestFileJpeg(PillowTestCase): | |||
|         # Act / Assert | ||||
|         self.assertEqual(im.info.get("dpi"), (508, 508)) | ||||
| 
 | ||||
|     def test_dpi_exif_zero_division(self): | ||||
|         # Arrange | ||||
|         # This is photoshop-200dpi.jpg with EXIF resolution set to 0/0: | ||||
|         # exiftool -XResolution=0/0 -YResolution=0/0 photoshop-200dpi.jpg | ||||
|         im = Image.open("Tests/images/exif-dpi-zerodivision.jpg") | ||||
| 
 | ||||
|         # Act / Assert | ||||
|         # This should return the default, and not raise a ZeroDivisionError | ||||
|         self.assertEqual(im.info.get("dpi"), (72, 72)) | ||||
| 
 | ||||
|     def test_no_dpi_in_exif(self): | ||||
|         # Arrange | ||||
|         # This is photoshop-200dpi.jpg with resolution removed from EXIF: | ||||
|  |  | |||
|  | @ -200,7 +200,7 @@ class TestFilePng(PillowTestCase): | |||
|         self.assert_image(im, "RGBA", (162, 150)) | ||||
| 
 | ||||
|         # image has 124 unique alpha values | ||||
|         self.assertEqual(len(im.split()[3].getcolors()), 124) | ||||
|         self.assertEqual(len(im.getchannel('A').getcolors()), 124) | ||||
| 
 | ||||
|     def test_load_transparent_rgb(self): | ||||
|         test_file = "Tests/images/rgb_trns.png" | ||||
|  | @ -212,7 +212,7 @@ class TestFilePng(PillowTestCase): | |||
|         self.assert_image(im, "RGBA", (64, 64)) | ||||
| 
 | ||||
|         # image has 876 transparent pixels | ||||
|         self.assertEqual(im.split()[3].getcolors()[0][0], 876) | ||||
|         self.assertEqual(im.getchannel('A').getcolors()[0][0], 876) | ||||
| 
 | ||||
|     def test_save_p_transparent_palette(self): | ||||
|         in_file = "Tests/images/pil123p.png" | ||||
|  | @ -234,7 +234,7 @@ class TestFilePng(PillowTestCase): | |||
|         self.assert_image(im, "RGBA", (162, 150)) | ||||
| 
 | ||||
|         # image has 124 unique alpha values | ||||
|         self.assertEqual(len(im.split()[3].getcolors()), 124) | ||||
|         self.assertEqual(len(im.getchannel('A').getcolors()), 124) | ||||
| 
 | ||||
|     def test_save_p_single_transparency(self): | ||||
|         in_file = "Tests/images/p_trns_single.png" | ||||
|  | @ -258,7 +258,7 @@ class TestFilePng(PillowTestCase): | |||
|         self.assertEqual(im.getpixel((31, 31)), (0, 255, 52, 0)) | ||||
| 
 | ||||
|         # image has 876 transparent pixels | ||||
|         self.assertEqual(im.split()[3].getcolors()[0][0], 876) | ||||
|         self.assertEqual(im.getchannel('A').getcolors()[0][0], 876) | ||||
| 
 | ||||
|     def test_save_p_transparent_black(self): | ||||
|         # check if solid black image with full transparency | ||||
|  | @ -287,7 +287,7 @@ class TestFilePng(PillowTestCase): | |||
| 
 | ||||
|         # There are 559 transparent pixels. | ||||
|         im = im.convert('RGBA') | ||||
|         self.assertEqual(im.split()[3].getcolors()[0][0], 559) | ||||
|         self.assertEqual(im.getchannel('A').getcolors()[0][0], 559) | ||||
| 
 | ||||
|     def test_save_rgb_single_transparency(self): | ||||
|         in_file = "Tests/images/caption_6_33_22.png" | ||||
|  | @ -550,7 +550,7 @@ class TestTruncatedPngPLeaks(PillowTestCase): | |||
|             # linux | ||||
|             # man 2 getrusage | ||||
|             #        ru_maxrss (since Linux 2.6.32) | ||||
|             #  This is the maximum resident set size used (in  kilobytes).  | ||||
|             #  This is the maximum resident set size used (in  kilobytes). | ||||
|             return mem / 1024 # megs | ||||
| 
 | ||||
|     def test_leak_load(self): | ||||
|  |  | |||
|  | @ -55,6 +55,22 @@ class TestFileSgi(PillowTestCase): | |||
|         for mode in ('L', 'RGB', 'RGBA'): | ||||
|             roundtrip(hopper(mode)) | ||||
| 
 | ||||
|         # Test 1 dimension for an L mode image | ||||
|         roundtrip(Image.new('L', (10, 1))) | ||||
| 
 | ||||
|     def test_unsupported_mode(self): | ||||
|         im = hopper('LA') | ||||
|         out = self.tempfile('temp.sgi') | ||||
| 
 | ||||
|         self.assertRaises(ValueError, lambda: im.save(out, format='sgi')) | ||||
| 
 | ||||
|     def test_incorrect_number_of_bands(self): | ||||
|         im = hopper('YCbCr') | ||||
|         im.mode = 'RGB' | ||||
|         out = self.tempfile('temp.sgi') | ||||
| 
 | ||||
|         self.assertRaises(ValueError, lambda: im.save(out, format='sgi')) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     unittest.main() | ||||
|  |  | |||
|  | @ -103,11 +103,11 @@ class TestFormatHSV(PillowTestCase): | |||
|         # im.split()[0].show() | ||||
|         # comparable.split()[0].show() | ||||
| 
 | ||||
|         self.assert_image_similar(im.split()[0], comparable.split()[0], | ||||
|         self.assert_image_similar(im.getchannel(0), comparable.getchannel(0), | ||||
|                                   1, "Hue conversion is wrong") | ||||
|         self.assert_image_similar(im.split()[1], comparable.split()[1], | ||||
|         self.assert_image_similar(im.getchannel(1), comparable.getchannel(1), | ||||
|                                   1, "Saturation conversion is wrong") | ||||
|         self.assert_image_similar(im.split()[2], comparable.split()[2], | ||||
|         self.assert_image_similar(im.getchannel(2), comparable.getchannel(2), | ||||
|                                   1, "Value conversion is wrong") | ||||
| 
 | ||||
|         # print(im.getpixel((192, 64))) | ||||
|  | @ -120,11 +120,11 @@ class TestFormatHSV(PillowTestCase): | |||
|         # print(im.getpixel((192, 64))) | ||||
|         # print(comparable.getpixel((192, 64))) | ||||
| 
 | ||||
|         self.assert_image_similar(im.split()[0], comparable.split()[0], | ||||
|         self.assert_image_similar(im.getchannel(0), comparable.getchannel(0), | ||||
|                                   3, "R conversion is wrong") | ||||
|         self.assert_image_similar(im.split()[1], comparable.split()[1], | ||||
|         self.assert_image_similar(im.getchannel(1), comparable.getchannel(1), | ||||
|                                   3, "G conversion is wrong") | ||||
|         self.assert_image_similar(im.split()[2], comparable.split()[2], | ||||
|         self.assert_image_similar(im.getchannel(2), comparable.getchannel(2), | ||||
|                                   3, "B conversion is wrong") | ||||
| 
 | ||||
|     def test_convert(self): | ||||
|  | @ -137,11 +137,11 @@ class TestFormatHSV(PillowTestCase): | |||
| #        print(im.split()[0].histogram()) | ||||
| #        print(comparable.split()[0].histogram()) | ||||
| 
 | ||||
|         self.assert_image_similar(im.split()[0], comparable.split()[0], | ||||
|         self.assert_image_similar(im.getchannel(0), comparable.getchannel(0), | ||||
|                                   1, "Hue conversion is wrong") | ||||
|         self.assert_image_similar(im.split()[1], comparable.split()[1], | ||||
|         self.assert_image_similar(im.getchannel(1), comparable.getchannel(1), | ||||
|                                   1, "Saturation conversion is wrong") | ||||
|         self.assert_image_similar(im.split()[2], comparable.split()[2], | ||||
|         self.assert_image_similar(im.getchannel(2), comparable.getchannel(2), | ||||
|                                   1, "Value conversion is wrong") | ||||
| 
 | ||||
|     def test_hsv_to_rgb(self): | ||||
|  | @ -155,11 +155,14 @@ class TestFormatHSV(PillowTestCase): | |||
|         # print([ord(x) for x  in target.split()[1].tobytes()[:80]]) | ||||
|         # print([ord(x) for x  in converted.split()[1].tobytes()[:80]]) | ||||
| 
 | ||||
|         self.assert_image_similar(converted.split()[0], comparable.split()[0], | ||||
|         self.assert_image_similar(converted.getchannel(0), | ||||
|                                   comparable.getchannel(0), | ||||
|                                   3, "R conversion is wrong") | ||||
|         self.assert_image_similar(converted.split()[1], comparable.split()[1], | ||||
|         self.assert_image_similar(converted.getchannel(1), | ||||
|                                   comparable.getchannel(1), | ||||
|                                   3, "G conversion is wrong") | ||||
|         self.assert_image_similar(converted.split()[2], comparable.split()[2], | ||||
|         self.assert_image_similar(converted.getchannel(2), | ||||
|                                   comparable.getchannel(2), | ||||
|                                   3, "B conversion is wrong") | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,6 +7,25 @@ import sys | |||
| 
 | ||||
| class TestImage(PillowTestCase): | ||||
| 
 | ||||
|     def test_image_modes_success(self): | ||||
|         for mode in [ | ||||
|             '1', 'P', 'PA', | ||||
|             'L', 'LA', 'La', | ||||
|             'F', 'I', 'I;16', 'I;16L', 'I;16B', 'I;16N', | ||||
|             'RGB', 'RGBX', 'RGBA', 'RGBa', | ||||
|             'CMYK', 'YCbCr', 'LAB', 'HSV', | ||||
|         ]: | ||||
|             Image.new(mode, (1, 1)) | ||||
| 
 | ||||
|     def test_image_modes_fail(self): | ||||
|         for mode in [ | ||||
|             '', 'bad', 'very very long', | ||||
|             'BGR;15', 'BGR;16', 'BGR;24', 'BGR;32' | ||||
|         ]: | ||||
|             with self.assertRaises(ValueError) as e: | ||||
|                 Image.new(mode, (1, 1)); | ||||
|             self.assertEqual(str(e.exception), 'unrecognized image mode') | ||||
| 
 | ||||
|     def test_sanity(self): | ||||
| 
 | ||||
|         im = Image.new("L", (100, 100)) | ||||
|  | @ -145,14 +164,28 @@ class TestImage(PillowTestCase): | |||
|         self.assertEqual(im.size[1], orig_size[1] + 2*ymargin) | ||||
| 
 | ||||
|     def test_getbands(self): | ||||
|         # Arrange | ||||
|         # Assert | ||||
|         self.assertEqual(hopper('RGB').getbands(), ('R', 'G', 'B')) | ||||
|         self.assertEqual(hopper('YCbCr').getbands(), ('Y', 'Cb', 'Cr')) | ||||
| 
 | ||||
|     def test_getchannel_wrong_params(self): | ||||
|         im = hopper() | ||||
| 
 | ||||
|         # Act | ||||
|         bands = im.getbands() | ||||
|         self.assertRaises(ValueError, im.getchannel, -1) | ||||
|         self.assertRaises(ValueError, im.getchannel, 3) | ||||
|         self.assertRaises(ValueError, im.getchannel, 'Z') | ||||
|         self.assertRaises(ValueError, im.getchannel, '1') | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(bands, ('R', 'G', 'B')) | ||||
|     def test_getchannel(self): | ||||
|         im = hopper('YCbCr') | ||||
|         Y, Cb, Cr = im.split() | ||||
| 
 | ||||
|         self.assert_image_equal(Y, im.getchannel(0)) | ||||
|         self.assert_image_equal(Y, im.getchannel('Y')) | ||||
|         self.assert_image_equal(Cb, im.getchannel(1)) | ||||
|         self.assert_image_equal(Cb, im.getchannel('Cb')) | ||||
|         self.assert_image_equal(Cr, im.getchannel(2)) | ||||
|         self.assert_image_equal(Cr, im.getchannel('Cr')) | ||||
| 
 | ||||
|     def test_getbbox(self): | ||||
|         # Arrange | ||||
|  |  | |||
|  | @ -133,7 +133,7 @@ class TestImageConvert(PillowTestCase): | |||
|         alpha = hopper('L') | ||||
|         im.putalpha(alpha) | ||||
| 
 | ||||
|         comparable = im.convert('P').convert('LA').split()[1] | ||||
|         comparable = im.convert('P').convert('LA').getchannel('A') | ||||
| 
 | ||||
|         self.assert_image_similar(alpha, comparable, 5) | ||||
| 
 | ||||
|  | @ -185,7 +185,7 @@ class TestImageConvert(PillowTestCase): | |||
|             if converted_im.mode == 'RGB': | ||||
|                 self.assert_image_similar(converted_im, target, 3) | ||||
|             else: | ||||
|                 self.assert_image_similar(converted_im, target.split()[0], 1) | ||||
|                 self.assert_image_similar(converted_im, target.getchannel(0), 1) | ||||
| 
 | ||||
|         matrix_convert('RGB') | ||||
|         matrix_convert('L') | ||||
|  |  | |||
|  | @ -94,6 +94,28 @@ class TestImageFilter(PillowTestCase): | |||
|         self.assertEqual(rankfilter.size, 1) | ||||
|         self.assertEqual(rankfilter.rank, 2) | ||||
| 
 | ||||
|     def test_consistency_3x3(self): | ||||
|         im = Image.open("Tests/images/hopper.bmp") | ||||
|         emboss = im.filter(ImageFilter.Kernel((3, 3), | ||||
|             (-1, -1,  0, | ||||
|              -1,  0,  1, | ||||
|               0,  1,  1), .3)) | ||||
| 
 | ||||
|         self.assert_image_equal( | ||||
|             emboss, Image.open("Tests/images/hopper_emboss.bmp")) | ||||
| 
 | ||||
|     def test_consistency_5x5(self): | ||||
|         im = Image.open("Tests/images/hopper.bmp") | ||||
|         emboss = im.filter(ImageFilter.Kernel((5, 5), | ||||
|             (-1, -1, -1, -1,  0, | ||||
|              -1, -1, -1,  0,  1, | ||||
|              -1, -1,  0,  1,  1, | ||||
|              -1,  0,  1,  1,  1, | ||||
|               0,  1,  1,  1,  1), 0.3)) | ||||
| 
 | ||||
|         self.assert_image_equal( | ||||
|             emboss, Image.open("Tests/images/hopper_emboss_more.bmp")) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     unittest.main() | ||||
|  |  | |||
|  | @ -360,8 +360,7 @@ class TestImageCms(PillowTestCase): | |||
|             return Image.merge(mode, chans) | ||||
| 
 | ||||
|         source_image = create_test_image() | ||||
|         preserved_channel_ndx = source_image.getbands().index(preserved_channel) | ||||
|         source_image_aux = source_image.split()[preserved_channel_ndx] | ||||
|         source_image_aux = source_image.getchannel(preserved_channel) | ||||
| 
 | ||||
|         # create some transform, it doesn't matter which one | ||||
|         source_profile = ImageCms.createProfile("sRGB") | ||||
|  | @ -374,7 +373,7 @@ class TestImageCms(PillowTestCase): | |||
|             result_image = source_image | ||||
|         else: | ||||
|             result_image = ImageCms.applyTransform(source_image, t, inPlace=False) | ||||
|         result_image_aux = result_image.split()[preserved_channel_ndx] | ||||
|         result_image_aux = result_image.getchannel(preserved_channel) | ||||
| 
 | ||||
|         self.assert_image_equal(source_image_aux, result_image_aux) | ||||
| 
 | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ class TestImageEnhance(PillowTestCase): | |||
| 
 | ||||
|     def _check_alpha(self, im, original, op, amount): | ||||
|         self.assertEqual(im.getbands(), original.getbands()) | ||||
|         self.assert_image_equal(im.split()[-1], original.split()[-1], | ||||
|         self.assert_image_equal(im.getchannel('A'), original.getchannel('A'), | ||||
|                                 "Diff on %s: %s" % (op, amount)) | ||||
| 
 | ||||
|     def test_alpha(self): | ||||
|  |  | |||
|  | @ -40,13 +40,15 @@ class SimplePatcher(object): | |||
|         else: | ||||
|             delattr(self._parent_obj, self._attr_name) | ||||
| 
 | ||||
| 
 | ||||
| @unittest.skipUnless(HAS_FREETYPE, "ImageFont not Available") | ||||
| class TestImageFont(PillowTestCase): | ||||
|     LAYOUT_ENGINE = ImageFont.LAYOUT_BASIC | ||||
| 
 | ||||
|     # Freetype has different metrics depending on the version. | ||||
|     # (and, other things, but first things first) | ||||
|     METRICS = { ('2', '3'): {'multiline': 30, | ||||
|     METRICS = { | ||||
|                 ('2', '3'): {'multiline': 30, | ||||
|                              'textsize': 12, | ||||
|                              'getters': (13, 16)}, | ||||
|                 ('2', '7'): {'multiline': 6.2, | ||||
|  | @ -213,6 +215,14 @@ class TestImageFont(PillowTestCase): | |||
|                                                       font=ttf, | ||||
|                                                       align="unknown")) | ||||
| 
 | ||||
|     def test_draw_align(self): | ||||
|         im = Image.new('RGB', (300, 100), 'white') | ||||
|         draw = ImageDraw.Draw(im) | ||||
|         ttf = self.get_font() | ||||
|         line = "some text" | ||||
|         draw.text((100, 40), line, (0, 0, 0), font=ttf, align='left') | ||||
|         del draw | ||||
| 
 | ||||
|     def test_multiline_size(self): | ||||
|         ttf = self.get_font() | ||||
|         im = Image.new(mode='RGB', size=(300, 100)) | ||||
|  | @ -395,7 +405,7 @@ class TestImageFont(PillowTestCase): | |||
| 
 | ||||
|     def test_getsize_empty(self): | ||||
|         font = self.get_font() | ||||
|         # should not crash.  | ||||
|         # should not crash. | ||||
|         self.assertEqual((0, 0), font.getsize('')) | ||||
| 
 | ||||
|     def _test_fake_loading_font(self, path_to_fake, fontname): | ||||
|  | @ -494,5 +504,6 @@ class TestImageFont(PillowTestCase): | |||
| class TestImageFont_RaqmLayout(TestImageFont): | ||||
|     LAYOUT_ENGINE = ImageFont.LAYOUT_RAQM | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     unittest.main() | ||||
|  |  | |||
|  | @ -52,7 +52,7 @@ class TestNumpy(PillowTestCase): | |||
|                 a = numpy.array([[x]*bands for x in data], dtype=dtype) | ||||
|                 a.shape = TEST_IMAGE_SIZE[0], TEST_IMAGE_SIZE[1], bands | ||||
|                 i = Image.fromarray(a) | ||||
|                 if list(i.split()[0].getdata()) != list(range(100)): | ||||
|                 if list(i.getchannel(0).getdata()) != list(range(100)): | ||||
|                     print("data mismatch for", dtype) | ||||
|             # print(dtype, list(i.getdata())) | ||||
|             return i | ||||
|  |  | |||
							
								
								
									
										60
									
								
								_imaging.c
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								_imaging.c
									
									
									
									
									
								
							|  | @ -599,7 +599,7 @@ _fill(PyObject* self, PyObject* args) | |||
|     if (!PyArg_ParseTuple(args, "s|(ii)O", &mode, &xsize, &ysize, &color)) | ||||
|         return NULL; | ||||
| 
 | ||||
|     im = ImagingNew(mode, xsize, ysize); | ||||
|     im = ImagingNewDirty(mode, xsize, ysize); | ||||
|     if (!im) | ||||
|         return NULL; | ||||
| 
 | ||||
|  | @ -791,23 +791,6 @@ _copy(ImagingObject* self, PyObject* args) | |||
|     return PyImagingNew(ImagingCopy(self->image)); | ||||
| } | ||||
| 
 | ||||
| static PyObject* | ||||
| _copy2(ImagingObject* self, PyObject* args) | ||||
| { | ||||
|     ImagingObject* imagep1; | ||||
|     ImagingObject* imagep2; | ||||
|     if (!PyArg_ParseTuple(args, "O!O!", | ||||
|                           &Imaging_Type, &imagep1, | ||||
|                           &Imaging_Type, &imagep2)) | ||||
|         return NULL; | ||||
| 
 | ||||
|     if (!ImagingCopy2(imagep1->image, imagep2->image)) | ||||
|         return NULL; | ||||
| 
 | ||||
|     Py_INCREF(Py_None); | ||||
|     return Py_None; | ||||
| } | ||||
| 
 | ||||
| static PyObject* | ||||
| _crop(ImagingObject* self, PyObject* args) | ||||
| { | ||||
|  | @ -874,7 +857,7 @@ _gaussian_blur(ImagingObject* self, PyObject* args) | |||
|         return NULL; | ||||
| 
 | ||||
|     imIn = self->image; | ||||
|     imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize); | ||||
|     imOut = ImagingNewDirty(imIn->mode, imIn->xsize, imIn->ysize); | ||||
|     if (!imOut) | ||||
|         return NULL; | ||||
| 
 | ||||
|  | @ -1539,7 +1522,7 @@ _resize(ImagingObject* self, PyObject* args) | |||
|         a[0] = (double) imIn->xsize / xsize; | ||||
|         a[4] = (double) imIn->ysize / ysize; | ||||
| 
 | ||||
|         imOut = ImagingNew(imIn->mode, xsize, ysize); | ||||
|         imOut = ImagingNewDirty(imIn->mode, xsize, ysize); | ||||
| 
 | ||||
|         imOut = ImagingTransform( | ||||
|             imOut, imIn, IMAGING_TRANSFORM_AFFINE, | ||||
|  | @ -1665,12 +1648,12 @@ _transpose(ImagingObject* self, PyObject* args) | |||
|     case 0: /* flip left right */ | ||||
|     case 1: /* flip top bottom */ | ||||
|     case 3: /* rotate 180 */ | ||||
|         imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize); | ||||
|         imOut = ImagingNewDirty(imIn->mode, imIn->xsize, imIn->ysize); | ||||
|         break; | ||||
|     case 2: /* rotate 90 */ | ||||
|     case 4: /* rotate 270 */ | ||||
|     case 5: /* transpose */ | ||||
|         imOut = ImagingNew(imIn->mode, imIn->ysize, imIn->xsize); | ||||
|         imOut = ImagingNewDirty(imIn->mode, imIn->ysize, imIn->xsize); | ||||
|         break; | ||||
|     default: | ||||
|         PyErr_SetString(PyExc_ValueError, "No such transpose operation"); | ||||
|  | @ -1715,7 +1698,7 @@ _unsharp_mask(ImagingObject* self, PyObject* args) | |||
|         return NULL; | ||||
| 
 | ||||
|     imIn = self->image; | ||||
|     imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize); | ||||
|     imOut = ImagingNewDirty(imIn->mode, imIn->xsize, imIn->ysize); | ||||
|     if (!imOut) | ||||
|         return NULL; | ||||
| 
 | ||||
|  | @ -1738,7 +1721,7 @@ _box_blur(ImagingObject* self, PyObject* args) | |||
|         return NULL; | ||||
| 
 | ||||
|     imIn = self->image; | ||||
|     imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize); | ||||
|     imOut = ImagingNewDirty(imIn->mode, imIn->xsize, imIn->ysize); | ||||
|     if (!imOut) | ||||
|         return NULL; | ||||
| 
 | ||||
|  | @ -1928,6 +1911,32 @@ _merge(PyObject* self, PyObject* args) | |||
|     return PyImagingNew(ImagingMerge(mode, bands)); | ||||
| } | ||||
| 
 | ||||
| static PyObject* | ||||
| _split(ImagingObject* self, PyObject* args) | ||||
| { | ||||
|     int fails = 0; | ||||
|     Py_ssize_t i; | ||||
|     PyObject* list; | ||||
|     PyObject* imaging_object; | ||||
|     Imaging bands[4] = {NULL, NULL, NULL, NULL}; | ||||
| 
 | ||||
|     if ( ! ImagingSplit(self->image, bands)) | ||||
|         return NULL; | ||||
| 
 | ||||
|     list = PyTuple_New(self->image->bands); | ||||
|     for (i = 0; i < self->image->bands; i++) { | ||||
|         imaging_object = PyImagingNew(bands[i]); | ||||
|         if ( ! imaging_object) | ||||
|             fails += 1; | ||||
|         PyTuple_SET_ITEM(list, i, imaging_object); | ||||
|     } | ||||
|     if (fails) { | ||||
|         Py_DECREF(list); | ||||
|         list = NULL; | ||||
|     } | ||||
|     return list; | ||||
| } | ||||
| 
 | ||||
| /* -------------------------------------------------------------------- */ | ||||
| 
 | ||||
| #ifdef WITH_IMAGECHOPS | ||||
|  | @ -2963,7 +2972,6 @@ static struct PyMethodDef methods[] = { | |||
|     {"convert_matrix", (PyCFunction)_convert_matrix, 1}, | ||||
|     {"convert_transparent", (PyCFunction)_convert_transparent, 1}, | ||||
|     {"copy", (PyCFunction)_copy, 1}, | ||||
|     {"copy2", (PyCFunction)_copy2, 1}, | ||||
|     {"crop", (PyCFunction)_crop, 1}, | ||||
|     {"expand", (PyCFunction)_expand_image, 1}, | ||||
|     {"filter", (PyCFunction)_filter, 1}, | ||||
|  | @ -2995,6 +3003,7 @@ static struct PyMethodDef methods[] = { | |||
| 
 | ||||
|     {"getband", (PyCFunction)_getband, 1}, | ||||
|     {"putband", (PyCFunction)_putband, 1}, | ||||
|     {"split", (PyCFunction)_split, 1}, | ||||
|     {"fillband", (PyCFunction)_fillband, 1}, | ||||
| 
 | ||||
|     {"setmode", (PyCFunction)im_setmode, 1}, | ||||
|  | @ -3345,7 +3354,6 @@ static PyMethodDef functions[] = { | |||
| 
 | ||||
|     /* Functions */ | ||||
|     {"convert", (PyCFunction)_convert2, 1}, | ||||
|     {"copy", (PyCFunction)_copy2, 1}, | ||||
| 
 | ||||
|     /* Codecs */ | ||||
|     {"bcn_decoder", (PyCFunction)PyImaging_BcnDecoderNew, 1}, | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| #!/bin/bash | ||||
| # install libimagequant | ||||
| 
 | ||||
| archive=libimagequant-2.10.1 | ||||
| archive=libimagequant-2.10.2 | ||||
| 
 | ||||
| ./download-and-extract.sh $archive https://raw.githubusercontent.com/python-pillow/pillow-depends/master/$archive.tar.gz | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| #!/bin/bash | ||||
| # install openjpeg | ||||
| 
 | ||||
| archive=openjpeg-2.1.2 | ||||
| archive=openjpeg-2.2.0 | ||||
| 
 | ||||
| ./download-and-extract.sh $archive https://raw.githubusercontent.com/python-pillow/pillow-depends/master/$archive.tar.gz | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										2
									
								
								docs/_templates/sidebarhelp.html
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								docs/_templates/sidebarhelp.html
									
									
									
									
										vendored
									
									
								
							|  | @ -1,4 +1,4 @@ | |||
| <h3>Need help?</h3> | ||||
| <p> | ||||
|     You can get help via IRC at <a href="irc://irc.freenode.net#pil">irc://irc.freenode.net#pil</a> or Stack Overflow <a href="https://stackoverflow.com/questions/tagged/pillow">here</a> and <a href="https://stackoverflow.com/questions/tagged/pil">here</a>. Please <a href="https://github.com/python-pillow/Pillow/issues/new">report issues on GitHub</a>. | ||||
|     You can get help via IRC at <a href="irc://irc.freenode.net#pil">irc://irc.freenode.net#pil</a> or Stack Overflow <a href="https://stackoverflow.com/questions/tagged/pillow">here</a> and <a href="https://stackoverflow.com/questions/tagged/python-imaging-library">here</a>. Please <a href="https://github.com/python-pillow/Pillow/issues/new">report issues on GitHub</a>. | ||||
| </p> | ||||
|  |  | |||
|  | @ -146,6 +146,7 @@ ITU-R 709, using the D65 luminant) to the CIE XYZ color space: | |||
| .. automethod:: PIL.Image.Image.seek | ||||
| .. automethod:: PIL.Image.Image.show | ||||
| .. automethod:: PIL.Image.Image.split | ||||
| .. automethod:: PIL.Image.Image.getchannel | ||||
| .. automethod:: PIL.Image.Image.tell | ||||
| .. automethod:: PIL.Image.Image.thumbnail | ||||
| .. automethod:: PIL.Image.Image.tobitmap | ||||
|  |  | |||
							
								
								
									
										9
									
								
								docs/releasenotes/4.3.0.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								docs/releasenotes/4.3.0.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| 4.3.0 | ||||
| ----- | ||||
| 
 | ||||
| Get One Channel From Image | ||||
| ========================== | ||||
| 
 | ||||
| New method :py:meth:`PIL.Image.Image.getchannel` added. | ||||
| It returns single channel by index or name. For example, | ||||
| ``image.getchannel("A")`` will return alpha channel as seperate image. | ||||
|  | @ -6,6 +6,7 @@ Release Notes | |||
| .. toctree:: | ||||
|   :maxdepth: 2 | ||||
| 
 | ||||
|   4.3.0 | ||||
|   4.2.1 | ||||
|   4.2.0 | ||||
|   4.1.1 | ||||
|  | @ -21,5 +22,3 @@ Release Notes | |||
|   3.0.0 | ||||
|   2.8.0 | ||||
|   2.7.0 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -42,7 +42,7 @@ ImagingAlphaComposite(Imaging imDst, Imaging imSrc) | |||
|         imDst->ysize != imSrc->ysize) | ||||
|         return ImagingError_Mismatch(); | ||||
| 
 | ||||
|     imOut = ImagingNew(imDst->mode, imDst->xsize, imDst->ysize); | ||||
|     imOut = ImagingNewDirty(imDst->mode, imDst->xsize, imDst->ysize); | ||||
|     if (!imOut) | ||||
|         return NULL; | ||||
| 
 | ||||
|  |  | |||
|  | @ -50,7 +50,7 @@ ImagingGetBand(Imaging imIn, int band) | |||
|     if (imIn->bands == 2 && band == 1) | ||||
|         band = 3; | ||||
| 
 | ||||
|     imOut = ImagingNew("L", imIn->xsize, imIn->ysize); | ||||
|     imOut = ImagingNewDirty("L", imIn->xsize, imIn->ysize); | ||||
|     if (!imOut) | ||||
|         return NULL; | ||||
| 
 | ||||
|  | @ -58,7 +58,12 @@ ImagingGetBand(Imaging imIn, int band) | |||
|     for (y = 0; y < imIn->ysize; y++) { | ||||
|         UINT8* in = (UINT8*) imIn->image[y] + band; | ||||
|         UINT8* out = imOut->image8[y]; | ||||
|         for (x = 0; x < imIn->xsize; x++) { | ||||
|         x = 0; | ||||
|         for (; x < imIn->xsize - 3; x += 4) { | ||||
|             *((UINT32*) (out + x)) = MAKE_UINT32(in[0], in[4], in[8], in[12]); | ||||
|             in += 16; | ||||
|         } | ||||
|         for (; x < imIn->xsize; x++) { | ||||
|             out[x] = *in; | ||||
|             in += 4; | ||||
|         } | ||||
|  | @ -67,6 +72,101 @@ ImagingGetBand(Imaging imIn, int band) | |||
|     return imOut; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| ImagingSplit(Imaging imIn, Imaging bands[4]) | ||||
| { | ||||
|     int i, j, x, y; | ||||
| 
 | ||||
|     /* Check arguments */ | ||||
|     if (!imIn || imIn->type != IMAGING_TYPE_UINT8) { | ||||
|         (Imaging) ImagingError_ModeError(); | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     /* Shortcuts */ | ||||
|     if (imIn->bands == 1) { | ||||
|         bands[0] = ImagingCopy(imIn); | ||||
|         return imIn->bands; | ||||
|     } | ||||
| 
 | ||||
|     for (i = 0; i < imIn->bands; i++) { | ||||
|         bands[i] = ImagingNew("L", imIn->xsize, imIn->ysize); | ||||
|         if ( ! bands[i]) { | ||||
|             for (j = 0; j < i; ++j) { | ||||
|                 ImagingDelete(bands[j]); | ||||
|             } | ||||
|             return 0; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /* Extract bands from image */ | ||||
|     if (imIn->bands == 2) { | ||||
|         for (y = 0; y < imIn->ysize; y++) { | ||||
|             UINT8* in = (UINT8*) imIn->image[y]; | ||||
|             UINT8* out0 = bands[0]->image8[y]; | ||||
|             UINT8* out1 = bands[1]->image8[y]; | ||||
|             x = 0; | ||||
|             for (; x < imIn->xsize - 3; x += 4) { | ||||
|                 *((UINT32*) (out0 + x)) = MAKE_UINT32(in[0], in[4], in[8], in[12]); | ||||
|                 *((UINT32*) (out1 + x)) = MAKE_UINT32(in[0+3], in[4+3], in[8+3], in[12+3]); | ||||
|                 in += 16; | ||||
|             } | ||||
|             for (; x < imIn->xsize; x++) { | ||||
|                 out0[x] = in[0]; | ||||
|                 out1[x] = in[3]; | ||||
|                 in += 4; | ||||
|             } | ||||
|         } | ||||
|     } else if (imIn->bands == 3) { | ||||
|         for (y = 0; y < imIn->ysize; y++) { | ||||
|             UINT8* in = (UINT8*) imIn->image[y]; | ||||
|             UINT8* out0 = bands[0]->image8[y]; | ||||
|             UINT8* out1 = bands[1]->image8[y]; | ||||
|             UINT8* out2 = bands[2]->image8[y]; | ||||
|             x = 0; | ||||
|             for (; x < imIn->xsize - 3; x += 4) { | ||||
|                 *((UINT32*) (out0 + x)) = MAKE_UINT32(in[0], in[4], in[8], in[12]); | ||||
|                 *((UINT32*) (out1 + x)) = MAKE_UINT32(in[0+1], in[4+1], in[8+1], in[12+1]); | ||||
|                 *((UINT32*) (out2 + x)) = MAKE_UINT32(in[0+2], in[4+2], in[8+2], in[12+2]); | ||||
|                 in += 16; | ||||
|             } | ||||
|             for (; x < imIn->xsize; x++) { | ||||
|                 out0[x] = in[0]; | ||||
|                 out1[x] = in[1]; | ||||
|                 out2[x] = in[2]; | ||||
|                 in += 4; | ||||
|             } | ||||
|         } | ||||
|     } else { | ||||
|         for (y = 0; y < imIn->ysize; y++) { | ||||
|             UINT8* in = (UINT8*) imIn->image[y]; | ||||
|             UINT8* out0 = bands[0]->image8[y]; | ||||
|             UINT8* out1 = bands[1]->image8[y]; | ||||
|             UINT8* out2 = bands[2]->image8[y]; | ||||
|             UINT8* out3 = bands[3]->image8[y]; | ||||
|             x = 0; | ||||
|             for (; x < imIn->xsize - 3; x += 4) { | ||||
|                 *((UINT32*) (out0 + x)) = MAKE_UINT32(in[0], in[4], in[8], in[12]); | ||||
|                 *((UINT32*) (out1 + x)) = MAKE_UINT32(in[0+1], in[4+1], in[8+1], in[12+1]); | ||||
|                 *((UINT32*) (out2 + x)) = MAKE_UINT32(in[0+2], in[4+2], in[8+2], in[12+2]); | ||||
|                 *((UINT32*) (out3 + x)) = MAKE_UINT32(in[0+3], in[4+3], in[8+3], in[12+3]); | ||||
|                 in += 16; | ||||
|             } | ||||
|             for (; x < imIn->xsize; x++) { | ||||
|                 out0[x] = in[0]; | ||||
|                 out1[x] = in[1]; | ||||
|                 out2[x] = in[2]; | ||||
|                 out3[x] = in[3]; | ||||
|                 in += 4; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return imIn->bands; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Imaging | ||||
| ImagingPutBand(Imaging imOut, Imaging imIn, int band) | ||||
| { | ||||
|  |  | |||
|  | @ -815,6 +815,7 @@ static int decode_bcn(Imaging im, ImagingCodecState state, const UINT8* src, int | |||
| 	case NN: \ | ||||
| 		while (bytes >= SZ) { \ | ||||
| 			TY col[16]; \ | ||||
| 			memset(col, 0, 16 * sizeof(col[0])); \ | ||||
| 			decode_bc##NN##_block(col, ptr); \ | ||||
| 			put_block(im, state, (const char *)col, sizeof(col[0]), C); \ | ||||
| 			ptr += SZ; \ | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha) | |||
|     else if (alpha == 1.0) | ||||
| 	return ImagingCopy(imIn2); | ||||
| 
 | ||||
|     imOut = ImagingNew(imIn1->mode, imIn1->xsize, imIn1->ysize); | ||||
|     imOut = ImagingNewDirty(imIn1->mode, imIn1->xsize, imIn1->ysize); | ||||
|     if (!imOut) | ||||
| 	return NULL; | ||||
| 
 | ||||
|  |  | |||
|  | @ -265,7 +265,7 @@ ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n) | |||
|           strcmp(imIn->mode, "La") == 0)) | ||||
|         return ImagingError_ModeError(); | ||||
| 
 | ||||
|     imTransposed = ImagingNew(imIn->mode, imIn->ysize, imIn->xsize); | ||||
|     imTransposed = ImagingNewDirty(imIn->mode, imIn->ysize, imIn->xsize); | ||||
|     if (!imTransposed) | ||||
|         return NULL; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1035,7 +1035,7 @@ frompalette(Imaging imOut, Imaging imIn, const char *mode) | |||
|     else | ||||
|         return (Imaging) ImagingError_ValueError("conversion not supported"); | ||||
| 
 | ||||
|     imOut = ImagingNew2(mode, imOut, imIn); | ||||
|     imOut = ImagingNew2Dirty(mode, imOut, imIn); | ||||
|     if (!imOut) | ||||
|         return NULL; | ||||
| 
 | ||||
|  | @ -1073,7 +1073,7 @@ topalette(Imaging imOut, Imaging imIn, ImagingPalette inpalette, int dither) | |||
|     if (!palette) | ||||
|         return (Imaging) ImagingError_ValueError("no palette"); | ||||
| 
 | ||||
|     imOut = ImagingNew2("P", imOut, imIn); | ||||
|     imOut = ImagingNew2Dirty("P", imOut, imIn); | ||||
|     if (!imOut) { | ||||
|       if (palette != inpalette) | ||||
|         ImagingPaletteDelete(palette); | ||||
|  | @ -1211,7 +1211,7 @@ tobilevel(Imaging imOut, Imaging imIn, int dither) | |||
|     if (strcmp(imIn->mode, "L") != 0 && strcmp(imIn->mode, "RGB") != 0) | ||||
|         return (Imaging) ImagingError_ValueError("conversion not supported"); | ||||
| 
 | ||||
|     imOut = ImagingNew2("1", imOut, imIn); | ||||
|     imOut = ImagingNew2Dirty("1", imOut, imIn); | ||||
|     if (!imOut) | ||||
|         return NULL; | ||||
| 
 | ||||
|  | @ -1344,7 +1344,7 @@ convert(Imaging imOut, Imaging imIn, const char *mode, | |||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     imOut = ImagingNew2(mode, imOut, imIn); | ||||
|     imOut = ImagingNew2Dirty(mode, imOut, imIn); | ||||
|     if (!imOut) | ||||
|         return NULL; | ||||
| 
 | ||||
|  | @ -1407,7 +1407,7 @@ ImagingConvertTransparent(Imaging imIn, const char *mode, | |||
|         g = b = r; | ||||
|     } | ||||
| 
 | ||||
|     imOut = ImagingNew2(mode, imOut, imIn); | ||||
|     imOut = ImagingNew2Dirty(mode, imOut, imIn); | ||||
|     if (!imOut){ | ||||
|         return NULL; | ||||
|     } | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ _copy(Imaging imOut, Imaging imIn) | |||
|     if (!imIn) | ||||
| 	return (Imaging) ImagingError_ValueError(NULL); | ||||
| 
 | ||||
|     imOut = ImagingNew2(imIn->mode, imOut, imIn); | ||||
|     imOut = ImagingNew2Dirty(imIn->mode, imOut, imIn); | ||||
|     if (!imOut) | ||||
|         return NULL; | ||||
| 
 | ||||
|  |  | |||
|  | @ -37,7 +37,7 @@ ImagingCrop(Imaging imIn, int sx0, int sy0, int sx1, int sy1) | |||
|     if (ysize < 0) | ||||
|         ysize = 0; | ||||
| 
 | ||||
|     imOut = ImagingNew(imIn->mode, xsize, ysize); | ||||
|     imOut = ImagingNewDirty(imIn->mode, xsize, ysize); | ||||
|     if (!imOut) | ||||
| 	return NULL; | ||||
| 
 | ||||
|  |  | |||
|  | @ -68,7 +68,7 @@ ImagingFillLinearGradient(const char *mode) | |||
|         return (Imaging) ImagingError_ModeError(); | ||||
|     } | ||||
| 
 | ||||
|     im = ImagingNew(mode, 256, 256); | ||||
|     im = ImagingNewDirty(mode, 256, 256); | ||||
|     if (!im) { | ||||
|         return NULL; | ||||
|     } | ||||
|  | @ -91,7 +91,7 @@ ImagingFillRadialGradient(const char *mode) | |||
|         return (Imaging) ImagingError_ModeError(); | ||||
|     } | ||||
| 
 | ||||
|     im = ImagingNew(mode, 256, 256); | ||||
|     im = ImagingNewDirty(mode, 256, 256); | ||||
|     if (!im) { | ||||
|         return NULL; | ||||
|     } | ||||
|  |  | |||
|  | @ -31,6 +31,7 @@ ImagingExpand(Imaging imIn, int xmargin, int ymargin, int mode) | |||
| { | ||||
|     Imaging imOut; | ||||
|     int x, y; | ||||
|     ImagingSectionCookie cookie; | ||||
| 
 | ||||
|     if (xmargin < 0 && ymargin < 0) | ||||
|         return (Imaging) ImagingError_ValueError("bad kernel size"); | ||||
|  | @ -60,11 +61,13 @@ ImagingExpand(Imaging imIn, int xmargin, int ymargin, int mode) | |||
|         EXPAND_LINE(type, image, imIn->ysize-1, ymargin+imIn->ysize+y);\ | ||||
|     } | ||||
| 
 | ||||
|     ImagingSectionEnter(&cookie); | ||||
|     if (imIn->image8) { | ||||
|         EXPAND(UINT8, image8); | ||||
|     } else { | ||||
|         EXPAND(INT32, image32); | ||||
|     } | ||||
|     ImagingSectionLeave(&cookie); | ||||
| 
 | ||||
|     ImagingCopyInfo(imOut, imIn); | ||||
| 
 | ||||
|  | @ -78,6 +81,7 @@ ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32* kernel, | |||
|     Imaging imOut; | ||||
|     int x, y; | ||||
|     FLOAT32 sum; | ||||
|     ImagingSectionCookie cookie; | ||||
| 
 | ||||
|     if (!im || strcmp(im->mode, "L") != 0) | ||||
|         return (Imaging) ImagingError_ModeError(); | ||||
|  | @ -92,6 +96,9 @@ ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32* kernel, | |||
|     if (!imOut) | ||||
|         return NULL; | ||||
| 
 | ||||
|     // Add one time for rounding
 | ||||
|     offset += 0.5; | ||||
| 
 | ||||
|     /* brute force kernel implementations */ | ||||
| #define KERNEL3x3(image, kernel, d) ( \ | ||||
|     (int) image[y+1][x-d] * kernel[0] + \ | ||||
|  | @ -131,6 +138,7 @@ ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32* kernel, | |||
|     (int) image[y-2][x+d]   * kernel[23] + \ | ||||
|     (int) image[y-2][x+d+d] * kernel[24]) | ||||
| 
 | ||||
|     ImagingSectionEnter(&cookie); | ||||
|     if (xsize == 3) { | ||||
|         /* 3x3 kernel. */ | ||||
|         for (x = 0; x < im->xsize; x++) | ||||
|  | @ -174,6 +182,7 @@ ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32* kernel, | |||
|             for (x = 0; x < im->xsize; x++) | ||||
|                 imOut->image8[y][x] = im->image8[y][x]; | ||||
|     } | ||||
|     ImagingSectionLeave(&cookie); | ||||
|     return imOut; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -159,11 +159,11 @@ struct ImagingPaletteInstance { | |||
| extern int ImagingNewCount; | ||||
| 
 | ||||
| extern Imaging ImagingNew(const char* mode, int xsize, int ysize); | ||||
| extern Imaging ImagingNew2(const char* mode, Imaging imOut, Imaging imIn); | ||||
| extern Imaging ImagingNewDirty(const char* mode, int xsize, int ysize); | ||||
| extern Imaging ImagingNew2Dirty(const char* mode, Imaging imOut, Imaging imIn); | ||||
| extern void    ImagingDelete(Imaging im); | ||||
| 
 | ||||
| extern Imaging ImagingNewBlock(const char* mode, int xsize, int ysize); | ||||
| extern Imaging ImagingNewArray(const char* mode, int xsize, int ysize); | ||||
| extern Imaging ImagingNewMap(const char* filename, int readonly, | ||||
|                              const char* mode, int xsize, int ysize); | ||||
| 
 | ||||
|  | @ -172,7 +172,6 @@ extern Imaging ImagingNewPrologue(const char *mode, | |||
| extern Imaging ImagingNewPrologueSubtype(const char *mode, | ||||
|                                   int xsize, int ysize, | ||||
|                                   int structure_size); | ||||
| extern Imaging ImagingNewEpilogue(Imaging im); | ||||
| 
 | ||||
| extern void ImagingCopyInfo(Imaging destination, Imaging source); | ||||
| 
 | ||||
|  | @ -268,6 +267,7 @@ extern Imaging ImagingGaussianBlur(Imaging imOut, Imaging imIn, float radius, | |||
|     int passes); | ||||
| extern Imaging ImagingGetBand(Imaging im, int band); | ||||
| extern Imaging ImagingMerge(const char* mode, Imaging bands[4]); | ||||
| extern int ImagingSplit(Imaging im, Imaging bands[4]); | ||||
| extern int ImagingGetBBox(Imaging im, int bbox[4]); | ||||
| typedef struct { int x, y; INT32 count; INT32 pixel; } ImagingColorItem; | ||||
| extern ImagingColorItem* ImagingGetColors(Imaging im, int maxcolors, | ||||
|  |  | |||
|  | @ -32,7 +32,7 @@ ImagingConvertMatrix(Imaging im, const char *mode, float m[]) | |||
| 
 | ||||
|     if (strcmp(mode, "L") == 0 && im->bands == 3) { | ||||
| 
 | ||||
| 	imOut = ImagingNew("L", im->xsize, im->ysize); | ||||
| 	imOut = ImagingNewDirty("L", im->xsize, im->ysize); | ||||
| 	if (!imOut) | ||||
| 	    return NULL; | ||||
| 
 | ||||
|  | @ -49,7 +49,7 @@ ImagingConvertMatrix(Imaging im, const char *mode, float m[]) | |||
| 
 | ||||
|     } else if (strlen(mode) == 3 && im->bands == 3) { | ||||
| 
 | ||||
| 	imOut = ImagingNew(mode, im->xsize, im->ysize); | ||||
| 	imOut = ImagingNewDirty(mode, im->xsize, im->ysize); | ||||
| 	if (!imOut) | ||||
| 	    return NULL; | ||||
| 
 | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ ImagingNegative(Imaging im) | |||
|     if (!im) | ||||
| 	return (Imaging) ImagingError_ModeError(); | ||||
| 
 | ||||
|     imOut = ImagingNew(im->mode, im->xsize, im->ysize); | ||||
|     imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); | ||||
|     if (!imOut) | ||||
| 	return NULL; | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ ImagingOffset(Imaging im, int xoffset, int yoffset) | |||
|     if (!im) | ||||
| 	return (Imaging) ImagingError_ModeError(); | ||||
| 
 | ||||
|     imOut = ImagingNew(im->mode, im->xsize, im->ysize); | ||||
|     imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); | ||||
|     if (!imOut) | ||||
| 	return NULL; | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,6 +5,13 @@ | |||
| 
 | ||||
| #define ROUND_UP(f) ((int) ((f) >= 0.0 ? (f) + 0.5F : (f) - 0.5F)) | ||||
| 
 | ||||
| #ifdef WORDS_BIGENDIAN | ||||
|     #define MAKE_UINT32(u0, u1, u2, u3) (u3 | (u2<<8) | (u1<<16) | (u0<<24)) | ||||
| #else | ||||
|     #define MAKE_UINT32(u0, u1, u2, u3) (u0 | (u1<<8) | (u2<<16) | (u3<<24)) | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| struct filter { | ||||
|     double (*filter)(double x); | ||||
|     double support; | ||||
|  | @ -249,7 +256,7 @@ ImagingResampleHorizontal_8bpc(Imaging imIn, int xsize, struct filter *filterp) | |||
|         return (Imaging) ImagingError_MemoryError(); | ||||
|     } | ||||
| 
 | ||||
|     imOut = ImagingNew(imIn->mode, xsize, imIn->ysize); | ||||
|     imOut = ImagingNewDirty(imIn->mode, xsize, imIn->ysize); | ||||
|     if ( ! imOut) { | ||||
|         free(kk); | ||||
|         free(xbounds); | ||||
|  | @ -281,8 +288,8 @@ ImagingResampleHorizontal_8bpc(Imaging imIn, int xsize, struct filter *filterp) | |||
|                         ss0 += ((UINT8) imIn->image[yy][(x + xmin)*4 + 0]) * k[x]; | ||||
|                         ss3 += ((UINT8) imIn->image[yy][(x + xmin)*4 + 3]) * k[x]; | ||||
|                     } | ||||
|                     imOut->image[yy][xx*4 + 0] = clip8(ss0); | ||||
|                     imOut->image[yy][xx*4 + 3] = clip8(ss3); | ||||
|                     ((UINT32 *) imOut->image[yy])[xx] = MAKE_UINT32( | ||||
|                         clip8(ss0), 0, 0, clip8(ss3)); | ||||
|                 } | ||||
|             } | ||||
|         } else if (imIn->bands == 3) { | ||||
|  | @ -297,9 +304,8 @@ ImagingResampleHorizontal_8bpc(Imaging imIn, int xsize, struct filter *filterp) | |||
|                         ss1 += ((UINT8) imIn->image[yy][(x + xmin)*4 + 1]) * k[x]; | ||||
|                         ss2 += ((UINT8) imIn->image[yy][(x + xmin)*4 + 2]) * k[x]; | ||||
|                     } | ||||
|                     imOut->image[yy][xx*4 + 0] = clip8(ss0); | ||||
|                     imOut->image[yy][xx*4 + 1] = clip8(ss1); | ||||
|                     imOut->image[yy][xx*4 + 2] = clip8(ss2); | ||||
|                     ((UINT32 *) imOut->image[yy])[xx] = MAKE_UINT32( | ||||
|                         clip8(ss0), clip8(ss1), clip8(ss2), 0); | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|  | @ -315,10 +321,8 @@ ImagingResampleHorizontal_8bpc(Imaging imIn, int xsize, struct filter *filterp) | |||
|                         ss2 += ((UINT8) imIn->image[yy][(x + xmin)*4 + 2]) * k[x]; | ||||
|                         ss3 += ((UINT8) imIn->image[yy][(x + xmin)*4 + 3]) * k[x]; | ||||
|                     } | ||||
|                     imOut->image[yy][xx*4 + 0] = clip8(ss0); | ||||
|                     imOut->image[yy][xx*4 + 1] = clip8(ss1); | ||||
|                     imOut->image[yy][xx*4 + 2] = clip8(ss2); | ||||
|                     imOut->image[yy][xx*4 + 3] = clip8(ss3); | ||||
|                     ((UINT32 *) imOut->image[yy])[xx] = MAKE_UINT32( | ||||
|                         clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3)); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | @ -354,7 +358,7 @@ ImagingResampleVertical_8bpc(Imaging imIn, int ysize, struct filter *filterp) | |||
|         return (Imaging) ImagingError_MemoryError(); | ||||
|     } | ||||
| 
 | ||||
|     imOut = ImagingNew(imIn->mode, imIn->xsize, ysize); | ||||
|     imOut = ImagingNewDirty(imIn->mode, imIn->xsize, ysize); | ||||
|     if ( ! imOut) { | ||||
|         free(kk); | ||||
|         free(xbounds); | ||||
|  | @ -386,8 +390,8 @@ ImagingResampleVertical_8bpc(Imaging imIn, int ysize, struct filter *filterp) | |||
|                         ss0 += ((UINT8) imIn->image[y + ymin][xx*4 + 0]) * k[y]; | ||||
|                         ss3 += ((UINT8) imIn->image[y + ymin][xx*4 + 3]) * k[y]; | ||||
|                     } | ||||
|                     imOut->image[yy][xx*4 + 0] = clip8(ss0); | ||||
|                     imOut->image[yy][xx*4 + 3] = clip8(ss3); | ||||
|                     ((UINT32 *) imOut->image[yy])[xx] = MAKE_UINT32( | ||||
|                         clip8(ss0), 0, 0, clip8(ss3)); | ||||
|                 } | ||||
|             } | ||||
|         } else if (imIn->bands == 3) { | ||||
|  | @ -402,9 +406,8 @@ ImagingResampleVertical_8bpc(Imaging imIn, int ysize, struct filter *filterp) | |||
|                         ss1 += ((UINT8) imIn->image[y + ymin][xx*4 + 1]) * k[y]; | ||||
|                         ss2 += ((UINT8) imIn->image[y + ymin][xx*4 + 2]) * k[y]; | ||||
|                     } | ||||
|                     imOut->image[yy][xx*4 + 0] = clip8(ss0); | ||||
|                     imOut->image[yy][xx*4 + 1] = clip8(ss1); | ||||
|                     imOut->image[yy][xx*4 + 2] = clip8(ss2); | ||||
|                     ((UINT32 *) imOut->image[yy])[xx] = MAKE_UINT32( | ||||
|                         clip8(ss0), clip8(ss1), clip8(ss2), 0); | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|  | @ -420,10 +423,8 @@ ImagingResampleVertical_8bpc(Imaging imIn, int ysize, struct filter *filterp) | |||
|                         ss2 += ((UINT8) imIn->image[y + ymin][xx*4 + 2]) * k[y]; | ||||
|                         ss3 += ((UINT8) imIn->image[y + ymin][xx*4 + 3]) * k[y]; | ||||
|                     } | ||||
|                     imOut->image[yy][xx*4 + 0] = clip8(ss0); | ||||
|                     imOut->image[yy][xx*4 + 1] = clip8(ss1); | ||||
|                     imOut->image[yy][xx*4 + 2] = clip8(ss2); | ||||
|                     imOut->image[yy][xx*4 + 3] = clip8(ss3); | ||||
|                     ((UINT32 *) imOut->image[yy])[xx] = MAKE_UINT32( | ||||
|                         clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3)); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | @ -451,7 +452,7 @@ ImagingResampleHorizontal_32bpc(Imaging imIn, int xsize, struct filter *filterp) | |||
|         return (Imaging) ImagingError_MemoryError(); | ||||
|     } | ||||
| 
 | ||||
|     imOut = ImagingNew(imIn->mode, xsize, imIn->ysize); | ||||
|     imOut = ImagingNewDirty(imIn->mode, xsize, imIn->ysize); | ||||
|     if ( ! imOut) { | ||||
|         free(kk); | ||||
|         free(xbounds); | ||||
|  | @ -511,7 +512,7 @@ ImagingResampleVertical_32bpc(Imaging imIn, int ysize, struct filter *filterp) | |||
|         return (Imaging) ImagingError_MemoryError(); | ||||
|     } | ||||
| 
 | ||||
|     imOut = ImagingNew(imIn->mode, imIn->xsize, ysize); | ||||
|     imOut = ImagingNewDirty(imIn->mode, imIn->xsize, ysize); | ||||
|     if ( ! imOut) { | ||||
|         free(kk); | ||||
|         free(xbounds); | ||||
|  |  | |||
|  | @ -46,21 +46,20 @@ int ImagingNewCount = 0; | |||
|  */ | ||||
| 
 | ||||
| Imaging | ||||
| ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, | ||||
|                           int size) | ||||
| ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size) | ||||
| { | ||||
|     Imaging im; | ||||
|     ImagingSectionCookie cookie; | ||||
| 
 | ||||
|     im = (Imaging) calloc(1, size); | ||||
|     if (!im) | ||||
|         return (Imaging) ImagingError_MemoryError(); | ||||
| 
 | ||||
|     /* linesize overflow check, roughly the current largest space req'd */ | ||||
|     if (xsize > (INT_MAX / 4) - 1) { | ||||
|         return (Imaging) ImagingError_MemoryError(); | ||||
|     } | ||||
| 
 | ||||
|     im = (Imaging) calloc(1, size); | ||||
|     if (!im) { | ||||
|         return (Imaging) ImagingError_MemoryError(); | ||||
|     } | ||||
| 
 | ||||
|     /* Setup image descriptor */ | ||||
|     im->xsize = xsize; | ||||
|     im->ysize = ysize; | ||||
|  | @ -206,47 +205,21 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, | |||
| 
 | ||||
|     } else { | ||||
|         free(im); | ||||
|         return (Imaging) ImagingError_ValueError("unrecognized mode"); | ||||
|         return (Imaging) ImagingError_ValueError("unrecognized image mode"); | ||||
|     } | ||||
| 
 | ||||
|     /* Setup image descriptor */ | ||||
|     strcpy(im->mode, mode); | ||||
| 
 | ||||
|     ImagingSectionEnter(&cookie); | ||||
| 
 | ||||
|     /* Pointer array (allocate at least one line, to avoid MemoryError
 | ||||
|        exceptions on platforms where calloc(0, x) returns NULL) */ | ||||
|     im->image = (char **) calloc((ysize > 0) ? ysize : 1, sizeof(void *)); | ||||
| 
 | ||||
|     ImagingSectionLeave(&cookie); | ||||
| 
 | ||||
|     if (!im->image) { | ||||
|     if ( ! im->image) { | ||||
|         free(im); | ||||
|         return (Imaging) ImagingError_MemoryError(); | ||||
|     } | ||||
| 
 | ||||
|     ImagingNewCount++; | ||||
| 
 | ||||
|     return im; | ||||
| } | ||||
| 
 | ||||
| Imaging | ||||
| ImagingNewPrologue(const char *mode, int xsize, int ysize) | ||||
| { | ||||
|     return ImagingNewPrologueSubtype( | ||||
|         mode, xsize, ysize, sizeof(struct ImagingMemoryInstance) | ||||
|         ); | ||||
| } | ||||
| 
 | ||||
| Imaging | ||||
| ImagingNewEpilogue(Imaging im) | ||||
| { | ||||
|     /* If the raster data allocator didn't setup a destructor,
 | ||||
|        assume that it couldn't allocate the required amount of | ||||
|        memory. */ | ||||
|     if (!im->destroy) | ||||
|         return (Imaging) ImagingError_MemoryError(); | ||||
| 
 | ||||
|     /* Initialize alias pointers to pixel data. */ | ||||
|     switch (im->pixelsize) { | ||||
|     case 1: case 2: case 3: | ||||
|  | @ -257,9 +230,18 @@ ImagingNewEpilogue(Imaging im) | |||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     ImagingNewCount++; | ||||
| 
 | ||||
|     return im; | ||||
| } | ||||
| 
 | ||||
| Imaging | ||||
| ImagingNewPrologue(const char *mode, int xsize, int ysize) | ||||
| { | ||||
|     return ImagingNewPrologueSubtype( | ||||
|         mode, xsize, ysize, sizeof(struct ImagingMemoryInstance)); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| ImagingDelete(Imaging im) | ||||
| { | ||||
|  | @ -295,24 +277,23 @@ ImagingDestroyArray(Imaging im) | |||
| } | ||||
| 
 | ||||
| Imaging | ||||
| ImagingNewArray(const char *mode, int xsize, int ysize) | ||||
| ImagingAllocateArray(Imaging im, int dirty) | ||||
| { | ||||
|     Imaging im; | ||||
|     ImagingSectionCookie cookie; | ||||
| 
 | ||||
|     int y; | ||||
|     char* p; | ||||
| 
 | ||||
|     im = ImagingNewPrologue(mode, xsize, ysize); | ||||
|     if (!im) | ||||
|         return NULL; | ||||
| 
 | ||||
|     ImagingSectionEnter(&cookie); | ||||
| 
 | ||||
|     /* Allocate image as an array of lines */ | ||||
|     for (y = 0; y < im->ysize; y++) { | ||||
|         /* malloc check linesize checked in prologue */ | ||||
|         p = (char *) calloc(1, im->linesize); | ||||
|         if (dirty) { | ||||
|             p = (char *) malloc(im->linesize); | ||||
|         } else { | ||||
|             p = (char *) calloc(1, im->linesize); | ||||
|         } | ||||
|         if (!p) { | ||||
|             ImagingDestroyArray(im); | ||||
|             break; | ||||
|  | @ -322,10 +303,13 @@ ImagingNewArray(const char *mode, int xsize, int ysize) | |||
| 
 | ||||
|     ImagingSectionLeave(&cookie); | ||||
| 
 | ||||
|     if (y == im->ysize) | ||||
|         im->destroy = ImagingDestroyArray; | ||||
|     if (y != im->ysize) { | ||||
|         return (Imaging) ImagingError_MemoryError(); | ||||
|     } | ||||
| 
 | ||||
|     return ImagingNewEpilogue(im); | ||||
|     im->destroy = ImagingDestroyArray; | ||||
| 
 | ||||
|     return im; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -341,15 +325,10 @@ ImagingDestroyBlock(Imaging im) | |||
| } | ||||
| 
 | ||||
| Imaging | ||||
| ImagingNewBlock(const char *mode, int xsize, int ysize) | ||||
| ImagingAllocateBlock(Imaging im, int dirty) | ||||
| { | ||||
|     Imaging im; | ||||
|     Py_ssize_t y, i; | ||||
| 
 | ||||
|     im = ImagingNewPrologue(mode, xsize, ysize); | ||||
|     if (!im) | ||||
|         return NULL; | ||||
| 
 | ||||
|     /* We shouldn't overflow, since the threshold defined
 | ||||
|        below says that we're only going to allocate max 4M | ||||
|        here before going to the array allocator. Check anyway. | ||||
|  | @ -357,7 +336,7 @@ ImagingNewBlock(const char *mode, int xsize, int ysize) | |||
|     if (im->linesize && | ||||
|         im->ysize > INT_MAX / im->linesize) { | ||||
|         /* punt if we're going to overflow */ | ||||
|         return NULL; | ||||
|         return (Imaging) ImagingError_MemoryError(); | ||||
|     } | ||||
| 
 | ||||
|     if (im->ysize * im->linesize <= 0) { | ||||
|  | @ -366,21 +345,27 @@ ImagingNewBlock(const char *mode, int xsize, int ysize) | |||
|            platforms */ | ||||
|         im->block = (char *) malloc(1); | ||||
|     } else { | ||||
|         /* malloc check ok, overflow check above */ | ||||
|         im->block = (char *) calloc(im->ysize, im->linesize); | ||||
|     } | ||||
| 
 | ||||
|     if (im->block) { | ||||
|         for (y = i = 0; y < im->ysize; y++) { | ||||
|             im->image[y] = im->block + i; | ||||
|             i += im->linesize; | ||||
|         if (dirty) { | ||||
|             /* malloc check ok, overflow check above */ | ||||
|             im->block = (char *) malloc(im->ysize * im->linesize); | ||||
|         } else { | ||||
|             /* malloc check ok, overflow check above */ | ||||
|             im->block = (char *) calloc(im->ysize, im->linesize); | ||||
|         } | ||||
| 
 | ||||
|         im->destroy = ImagingDestroyBlock; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     return ImagingNewEpilogue(im); | ||||
|     if ( ! im->block) { | ||||
|         return (Imaging) ImagingError_MemoryError(); | ||||
|     } | ||||
| 
 | ||||
|     for (y = i = 0; y < im->ysize; y++) { | ||||
|         im->image[y] = im->block + i; | ||||
|         i += im->linesize; | ||||
|     } | ||||
|      | ||||
|     im->destroy = ImagingDestroyBlock; | ||||
| 
 | ||||
|     return im; | ||||
| } | ||||
| 
 | ||||
| /* --------------------------------------------------------------------
 | ||||
|  | @ -393,39 +378,65 @@ ImagingNewBlock(const char *mode, int xsize, int ysize) | |||
| #endif | ||||
| 
 | ||||
| Imaging | ||||
| ImagingNew(const char* mode, int xsize, int ysize) | ||||
| ImagingNewInternal(const char* mode, int xsize, int ysize, int dirty) | ||||
| { | ||||
|     int bytes; | ||||
|     Imaging im; | ||||
| 
 | ||||
|     if (strcmp(mode, "") == 0) | ||||
|         return (Imaging) ImagingError_ValueError("empty mode"); | ||||
| 
 | ||||
|     if (strlen(mode) == 1) { | ||||
|         if (mode[0] == 'F' || mode[0] == 'I') | ||||
|             bytes = 4; | ||||
|         else | ||||
|             bytes = 1; | ||||
|     } else | ||||
|         bytes = strlen(mode); /* close enough */ | ||||
| 
 | ||||
|     if (xsize < 0 || ysize < 0) { | ||||
|         return (Imaging) ImagingError_ValueError("bad image size"); | ||||
|     } | ||||
| 
 | ||||
|     if ((int64_t) xsize * (int64_t) ysize <= THRESHOLD / bytes) { | ||||
|         im = ImagingNewBlock(mode, xsize, ysize); | ||||
|         if (im) | ||||
|     im = ImagingNewPrologue(mode, xsize, ysize); | ||||
|     if ( ! im) | ||||
|         return NULL; | ||||
| 
 | ||||
|     if (im->ysize && im->linesize <= THRESHOLD / im->ysize) { | ||||
|         if (ImagingAllocateBlock(im, dirty)) { | ||||
|             return im; | ||||
|         } | ||||
|         /* assume memory error; try allocating in array mode instead */ | ||||
|         ImagingError_Clear(); | ||||
|     } | ||||
| 
 | ||||
|     return ImagingNewArray(mode, xsize, ysize); | ||||
|     if (ImagingAllocateArray(im, dirty)) { | ||||
|         return im; | ||||
|     } | ||||
| 
 | ||||
|     ImagingDelete(im); | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| Imaging | ||||
| ImagingNew2(const char* mode, Imaging imOut, Imaging imIn) | ||||
| ImagingNew(const char* mode, int xsize, int ysize) | ||||
| { | ||||
|     return ImagingNewInternal(mode, xsize, ysize, 0); | ||||
| } | ||||
| 
 | ||||
| Imaging | ||||
| ImagingNewDirty(const char* mode, int xsize, int ysize) | ||||
| { | ||||
|     return ImagingNewInternal(mode, xsize, ysize, 1); | ||||
| } | ||||
| 
 | ||||
| Imaging | ||||
| ImagingNewBlock(const char* mode, int xsize, int ysize) | ||||
| { | ||||
|     Imaging im; | ||||
| 
 | ||||
|     im = ImagingNewPrologue(mode, xsize, ysize); | ||||
|     if ( ! im) | ||||
|         return NULL; | ||||
| 
 | ||||
|     if (ImagingAllocateBlock(im, 0)) { | ||||
|         return im; | ||||
|     } | ||||
| 
 | ||||
|     ImagingDelete(im); | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| Imaging | ||||
| ImagingNew2Dirty(const char* mode, Imaging imOut, Imaging imIn) | ||||
| { | ||||
|     /* allocate or validate output image */ | ||||
| 
 | ||||
|  | @ -438,7 +449,7 @@ ImagingNew2(const char* mode, Imaging imOut, Imaging imIn) | |||
|         } | ||||
|     } else { | ||||
|         /* create new image */ | ||||
|         imOut = ImagingNew(mode, imIn->xsize, imIn->ysize); | ||||
|         imOut = ImagingNewDirty(mode, imIn->xsize, imIn->ysize); | ||||
|         if (!imOut) | ||||
|             return NULL; | ||||
|     } | ||||
|  |  | |||
							
								
								
									
										9
									
								
								map.c
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								map.c
									
									
									
									
									
								
							|  | @ -229,9 +229,6 @@ mapping_readimage(ImagingMapperObject* mapper, PyObject* args) | |||
| 
 | ||||
|     im->destroy = ImagingDestroyMap; | ||||
| 
 | ||||
|     if (!ImagingNewEpilogue(im)) | ||||
|         return NULL; | ||||
| 
 | ||||
|     mapper->offset += size; | ||||
| 
 | ||||
|     return PyImagingNew(im); | ||||
|  | @ -368,8 +365,7 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args) | |||
|     } | ||||
| 
 | ||||
|     im = ImagingNewPrologueSubtype( | ||||
|         mode, xsize, ysize, sizeof(ImagingBufferInstance) | ||||
|         ); | ||||
|         mode, xsize, ysize, sizeof(ImagingBufferInstance)); | ||||
|     if (!im) | ||||
|         return NULL; | ||||
| 
 | ||||
|  | @ -387,9 +383,6 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args) | |||
|     ((ImagingBufferInstance*) im)->target = target; | ||||
|     ((ImagingBufferInstance*) im)->view = view; | ||||
| 
 | ||||
|     if (!ImagingNewEpilogue(im)) | ||||
|         return NULL; | ||||
| 
 | ||||
|     return PyImagingNew(im); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -55,15 +55,15 @@ libs = { | |||
|         'version': '8.5.19', | ||||
|     }, | ||||
|     'tcl-8.6': { | ||||
|         'url': SF_MIRROR+'/project/tcl/Tcl/8.6.6/tcl866-src.zip', | ||||
|         'filename': PILLOW_DEPENDS_DIR + 'tcl866-src.zip', | ||||
|         'url': SF_MIRROR+'/project/tcl/Tcl/8.6.7/tcl867-src.zip', | ||||
|         'filename': PILLOW_DEPENDS_DIR + 'tcl867-src.zip', | ||||
|         'dir': '', | ||||
|     }, | ||||
|     'tk-8.6': { | ||||
|         'url': SF_MIRROR+'/project/tcl/Tcl/8.6.6/tk866-src.zip', | ||||
|         'filename': PILLOW_DEPENDS_DIR + 'tk866-src.zip', | ||||
|         'url': SF_MIRROR+'/project/tcl/Tcl/8.6.7/tk867-src.zip', | ||||
|         'filename': PILLOW_DEPENDS_DIR + 'tk867-src.zip', | ||||
|         'dir': '', | ||||
|         'version': '8.6.6', | ||||
|         'version': '8.6.7', | ||||
|     }, | ||||
|     'webp': { | ||||
|         'url': 'http://downloads.webmproject.org/releases/webp/libwebp-0.6.0.tar.gz', | ||||
|  | @ -71,9 +71,9 @@ libs = { | |||
|         'dir': 'libwebp-0.6.0', | ||||
|     }, | ||||
|     'openjpeg': { | ||||
|         'url': SF_MIRROR+'/project/openjpeg/openjpeg/2.1.2/openjpeg-2.1.2.tar.gz', | ||||
|         'filename': PILLOW_DEPENDS_DIR + 'openjpeg-2.1.2.tar.gz', | ||||
|         'dir': 'openjpeg-2.1.2', | ||||
|         'url': SF_MIRROR+'/project/openjpeg/openjpeg/2.2.0/openjpeg-2.2.0.tar.gz', | ||||
|         'filename': PILLOW_DEPENDS_DIR + 'openjpeg-2.2.0.tar.gz', | ||||
|         'dir': 'openjpeg-2.2.0', | ||||
|     }, | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user