Processors are now instance-based.

This commit is contained in:
Matthew Tretter 2011-09-08 09:15:08 -04:00
parent a9895f335a
commit cd3395b68f
2 changed files with 50 additions and 55 deletions

View file

@ -11,22 +11,22 @@ from imagekit.lib import *
class ImageProcessor(object):
""" Base image processor class """
@classmethod
def process(cls, img, fmt, obj):
def process(self, img, fmt, obj):
return img, fmt
class Adjustment(ImageProcessor):
color = 1.0
brightness = 1.0
contrast = 1.0
sharpness = 1.0
class Adjust(ImageProcessor):
def __init__(self, color=1.0, brightness=1.0, contrast=1.0, sharpness=1.0):
self.color = color
self.brightness = brightness
self.contrast = contrast
self.sharpness = sharpness
@classmethod
def process(cls, img, fmt, obj):
def process(self, img, fmt, obj):
img = img.convert('RGB')
for name in ['Color', 'Brightness', 'Contrast', 'Sharpness']:
factor = getattr(cls, name.lower())
factor = getattr(self, name.lower())
if factor != 1.0:
try:
img = getattr(ImageEnhance, name)(img).enhance(factor)
@ -39,9 +39,8 @@ class Format(ImageProcessor):
format = 'JPEG'
extension = 'jpg'
@classmethod
def process(cls, img, fmt, obj):
return img, cls.format
def process(self, img, fmt, obj):
return img, self.format
class Reflection(ImageProcessor):
@ -49,10 +48,9 @@ class Reflection(ImageProcessor):
size = 0.0
opacity = 0.6
@classmethod
def process(cls, img, fmt, obj):
def process(self, img, fmt, obj):
# convert bgcolor string to rgb value
background_color = ImageColor.getrgb(cls.background_color)
background_color = ImageColor.getrgb(self.background_color)
# handle palleted images
img = img.convert('RGB')
# copy orignial image and flip the orientation
@ -60,8 +58,8 @@ class Reflection(ImageProcessor):
# create a new image filled with the bgcolor the same size
background = Image.new("RGB", img.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
start = int(255 - (255 * self.opacity)) # The start of our gradient
steps = int(255 * self.size) # the number of intermedite values
increment = (255 - start) / float(steps)
mask = Image.new('L', (1, 255))
for y in range(255):
@ -74,7 +72,7 @@ class Reflection(ImageProcessor):
# merge the reflection onto our background color using the alpha mask
reflection = Image.composite(background, reflection, alpha_mask)
# crop the reflection
reflection_height = int(img.size[1] * cls.size)
reflection_height = int(img.size[1] * self.size)
reflection = reflection.crop((0, 0, img.size[0], reflection_height))
# create new image sized to hold both the original image and the reflection
composite = Image.new("RGB", (img.size[0], img.size[1]+reflection_height), background_color)
@ -88,47 +86,48 @@ class Reflection(ImageProcessor):
class Resize(ImageProcessor):
width = None
height = None
crop = False
upscale = False
def __init__(self, width, height, crop=False, upscale=False):
self.width = width
self.height = height
self.crop = crop
self.upscale = upscale
@classmethod
def process(cls, img, fmt, obj):
def process(self, img, fmt, obj):
cur_width, cur_height = img.size
if cls.crop:
if self.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)
ratio = max(float(self.width)/cur_width, float(self.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))
crop_x, crop_y = (abs(self.width - resize_x), abs(self.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)),
0: (0, self.width),
1: (int(x_diff), int(x_diff + self.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)),
0: (0, self.height),
1: (int(y_diff), int(y_diff + self.height)),
2: (int(crop_y), int(resize_y)),
}[crop_vert]
box = (box_left, box_upper, box_right, box_lower)
img = img.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)
if not self.width is None and not self.height is None:
ratio = min(float(self.width)/cur_width,
float(self.height)/cur_height)
else:
if cls.width is None:
ratio = float(cls.height)/cur_height
if self.width is None:
ratio = float(self.height)/cur_height
else:
ratio = float(cls.width)/cur_width
ratio = float(self.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:
if not self.upscale:
return img, fmt
img = img.resize(new_dimensions, Image.ANTIALIAS)
return img, fmt
@ -162,16 +161,15 @@ class Transpose(ImageProcessor):
method = 'auto'
@classmethod
def process(cls, img, fmt, obj):
if cls.method == 'auto':
def process(self, img, fmt, obj):
if self.method == 'auto':
try:
orientation = Image.open(obj._imgfield.file)._getexif()[0x0112]
ops = cls.EXIF_ORIENTATION_STEPS[orientation]
ops = self.EXIF_ORIENTATION_STEPS[orientation]
except:
ops = []
else:
ops = [cls.method]
ops = [self.method]
for method in ops:
img = img.transpose(getattr(Image, method))
return img, fmt

View file

@ -14,20 +14,17 @@ from django.core.files.base import ContentFile
class ImageSpec(object):
pre_cache = False
quality = 70
increment_count = False
processors = []
@classmethod
def name(cls):
return getattr(cls, 'access_as', cls.__name__.lower())
def __init__(self, processors, pre_cache=False, quality=70, increment_count=False):
self.processors = list(processors or [])
self.pre_cache = pre_cache
self.quality = quality
self.increment_count = increment_count
@classmethod
def process(cls, image, obj):
def process(self, image, obj):
fmt = image.format
img = image.copy()
for proc in cls.processors:
for proc in self.processors:
img, fmt = proc.process(img, fmt, obj)
img.format = fmt
return img, fmt
@ -84,7 +81,7 @@ class Accessor(object):
filepath, basename = os.path.split(self._obj._imgfield.name)
filename, extension = os.path.splitext(basename)
for processor in self.spec.processors:
if issubclass(processor, processors.Format):
if isinstance(processor, processors.Format):
extension = processor.extension
filename_format_dict = {'filename': filename,
'specname': self.property_name,