personal-site/generate_thumbnails.py

94 lines
3.9 KiB
Python

import logging
import os
import pprint
from pelican import signals
from PIL import Image
log = logging.getLogger(__name__)
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']
media_path = os.path.join(content_path, 'media')
thumb_dir = os.path.join(output_path, 'media', 'thumbnails')
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(media_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)
_, ext = os.path.splitext(image_filename)
ext_lower = ext.lower()
if ext_lower not in ['.jpg', '.jpeg', '.png']:
log.info(f"Skipping non-JPG/PNG image for article '{article.slug}': {image_filename}")
continue
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():
signals.article_generator_finalized.connect(generator_finalized)