python-gallery/onlylegs/utils/generate_image.py

80 lines
2.7 KiB
Python
Raw Normal View History

"""
Tools for generating images and thumbnails
"""
2023-03-26 20:58:17 +00:00
import os
from PIL import Image, ImageOps
2023-03-26 20:58:17 +00:00
from werkzeug.utils import secure_filename
2023-04-21 17:49:08 +00:00
from onlylegs.config import MEDIA_FOLDER, CACHE_FOLDER
2023-03-26 20:58:17 +00:00
def generate_thumbnail(file_path, resolution, ext=None):
"""
Image thumbnail generator
Uses PIL to generate a thumbnail of the image and saves it to the cache directory
Name is the filename
resolution: 400x400 or thumb, or any other resolution
ext is the file extension of the image
"""
# Make image cache directory if it doesn't exist
if not os.path.exists(CACHE_FOLDER):
os.makedirs(CACHE_FOLDER)
# no sussy business
file_name = os.path.basename(file_path)
2023-04-07 12:35:30 +00:00
file_name, file_ext = secure_filename(file_name).rsplit(".")
if not ext:
2023-04-07 12:35:30 +00:00
ext = file_ext.strip(".")
# PIL doesnt like jpg so we convert it to jpeg
if ext.lower() == "jpg":
ext = "jpeg"
# Set resolution based on preset resolutions
2023-04-07 12:35:30 +00:00
if resolution in ["prev", "preview"]:
res_x, res_y = (1920, 1080)
2023-04-07 12:35:30 +00:00
elif resolution in ["thumb", "thumbnail"]:
2023-04-22 10:29:57 +00:00
res_x, res_y = (300, 300)
2023-04-21 16:21:47 +00:00
elif resolution in ["pfp", "profile"]:
2023-04-22 09:02:25 +00:00
res_x, res_y = (150, 150)
2023-04-07 12:35:30 +00:00
elif resolution in ["icon", "favicon"]:
2023-04-22 09:02:25 +00:00
res_x, res_y = (30, 30)
else:
return None
# If image has been already generated, return it from the cache
if os.path.exists(os.path.join(CACHE_FOLDER, f"{file_name}_{res_x}x{res_y}.{ext}")):
return os.path.join(CACHE_FOLDER, f"{file_name}_{res_x}x{res_y}.{ext}")
# Check if image exists in the uploads directory
2023-04-21 13:33:32 +00:00
if not os.path.exists(os.path.join(MEDIA_FOLDER, file_path)):
return None
# Open image and rotate it based on EXIF data and get ICC profile so colors are correct
2023-04-21 13:33:32 +00:00
image = Image.open(os.path.join(MEDIA_FOLDER, file_path))
image_icc = image.info.get("icc_profile")
img_x, img_y = image.size
# Resize image to fit the resolution
image = ImageOps.exif_transpose(image)
image.thumbnail((min(img_x, int(res_x)), min(img_y, int(res_y))), Image.ANTIALIAS)
# Save image to cache directory
try:
2023-04-07 12:35:30 +00:00
image.save(
os.path.join(CACHE_FOLDER, f"{file_name}_{res_x}x{res_y}.{ext}"),
2023-04-07 12:35:30 +00:00
icc_profile=image_icc,
)
except OSError:
# This usually happens when saving a JPEG with an ICC profile,
# so we convert to RGB and try again
2023-04-07 12:35:30 +00:00
image = image.convert("RGB")
image.save(
os.path.join(CACHE_FOLDER, f"{file_name}_{res_x}x{res_y}.{ext}"),
2023-04-07 12:35:30 +00:00
icc_profile=image_icc,
)
2023-03-26 20:58:17 +00:00
# No need to keep the image in memory, learned the hard way
image.close()
2023-03-26 20:58:17 +00:00
return os.path.join(CACHE_FOLDER, f"{file_name}_{res_x}x{res_y}.{ext}")