1 from sorl.thumbnail.engines import pil_engine
2 from sorl.thumbnail import parsers
7 # http://timmyomahony.com/blog/custom-cropping-engine-sorl-thumbnail/
9 class CustomCroppingEngine(pil_engine.Engine):
11 A custom sorl.thumbnail engine (using PIL) that first crops an image
12 according to 4 pixel/percentage values in the source image, then scales
13 that crop down to the size specified in the geometry. This is in contrast
14 to sorl.thumbnails default engine which first scales the image down to the
15 specified geometry and applies the crop afterward.
17 def create(self, image, geometry, options):
18 image = self.orientation(image, geometry, options)
19 image = self.colorspace(image, geometry, options)
20 image = self.crop(image, geometry, options)
21 image = self.scale(image, geometry, options)
24 def _crop_parse(self, crop, xy_image, xy_window):
26 Conver the crop string passed by the user to accurate cropping values
27 (This is adapter from the default sorl.thumbnail.parsers.parse_crop)
29 crops = crop.split(' ')
31 raise parsers.ThumbnailParseError('Unrecognized crop option: %s' % crop)
32 x1, y1, x2, y2 = crops
34 def get_offset(crop, epsilon):
35 m = parsers.bgpos_pat.match(crop)
37 raise parsers.ThumbnailParseError('Unrecognized crop option: %s' % crop)
38 value = int(m.group('value')) # we only take ints in the regexp
39 unit = m.group('unit')
41 value = epsilon * value / 100.0
42 return int(max(0, min(value, epsilon)))
43 x1 = get_offset(x1, xy_image[0])
44 y1 = get_offset(y1, xy_image[1])
45 x2 = get_offset(x2, xy_image[0])
46 y2 = get_offset(y2, xy_image[1])
49 def crop(self, image, geometry, options):
50 crop = options['crop']
51 if not crop or crop == 'noop':
53 x_image, y_image = self.get_image_size(image)
54 x1, y1, x2, y2 = self._crop_parse(crop, (x_image, y_image), geometry)
55 return self._crop(image, x1, y1, x2, y2)
57 def _crop(self, image, x1, y1, x2, y2):
58 return image.crop((x1, y1, x2, y2))