Skip to content
This repository has been archived by the owner on Feb 13, 2019. It is now read-only.

Commit

Permalink
Adding tests and responses for image states
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Sinchok committed Oct 13, 2014
1 parent 7338086 commit 8561a92
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 43 deletions.
107 changes: 107 additions & 0 deletions betty/cropper/http.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import io
import random

from django.http import HttpResponse

from PIL import Image, ImageDraw, ImageFont

from betty.cropper.models import Ratio
from betty.conf.app import settings


EXTENSION_MAP = {
"jpg": {
"format": "jpeg",
"mime_type": "image/jpeg"
},
"png": {
"format": "png",
"mime_type": "image/png"
},
}


class PlaceholderResponse(HttpResponse):

def __init__(self, ratio, width, extension, *args, **kwargs):
super(PlaceholderResponse, self).__init__(*args, **kwargs)
self.status_code = 200

if ratio.string == "original":
ratio = Ratio(random.choice((settings.BETTY_RATIOS)))
height = int(round((width * ratio.height / float(ratio.width))))

bg_fill = random.choice(settings.BETTY_PLACEHOLDER_COLORS)
img = Image.new("RGB", (width, height), bg_fill)

draw = ImageDraw.Draw(img)

font = ImageFont.truetype(filename=settings.BETTY_PLACEHOLDER_FONT, size=45)
text_size = draw.textsize(ratio.string, font=font)
text_coords = (
int(round((width - text_size[0]) / 2.0)),
int(round((height - text_size[1]) / 2) - 15),
)
draw.text(text_coords, ratio.string, font=font, fill=(256, 256, 256))

if extension == "jpg":
self._container = [img.tobytes("jpeg", "RGB")]
if extension == "png":
# I apparently can't get an encoder for this
tmp = io.BytesIO()
img.save(tmp, format="png")
self._container = [tmp.getvalue()]

self["Cache-Control"] = "no-cache, no-store, must-revalidate"
self["Pragma"] = "no-cache"
self["Expires"] = "0"
self["Content-Type"] = EXTENSION_MAP[extension]["mime_type"]


class PendingResponse(HttpResponse):
def __init__(self, ratio, width, extension, *args, **kwargs):
super(PendingResponse, self).__init__(*args, **kwargs)
self.status_code = 202

if ratio.string == "original":
ratio = Ratio(settings.BETTY_RATIOS[0])
height = int(round((width * ratio.height / float(ratio.width))))

bg_fill = (211, 211, 211)
img = Image.new("RGB", (width, height), bg_fill)

if extension == "jpg":
self._container = [img.tobytes("jpeg", "RGB")]
if extension == "png":
# I apparently can't get an encoder for this
tmp = io.BytesIO()
img.save(tmp, format="png")
self._container = [tmp.getvalue()]

self["Cache-Control"] = "no-cache, no-store, must-revalidate"
self["Pragma"] = "no-cache"
self["Expires"] = "0"
self["Content-Type"] = EXTENSION_MAP[extension]["mime_type"]


class FailureResponse(HttpResponse):
def __init__(self, ratio, width, extension, *args, **kwargs):
super(FailureResponse, self).__init__(*args, **kwargs)
self.status_code = 410

if ratio.string == "original":
ratio = Ratio(settings.BETTY_RATIOS[0])
height = int(round((width * ratio.height / float(ratio.width))))

bg_fill = (166, 18, 18)
img = Image.new("RGB", (width, height), bg_fill)

if extension == "jpg":
self._container = [img.tobytes("jpeg", "RGB")]
if extension == "png":
# I apparently can't get an encoder for this
tmp = io.BytesIO()
img.save(tmp, format="png")
self._container = [tmp.getvalue()]

self["Content-Type"] = EXTENSION_MAP[extension]["mime_type"]
1 change: 0 additions & 1 deletion betty/cropper/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ def create_from_url(self, url, name=None, credit=None):
)
os.makedirs(image.path())
download_image.apply_async(args=(image.id,))

return image

def create_from_path(self, path, filename=None, name=None, credit=None):
Expand Down
34 changes: 0 additions & 34 deletions betty/cropper/utils/placeholder.py

This file was deleted.

17 changes: 9 additions & 8 deletions betty/cropper/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
from six.moves import urllib

from .models import Image, Ratio
from .utils.placeholder import placeholder
from .http import PlaceholderResponse, PendingResponse, FailureResponse


EXTENSION_MAP = {
"jpg": {
Expand Down Expand Up @@ -82,16 +83,16 @@ def crop(request, id, ratio_slug, width, extension):
image = Image.objects.get(id=image_id)
except Image.DoesNotExist:
if settings.BETTY_PLACEHOLDER:
img_blob = placeholder(ratio, width, extension)
resp = HttpResponse(img_blob)
resp["Cache-Control"] = "no-cache, no-store, must-revalidate"
resp["Pragma"] = "no-cache"
resp["Expires"] = "0"
resp["Content-Type"] = EXTENSION_MAP[extension]["mime_type"]
return resp
return PlaceholderResponse(ratio, width, extension)
else:
raise Http404

if image.status == Image.PENDING:
return PendingResponse(ratio, width, extension)

if image.status == Image.FAILED:
return FailureResponse(ratio, width, extension)

try:
image_blob = image.crop(ratio, width, extension)
except Exception:
Expand Down
24 changes: 24 additions & 0 deletions tests/test_cropping.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,30 @@ def test_image_save(self):
self.assertEqual(res.status_code, 200)
self.assertFalse(os.path.exists(os.path.join(image.path(), 'original', '666.jpg')))

def test_image_pending(self):
image = Image.objects.create(
name="Lenna.png",
width=512,
height=512,
status=Image.PENDING,
url="http://example.com/lenna/png"
)

res = self.client.get('/images/{}/original/666.jpg'.format(image.id))
self.assertEqual(res.status_code, 202)

def test_image_failed(self):
image = Image.objects.create(
name="Lenna.png",
width=512,
height=512,
status=Image.FAILED,
url="http://example.com/lenna/png"
)

res = self.client.get('/images/{}/original/666.jpg'.format(image.id))
self.assertEqual(res.status_code, 410)

def test_non_rgb(self):
image = Image.objects.create(
name="animated.gif",
Expand Down

0 comments on commit 8561a92

Please sign in to comment.