feat: Generate thumbnails for article images using Pillow
This commit is contained in:
parent
5c23a13501
commit
257ea3d1a0
|
@ -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():
|
||||
|
|
Loading…
Reference in New Issue
Block a user