def test_jpeg_with_orientation_8(self): with open('tests/images/orientation/landscape_8.jpg', 'rb') as f: image = PillowImage.open(JPEGImageFile(f)) image = image.auto_orient() self.assert_orientation_landscape_image_is_correct(image)
def draw_googly(image_name, faces): imagepath = 'img/' + image_name for face in faces: portrait = Image.open(imagepath) rect = face['faceRectangle'] print('rectangle:', rect) eye = Image.open('eye.png') eye.thumbnail((rect['width'] / 3, rect['height'] / 3)) eye_size = eye.size[0] offset = int(eye_size / 2) eye_left_x = int(face['faceLandmarks']['pupilLeft']['x']) - offset eye_left_y = int(face['faceLandmarks']['pupilLeft']['y']) - offset eye_right_x = int(face['faceLandmarks']['pupilRight']['x']) - offset eye_right_y = int(face['faceLandmarks']['pupilRight']['y']) - offset # center it on face paste_position_left = eye_left_x, eye_left_y paste_position_right = eye_right_x, eye_right_y # last property is a mask portrait.paste(eye, paste_position_left, eye) portrait.paste(eye, paste_position_right, eye) # check if it has an alpha channel if 'A' in portrait.getbands(): PillowImage(portrait).set_background_color_rgb( (255, 255, 255)).save_as_jpeg(imagepath) else: portrait.save(imagepath) if DEV == 'TRUE': print('showing portrait.') portrait.show()
def setUp(self): with open('tests/images/people.jpg', 'rb') as f: # Open the image via Pillow pillow_image = PillowImage.open(JPEGImageFile(f)) buffer_rgb = pillow_image.to_buffer_rgb() colour_image = OpenCVColorImage.from_buffer_rgb(buffer_rgb) self.image = OpenCVGrayscaleImage.from_color(colour_image)
def test_resize_animated_gif(self): with open('tests/images/newtons_cradle.gif', 'rb') as f: image = PillowImage.open(GIFImageFile(f)) resized_image = image.resize((100, 75)) self.assertFalse(resized_image.has_alpha()) self.assertTrue(resized_image.has_animation())
def test_save_transparent_gif(self): with open('tests/images/transparent.gif', 'rb') as f: image = PillowImage.open(GIFImageFile(f)) # Save it into memory f = io.BytesIO() image.save_as_gif(f) # Reload it f.seek(0) image = PillowImage.open(GIFImageFile(f)) self.assertTrue(image.has_alpha()) self.assertFalse(image.has_animation()) # Check that the alpha of pixel 1,1 is 0 self.assertEqual(image.image.convert('RGBA').getpixel((1, 1))[3], 0)
def pillow_quantize(image): try: quantized_image = image.image.quantize(method=3) except ValueError: # libimagequant is missing, use the default method quantized_image = image.image.quantize() return PillowImage(quantized_image)
def test_transparent_gif(self): with open('tests/images/transparent.gif', 'rb') as f: image = PillowImage.open(GIFImageFile(f)) self.assertTrue(image.has_alpha()) self.assertFalse(image.has_animation()) # Check that the alpha of pixel 1,1 is 0 self.assertEqual(image.image.convert('RGBA').getpixel((1, 1))[3], 0)
def test_save_as_jpeg_with_icc_profile(self): with open('tests/images/trees.jpg', 'rb') as f: image = PillowImage.open(JPEGImageFile(f)) icc_profile = PILImage.open(f).info.get('icc_profile') self.assertIsNotNone(icc_profile) saved = image.save_as_jpeg(io.BytesIO()) saved_icc_profile = PILImage.open(saved.f).info.get('icc_profile') self.assertEqual(saved_icc_profile, icc_profile)
def test_jpeg_with_orientation_7(self): with open('tests/images/orientation/landscape_7.jpg', 'rb') as f: image = PillowImage.open(JPEGImageFile(f)) self.assert_exif_orientation_equals_value(image, 7) image = image.auto_orient() self.assert_orientation_landscape_image_is_correct(image) self.assert_exif_orientation_equals_value(image, 1)
def test_save_as_jpeg_with_exif(self): with open('tests/images/trees.jpg', 'rb') as f: image = PillowImage.open(JPEGImageFile(f)) exif = PILImage.open(f).info.get('exif') self.assertIsNotNone(exif) saved = image.save_as_jpeg(io.BytesIO()) saved_exif = PILImage.open(saved.f).info.get('exif') self.assertEqual(saved_exif, exif)
def test_save_as_gif_converts_back_to_supported_mode(self): output = io.BytesIO() with open('tests/images/transparent.gif', 'rb') as f: image = PillowImage.open(GIFImageFile(f)) image.image = image.image.convert('RGB') image.save_as_gif(output) output.seek(0) image = _PIL_Image().open(output) self.assertEqual(image.mode, 'P')
def test_open_webp_lossless(self): original_image = self.image.image lossless_file = self.image.save_as_webp(io.BytesIO(), lossless=True) lossless_image = PillowImage.open(lossless_file).image identically = True for x in range(original_image.width): for y in range(original_image.height): original_pixel = original_image.getpixel((x, y)) # don't compare fully transparent pixels if original_pixel[3] == 0: continue if original_pixel != lossless_image.getpixel((x, y)): identically = False break self.assertTrue(identically)
def setUp(self): with open('tests/images/people.jpg', 'rb') as f: # Open the image via Pillow pillow_image = PillowImage.open(JPEGImageFile(f)) buffer_rgb = pillow_image.to_buffer_rgb() colour_image = OpenCVColorImage.from_buffer_rgb(buffer_rgb) self.image = OpenCVGrayscaleImage.from_color(colour_image) self.expected_features = [[41.0, 206.0], [16.0, 201.0], [243.0, 208.0], [79.0, 130.0], [120.0, 24.0], [43.0, 119.0], [40.0, 165.0], [37.0, 14.0], [250.0, 59.0], [98.0, 6.0], [78.0, 61.0], [201.0, 93.0], [8.0, 114.0], [189.0, 142.0], [292.0, 188.0], [201.0, 199.0], [7.0, 154.0], [198.0, 247.0], [235.0, 55.0], [22.0, 36.0]] self.expected_faces = [(272, 89, 364, 181), (91, 165, 187, 261)]
def run(self, willow, image, env): # Note that `image` here is the database model of the Image, not the actual image if image.width < self.width or image.height < self.height: # unable to process image at all since the putalpha will fail return willow = super(CircleCropOperation, self).run(willow, image, env) with image.get_willow_image() as willow_image: original_format = willow_image.format_name pillow_image = willow.image # pillow_image.save('filled.{0}'.format(original_format)) # We can get fancy with transparencies... if original_format == 'png': mask = self._draw_circular_mask() if self.border_width > 0: # Add a border... border_mask = self._draw_circular_mask(with_border=True) draw = ImageDraw.Draw(pillow_image) draw.bitmap((0, 0), border_mask, self.border_color) del draw # pillow_image.save('bitmap.png') mask.paste(border_mask, (0, 0), border_mask) # mask.save('pasted.png') pillow_image.putalpha(mask) else: mask = self._draw_circular_mask(invert=True) pillow_image.paste(mask, (0, 0), mask) width, height = pillow_image.size if self.border_width > 0: draw = ImageDraw.Draw(pillow_image) # We need this first ellipse which won't actually be a closed circle since we are using 'outline'... _border_color = self.border_color if draw.im.mode == 'L': # 'L' implies the image is grayscale so providing (r, g, b[, alpha]) doesn't make any sense as there is one channel; it's expecting an integer _border_color = self.border_color[0] draw.ellipse((0, 0) + (width, height), outline=_border_color) # Move in 1 pixel and draw another ellipse for each pixel of width for i in range(self.border_width): draw.ellipse( (i + 1, i + 1) + (width - i - 1, height - i - 1), outline=_border_color) del draw # pillow_image.save('masked.{0}'.format(original_format)) return PillowImage(pillow_image)
def assert_orientation_landscape_image_is_correct(self, rendition): """ Check that the image has the correct colored pixels in the right places so that we know the image did not physically rotate. """ from willow.plugins.pillow import PillowImage with rendition.get_willow_image() as willow_image: image = PillowImage.open(willow_image) # Check that the image is the correct size (and not rotated) self.assertEqual(image.get_size(), (600, 450)) # Check that the red flower is in the bottom left # The JPEGs have compressed slightly differently so the colours won't be spot on colour = image.image.convert("RGB").getpixel((155, 282)) self.assertAlmostEqual(colour[0], 217, delta=25) self.assertAlmostEqual(colour[1], 38, delta=25) self.assertAlmostEqual(colour[2], 46, delta=25) # Check that the water is at the bottom colour = image.image.convert("RGB").getpixel((377, 434)) self.assertAlmostEqual(colour[0], 85, delta=25) self.assertAlmostEqual(colour[1], 93, delta=25) self.assertAlmostEqual(colour[2], 65, delta=25)
def run(self, willow, image, env): return PillowImage(willow.get_pillow_image().convert('L'))
def test_open_webp_w_alpha(self): with open('tests/images/tux_w_alpha.webp', 'rb') as f: image = PillowImage.open(WebPImageFile(f)) self.assertTrue(image.has_alpha()) self.assertFalse(image.has_animation())
import unittest import io import imghdr from PIL import Image as PILImage from willow.image import JPEGImageFile, PNGImageFile, GIFImageFile, WebPImageFile from willow.plugins.pillow import _PIL_Image, PillowImage, UnsupportedRotation no_webp_support = not PillowImage.is_format_supported("WEBP") class TestPillowOperations(unittest.TestCase): def setUp(self): with open('tests/images/transparent.png', 'rb') as f: self.image = PillowImage.open(PNGImageFile(f)) def test_get_size(self): width, height = self.image.get_size() self.assertEqual(width, 200) self.assertEqual(height, 150) def test_resize(self): resized_image = self.image.resize((100, 75)) self.assertEqual(resized_image.get_size(), (100, 75)) def test_crop(self): cropped_image = self.image.crop((10, 10, 100, 100)) self.assertEqual(cropped_image.get_size(), (90, 90))
def putalpha(self, willow, alpha): willow.image.putalpha(alpha) # willow.image.save('alpha.png') return PillowImage(willow.image)
def setUp(self): with open('tests/images/transparent.png', 'rb') as f: self.image = PillowImage.open(PNGImageFile(f))
def draw_bitmap(self, willow, bitmap, fill): draw = ImageDraw.Draw(willow.image) draw.bitmap((0, 0), bitmap, fill) del draw # willow.image.save('bitmap.png') return PillowImage(willow.image)
import unittest import io import imghdr from PIL import Image as PILImage from willow.image import JPEGImageFile, PNGImageFile, GIFImageFile, WebPImageFile from willow.plugins.pillow import _PIL_Image, PillowImage, UnsupportedRotation no_webp_support = not PillowImage.is_format_supported("WEBP") class TestPillowOperations(unittest.TestCase): def setUp(self): with open('tests/images/transparent.png', 'rb') as f: self.image = PillowImage.open(PNGImageFile(f)) def test_get_size(self): width, height = self.image.get_size() self.assertEqual(width, 200) self.assertEqual(height, 150) def test_get_frame_count(self): frames = self.image.get_frame_count() self.assertEqual(frames, 1) def test_resize(self): resized_image = self.image.resize((100, 75)) self.assertEqual(resized_image.get_size(), (100, 75))
def fill_image(final_image_size, pillow, crop_closeness=0): willow = PillowImage(pillow) width, height = final_image_size image_width, image_height = willow.get_size() focal_point = Rect(image_width / 2, image_height / 2, image_width / 2, image_height / 2) # Get crop aspect ratio crop_aspect_ratio = width / height # Get crop max crop_max_scale = min(image_width, image_height * crop_aspect_ratio) crop_max_width = crop_max_scale crop_max_height = crop_max_scale / crop_aspect_ratio # Initialise crop width and height to max crop_width = crop_max_width crop_height = crop_max_height # Use crop closeness to zoom in if focal_point is not None: # Get crop min crop_min_scale = max(focal_point.width, focal_point.height * crop_aspect_ratio) crop_min_width = crop_min_scale crop_min_height = crop_min_scale / crop_aspect_ratio # Sometimes, the focal point may be bigger than the image... if not crop_min_scale >= crop_max_scale: # Calculate max crop closeness to prevent upscaling max_crop_closeness = max( 1 - (width - crop_min_width) / (crop_max_width - crop_min_width), 1 - (height - crop_min_height) / (crop_max_height - crop_min_height) ) # Apply max crop closeness crop_closeness = min(crop_closeness, max_crop_closeness) if 1 >= crop_closeness >= 0: # Get crop width and height crop_width = crop_max_width + (crop_min_width - crop_max_width) * crop_closeness crop_height = crop_max_height + (crop_min_height - crop_max_height) * crop_closeness # Find focal point UV if focal_point is not None: fp_x, fp_y = focal_point.centroid else: # Fall back to positioning in the centre fp_x = image_width / 2 fp_y = image_height / 2 fp_u = fp_x / image_width fp_v = fp_y / image_height # Position crop box based on focal point UV crop_x = fp_x - (fp_u - 0.5) * crop_width crop_y = fp_y - (fp_v - 0.5) * crop_height # Convert crop box into rect rect = Rect.from_point(crop_x, crop_y, crop_width, crop_height) # Make sure the entire focal point is in the crop box if focal_point is not None: rect = rect.move_to_cover(focal_point) # Don't allow the crop box to go over the image boundary rect = rect.move_to_clamp(Rect(0, 0, image_width, image_height)) # Crop! willow = willow.crop(rect.round()) # Get scale for resizing # The scale should be the same for both the horizontal and # vertical axes aftercrop_width, aftercrop_height = willow.get_size() scale = width / aftercrop_width # Only resize if the image is too big if scale < 1.0: # Resize! willow = willow.resize((width, height)) return willow.get_pillow_image()