diff --git a/sigal/gallery.py b/sigal/gallery.py index ce738c8..bedebc3 100644 --- a/sigal/gallery.py +++ b/sigal/gallery.py @@ -38,6 +38,7 @@ from urllib.parse import quote as url_quote from click import get_terminal_size, progressbar from natsort import natsort_keygen, ns +from PIL import Image as PILImage from . import image, signals, video from .image import get_exif_tags, get_image_metadata, get_size, process_image @@ -66,18 +67,20 @@ class Media: """Type of media, e.g. ``"image"`` or ``"video"``.""" def __init__(self, filename, path, settings): + self.path = path + self.settings = settings + self.filename = filename """Filename of the resized image.""" self.src_filename = filename - """Filename of the resized image.""" + """Filename of the input image.""" - self.path = path - self.settings = settings self.ext = os.path.splitext(filename)[1].lower() + """Input extension.""" - self.src_path = join(settings['source'], path, filename) - self.dst_path = join(settings['destination'], path, filename) + self.src_path = join(settings['source'], path, self.src_filename) + self.dst_path = join(settings['destination'], path, self.filename) self.thumb_name = get_thumb(self.settings, self.filename) self.thumb_path = join(settings['destination'], path, self.thumb_name) @@ -96,7 +99,7 @@ class Media: return "<{}>({!r})".format(self.__class__.__name__, str(self)) def __str__(self): - return join(self.path, self.filename) + return join(self.path, self.src_filename) @property def url(self): @@ -112,7 +115,7 @@ class Media: s = self.settings if s['use_orig']: # The image *is* the original, just use it - return self.filename + return self.src_filename orig_path = join(s['destination'], self.path, s['orig_dir']) check_or_create_dir(orig_path) big_path = join(orig_path, self.src_filename) @@ -180,6 +183,17 @@ class Image(Media): type = 'image' + def __init__(self, filename, path, settings): + super().__init__(filename, path, settings) + img_format = settings.get('img_format') + + if img_format and PILImage.EXTENSION[self.ext] != img_format.upper(): + # Find the extension that should match img_format + extensions = {v: k for k, v in PILImage.EXTENSION.items()} + outname = (os.path.splitext(filename)[0] + + extensions[img_format.upper()]) + self.dst_path = join(settings['destination'], path, outname) + @cached_property def date(self): """The date from the EXIF DateTimeOriginal metadata if available, or @@ -241,8 +255,9 @@ class Video(Media): def __init__(self, filename, path, settings): super().__init__(filename, path, settings) base, ext = splitext(filename) - self.src_filename = filename + # self.src_filename = filename self.date = self._get_file_date() + if not settings['use_orig'] or not is_valid_html5_video(ext): video_format = settings['video_format'] ext = '.' + video_format @@ -775,7 +790,7 @@ class Gallery: self.stats[f.type + '_skipped'] += 1 else: self.stats[f.type] += 1 - yield (f.type, f.path, f.filename, f.src_path, album.dst_path, + yield (f.type, f.path, f.filename, f.src_path, f.dst_path, self.settings) diff --git a/sigal/image.py b/sigal/image.py index 3c60dcd..126e7f6 100644 --- a/sigal/image.py +++ b/sigal/image.py @@ -143,7 +143,9 @@ def generate_image(source, outname, settings, options=None): # first, use hard-coded output format, or PIL format, or original image # format, or fall back to JPEG - outformat = settings.get('img_format') or img.format or original_format or 'JPEG' + outformat = (settings.get('img_format') or img.format or + original_format or 'JPEG') + logger.debug('Save resized image to %s (%s)', outname, outformat) save_image(img, outname, outformat, options=options, autoconvert=True) @@ -174,7 +176,6 @@ def process_image(filepath, outpath, settings): logger = logging.getLogger(__name__) logger.info('Processing %s', filepath) filename = os.path.split(filepath)[1] - outname = os.path.join(outpath, filename) ext = os.path.splitext(filename)[1] if ext in ('.jpg', '.jpeg', '.JPG', '.JPEG'): @@ -185,15 +186,21 @@ def process_image(filepath, outpath, settings): options = {} try: - generate_image(filepath, outname, settings, options=options) + generate_image(filepath, outpath, settings, options=options) if settings['make_thumbs']: - thumb_name = os.path.join(outpath, get_thumb(settings, filename)) + thumb_name = os.path.join(os.path.dirname(outpath), + get_thumb(settings, filename)) generate_thumbnail( - outname, thumb_name, settings['thumb_size'], - fit=settings['thumb_fit'], options=options, - thumb_fit_centering=settings["thumb_fit_centering"]) + outpath, + thumb_name, + settings['thumb_size'], + fit=settings['thumb_fit'], + options=options, + thumb_fit_centering=settings["thumb_fit_centering"] + ) except Exception as e: + __import__('pdb').set_trace() logger.info('Failed to process: %r', e) if logger.getEffectiveLevel() == logging.DEBUG: raise diff --git a/sigal/settings.py b/sigal/settings.py index 2d655df..f00a170 100644 --- a/sigal/settings.py +++ b/sigal/settings.py @@ -39,7 +39,7 @@ _DEFAULT_CONFIG = { 'google_tag_manager': '', 'ignore_directories': [], 'ignore_files': [], - 'img_extensions': ['.jpg', '.jpeg', '.png', '.gif'], + 'img_extensions': ['.jpg', '.jpeg', '.png', '.gif', '.tif', '.tiff'], 'img_processor': 'ResizeToFit', 'img_size': (640, 480), 'img_format': None, diff --git a/sigal/video.py b/sigal/video.py index a595e8a..337b087 100644 --- a/sigal/video.py +++ b/sigal/video.py @@ -166,8 +166,7 @@ def process_video(filepath, outpath, settings): try: if settings['use_orig'] and is_valid_html5_video(ext): - outname = os.path.join(outpath, filename) - utils.copy(filepath, outname, symlink=settings['orig_link']) + utils.copy(filepath, outpath, symlink=settings['orig_link']) else: valid_formats = ['mp4', 'webm'] video_format = settings['video_format'] @@ -177,8 +176,7 @@ def process_video(filepath, outpath, settings): valid_formats) raise ValueError - outname = os.path.join(outpath, basename + '.' + video_format) - generate_video(filepath, outname, settings, + generate_video(filepath, outpath, settings, options=settings.get(video_format + '_options')) except Exception: if logger.getEffectiveLevel() == logging.DEBUG: @@ -187,13 +185,18 @@ def process_video(filepath, outpath, settings): return Status.FAILURE if settings['make_thumbs']: - thumb_name = os.path.join(outpath, get_thumb(settings, filename)) + thumb_name = os.path.join(os.path.dirname(outpath), + get_thumb(settings, filename)) try: generate_thumbnail( - outname, thumb_name, settings['thumb_size'], - settings['thumb_video_delay'], fit=settings['thumb_fit'], + outpath, + thumb_name, + settings['thumb_size'], + settings['thumb_video_delay'], + fit=settings['thumb_fit'], options=settings['jpg_options'], - converter=settings['video_converter']) + converter=settings['video_converter'] + ) except Exception: if logger.getEffectiveLevel() == logging.DEBUG: raise diff --git a/tests/sample/pictures/dir1/test2/21.jpg b/tests/sample/pictures/dir1/test2/21.jpg deleted file mode 100644 index 0b60190..0000000 Binary files a/tests/sample/pictures/dir1/test2/21.jpg and /dev/null differ diff --git a/tests/sample/sigal.conf.py b/tests/sample/sigal.conf.py index cf20d4b..8cdafcd 100644 --- a/tests/sample/sigal.conf.py +++ b/tests/sample/sigal.conf.py @@ -4,6 +4,7 @@ source = 'pictures' thumb_suffix = '.tn' keep_orig = True thumb_video_delay = 5 +img_format = 'jpeg' links = [('Example link', 'http://example.org'), ('Another link', 'http://example.org')] diff --git a/tests/test_image.py b/tests/test_image.py index 0377e87..d504c35 100644 --- a/tests/test_image.py +++ b/tests/test_image.py @@ -43,13 +43,16 @@ def test_generate_image(tmpdir): im = Image.open(dstfile) assert im.size == size + def test_generate_image_imgformat(tmpdir): "Test the effects of the img_format setting on generate_image." dstfile = str(tmpdir.join(TEST_IMAGE)) for i, outfmt in enumerate(["JPEG", "PNG", "TIFF"]): - settings = create_settings(img_size=(300,300), img_processor='ResizeToFill', - copy_exif_data=True, img_format=outfmt) + settings = create_settings(img_size=(300, 300), + img_processor='ResizeToFill', + copy_exif_data=True, + img_format=outfmt) options = {'quality': 85} generate_image(SRCFILE, dstfile, settings, options=options) im = Image.open(dstfile)