process() accepts file

In the old IK API, processors (like `Transpose`) were able to access
the file by inspecting the model instance (which carried an options
object that specified the attribute name of the ImageField from which
the file could be extracted). Since the new API allows for multiple
ImageFields (and because IKOptions have been removed), it became
necessary to provide more information. Initially, this was accomplished
by passing the spec to `process()`, however with the addition of
ProcessedImageField, it became clear the a cleaner solution was to pass
only the field file (ImageSpecFile or ProcessedImageFieldFile).

This keeps the ORM stuff (fields, etc.) out of the `ImageProcessor` API
but (because field files, not just regular files, are passed) the
average hacker can still have their processor make use of model
information by accessing the model through the file's `instance`
property.
This commit is contained in:
Matthew Tretter 2011-09-22 17:31:26 -04:00
parent bd7eb7284b
commit 0ef56e1aaa
2 changed files with 13 additions and 13 deletions

View file

@ -24,11 +24,11 @@ class _ImageSpecMixin(object):
self.quality = quality
self.format = format
def process(self, image, obj):
def process(self, image, file):
fmt = image.format
img = image.copy()
for proc in self.processors:
img, fmt = proc.process(img, fmt, obj, self)
img, fmt = proc.process(img, fmt, file)
format = self.format or fmt
img.format = format
return img, format
@ -161,7 +161,7 @@ class ImageSpecFile(object):
return
fp.seek(0)
fp = StringIO(fp.read())
self._img, self._fmt = self._spec.process(Image.open(fp), self._obj)
self._img, self._fmt = self._spec.process(Image.open(fp), self)
# save the new image to the cache
content = ContentFile(self._get_imgfile().read())
self.storage.save(self.name, content)
@ -270,7 +270,7 @@ def _post_save_handler(sender, instance=None, created=False, raw=False, **kwargs
if imgfield:
newfile = imgfield.storage.open(imgfield.name)
img = Image.open(newfile)
img, format = spec_file._spec.process(img, instance)
img, format = spec_file._spec.process(img, spec_file)
if format != 'JPEG':
imgfile = img_to_fobj(img, format)
else:
@ -347,7 +347,7 @@ class ProcessedImageFieldFile(ImageFieldFile):
def save(self, name, content, save=True):
new_filename = self.field.generate_filename(self.instance, name)
img = Image.open(content)
img, format = self.field.process(img, self.instance)
img, format = self.field.process(img, self)
format = self._get_format(new_filename, format)
if format != 'JPEG':
imgfile = img_to_fobj(img, format)

View file

@ -11,7 +11,7 @@ from imagekit.lib import *
class ImageProcessor(object):
""" Base image processor class """
def process(self, img, fmt, obj, spec):
def process(self, img, fmt, file):
return img, fmt
@ -23,7 +23,7 @@ class Adjust(ImageProcessor):
self.contrast = contrast
self.sharpness = sharpness
def process(self, img, fmt, obj, spec):
def process(self, img, fmt, file):
img = img.convert('RGB')
for name in ['Color', 'Brightness', 'Contrast', 'Sharpness']:
factor = getattr(self, name.lower())
@ -40,7 +40,7 @@ class Reflection(ImageProcessor):
size = 0.0
opacity = 0.6
def process(self, img, fmt, obj, spec):
def process(self, img, fmt, file):
# convert bgcolor string to rgb value
background_color = ImageColor.getrgb(self.background_color)
# handle palleted images
@ -88,7 +88,7 @@ class _Resize(ImageProcessor):
if height is not None:
self.height = height
def process(self, img, fmt, obj, spec):
def process(self, img, fmt, file):
raise NotImplementedError('process must be overridden by subclasses.')
@ -120,7 +120,7 @@ class Crop(_Resize):
super(Crop, self).__init__(width, height)
self.anchor = anchor
def process(self, img, fmt, obj, spec):
def process(self, img, fmt, file):
cur_width, cur_height = img.size
horizontal_anchor, vertical_anchor = Crop._ANCHOR_PTS[self.anchor or \
Crop.CENTER]
@ -148,7 +148,7 @@ class Fit(_Resize):
super(Fit, self).__init__(width, height)
self.upscale = upscale
def process(self, img, fmt, obj, spec):
def process(self, img, fmt, file):
cur_width, cur_height = img.size
if not self.width is None and not self.height is None:
ratio = min(float(self.width)/cur_width,
@ -196,10 +196,10 @@ class Transpose(ImageProcessor):
method = 'auto'
def process(self, img, fmt, obj, spec):
def process(self, img, fmt, file):
if self.method == 'auto':
try:
orientation = Image.open(spec._get_imgfield(obj).file)._getexif()[0x0112]
orientation = Image.open(file.file)._getexif()[0x0112]
ops = self.EXIF_ORIENTATION_STEPS[orientation]
except:
ops = []