Generated: Wed 2013-03-13 10:33 CET
Source file: /media/Envs/Envs/filer-gallery/lib/python2.7/site-packages/filer/thumbnail_processors.py
Stats: 0 executed, 61 missed, 7 excluded, 51 ignored
#-*- coding: utf-8 -*-
import re
try:
from PIL import Image
from PIL import ImageDraw
except ImportError:
try:
import Image
import ImageDraw
except ImportError:
raise ImportError("The Python Imaging Library was not found.")
from easy_thumbnails import processors
from filer.settings import FILER_SUBJECT_LOCATION_IMAGE_DEBUG
RE_SUBJECT_LOCATION = re.compile(r'^(\d+),(\d+)$')
def normalize_subject_location(subject_location):
if subject_location:
if isinstance(subject_location, basestring):
m = RE_SUBJECT_LOCATION.match(subject_location)
if m:
return (int(m.group(1)), int(m.group(2)))
else:
try:
return (int(subject_location[0]), int(subject_location[1]))
except (TypeError, ValueError):
pass
return False
def scale_and_crop_with_subject_location(im, size, subject_location=False,
crop=False, upscale=False, **kwargs):
"""
Like ``easy_thumbnails.processors.scale_and_crop``, but will use the
coordinates in ``subject_location`` to make sure that that part of the
image is in the center or at least somewhere on the cropped image.
Please not that this does *not* work correctly if the image has been
resized by a previous processor (e.g ``autocrop``).
``crop`` needs to be set for this to work, but any special cropping
parameters will be ignored.
"""
subject_location = normalize_subject_location(subject_location)
if not (subject_location and crop):
# use the normal scale_and_crop
return processors.scale_and_crop(im, size, crop=crop,
upscale=upscale, **kwargs)
# for here on we have a subject_location and cropping is on
# --snip-- this is a copy and paste of the first few
# lines of ``scale_and_crop``
source_x, source_y = [float(v) for v in im.size]
target_x, target_y = [float(v) for v in size]
if crop or not target_x or not target_y:
scale = max(target_x / source_x, target_y / source_y)
else:
scale = min(target_x / source_x, target_y / source_y)
# Handle one-dimensional targets.
if not target_x:
target_x = source_x * scale
elif not target_y:
target_y = source_y * scale
if scale < 1.0 or (scale > 1.0 and upscale):
im = im.resize((int(source_x * scale), int(source_y * scale)),
resample=Image.ANTIALIAS)
# --endsnip-- begin real code
# ===============================
# subject location aware cropping
# ===============================
# res_x, res_y: the resolution of the possibly already resized image
res_x, res_y = [float(v) for v in im.size]
# subj_x, subj_y: the position of the subject (maybe already re-scaled)
subj_x = res_x * float(subject_location[0]) / source_x
subj_y = res_y * float(subject_location[1]) / source_y
ex = (res_x - min(res_x, target_x)) / 2
ey = (res_y - min(res_y, target_y)) / 2
fx, fy = res_x - ex, res_y - ey
# box_width, box_height: dimensions of the target image
box_width, box_height = fx - ex, fy - ey
# try putting the box in the center around the subject point
# (this will be partially outside of the image in most cases)
tex, tey = subj_x - (box_width / 2), subj_y - (box_height / 2)
tfx, tfy = subj_x + (box_width / 2), subj_y + (box_height / 2)
if tex < 0:
# its out of the img to the left, move both to the right until tex is 0
tfx = tfx - tex # tex is negative!
tex = 0
elif tfx > res_x:
# its out of the img to the right
tex = tex - (tfx - res_x)
tfx = res_x
if tey < 0:
# its out of the img to the top, move both to the bottom until tey is 0
tfy = tfy - tey # tey is negative!)
tey = 0
elif tfy > res_y:
# its out of the img to the bottom
tey = tey - (tfy - res_y)
tfy = res_y
if ex or ey:
crop_box = ((int(tex), int(tey), int(tfx), int(tfy)))
if FILER_SUBJECT_LOCATION_IMAGE_DEBUG:
# draw elipse on focal point for Debugging
draw = ImageDraw.Draw(im)
esize = 10
draw.ellipse(((subj_x - esize, subj_y - esize),
(subj_x + esize, subj_y + esize)), outline="#FF0000")
im = im.crop(crop_box)
return im