Merge pull request #30 from matze/adjust-images-after-resizing
Adjust images after resizing
This commit is contained in:
@@ -289,15 +289,12 @@ def process_image(filepath, outpath, settings):
|
||||
if settings['keep_orig']:
|
||||
shutil.copy(filepath, join(outpath, settings['orig_dir'], filename))
|
||||
|
||||
sigal.image.generate_image(
|
||||
filepath, outname, settings['img_size'], None, options=options,
|
||||
copyright_text=settings['copyright'], method=settings['img_processor'],
|
||||
copy_exif_data=settings['copy_exif_data'])
|
||||
sigal.image.generate_image(filepath, outname, settings, options=options)
|
||||
|
||||
if settings['make_thumbs']:
|
||||
thumb_name = join(outpath, get_thumb(settings, filename))
|
||||
sigal.image.generate_thumbnail(
|
||||
outname, thumb_name, settings['thumb_size'], None,
|
||||
outname, thumb_name, settings['thumb_size'],
|
||||
fit=settings['thumb_fit'], options=options)
|
||||
|
||||
|
||||
|
||||
@@ -27,14 +27,16 @@ import sys
|
||||
from PIL import Image as PILImage
|
||||
from PIL import ImageDraw, ImageOps
|
||||
from PIL.ExifTags import TAGS
|
||||
from pilkit.processors import Transpose
|
||||
from pilkit.processors import Transpose, Adjust
|
||||
from pilkit.utils import save_image
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def generate_image(source, outname, size, format, options=None,
|
||||
autoconvert=True, copyright_text='', method='ResizeToFit',
|
||||
copy_exif_data=True):
|
||||
def _has_exif_tags(img):
|
||||
return hasattr(img, 'info') and 'exif' in img.info
|
||||
|
||||
|
||||
def generate_image(source, outname, settings, options=None):
|
||||
"""Image processor, rotate and resize the image.
|
||||
|
||||
:param source: path to an image
|
||||
@@ -47,7 +49,7 @@ def generate_image(source, outname, size, format, options=None,
|
||||
original_format = img.format
|
||||
|
||||
# Preserve EXIF data
|
||||
if copy_exif_data and hasattr(img, 'info') and 'exif' in img.info:
|
||||
if settings['copy_exif_data'] and _has_exif_tags(img):
|
||||
options = options or {}
|
||||
options['exif'] = img.info['exif']
|
||||
|
||||
@@ -58,6 +60,8 @@ def generate_image(source, outname, size, format, options=None,
|
||||
pass
|
||||
|
||||
# Resize the image
|
||||
method = settings['img_processor']
|
||||
|
||||
try:
|
||||
logger.debug('Processor: %s', method)
|
||||
processor_cls = getattr(pilkit.processors, method)
|
||||
@@ -65,18 +69,21 @@ def generate_image(source, outname, size, format, options=None,
|
||||
logger.error('Wrong processor name: %s', method)
|
||||
sys.exit()
|
||||
|
||||
processor = processor_cls(*size, upscale=False)
|
||||
processor = processor_cls(*settings['img_size'], upscale=False)
|
||||
img = processor.process(img)
|
||||
|
||||
if copyright_text:
|
||||
add_copyright(img, copyright_text)
|
||||
# Adjust the image after resizing
|
||||
img = Adjust(**settings['adjust_options']).process(img)
|
||||
|
||||
format = format or img.format or original_format or 'JPEG'
|
||||
logger.debug(u'Save resized image to {0} ({1})'.format(outname, format))
|
||||
save_image(img, outname, format, options=options, autoconvert=autoconvert)
|
||||
if settings['copyright']:
|
||||
add_copyright(img, settings['copyright'])
|
||||
|
||||
outformat = img.format or original_format or 'JPEG'
|
||||
logger.debug(u'Save resized image to {0} ({1})'.format(outname, outformat))
|
||||
save_image(img, outname, outformat, options=options, autoconvert=True)
|
||||
|
||||
|
||||
def generate_thumbnail(source, outname, box, format, fit=True, options=None):
|
||||
def generate_thumbnail(source, outname, box, fit=True, options=None):
|
||||
"Create a thumbnail image"
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -88,9 +95,9 @@ def generate_thumbnail(source, outname, box, format, fit=True, options=None):
|
||||
else:
|
||||
img.thumbnail(box, PILImage.ANTIALIAS)
|
||||
|
||||
format = format or img.format or original_format or 'JPEG'
|
||||
logger.debug(u'Save thumnail image to {0} ({1})'.format(outname, format))
|
||||
save_image(img, outname, format, options=options, autoconvert=True)
|
||||
outformat = img.format or original_format or 'JPEG'
|
||||
logger.debug(u'Save thumnail image to {0} ({1})'.format(outname, outformat))
|
||||
save_image(img, outname, outformat, options=options, autoconvert=True)
|
||||
|
||||
|
||||
def add_copyright(img, text):
|
||||
|
||||
@@ -29,6 +29,8 @@ _DEFAULT_CONFIG = {
|
||||
'destination': '_build',
|
||||
'img_size': (640, 480),
|
||||
'img_processor': 'ResizeToFit',
|
||||
'adjust_options': {'color': 1.0, 'brightness': 1.0,
|
||||
'contrast': 1.0, 'sharpness': 1.0},
|
||||
'make_thumbs': True,
|
||||
'thumb_prefix': '',
|
||||
'thumb_suffix': '',
|
||||
@@ -119,3 +121,10 @@ def read_settings(filename=None):
|
||||
"largest value first.", key)
|
||||
|
||||
return settings
|
||||
|
||||
|
||||
def create_settings(**kwargs):
|
||||
"""Create a new default setting copy and initialize it with kwargs."""
|
||||
settings = _DEFAULT_CONFIG.copy()
|
||||
settings.update(kwargs)
|
||||
return settings
|
||||
|
||||
@@ -26,6 +26,13 @@ img_size = (800, 600)
|
||||
# - SmartResize: identical to ResizeToFill, but uses entropy to crop the image
|
||||
# img_processor = 'ResizeToFit'
|
||||
|
||||
# Adjust the image after resizing it. A default value of 1.0 leaves the images
|
||||
# untouched.
|
||||
# adjust_options = {'color': 1.0,
|
||||
# 'brightness': 1.0,
|
||||
# 'contrast': 1.0,
|
||||
# 'sharpness': 1.0}
|
||||
|
||||
# Generate thumbnails
|
||||
# make_thumbs = True
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ def generate_video(source, outname, size, options={}):
|
||||
stderr=devnull)
|
||||
|
||||
|
||||
def generate_thumbnail(source, outname, box, format, fit=True, options=None):
|
||||
def generate_thumbnail(source, outname, box, fit=True, options=None):
|
||||
"Create a thumbnail image"
|
||||
# 1) dump an image of the video
|
||||
tmpfile = outname + ".tmp.jpg"
|
||||
@@ -94,6 +94,6 @@ def generate_thumbnail(source, outname, box, format, fit=True, options=None):
|
||||
subprocess.call(['ffmpeg', '-i', source, '-an', '-r', '1',
|
||||
'-vframes', '1', '-y', tmpfile], stderr=devnull)
|
||||
# 2) use the generate_thumbnail function from sigal.image
|
||||
sigal.image.generate_thumbnail(tmpfile, outname, box, format, fit, options)
|
||||
sigal.image.generate_thumbnail(tmpfile, outname, box, fit, options)
|
||||
# 3) remove the image
|
||||
os.unlink(tmpfile)
|
||||
|
||||
@@ -181,11 +181,11 @@ class Writer(object):
|
||||
if ext in self.settings['img_ext_list']:
|
||||
sigal.image.generate_thumbnail(
|
||||
source, thumb_path, self.settings['thumb_size'],
|
||||
None, fit=self.settings['thumb_fit'])
|
||||
fit=self.settings['thumb_fit'])
|
||||
else:
|
||||
sigal.video.generate_thumbnail(
|
||||
source, thumb_path, self.settings['thumb_size'],
|
||||
None, fit=self.settings['thumb_fit'])
|
||||
fit=self.settings['thumb_fit'])
|
||||
|
||||
ctx['albums'].append({
|
||||
'url': d + '/' + self.url_ext,
|
||||
|
||||
@@ -6,6 +6,7 @@ from PIL import Image
|
||||
|
||||
from sigal import init_logging
|
||||
from sigal.image import generate_image, generate_thumbnail, get_exif_tags
|
||||
from sigal.settings import create_settings
|
||||
|
||||
CURRENT_DIR = os.path.dirname(__file__)
|
||||
TEST_IMAGE = 'exo20101028-b-full.jpg'
|
||||
@@ -17,7 +18,8 @@ def test_generate_image(tmpdir):
|
||||
|
||||
dstfile = str(tmpdir.join(TEST_IMAGE))
|
||||
for size in [(600, 600), (300, 200)]:
|
||||
generate_image(SRCFILE, dstfile, size, None, method='ResizeToFill')
|
||||
settings = create_settings(img_size=size, img_processor='ResizeToFill')
|
||||
generate_image(SRCFILE, dstfile, settings)
|
||||
im = Image.open(dstfile)
|
||||
assert im.size == size
|
||||
|
||||
@@ -28,8 +30,8 @@ def test_generate_image_processor(tmpdir):
|
||||
init_logging()
|
||||
dstfile = str(tmpdir.join(TEST_IMAGE))
|
||||
with pytest.raises(SystemExit):
|
||||
generate_image(SRCFILE, dstfile, (200, 200), None,
|
||||
method='WrongMethod')
|
||||
settings = create_settings(img_size=(200, 200), img_processor='WrongMethod')
|
||||
generate_image(SRCFILE, dstfile, settings)
|
||||
|
||||
|
||||
def test_generate_thumbnail(tmpdir):
|
||||
@@ -37,13 +39,13 @@ def test_generate_thumbnail(tmpdir):
|
||||
|
||||
dstfile = str(tmpdir.join(TEST_IMAGE))
|
||||
for size in [(200, 150), (150, 200)]:
|
||||
generate_thumbnail(SRCFILE, dstfile, size, None)
|
||||
generate_thumbnail(SRCFILE, dstfile, size)
|
||||
im = Image.open(dstfile)
|
||||
assert im.size == size
|
||||
|
||||
for size, thumb_size in [((200, 150), (185, 150)),
|
||||
((150, 200), (150, 122))]:
|
||||
generate_thumbnail(SRCFILE, dstfile, size, None, fit=False)
|
||||
generate_thumbnail(SRCFILE, dstfile, size, fit=False)
|
||||
im = Image.open(dstfile)
|
||||
assert im.size == thumb_size
|
||||
|
||||
@@ -56,11 +58,13 @@ def test_exif_copy(tmpdir):
|
||||
test_image)
|
||||
dst_file = str(tmpdir.join(test_image))
|
||||
|
||||
generate_image(src_file, dst_file, (300, 400), None, copy_exif_data=True)
|
||||
settings = create_settings(img_size=(300, 400), copy_exif_data=True)
|
||||
generate_image(src_file, dst_file, settings)
|
||||
raw, simple = get_exif_tags(dst_file)
|
||||
assert simple['iso'] == 50
|
||||
|
||||
generate_image(src_file, dst_file, (300, 400), None, copy_exif_data=False)
|
||||
settings['copy_exif_data'] = False
|
||||
generate_image(src_file, dst_file, settings)
|
||||
raw, simple = get_exif_tags(dst_file)
|
||||
assert not raw
|
||||
assert not simple
|
||||
|
||||
Reference in New Issue
Block a user