Skip to content

Commit

Permalink
Add process_variation classmethod to simplify customization (#188)
Browse files Browse the repository at this point in the history
* Add missed variables to logger
* make rendervariation easier to customize
* a bit ugly way to make management command aware that if might be working with children of StdImageFieldFile
  • Loading branch information
marojenka authored and codingjoe committed Apr 15, 2018
1 parent 3d98e33 commit 3b02bd5
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 48 deletions.
2 changes: 2 additions & 0 deletions stdimage/management/commands/rendervariations.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def render(field, images, count, replace, do_render):
variations=field.variations,
replace=replace,
storage=field.storage.deconstruct()[0],
field_class=field.attr_class,
)
for file_name in images
)
Expand All @@ -78,6 +79,7 @@ def render_field_variations(kwargs):
kwargs['storage'] = get_storage_class(kwargs['storage'])()
do_render = kwargs.pop('do_render')
if callable(do_render):
kwargs.pop('field_class')
do_render = do_render(**kwargs)
if do_render:
render_variations(**kwargs)
100 changes: 54 additions & 46 deletions stdimage/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,63 +62,71 @@ def render_variation(cls, file_name, variation, replace=False,
if storage.exists(variation_name):
if replace:
storage.delete(variation_name)
logger.info('File "{}" already exists and has been replaced.')
logger.info('File "{}" already exists and has been replaced.',
variation_name)
else:
logger.info('File "{}" already exists.')
logger.info('File "{}" already exists.', variation_name)
return variation_name

resample = variation['resample']

ImageFile.LOAD_TRUNCATED_IMAGES = True
with storage.open(file_name) as f:
with Image.open(f) as img:
save_kargs = {}
file_format = img.format

if cls.is_smaller(img, variation):
factor = 1
while img.size[0] / factor \
> 2 * variation['width'] \
and img.size[1] * 2 / factor \
> 2 * variation['height']:
factor *= 2
if factor > 1:
img.thumbnail(
(int(img.size[0] / factor),
int(img.size[1] / factor)),
resample=resample
)

size = variation['width'], variation['height']
size = tuple(int(i) if i != float('inf') else i
for i in size)

if file_format == 'JPEG':
# http://stackoverflow.com/a/21669827
img = img.convert('RGB')
save_kargs['optimize'] = True
save_kargs['quality'] = 'web_high'
if size[0] * size[1] > 10000: # roughly <10kb
save_kargs['progressive'] = True

if variation['crop']:
img = ImageOps.fit(
img,
size,
method=resample
)
else:
img.thumbnail(
size,
resample=resample
)

img, save_kargs = cls.process_variation(variation, image=img)
with BytesIO() as file_buffer:
img.save(file_buffer, file_format, **save_kargs)
img.save(file_buffer, **save_kargs)
f = ContentFile(file_buffer.getvalue())
storage.save(variation_name, f)
return variation_name

@classmethod
def process_variation(cls, variation, image):
"""Process variation before actual saving."""
save_kargs = {}
file_format = image.format
save_kargs['format'] = file_format

resample = variation['resample']

if cls.is_smaller(image, variation):
factor = 1
while image.size[0] / factor \
> 2 * variation['width'] \
and image.size[1] * 2 / factor \
> 2 * variation['height']:
factor *= 2
if factor > 1:
image.thumbnail(
(int(image.size[0] / factor),
int(image.size[1] / factor)),
resample=resample
)

size = variation['width'], variation['height']
size = tuple(int(i) if i != float('inf') else i
for i in size)

if file_format == 'JPEG':
# http://stackoverflow.com/a/21669827
image = image.convert('RGB')
save_kargs['optimize'] = True
save_kargs['quality'] = 'web_high'
if size[0] * size[1] > 10000: # roughly <10kb
save_kargs['progressive'] = True

if variation['crop']:
image = ImageOps.fit(
image,
size,
method=resample
)
else:
image.thumbnail(
size,
resample=resample
)

return image, save_kargs

@classmethod
def get_variation_name(cls, file_name, variation_name):
"""Return the variation file name based on the variation."""
Expand Down
4 changes: 2 additions & 2 deletions stdimage/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ def pre_save_delete_callback(sender, instance, **kwargs):


def render_variations(file_name, variations, replace=False,
storage=default_storage):
storage=default_storage, field_class=StdImageFieldFile):
"""Render all variations for a given field."""
for key, variation in variations.items():
StdImageFieldFile.render_variation(
field_class.render_variation(
file_name, variation, replace, storage
)

0 comments on commit 3b02bd5

Please sign in to comment.