diff --git a/generate_thumbnails.py b/generate_thumbnails.py index 27e01bc..ecd9632 100644 --- a/generate_thumbnails.py +++ b/generate_thumbnails.py @@ -1,13 +1,84 @@ import logging +import os import pprint from pelican import signals +from PIL import Image log = logging.getLogger(__name__) -def generator_finalized(context): - for article in context['articles']: - pass +THUMBNAIL_MAX_SIZE = 448 + +def generator_finalized(generator): + """ + Generates thumbnails for images specified in article metadata. + """ + output_path = generator.settings['OUTPUT_PATH'] + content_path = generator.settings['PATH'] + thumb_dir = os.path.join(output_path, 'media', 'thumbs') + + if not os.path.exists(thumb_dir): + try: + os.makedirs(thumb_dir) + log.info(f"Created thumbnail directory: {thumb_dir}") + except OSError as e: + log.error(f"Could not create thumbnail directory {thumb_dir}: {e}") + return + + for article in generator.articles: + if hasattr(article, 'image'): + image_path_rel_to_content = article.image + # image_path_rel_to_content is often like 'media/imagename.jpg' + # or just 'imagename.jpg' if it's directly in 'content/media/' + # and STATIC_PATHS includes 'media'. + # We assume article.image is a path relative to the 'content' folder. + + source_image_full_path = os.path.join(content_path, image_path_rel_to_content) + + if not os.path.exists(source_image_full_path): + log.warning(f"Source image not found for article '{article.slug}': {source_image_full_path}") + continue + + image_filename = os.path.basename(image_path_rel_to_content) + thumb_path = os.path.join(thumb_dir, image_filename) + + try: + log.debug(f"Processing image: {source_image_full_path}") + img = Image.open(source_image_full_path) + + # Preserve original format, handle potential conversion issues for some modes + original_format = img.format + if img.mode == 'P' and 'transparency' in img.info: # Palette mode with transparency + img = img.convert('RGBA') + elif img.mode not in ('RGB', 'RGBA', 'L'): # L is grayscale + log.info(f"Converting image {image_filename} from mode {img.mode} to RGB for thumbnailing.") + img = img.convert('RGB') + + img.thumbnail((THUMBNAIL_MAX_SIZE, THUMBNAIL_MAX_SIZE)) + + save_kwargs = {} + if original_format: + save_kwargs['format'] = original_format + if original_format == 'JPEG': + save_kwargs['quality'] = 85 # Adjust quality for JPEGs + save_kwargs['optimize'] = True + elif original_format == 'PNG': + save_kwargs['optimize'] = True + + img.save(thumb_path, **save_kwargs) + log.info(f"Generated thumbnail for '{article.slug}': {thumb_path}") + + # Optionally, add thumbnail URL to article metadata if needed by templates + # This depends on how SITEURL and paths are structured. + # For now, just creating the file. + # article.thumbnail_url = f"{generator.settings.get('SITEURL', '')}/media/thumbs/{image_filename}" + + except FileNotFoundError: + log.error(f"Image file not found: {source_image_full_path}") + except IOError as e: + log.error(f"Could not open or process image {source_image_full_path}: {e}") + except Exception as e: + log.error(f"An unexpected error occurred while processing {source_image_full_path}: {e}") def register():