summaryrefslogtreecommitdiffstats
path: root/imagekit/processors.py
diff options
context:
space:
mode:
Diffstat (limited to 'imagekit/processors.py')
-rw-r--r--imagekit/processors.py134
1 files changed, 134 insertions, 0 deletions
diff --git a/imagekit/processors.py b/imagekit/processors.py
new file mode 100644
index 0000000..6f6b480
--- /dev/null
+++ b/imagekit/processors.py
@@ -0,0 +1,134 @@
+""" Imagekit Image "ImageProcessors"
+
+A processor defines a set of class variables (optional) and a
+class method named "process" which processes the supplied image using
+the class properties as settings. The process method can be overridden as well allowing user to define their
+own effects/processes entirely.
+
+"""
+from imagekit.lib import *
+
+class ImageProcessor(object):
+ """ Base image processor class """
+ @classmethod
+ def process(cls, image, obj=None):
+ return image
+
+
+class Adjustment(ImageProcessor):
+ color = 1.0
+ brightness = 1.0
+ contrast = 1.0
+ sharpness = 1.0
+
+ @classmethod
+ def process(cls, image, obj=None):
+ for name in ['Color', 'Brightness', 'Contrast', 'Sharpness']:
+ factor = getattr(cls, name.lower())
+ if factor != 1.0:
+ image = getattr(ImageEnhance, name)(image).enhance(factor)
+ return image
+
+
+class Reflection(ImageProcessor):
+ background_color = '#FFFFFF'
+ size = 0.0
+ opacity = 0.6
+
+ @classmethod
+ def process(cls, image, obj=None):
+ # convert bgcolor string to rgb value
+ background_color = ImageColor.getrgb(cls.background_color)
+ # copy orignial image and flip the orientation
+ reflection = image.copy().transpose(Image.FLIP_TOP_BOTTOM)
+ # create a new image filled with the bgcolor the same size
+ background = Image.new("RGB", image.size, background_color)
+ # calculate our alpha mask
+ start = int(255 - (255 * cls.opacity)) # The start of our gradient
+ steps = int(255 * cls.size) # the number of intermedite values
+ increment = (255 - start) / float(steps)
+ mask = Image.new('L', (1, 255))
+ for y in range(255):
+ if y < steps:
+ val = int(y * increment + start)
+ else:
+ val = 255
+ mask.putpixel((0, y), val)
+ alpha_mask = mask.resize(image.size)
+ # merge the reflection onto our background color using the alpha mask
+ reflection = Image.composite(background, reflection, alpha_mask)
+ # crop the reflection
+ reflection_height = int(image.size[1] * cls.size)
+ reflection = reflection.crop((0, 0, image.size[0], reflection_height))
+ # create new image sized to hold both the original image and the reflection
+ composite = Image.new("RGB", (image.size[0], image.size[1]+reflection_height), background_color)
+ # paste the orignal image and the reflection into the composite image
+ composite.paste(image, (0, 0))
+ composite.paste(reflection, (0, image.size[1]))
+ # return the image complete with reflection effect
+ return composite
+
+
+class Resize(ImageProcessor):
+ width = None
+ height = None
+ crop = False
+ upscale = False
+
+ @classmethod
+ def process(cls, image, obj=None):
+ cur_width, cur_height = image.size
+ if cls.crop:
+ crop_horz = getattr(obj, obj._ik.crop_horz_field, 1)
+ crop_vert = getattr(obj, obj._ik.crop_vert_field, 1)
+ ratio = max(float(cls.width)/cur_width, float(cls.height)/cur_height)
+ resize_x, resize_y = ((cur_width * ratio), (cur_height * ratio))
+ crop_x, crop_y = (abs(cls.width - resize_x), abs(cls.height - resize_y))
+ x_diff, y_diff = (int(crop_x / 2), int(crop_y / 2))
+ box_left, box_right = {
+ 0: (0, cls.width),
+ 1: (int(x_diff), int(x_diff + cls.width)),
+ 2: (int(crop_x), int(resize_x)),
+ }[crop_horz]
+ box_upper, box_lower = {
+ 0: (0, cls.height),
+ 1: (int(y_diff), int(y_diff + cls.height)),
+ 2: (int(crop_y), int(resize_y)),
+ }[crop_vert]
+ box = (box_left, box_upper, box_right, box_lower)
+ image = image.resize((int(resize_x), int(resize_y)), Image.ANTIALIAS).crop(box)
+ else:
+ if not cls.width is None and not cls.height is None:
+ ratio = min(float(cls.width)/cur_width,
+ float(cls.height)/cur_height)
+ else:
+ if cls.width is None:
+ ratio = float(cls.height)/cur_height
+ else:
+ ratio = float(cls.width)/cur_width
+ new_dimensions = (int(round(cur_width*ratio)),
+ int(round(cur_height*ratio)))
+ if new_dimensions[0] > cur_width or \
+ new_dimensions[1] > cur_height:
+ if not cls.upscale:
+ return image
+ image = image.resize(new_dimensions, Image.ANTIALIAS)
+ return image
+
+
+class Transpose(ImageProcessor):
+ """ Rotates or flips the image
+
+ Method should be one of the following strings:
+ - FLIP_LEFT RIGHT
+ - FLIP_TOP_BOTTOM
+ - ROTATE_90
+ - ROTATE_270
+ - ROTATE_180
+
+ """
+ method = 'FLIP_LEFT_RIGHT'
+
+ @classmethod
+ def process(cls, image, obj=None):
+ return image.transpose(getattr(Image, cls.method))