Last active
August 29, 2015 13:57
-
-
Save shazow/9655002 to your computer and use it in GitHub Desktop.
Thumbnailing helpers.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from math import ceil | |
def resize_dimensions(x, y, max_width=None, max_height=None, min_side=None, max_side=None): | |
if not any([max_width, max_height, min_side, max_side]): | |
return x, y | |
original_x, original_y = x, y | |
priority_width = True | |
if max_width and x > max_width: | |
ratio = max_width / float(x) | |
x *= ratio | |
y *= ratio | |
if max_height and y > max_height: | |
priority_width = False | |
ratio = max_height / float(y) | |
y *= ratio | |
x *= ratio | |
biggest_side = max(x, y) | |
if max_side and biggest_side > max_side: | |
priority_width = x == biggest_side | |
ratio = float(max_side) / biggest_side | |
x *= ratio | |
y *= ratio | |
smallest_side = min(x, y) | |
if min_side and smallest_side > min_side: | |
priority_width = x == smallest_side | |
ratio = float(min_side) / smallest_side | |
x *= ratio | |
y *= ratio | |
if priority_width: | |
x = round(x) | |
y = ceil((x / original_x) * original_y) | |
else: | |
y = round(y) | |
x = ceil((y / original_y) * original_x) | |
return int(x), int(y) | |
def crop_center(width, height, target_width, target_height): | |
""" | |
Only crops if the image is bigger than targets. | |
""" | |
left = max(0, int(round((width - target_width) / 2.0))) | |
top = max(0, int(round((height - target_height) / 2.0))) | |
right = int(round((width + min(width, target_width)) / 2.0)) | |
bottom = int(round((height + min(height, target_height)) / 2.0)) | |
return left, top, right, bottom |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def _path_trim(abs_path, rel_path): | |
cur_dir = os.path.dirname(rel_path) | |
while cur_dir: | |
abs_path = os.path.dirname(abs_path) | |
cur_dir = os.path.dirname(cur_dir) | |
return abs_path | |
def _get_thumbnail_path(file_name, file_path, file_url, size): | |
thumb_dir = os.path.join(_path_trim(file_path, file_name), 'thumbs') | |
thumb_url = os.path.join(_path_trim(file_url, file_name), 'thumbs') | |
filedir, filename = os.path.split(file_name) | |
basename, format = os.path.splitext(filename) | |
thumb_filename = basename + '_' + size + format | |
path = os.path.join(thumb_dir, filedir, thumb_filename) | |
url = os.path.join(thumb_url, filedir, thumb_filename) | |
return path, url | |
def thumbnail(file, ...): | |
""" | |
This function is a disaster due to restrictions in Django templatetags. Removed the disasterous parts. Enter at your own peril. | |
""" | |
time_started = time.time() | |
if not os.path.exists(file.path): | |
log.error("thumbnail: Original image does not exist: %s" % file.path) | |
return "" # TODO: Return a placeholder URL? | |
# ... | |
target_path, target_url = _get_thumbnail_path(file.name, file.path, file.url, size_name) | |
if os.path.exists(target_path): | |
# Does the thumb already exist? | |
if os.path.getmtime(file.path) <= os.path.getmtime(target_path): | |
# Still valid | |
return target_url | |
elif not os.path.isdir(os.path.dirname(target_path)): | |
# Does the directory need to be created? | |
os.makedirs(os.path.dirname(target_path)) | |
# Get original x, y | |
try: | |
image = Image.open(file.path) | |
except IOError, e: | |
raise ValueError("Failed to open image path: %s (error: %s)" % (file.path, e)) | |
if image.mode == 'P': | |
# Some people have uploaded jpeg images that are actually PNGs -- deal with this | |
image = image.convert('RGB') | |
original_x, original_y = image.size | |
x, y = resize_dimensions(original_x, original_y, max_width=max_width, max_height=max_height, min_side=min_side, max_side=max_side) | |
image.thumbnail([x, y], Image.ANTIALIAS) | |
if crop_size: | |
box = crop_center(x, y, crop_width, crop_height) | |
image = image.crop(box) | |
try: | |
image.save(target_path, "JPEG", quality=85, optimize=True) | |
except IOError: | |
image.save(target_path, "JPEG", quality=85) | |
time_elapsed = time.time() - time_started | |
log.info("Created new thumbnail in %s seconds: %s" % (time_elapsed, target_path)) | |
return target_url |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment