mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-30 07:27:49 +03:00 
			
		
		
		
	Merge pull request #2595 from wiredfool/issue_1911
Image.Image.alpha_composite Added
This commit is contained in:
		
						commit
						b9b5d39f2b
					
				
							
								
								
									
										48
									
								
								PIL/Image.py
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								PIL/Image.py
									
									
									
									
									
								
							|  | @ -1376,6 +1376,54 @@ class Image(object): | ||||||
|         else: |         else: | ||||||
|             self.im.paste(im, box) |             self.im.paste(im, box) | ||||||
| 
 | 
 | ||||||
|  |     def alpha_composite(self, im, dest=(0,0), source=(0,0)): | ||||||
|  |         """ 'In-place' analog of Image.alpha_composite. Composites an image | ||||||
|  |         onto this image. | ||||||
|  | 
 | ||||||
|  |         :param im: image to composite over this one | ||||||
|  |         :param dest: Optional 2 tuple (top, left) specifying the upper | ||||||
|  |           left corner in this (destination) image. | ||||||
|  |         :param source: Optional 2 (top, left) tuple for the upper left | ||||||
|  |           corner in the overlay source image, or 4 tuple (top, left, bottom, | ||||||
|  |           right) for the bounds of the source rectangle | ||||||
|  |            | ||||||
|  |         Performance Note: Not currently implemented in-place in the core layer. | ||||||
|  |         """ | ||||||
|  | 
 | ||||||
|  |         if not isinstance(source, tuple): | ||||||
|  |             raise ValueError("Source must be a tuple") | ||||||
|  |         if not isinstance(dest, tuple): | ||||||
|  |             raise ValueError("Destination must be a tuple") | ||||||
|  |         if not len(source) in (2, 4): | ||||||
|  |             raise ValueError("Source must be a 2 or 4-tuple") | ||||||
|  |         if not len(dest) == 2: | ||||||
|  |             raise ValueError("Destination must be a 2-tuple") | ||||||
|  |         if min(source) < 0: | ||||||
|  |             raise ValueError("Source must be non-negative") | ||||||
|  |         if min(dest) < 0: | ||||||
|  |             raise ValueError("Destination must be non-negative") | ||||||
|  | 
 | ||||||
|  |         if len(source) == 2: | ||||||
|  |             source = source + im.size | ||||||
|  | 
 | ||||||
|  |         # over image, crop if it's not the whole thing.  | ||||||
|  |         if source == (0,0) + im.size: | ||||||
|  |             overlay = im | ||||||
|  |         else: | ||||||
|  |             overlay = im.crop(source) | ||||||
|  | 
 | ||||||
|  |         # target for the paste | ||||||
|  |         box = dest + (dest[0] + overlay.width, dest[1] + overlay.height) | ||||||
|  |              | ||||||
|  |         # destination image. don't copy if we're using the whole image. | ||||||
|  |         if dest == (0,0) + self.size: | ||||||
|  |             background = self | ||||||
|  |         else: | ||||||
|  |             background = self.crop(box) | ||||||
|  |                          | ||||||
|  |         result = alpha_composite(background, overlay) | ||||||
|  |         self.paste(result, box) | ||||||
|  |          | ||||||
|     def point(self, lut, mode=None): |     def point(self, lut, mode=None): | ||||||
|         """ |         """ | ||||||
|         Maps this image through a lookup table or function. |         Maps this image through a lookup table or function. | ||||||
|  |  | ||||||
|  | @ -202,6 +202,44 @@ class TestImage(PillowTestCase): | ||||||
|         img_colors = sorted(img.getcolors()) |         img_colors = sorted(img.getcolors()) | ||||||
|         self.assertEqual(img_colors, expected_colors) |         self.assertEqual(img_colors, expected_colors) | ||||||
| 
 | 
 | ||||||
|  |     def test_alpha_inplace(self): | ||||||
|  |         src = Image.new('RGBA', (128,128), 'blue') | ||||||
|  | 
 | ||||||
|  |         over = Image.new('RGBA', (128,128), 'red') | ||||||
|  |         mask = hopper('L') | ||||||
|  |         over.putalpha(mask) | ||||||
|  | 
 | ||||||
|  |         target = Image.alpha_composite(src, over) | ||||||
|  | 
 | ||||||
|  |         # basic | ||||||
|  |         full = src.copy() | ||||||
|  |         full.alpha_composite(over) | ||||||
|  |         self.assert_image_equal(full, target) | ||||||
|  | 
 | ||||||
|  |         # with offset down to right | ||||||
|  |         offset = src.copy() | ||||||
|  |         offset.alpha_composite(over, (64, 64)) | ||||||
|  |         self.assert_image_equal(offset.crop((64, 64, 127, 127)), | ||||||
|  |                                 target.crop((0, 0, 63, 63))) | ||||||
|  |         self.assertEqual(offset.size, (128, 128)) | ||||||
|  | 
 | ||||||
|  |         # offset and crop | ||||||
|  |         box = src.copy() | ||||||
|  |         box.alpha_composite(over, (64, 64), (0, 0, 32, 32)) | ||||||
|  |         self.assert_image_equal(box.crop((64, 64, 96, 96)), | ||||||
|  |                                 target.crop((0, 0, 32, 32))) | ||||||
|  |         self.assert_image_equal(box.crop((96, 96, 128, 128)), | ||||||
|  |                                 src.crop((0, 0, 32, 32))) | ||||||
|  |         self.assertEqual(box.size, (128, 128)) | ||||||
|  | 
 | ||||||
|  |         # source point | ||||||
|  |         source = src.copy() | ||||||
|  |         source.alpha_composite(over, (32, 32), (32, 32, 96, 96)) | ||||||
|  | 
 | ||||||
|  |         self.assert_image_equal(source.crop((32, 32, 96, 96)), | ||||||
|  |                                 target.crop((32, 32, 96, 96))) | ||||||
|  |         self.assertEqual(source.size, (128, 128)) | ||||||
|  | 
 | ||||||
|     def test_registered_extensions_uninitialized(self): |     def test_registered_extensions_uninitialized(self): | ||||||
|         # Arrange |         # Arrange | ||||||
|         Image._initialized = 0 |         Image._initialized = 0 | ||||||
|  |  | ||||||
|  | @ -104,6 +104,8 @@ An instance of the :py:class:`~PIL.Image.Image` class has the following | ||||||
| methods. Unless otherwise stated, all methods return a new instance of the | methods. Unless otherwise stated, all methods return a new instance of the | ||||||
| :py:class:`~PIL.Image.Image` class, holding the resulting image. | :py:class:`~PIL.Image.Image` class, holding the resulting image. | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | .. automethod:: PIL.Image.Image.alpha_composite | ||||||
| .. automethod:: PIL.Image.Image.convert | .. automethod:: PIL.Image.Image.convert | ||||||
| 
 | 
 | ||||||
| The following example converts an RGB image (linearly calibrated according to | The following example converts an RGB image (linearly calibrated according to | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user