Image previews: smart crop down to 1:2 aspect ratio

Per request from the mobile team, image previews should be cropped down to a
1:2 width-to-height ratio as necessary.
This commit is contained in:
xiongchiamiov
2015-03-25 11:08:18 -07:00
parent bfa5230fa8
commit df671653f2
6 changed files with 35 additions and 6 deletions

View File

@@ -581,6 +581,7 @@ class LinkJsonTemplate(ThingJsonTemplate):
)
PREVIEW_RESOLUTIONS = (108, 216, 320, 640, 960, 1080)
PREVIEW_MAX_RATIO = 2
def __init__(self):
super(LinkJsonTemplate, self).__init__()
@@ -650,7 +651,7 @@ class LinkJsonTemplate(ThingJsonTemplate):
continue
url = g.image_resizing_provider.resize_image(
preview_object, w, censor_nsfw)
preview_object, w, censor_nsfw, self.PREVIEW_MAX_RATIO)
h = int(w * source_ratio)
preview_resolutions.append({
"url": url,

View File

@@ -24,7 +24,7 @@ class ImageResizingProvider(object):
"""Provider for generating resizable image urls.
"""
def resize_image(self, image, width=None, censor_nsfw=False):
def resize_image(self, image, width=None, censor_nsfw=False, max_ratio=None):
"""Turn a url of an image in storage into one that will produce a
resized image.
@@ -39,6 +39,10 @@ class ImageResizingProvider(object):
`censor_nsfw` is a boolean indicating whether the resizer should
attempt to censor the image (e.g. by blurring it) due to it being NSFW.
`max_ratio` is the maximum value of the height of the resultant image
divided by the width; if not specified, the aspect ratio will be the
same as the source image.
The return value should be an absolute URL with the `https` scheme if
supported, but should also work if accessed with `http`.

View File

@@ -39,12 +39,19 @@ class ImgixImageResizingProvider(ImageResizingProvider):
],
}
def resize_image(self, image, width=None, censor_nsfw=False):
def resize_image(self, image, width=None, censor_nsfw=False, max_ratio=None):
url = UrlParser(image['url'])
url.hostname = g.imgix_domain
# Let's encourage HTTPS; it's cool, works just fine on HTTP pages, and
# will prevent insecure content warnings on HTTPS pages.
url.scheme = 'https'
if max_ratio:
url.update_query(fit='crop')
# http://www.imgix.com/docs/reference/size#param-crop
url.update_query(crop='faces,entropy')
url.update_query(arh=max_ratio)
if width:
if width > image['width']:
raise NotLargeEnough()

View File

@@ -28,6 +28,6 @@ class NoOpImageResizingProvider(ImageResizingProvider):
Combines well with the filesystem media provider for an entirely local
setup.
"""
def resize_image(self, image, width=None, censor_nsfw=False):
def resize_image(self, image, width=None, censor_nsfw=False, max_ratio=None):
# The simplest solution: just pass it on through.
return image['url']

View File

@@ -28,7 +28,7 @@ class UnsplashitImageResizingProvider(ImageResizingProvider):
Useful if you don't want the external dependencies of imgix, but need
correctly-sized images for testing a UI.
"""
def resize_image(self, image, width=None, censor_nsfw=False):
def resize_image(self, image, width=None, censor_nsfw=False, max_ratio=None):
if width is None:
width = image['width']
height = width * 2

View File

@@ -33,6 +33,9 @@ from r2.lib.providers.image_resizing.imgix import ImgixImageResizingProvider
from r2.lib.utils import UrlParser
URLENCODED_COMMA = '%2C'
class TestImgixResizer(unittest.TestCase):
@classmethod
def setUpClass(cls):
@@ -66,7 +69,21 @@ class TestImgixResizer(unittest.TestCase):
url = self.provider.resize_image(image, width)
self.assertEqual(url, 'https://example.com/a.jpg?w=%d' % width)
# TODO: test acceptable aspect ratios per spec!
def test_cropping(self):
image = dict(url='http://s3.amazonaws.com/a.jpg', width=1200,
height=800)
max_ratio = 0.5
url = self.provider.resize_image(image, max_ratio=max_ratio)
crop = URLENCODED_COMMA.join(('faces', 'entropy'))
self.assertEqual(url,
('https://example.com/a.jpg?fit=crop&crop=%s&arh=%s'
% (crop, max_ratio)))
width = 108
url = self.provider.resize_image(image, width, max_ratio=max_ratio)
self.assertEqual(url,
('https://example.com/a.jpg?fit=crop&crop=%s&arh=%s&w=%s'
% (crop, max_ratio, width)))
def test_sign_url(self):
u = UrlParser('http://examples.imgix.net/frog.jpg?w=100')