def scales_extractor(widget, data): scales = attr_value('scales', widget, data) if not scales or not data.extracted or not data.extracted.get('image'): return data.extracted image = data.extracted['image'] scaled_images = dict() image_appr = aspect_ratio_approximate(image.size) for name, size in scales.items(): scale_appr = aspect_ratio_approximate(size) if same_aspect_ratio(size, image.size): image_size = size # scale x if image_appr > scale_appr: image_size = scale_size(image.size, (size[0], None)) # scale y if image_appr < scale_appr: image_size = scale_size(image.size, (None, size[1])) scaled_images[name] = image.resize(image_size, Image.ANTIALIAS) data.extracted['scales'] = scaled_images return data.extracted
def crop_extractor(widget, data): """XXX: - support cropping definitions as request parameters. left, top, width, height (for use with JS cropping plugin) - alignment tl (top left), tr (top right), bl (bottom left), br (bottom right), ce (center), rc (right center), lc (left center), tc (top center), bc (bottom center) """ crop = attr_value('crop', widget, data) if not crop or not data.extracted or not data.extracted.get('image'): return data.extracted size = crop['size'] offset = crop.get('offset', (0, 0)) fitting = crop.get('fitting', False) image = data.extracted['image'] image_appr = aspect_ratio_approximate(image.size) crop_appr = aspect_ratio_approximate(size) if fitting: if same_aspect_ratio(size, image.size): image = image.resize(size, Image.ANTIALIAS) offset = (0, 0) # scale x if image_appr < crop_appr: image_size = scale_size(image.size, (size[0], None)) image = image.resize(image_size, Image.ANTIALIAS) offset = (0, (image_size[1] - size[1]) / 2) # scale y if image_appr > crop_appr: image_size = scale_size(image.size, (None, size[1])) image = image.resize(image_size, Image.ANTIALIAS) offset = ((image_size[0] - size[0]) / 2, 0) image = image.crop( (offset[0], offset[1], size[0] + offset[0], size[1] + offset[1])) data.extracted['cropped'] = image return data.extracted
def test_extract_from_image_cropping_foundations(self): buffer = StringIO(self.dummy_png) image = PIL.Image.open(buffer) buffer.seek(0) data = buffer.read() # save cropped image to testing folder for manual inspection left, top, width, height = 7, 3, 30, 40 cropped = image.crop((left, top, width, height)) path = pkg_resources.resource_filename( 'yafowil.widget.image', 'testing/cropped.png') cropped.save(path, quality=100) # fitting logic self.assertTrue(same_aspect_ratio((300, 200), (600, 400))) # scale X down self.assertEqual(scale_size((100, 50), (75, None)), (75, 37)) # scale X up self.assertEqual(scale_size((100, 50), (150, None)), (150, 75)) # scale Y down self.assertEqual(scale_size((100, 50), (None, 25)), (50, 25)) # scale Y up self.assertEqual(scale_size((100, 50), (None, 100)), (200, 100)) # scale x size_from = (60, 40) self.assertEqual(aspect_ratio_approximate(size_from), Decimal('1.50')) size_to = (50, 25) self.assertEqual(aspect_ratio_approximate(size_to), Decimal('2.00')) self.assertTrue( aspect_ratio_approximate(size_from) < aspect_ratio_approximate(size_to) ) scaled = scale_size(size_from, (size_to[0], None)) self.assertEqual(scaled, (50, 33)) offset_y = (scaled[1] - size_to[1]) / 2 self.assertEqual(offset_y, 4) # scale y size_from = (60, 40) self.assertEqual(aspect_ratio_approximate(size_from), Decimal('1.50')) size_to = (50, 35) self.assertEqual(aspect_ratio_approximate(size_to), Decimal('1.43')) self.assertTrue( aspect_ratio_approximate(size_from) > aspect_ratio_approximate(size_to) ) scaled = scale_size(size_from, (None, size_to[1])) self.assertEqual(scaled, (52, 35)) offset_x = (scaled[0] - size_to[0]) / 2 self.assertEqual(offset_x, 1)
def test_scale_size(self): self.assertEqual(scale_size((640, 480), (800, None)), (800, 600)) self.assertEqual(scale_size((640, 480), (None, 3)), (4, 3))