papiez_ipsum/src/papiezator/pope_utils.py

110 lines
2.9 KiB
Python

from papiezator.models import PopeImage, PerfectPope, DECIMAL_PLACES
from PIL import Image
from io import BytesIO
from django.core.exceptions import ObjectDoesNotExist
from papiezator.papiezator_settings import REDIS_TTL
try:
from redis import Redis
from redis.exceptions import ConnectionError as RedisConnectionError
redis = Redis()
except ImportError:
redis = None
def select_best_pope(aspect_ratio, pope):
""" (float, pope) -> PopeImage
"""
pp = PerfectPope.objects.filter(aspect_ratio=aspect_ratio, pope=pope)
if pp:
return pp[0].image
# popes below and above this ratio
lte = PopeImage.objects.filter(aspect_ratio__lte=aspect_ratio, pope=pope).order_by('-aspect_ratio')[0:1]
gte = PopeImage.objects.filter(aspect_ratio__gte=aspect_ratio, pope=pope).order_by('aspect_ratio')[0:1]
if gte and lte:
lte, gte = lte[0], gte[0]
lte_distance = abs(aspect_ratio - lte.aspect_ratio)
gte_distance = abs(aspect_ratio - gte.aspect_ratio)
if lte_distance >= gte_distance:
return_image_path = gte
else:
return_image_path = lte
# if there are no popes above or below this ratio
elif gte:
return_image_path = gte[0]
elif lte:
return_image_path = lte[0]
# or even if there are no popes at all :c
else:
return None
return habemus_papam(aspect_ratio, image_path=return_image_path, pope=pope)
def habemus_papam(aspect_ratio, image_path, pope):
pp = PerfectPope(aspect_ratio=aspect_ratio, image=image_path, pope=pope)
pp.save()
return image_path
def unpopable(width, height):
if width == 0 or height == 0:
return True
if (width+height) >= 9001:
return True
return False
def read_pope_from_fs(width, height, pope_image):
im = Image.open(pope_image.path)
im = im.resize((width, height))
f = BytesIO() # FIXME: ceriously.
im.save(f, "jpeg")
f.seek(0)
return f.read()
def read_pope(width, height, pope_image):
""" (int, int, Pope) -> bytes
get pope and scale for display
"""
if redis:
try:
im = redis.get((width,height))
if not im:
im = read_pope_from_fs(width, height, pope_image)
redis.set((width,height), im)
redis.expire((width,height), REDIS_TTL)
except RedisConnectionError:
im = read_pope_from_fs(width, height, pope_image)
else: #TODO: join those two
im = read_pope_from_fs(width, height, pope_image)
return im
def parse_pope(path):
im = Image.open(path)
width, height = im.size
aspect_ratio = round(width/height, DECIMAL_PLACES)
return PopeImage(path=path, width=width, height=height, aspect_ratio=aspect_ratio)
def pope_or_death(p, **kwargs):
try:
x = p.objects.get(**kwargs)
except ObjectDoesNotExist:
x = None
return x