diff --git a/sigal/gallery.py b/sigal/gallery.py index 78561f6..e1bbb09 100644 --- a/sigal/gallery.py +++ b/sigal/gallery.py @@ -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) diff --git a/sigal/image.py b/sigal/image.py index 76cad30..f1e893e 100644 --- a/sigal/image.py +++ b/sigal/image.py @@ -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): diff --git a/sigal/settings.py b/sigal/settings.py index e3ea0e5..913f177 100644 --- a/sigal/settings.py +++ b/sigal/settings.py @@ -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 diff --git a/sigal/templates/sigal.conf.py b/sigal/templates/sigal.conf.py index ce2976c..d214535 100644 --- a/sigal/templates/sigal.conf.py +++ b/sigal/templates/sigal.conf.py @@ -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 diff --git a/sigal/video.py b/sigal/video.py index 9b7d947..5ef4eb0 100644 --- a/sigal/video.py +++ b/sigal/video.py @@ -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) diff --git a/sigal/writer.py b/sigal/writer.py index bcb0d77..c25da54 100644 --- a/sigal/writer.py +++ b/sigal/writer.py @@ -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, diff --git a/tests/test_image.py b/tests/test_image.py index b0f1621..15e9db0 100644 --- a/tests/test_image.py +++ b/tests/test_image.py @@ -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