mirror of
https://github.com/Hopiu/django-imagekit.git
synced 2026-04-20 13:10:58 +00:00
PEP8-ing and whitespacing.
This commit is contained in:
parent
a45f3af2a5
commit
06c1c678b6
7 changed files with 113 additions and 100 deletions
|
|
@ -3,8 +3,8 @@ from django.template.loader import render_to_string
|
|||
|
||||
|
||||
class AdminThumbnail(object):
|
||||
"""A convenience utility for adding thumbnails to the Django admin change
|
||||
list.
|
||||
"""
|
||||
A convenience utility for adding thumbnails to Django's admin change list.
|
||||
|
||||
"""
|
||||
short_description = _('Thumbnail')
|
||||
|
|
@ -12,8 +12,8 @@ class AdminThumbnail(object):
|
|||
|
||||
def __init__(self, image_field, template=None):
|
||||
"""
|
||||
:param image_field: The name of the ImageField or ImageSpec on the model
|
||||
to use for the thumbnail.
|
||||
:param image_field: The name of the ImageField or ImageSpec on the
|
||||
model to use for the thumbnail.
|
||||
:param template: The template with which to render the thumbnail
|
||||
|
||||
"""
|
||||
|
|
@ -25,7 +25,7 @@ class AdminThumbnail(object):
|
|||
|
||||
if not thumbnail:
|
||||
raise Exception('The property {0} is not defined on {1}.'.format(
|
||||
obj, self.image_field))
|
||||
obj, self.image_field))
|
||||
|
||||
original_image = getattr(thumbnail, 'source_file', None) or thumbnail
|
||||
template = self.template or 'imagekit/admin/thumbnail.html'
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
"""Flushes the cached ImageKit images.
|
||||
"""
|
||||
Flushes and re-caches all images under ImageKit.
|
||||
|
||||
"""
|
||||
|
||||
from django.db.models.loading import cache
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@ class _ImageSpecMixin(object):
|
|||
|
||||
|
||||
class ImageSpec(_ImageSpecMixin):
|
||||
"""The heart and soul of the ImageKit library, ImageSpec allows you to add
|
||||
"""
|
||||
The heart and soul of the ImageKit library, ImageSpec allows you to add
|
||||
variants of uploaded images to your models.
|
||||
|
||||
"""
|
||||
|
||||
_upload_to_attr = 'cache_to'
|
||||
|
||||
def __init__(self, processors=None, quality=70, format=None,
|
||||
|
|
@ -41,31 +41,31 @@ class ImageSpec(_ImageSpecMixin):
|
|||
"""
|
||||
:param processors: A list of processors to run on the original image.
|
||||
:param quality: The quality of the output image. This option is only
|
||||
used for the JPEG format.
|
||||
:param format: The format of the output file. If not provided, ImageSpec
|
||||
will try to guess the appropriate format based on the extension
|
||||
of the filename and the format of the input image.
|
||||
used for the JPEG format.
|
||||
:param format: The format of the output file. If not provided,
|
||||
ImageSpec will try to guess the appropriate format based on the
|
||||
extension of the filename and the format of the input image.
|
||||
:param image_field: The name of the model property that contains the
|
||||
original image.
|
||||
:param pre_cache: A boolean that specifies whether the image should be
|
||||
generated immediately (True) or on demand (False).
|
||||
original image.
|
||||
:param pre_cache: A boolean that specifies whether the image should
|
||||
be generated immediately (True) or on demand (False).
|
||||
:param storage: A Django storage system to use to save the generated
|
||||
image.
|
||||
image.
|
||||
:param cache_to: Specifies the filename to use when saving the image
|
||||
cache file. This is modeled after ImageField's ``upload_to`` and
|
||||
can be either a string (that specifies a directory) or a
|
||||
callable (that returns a filepath). Callable values should
|
||||
accept the following arguments:
|
||||
cache file. This is modeled after ImageField's ``upload_to`` and
|
||||
can be either a string (that specifies a directory) or a
|
||||
callable (that returns a filepath). Callable values should
|
||||
accept the following arguments:
|
||||
|
||||
- instance -- The model instance this spec belongs to
|
||||
- path -- The path of the original image
|
||||
- specname -- the property name that the spec is bound to on
|
||||
the model instance
|
||||
- extension -- A recommended extension. If the format of the
|
||||
spec is set explicitly, this suggestion will be
|
||||
based on that format. if not, the extension of the
|
||||
original file will be passed. You do not have to use
|
||||
this extension, it's only a recommendation.
|
||||
- instance -- The model instance this spec belongs to
|
||||
- path -- The path of the original image
|
||||
- specname -- the property name that the spec is bound to on
|
||||
the model instance
|
||||
- extension -- A recommended extension. If the format of the
|
||||
spec is set explicitly, this suggestion will be
|
||||
based on that format. if not, the extension of the
|
||||
original file will be passed. You do not have to use
|
||||
this extension, it's only a recommendation.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ class ImageSpec(_ImageSpecMixin):
|
|||
|
||||
def _get_suggested_extension(name, format):
|
||||
if format:
|
||||
# Try to look up an extension by the format
|
||||
# Try to look up an extension by the format.
|
||||
extensions = [k for k, v in Image.EXTENSION.iteritems() \
|
||||
if v == format.upper()]
|
||||
else:
|
||||
|
|
@ -112,7 +112,6 @@ def _get_suggested_extension(name, format):
|
|||
|
||||
|
||||
class _ImageSpecFileMixin(object):
|
||||
|
||||
def _process_content(self, filename, content):
|
||||
img = open_image(content)
|
||||
original_format = img.format
|
||||
|
|
@ -161,18 +160,20 @@ class ImageSpecFile(_ImageSpecFileMixin, ImageFieldFile):
|
|||
return super(ImageFieldFile, self).url
|
||||
|
||||
def _create(self, lazy=False):
|
||||
"""Creates a new image by running the processors on the source file.
|
||||
"""
|
||||
Creates a new image by running the processors on the source file.
|
||||
|
||||
Keyword Arguments:
|
||||
lazy -- True if an already-existing image should be returned; False if
|
||||
a new image should be created and the existing one overwritten.
|
||||
lazy -- True if an already-existing image should be returned;
|
||||
False if a new image should be created and the existing
|
||||
one overwritten.
|
||||
|
||||
"""
|
||||
if lazy and (getattr(self, '_file', None) or self.storage.exists(self.name)):
|
||||
return
|
||||
|
||||
if self.source_file: # TODO: Should we error here or something if the source_file doesn't exist?
|
||||
# Process the original image file
|
||||
# Process the original image file.
|
||||
try:
|
||||
fp = self.source_file.storage.open(self.source_file.name)
|
||||
except IOError:
|
||||
|
|
@ -184,7 +185,8 @@ class ImageSpecFile(_ImageSpecFileMixin, ImageFieldFile):
|
|||
self.storage.save(self.name, content)
|
||||
|
||||
def delete(self, save=False):
|
||||
"""Pulled almost verbatim from ``ImageFieldFile.delete()`` and
|
||||
"""
|
||||
Pulled almost verbatim from ``ImageFieldFile.delete()`` and
|
||||
``FieldFile.delete()`` but with the attempts to reset the instance
|
||||
property removed.
|
||||
|
||||
|
|
@ -194,7 +196,7 @@ class ImageSpecFile(_ImageSpecFileMixin, ImageFieldFile):
|
|||
del self._dimensions_cache
|
||||
|
||||
# Only close the file if it's already open, which we know by the
|
||||
# presence of self._file
|
||||
# presence of self._file.
|
||||
if hasattr(self, '_file'):
|
||||
self.close()
|
||||
del self.file
|
||||
|
|
@ -204,7 +206,7 @@ class ImageSpecFile(_ImageSpecFileMixin, ImageFieldFile):
|
|||
except (NotImplementedError, IOError):
|
||||
pass
|
||||
|
||||
# Delete the filesize cache
|
||||
# Delete the filesize cache.
|
||||
if hasattr(self, '_size'):
|
||||
del self._size
|
||||
self._committed = False
|
||||
|
|
@ -217,9 +219,10 @@ class ImageSpecFile(_ImageSpecFileMixin, ImageFieldFile):
|
|||
return _get_suggested_extension(self.source_file.name, self.field.format)
|
||||
|
||||
def _default_cache_to(self, instance, path, specname, extension):
|
||||
"""Determines the filename to use for the transformed image. Can be
|
||||
overridden on a per-spec basis by setting the cache_to property on the
|
||||
spec.
|
||||
"""
|
||||
Determines the filename to use for the transformed image. Can be
|
||||
overridden on a per-spec basis by setting the cache_to property on
|
||||
the spec.
|
||||
|
||||
"""
|
||||
filepath, basename = os.path.split(path)
|
||||
|
|
@ -253,10 +256,10 @@ class ImageSpecFile(_ImageSpecFileMixin, ImageFieldFile):
|
|||
|
||||
@name.setter
|
||||
def name(self, value):
|
||||
# TODO: Figure out a better way to handle this. We really don't want to
|
||||
# allow anybody to set the name, but ``File.__init__`` (which is called
|
||||
# by ``ImageSpecFile.__init__``) does, so we have to allow it at least
|
||||
# that one time.
|
||||
# TODO: Figure out a better way to handle this. We really don't want
|
||||
# to allow anybody to set the name, but ``File.__init__`` (which is
|
||||
# called by ``ImageSpecFile.__init__``) does, so we have to allow it
|
||||
# at least that one time.
|
||||
pass
|
||||
|
||||
|
||||
|
|
@ -322,7 +325,8 @@ class ProcessedImageFieldFile(ImageFieldFile, _ImageSpecFileMixin):
|
|||
|
||||
|
||||
class ProcessedImageField(models.ImageField, _ImageSpecMixin):
|
||||
"""ProcessedImageField is an ImageField that runs processors on the uploaded
|
||||
"""
|
||||
ProcessedImageField is an ImageField that runs processors on the uploaded
|
||||
image *before* saving it to storage. This is in contrast to specs, which
|
||||
maintain the original. Useful for coercing fileformats or keeping images
|
||||
within a reasonable size.
|
||||
|
|
@ -336,12 +340,11 @@ class ProcessedImageField(models.ImageField, _ImageSpecMixin):
|
|||
**kwargs):
|
||||
"""
|
||||
The ProcessedImageField constructor accepts all of the arguments that
|
||||
the :class:`django.db.models.ImageField` constructor accepts, as well as
|
||||
the ``processors``, ``format``, and ``quality`` arguments of
|
||||
the :class:`django.db.models.ImageField` constructor accepts, as well
|
||||
as the ``processors``, ``format``, and ``quality`` arguments of
|
||||
:class:`imagekit.models.ImageSpec`.
|
||||
|
||||
"""
|
||||
|
||||
_ImageSpecMixin.__init__(self, processors, quality=quality,
|
||||
format=format)
|
||||
models.ImageField.__init__(self, verbose_name, name, width_field,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
"""Imagekit image processors.
|
||||
"""
|
||||
Imagekit image processors.
|
||||
|
||||
A processor accepts an image, does some stuff, and returns the result.
|
||||
Processors can do anything with the image you want, but their responsibilities
|
||||
|
|
@ -6,12 +7,13 @@ should be limited to image manipulations--they should be completely decoupled
|
|||
from both the filesystem and the ORM.
|
||||
|
||||
"""
|
||||
from imagekit.lib import *
|
||||
from imagekit.lib import Image, ImageColor, ImageEnhance
|
||||
from imagekit.processors import resize
|
||||
|
||||
|
||||
class ProcessorPipeline(list):
|
||||
"""A :class:`list` of other processors. This class allows any object that
|
||||
"""
|
||||
A :class:`list` of other processors. This class allows any object that
|
||||
knows how to deal with a single processor to deal with a list of them.
|
||||
For example::
|
||||
|
||||
|
|
@ -25,27 +27,28 @@ class ProcessorPipeline(list):
|
|||
|
||||
|
||||
class Adjust(object):
|
||||
"""Performs color, brightness, contrast, and sharpness enhancements on the
|
||||
"""
|
||||
Performs color, brightness, contrast, and sharpness enhancements on the
|
||||
image. See :mod:`PIL.ImageEnhance` for more imformation.
|
||||
|
||||
"""
|
||||
def __init__(self, color=1.0, brightness=1.0, contrast=1.0, sharpness=1.0):
|
||||
"""
|
||||
:param color: A number between 0 and 1 that specifies the saturation of
|
||||
the image. 0 corresponds to a completely desaturated image
|
||||
(black and white) and 1 to the original color.
|
||||
See :class:`PIL.ImageEnhance.Color`
|
||||
:param brightness: A number representing the brightness; 0 results in a
|
||||
completely black image whereas 1 corresponds to the brightness
|
||||
of the original. See :class:`PIL.ImageEnhance.Brightness`
|
||||
:param color: A number between 0 and 1 that specifies the saturation
|
||||
of the image. 0 corresponds to a completely desaturated image
|
||||
(black and white) and 1 to the original color.
|
||||
See :class:`PIL.ImageEnhance.Color`
|
||||
:param brightness: A number representing the brightness; 0 results in
|
||||
a completely black image whereas 1 corresponds to the brightness
|
||||
of the original. See :class:`PIL.ImageEnhance.Brightness`
|
||||
:param contrast: A number representing the contrast; 0 results in a
|
||||
completely gray image whereas 1 corresponds to the contrast of
|
||||
the original. See :class:`PIL.ImageEnhance.Contrast`
|
||||
completely gray image whereas 1 corresponds to the contrast of
|
||||
the original. See :class:`PIL.ImageEnhance.Contrast`
|
||||
:param sharpness: A number representing the sharpness; 0 results in a
|
||||
blurred image; 1 corresponds to the original sharpness; 2
|
||||
results in a sharpened image. See
|
||||
:class:`PIL.ImageEnhance.Sharpness`
|
||||
|
||||
blurred image; 1 corresponds to the original sharpness; 2
|
||||
results in a sharpened image. See
|
||||
:class:`PIL.ImageEnhance.Sharpness`
|
||||
|
||||
"""
|
||||
self.color = color
|
||||
self.brightness = brightness
|
||||
|
|
@ -65,25 +68,26 @@ class Adjust(object):
|
|||
|
||||
|
||||
class Reflection(object):
|
||||
"""Creates an image with a reflection.
|
||||
|
||||
"""
|
||||
Creates an image with a reflection.
|
||||
|
||||
"""
|
||||
background_color = '#FFFFFF'
|
||||
size = 0.0
|
||||
opacity = 0.6
|
||||
|
||||
def process(self, img):
|
||||
# convert bgcolor string to rgb value
|
||||
# Convert bgcolor string to RGB value.
|
||||
background_color = ImageColor.getrgb(self.background_color)
|
||||
# handle palleted images
|
||||
# Handle palleted images.
|
||||
img = img.convert('RGB')
|
||||
# copy orignial image and flip the orientation
|
||||
# Copy orignial image and flip the orientation.
|
||||
reflection = img.copy().transpose(Image.FLIP_TOP_BOTTOM)
|
||||
# create a new image filled with the bgcolor the same size
|
||||
# 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 * self.opacity)) # The start of our gradient
|
||||
steps = int(255 * self.size) # the number of intermedite values
|
||||
# Calculate our alpha mask.
|
||||
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):
|
||||
|
|
@ -93,22 +97,24 @@ class Reflection(object):
|
|||
val = 255
|
||||
mask.putpixel((0, y), val)
|
||||
alpha_mask = mask.resize(img.size)
|
||||
# merge the reflection onto our background color using the alpha mask
|
||||
# Merge the reflection onto our background color using the alpha mask.
|
||||
reflection = Image.composite(background, reflection, alpha_mask)
|
||||
# crop the reflection
|
||||
# Crop the reflection.
|
||||
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)
|
||||
# paste the orignal image and the reflection into the composite image
|
||||
# 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)
|
||||
# Paste the orignal image and the reflection into the composite image.
|
||||
composite.paste(img, (0, 0))
|
||||
composite.paste(reflection, (0, img.size[1]))
|
||||
# return the image complete with reflection effect
|
||||
# Return the image complete with reflection effect.
|
||||
return composite
|
||||
|
||||
|
||||
class Transpose(object):
|
||||
""" Rotates or flips the image
|
||||
"""
|
||||
Rotates or flips the image.
|
||||
|
||||
"""
|
||||
AUTO = 'auto'
|
||||
|
|
@ -133,18 +139,18 @@ class Transpose(object):
|
|||
def __init__(self, *args):
|
||||
"""
|
||||
Possible arguments:
|
||||
- Transpose.AUTO
|
||||
- Transpose.AUTO
|
||||
- Transpose.FLIP_HORIZONTAL
|
||||
- Transpose.FLIP_VERTICAL
|
||||
- Transpose.ROTATE_90
|
||||
- Transpose.ROTATE_180
|
||||
- Transpose.ROTATE_270
|
||||
|
||||
The order of the arguments dictates the order in which the Transposition
|
||||
steps are taken.
|
||||
The order of the arguments dictates the order in which the
|
||||
Transposition steps are taken.
|
||||
|
||||
If Transpose.AUTO is present, all other arguments are ignored, and the
|
||||
processor will attempt to rotate the image according to the
|
||||
If Transpose.AUTO is present, all other arguments are ignored, and
|
||||
the processor will attempt to rotate the image according to the
|
||||
EXIF Orientation data.
|
||||
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ from imagekit.lib import Image
|
|||
|
||||
|
||||
class _Resize(object):
|
||||
|
||||
width = None
|
||||
height = None
|
||||
|
||||
|
|
@ -17,10 +16,10 @@ class _Resize(object):
|
|||
|
||||
|
||||
class Crop(_Resize):
|
||||
"""Resizes an image , cropping it to the specified width and height.
|
||||
"""
|
||||
Resizes an image , cropping it to the specified width and height.
|
||||
|
||||
"""
|
||||
|
||||
TOP_LEFT = 'tl'
|
||||
TOP = 't'
|
||||
TOP_RIGHT = 'tr'
|
||||
|
|
@ -47,8 +46,8 @@ class Crop(_Resize):
|
|||
"""
|
||||
:param width: The target width, in pixels.
|
||||
:param height: The target height, in pixels.
|
||||
:param anchor: Specifies which part of the image should be retained when
|
||||
cropping. Valid values are:
|
||||
:param anchor: Specifies which part of the image should be retained
|
||||
when cropping. Valid values are:
|
||||
|
||||
- Crop.TOP_LEFT
|
||||
- Crop.TOP
|
||||
|
|
@ -68,7 +67,7 @@ class Crop(_Resize):
|
|||
cur_width, cur_height = img.size
|
||||
horizontal_anchor, vertical_anchor = Crop._ANCHOR_PTS[self.anchor or \
|
||||
Crop.CENTER]
|
||||
ratio = max(float(self.width) / cur_width, float(self.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(self.width - resize_x), abs(self.height - resize_y))
|
||||
x_diff, y_diff = (int(crop_x / 2), int(crop_y / 2))
|
||||
|
|
@ -88,17 +87,17 @@ class Crop(_Resize):
|
|||
|
||||
|
||||
class Fit(_Resize):
|
||||
"""Resizes an image to fit within the specified dimensions.
|
||||
"""
|
||||
Resizes an image to fit within the specified dimensions.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, width=None, height=None, upscale=None):
|
||||
"""
|
||||
:param width: The maximum width of the desired image.
|
||||
:param height: The maximum height of the desired image.
|
||||
:param upscale: A boolean value specifying whether the image should be
|
||||
enlarged if its dimensions are smaller than the target
|
||||
dimensions.
|
||||
:param upscale: A boolean value specifying whether the image should
|
||||
be enlarged if its dimensions are smaller than the target
|
||||
dimensions.
|
||||
|
||||
"""
|
||||
super(Fit, self).__init__(width, height)
|
||||
|
|
|
|||
|
|
@ -5,24 +5,30 @@ from imagekit.specs import ImageSpec
|
|||
class ResizeToWidth(processors.Resize):
|
||||
width = 100
|
||||
|
||||
|
||||
class ResizeToHeight(processors.Resize):
|
||||
height = 100
|
||||
|
||||
|
||||
class ResizeToFit(processors.Resize):
|
||||
width = 100
|
||||
height = 100
|
||||
|
||||
|
||||
class ResizeCropped(ResizeToFit):
|
||||
crop = ('center', 'center')
|
||||
|
||||
|
||||
class TestResizeToWidth(ImageSpec):
|
||||
access_as = 'to_width'
|
||||
processors = [ResizeToWidth]
|
||||
|
||||
|
||||
class TestResizeToHeight(ImageSpec):
|
||||
access_as = 'to_height'
|
||||
processors = [ResizeToHeight]
|
||||
|
||||
|
||||
class TestResizeCropped(ImageSpec):
|
||||
access_as = 'cropped'
|
||||
processors = [ResizeCropped]
|
||||
|
|
|
|||
Loading…
Reference in a new issue