Merge branch 'kaedroho-image-backend-tweaks'

pull/309/head
Matt Westcott 2014-06-10 15:52:51 +01:00
commit a989824b9b
5 zmienionych plików z 34 dodań i 36 usunięć

Wyświetl plik

@ -1,6 +1,7 @@
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
class InvalidImageBackendError(ImproperlyConfigured):
pass
@ -8,23 +9,22 @@ class InvalidImageBackendError(ImproperlyConfigured):
class BaseImageBackend(object):
def __init__(self, params):
self.quality = getattr(settings, 'IMAGE_COMPRESSION_QUALITY', 85)
def open_image(self, input_file):
"""
Open an image and return the backend specific image object to pass
to other methods. The object return has to have a size attribute
Open an image and return the backend specific image object to pass
to other methods. The object return has to have a size attribute
which is a tuple with the width and height of the image and a format
attribute with the format of the image.
"""
raise NotImplementedError('subclasses of BaseImageBackend must provide an open_image() method')
def save_image(self, image, output):
"""
Save the image to the output
"""
raise NotImplementedError('subclasses of BaseImageBackend must provide a save_image() method')
def resize(self, image, size):
"""
resize image to the requested size, using highest quality settings
@ -32,11 +32,9 @@ class BaseImageBackend(object):
"""
raise NotImplementedError('subclasses of BaseImageBackend must provide an resize() method')
def crop_to_centre(self, image, size):
raise NotImplementedError('subclasses of BaseImageBackend must provide a crop_to_centre() method')
def resize_to_max(self, image, size):
"""
Resize image down to fit within the given dimensions, preserving aspect ratio.
@ -58,10 +56,8 @@ class BaseImageBackend(object):
final_size = (target_width, int(original_height * horz_scale))
else:
final_size = (int(original_width * vert_scale), target_height)
return self.resize(image, final_size)
return self.resize(image, final_size)
def resize_to_min(self, image, size):
"""
@ -87,7 +83,6 @@ class BaseImageBackend(object):
return self.resize(image, final_size)
def resize_to_width(self, image, target_width):
"""
Resize image down to the given width, preserving aspect ratio.
@ -104,7 +99,6 @@ class BaseImageBackend(object):
return self.resize(image, final_size)
def resize_to_height(self, image, target_height):
"""
Resize image down to the given height, preserving aspect ratio.
@ -121,7 +115,6 @@ class BaseImageBackend(object):
return self.resize(image, final_size)
def resize_to_fill(self, image, size):
"""
Resize down and crop image to fill the given dimensions. Most suitable for thumbnails.

Wyświetl plik

@ -1,6 +1,9 @@
from base import BaseImageBackend
from __future__ import absolute_import
from .base import BaseImageBackend
import PIL.Image
class PillowBackend(BaseImageBackend):
def __init__(self, params):
super(PillowBackend, self).__init__(params)
@ -32,4 +35,4 @@ class PillowBackend(BaseImageBackend):
top = (original_height - final_height) / 2
return image.crop(
(left, top, left + final_width, top + final_height)
)
)

Wyświetl plik

@ -1,8 +1,9 @@
from __future__ import absolute_import
from .base import BaseImageBackend
from wand.image import Image
from wand.api import library
class WandBackend(BaseImageBackend):
def __init__(self, params):
@ -10,6 +11,7 @@ class WandBackend(BaseImageBackend):
def open_image(self, input_file):
image = Image(file=input_file)
image.wand = library.MagickCoalesceImages(image.wand)
return image
def save_image(self, image, output, format):
@ -18,8 +20,9 @@ class WandBackend(BaseImageBackend):
image.save(file=output)
def resize(self, image, size):
image.resize(size[0], size[1])
return image
new_image = image.clone()
new_image.resize(size[0], size[1])
return new_image
def crop_to_centre(self, image, size):
(original_width, original_height) = image.size
@ -34,7 +37,9 @@ class WandBackend(BaseImageBackend):
left = (original_width - final_width) / 2
top = (original_height - final_height) / 2
image.crop(
new_image = image.clone()
new_image.crop(
left=left, top=top, right=left + final_width, bottom=top + final_height
)
return image
return new_image

Wyświetl plik

@ -194,27 +194,25 @@ class Filter(models.Model):
generate an output image with this filter applied, returning it
as another django.core.files.File object
"""
backend = get_image_backend(backend_name)
if not self.method:
self._parse_spec_string()
# If file is closed, open it
input_file.open('rb')
image = backend.open_image(input_file)
file_format = image.format
method = getattr(backend, self.method_name)
image = method(image, self.method_arg)
output = StringIO.StringIO()
backend.save_image(image, output, file_format)
# and then close the input file
input_file.close()
# generate new filename derived from old one, inserting the filter spec string before the extension
input_filename_parts = os.path.basename(input_file.name).split('.')
@ -224,7 +222,6 @@ class Filter(models.Model):
output_filename = '.'.join(output_filename_parts)
output_file = File(output, name=output_filename)
return output_file

Wyświetl plik

@ -84,10 +84,10 @@ class TestRenditions(TestCase):
# default backend should be pillow
backend = get_image_backend()
self.assertTrue(isinstance(backend, PillowBackend))
def test_minification(self):
rendition = self.image.get_rendition('width-400')
# Check size
self.assertEqual(rendition.width, 400)
self.assertEqual(rendition.height, 300)
@ -121,7 +121,7 @@ class TestRenditions(TestCase):
# Check that they are the same object
self.assertEqual(first_rendition, second_rendition)
class TestRenditionsWand(TestCase):
def setUp(self):
@ -141,18 +141,18 @@ class TestRenditionsWand(TestCase):
def test_minification(self):
rendition = self.image.get_rendition('width-400')
# Check size
self.assertEqual(rendition.width, 400)
self.assertEqual(rendition.height, 300)
def test_resize_to_max(self):
rendition = self.image.get_rendition('max-100x100')
# Check size
self.assertEqual(rendition.width, 100)
self.assertEqual(rendition.height, 75)
def test_resize_to_min(self):
rendition = self.image.get_rendition('min-120x120')
@ -174,7 +174,7 @@ class TestRenditionsWand(TestCase):
# Check that they are the same object
self.assertEqual(first_rendition, second_rendition)
class TestImageTag(TestCase):
def setUp(self):