Skip to content

Commit

Permalink
initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
Stefan Foulis committed Apr 23, 2009
0 parents commit cd4e914
Show file tree
Hide file tree
Showing 21 changed files with 4,983 additions and 0 deletions.
Empty file added image_filer/__init__.py
Empty file.
33 changes: 33 additions & 0 deletions image_filer/admin.py
@@ -0,0 +1,33 @@
from django.contrib import admin
from models import Folder, Image, FolderPermission, ImagePermission
from models import ImageManipulationProfile, ImageManipulationStep, ImageManipulationTemplate
from models import Bucket, BucketItem

admin.site.register([FolderPermission, ImagePermission, ImageManipulationTemplate])


class ImageAdmin(admin.ModelAdmin):
list_display = ('label','admin_thumbnail', 'has_all_mandatory_data')
list_per_page = 10
search_fields = ['name', 'original_filename','default_alt_text','default_caption','usage_restriction_notes','notes']
admin.site.register(Image, ImageAdmin)

class FolderAdmin(admin.ModelAdmin):
list_display = ('name', 'owner',)
list_per_page = 20
admin.site.register(Folder, FolderAdmin)

class ImageManipulationStepInline(admin.TabularInline):
model = ImageManipulationStep
class ImageManipulationProfileAdmin(admin.ModelAdmin):
inlines = [ ImageManipulationStepInline, ]
admin.site.register(ImageManipulationProfile, ImageManipulationProfileAdmin)



class BucketItemInline(admin.TabularInline):
model = BucketItem
class BucketAdmin(admin.ModelAdmin):
model = Bucket
inlines = [ BucketItemInline, ]
admin.site.register(Bucket, BucketAdmin)
50 changes: 50 additions & 0 deletions image_filer/fields.py
@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
# --------------------------------------- fields.py --------------------------------------- #
# http://www.djangosnippets.org/snippets/513/
# 2009-04-05 Stefan Foulis: added base64 encoding to avoid problems with unicode strings

from django.db import models

try:
import cPickle as pickle
except ImportError:
import pickle

class PickledObject(str):
"""A subclass of string so it can be told whether a string is
a pickled object or not (if the object is an instance of this class
then it must [well, should] be a pickled one)."""
pass

class PickledObjectField(models.Field):
__metaclass__ = models.SubfieldBase

def to_python(self, value):
if isinstance(value, PickledObject):
# If the value is a definite pickle; and an error is raised in de-pickling
# it should be allowed to propogate.
return pickle.loads( str(value).decode('base64') )
else:
try:
return pickle.loads( str(value).decode('base64') )
except:
# If an error was raised, just return the plain value
return value

def get_db_prep_save(self, value):
if value is not None and not isinstance(value, PickledObject):
value = PickledObject( pickle.dumps(value).encode('base64') )
return value

def get_internal_type(self):
return 'TextField'

def get_db_prep_lookup(self, lookup_type, value):
if lookup_type == 'exact':
value = self.get_db_prep_save(value)
return super(PickledObjectField, self).get_db_prep_lookup(lookup_type, value)
elif lookup_type == 'in':
value = [self.get_db_prep_save(v) for v in value]
return super(PickledObjectField, self).get_db_prep_lookup(lookup_type, value)
else:
raise TypeError('Lookup type %s is not supported.' % lookup_type)
146 changes: 146 additions & 0 deletions image_filer/filters.py
@@ -0,0 +1,146 @@
from inspect import isclass
try:
import Image
import ImageColor
import ImageFile
import ImageFilter
import ImageEnhance
except ImportError:
try:
from PIL import Image
from PIL import ImageColor
from PIL import ImageFile
from PIL import ImageFilter
from PIL import ImageEnhance
except ImportError:
raise ImportError("The Python Imaging Library was not found.")

filters = []

class BaseFilter(object):
pass

class ResizeFilter(BaseFilter):
name = "Resize to specified dimensions"
identifier = "resize_simple"
def render(self, im, size_x=128, size_y=64, crop=True, crop_from='top', upscale=True):
cur_width, cur_height = im.size
new_width, new_height = (size_x, size_y)
if crop:
ratio = max(float(new_width)/cur_width,float(new_height)/cur_height)
x = (cur_width * ratio)
y = (cur_height * ratio)
xd = abs(new_width - x)
yd = abs(new_height - y)
x_diff = int(xd / 2)
y_diff = int(yd / 2)
if crop_from == 'top':
box = (int(x_diff), 0, int(x_diff+new_width), new_height)
elif crop_from == 'left':
box = (0, int(y_diff), new_width, int(y_diff+new_height))
elif crop_from == 'bottom':
box = (int(x_diff), int(yd), int(x_diff+new_width), int(y)) # y - yd = new_height
elif crop_from == 'right':
box = (int(xd), int(y_diff), int(x), int(y_diff+new_height)) # x - xd = new_width
else:
box = (int(x_diff), int(y_diff), int(x_diff+new_width), int(y_diff+new_height))
im = im.resize((int(x), int(y)), Image.ANTIALIAS).crop(box)
else:
if not new_width == 0 and not new_height == 0:
ratio = min(float(new_width)/cur_width,
float(new_height)/cur_height)
else:
if new_width == 0:
ratio = float(new_height)/cur_height
else:
ratio = float(new_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 upscale:
return im
im = im.resize(new_dimensions, Image.ANTIALIAS)
return im
filters.append(ResizeFilter)
class TinyResizeFilterHack(ResizeFilter):
name = "Tiny Resize Filter Hack"
def render(self, im, size_x=24, size_y=24, crop=True, crop_from='top', upscale=True):
return super(TinyResizeFilterHack, self).render(im, size_x=size_x, size_y=size_y)
filters.append(TinyResizeFilterHack)

class ReflectionFilter(BaseFilter):
name = "Sexy Web 2.0 reflection filter"
identifier = "reflection"
def render(self, im, bgcolor="#FFFFFF", amount=0.4, opacity=0.6):
""" Returns the supplied PIL Image (im) with a reflection effect
bgcolor The background color of the reflection gradient
amount The height of the reflection as a percentage of the orignal image
opacity The initial opacity of the reflection gradient
Originally written for the Photologue image management system for Django
and Based on the original concept by Bernd Schlapsi
"""
# convert bgcolor string to rgb value
background_color = ImageColor.getrgb(bgcolor)

# copy orignial image and flip the orientation
reflection = im.copy().transpose(Image.FLIP_TOP_BOTTOM)

# create a new image filled with the bgcolor the same size
background = Image.new("RGB", im.size, background_color)

# calculate our alpha mask
start = int(255 - (255 * opacity)) # The start of our gradient
steps = int(255 * amount) # 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(im.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(im.size[1] * amount)
reflection = reflection.crop((0, 0, im.size[0], reflection_height))

# create new image sized to hold both the original image and the reflection
composite = Image.new("RGB", (im.size[0], im.size[1]+reflection_height), background_color)

# paste the orignal image and the reflection into the composite image
composite.paste(im, (0, 0))
composite.paste(reflection, (0, im.size[1]))

# return the image complete with reflection effect
return composite
filters.append(ReflectionFilter)

"""
Create image filter objects for all the built in PIL filters
"""
for n in dir(ImageFilter):
klass = getattr(ImageFilter, n)
if isclass(klass) and issubclass(klass, ImageFilter.BuiltinFilter) and \
hasattr(klass, 'name'):
class NewSubclass(BaseFilter):
_pil_filter = klass
name = klass.name
identifier = klass.name
def render(self, im):
return im.filter(self._pil_filter)
NewSubclass.__name__ = "%s%s" % (klass.name, "Filter")
filters.append(NewSubclass)



filters_by_identifier = {}
for filter in filters:
filters_by_identifier[filter.identifier] = filter

0 comments on commit cd4e914

Please sign in to comment.