mirror of
https://github.com/Derpy-Leggies/OnlyLegs.git
synced 2025-02-05 21:18:08 +00:00
Remove Thumbnails table
Daddy PyLint not happy with me
This commit is contained in:
parent
db20ce7919
commit
3331edf24d
|
@ -69,14 +69,13 @@ def create_app(test_config=None):
|
|||
# Error handlers
|
||||
@app.errorhandler(Exception)
|
||||
def error_page(err):
|
||||
# If the error is a HTTP error, return the error page
|
||||
if isinstance(err, HTTPException):
|
||||
error = err.code
|
||||
msg = err.description
|
||||
return render_template('error.html', error=error, msg=msg), err.code
|
||||
# If the error is not an HTTPException, return a 500 error
|
||||
if not isinstance(err, HTTPException):
|
||||
abort(500)
|
||||
|
||||
# Otherwise this an internal error
|
||||
abort(500)
|
||||
error = err.code
|
||||
msg = err.description
|
||||
return render_template('error.html', error=error, msg=msg), err.code
|
||||
|
||||
# Load login, registration and logout manager
|
||||
from gallery import auth
|
||||
|
|
|
@ -60,20 +60,6 @@ class Posts (base): # pylint: disable=too-few-public-methods, C0103
|
|||
post_alt = Column(String, nullable=False)
|
||||
|
||||
junction = relationship('GroupJunction', backref='posts')
|
||||
thumbnail = relationship('Thumbnails', backref='posts')
|
||||
|
||||
|
||||
class Thumbnails (base): # pylint: disable=too-few-public-methods, C0103
|
||||
"""
|
||||
Thumbnail table
|
||||
"""
|
||||
__tablename__ = 'thumbnails'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
file_name = Column(String, unique=True, nullable=False)
|
||||
file_ext = Column(String, nullable=False)
|
||||
resolution = Column(PickleType, nullable=False)
|
||||
post_id = Column(Integer, ForeignKey('posts.id'))
|
||||
|
||||
|
||||
class Groups (base): # pylint: disable=too-few-public-methods, C0103
|
||||
|
|
|
@ -4,9 +4,9 @@ Onlylegs - API endpoints
|
|||
from uuid import uuid4
|
||||
import os
|
||||
import pathlib
|
||||
import platformdirs
|
||||
import logging
|
||||
from datetime import datetime as dt
|
||||
import platformdirs
|
||||
|
||||
from flask import Blueprint, send_from_directory, abort, flash, jsonify, request, g, current_app
|
||||
from werkzeug.utils import secure_filename
|
||||
|
@ -18,7 +18,7 @@ from gallery.auth import login_required
|
|||
|
||||
from gallery import db
|
||||
from gallery.utils import metadata as mt
|
||||
from gallery.utils.generate_image import ImageGenerator
|
||||
from gallery.utils.generate_image import generate_thumbnail
|
||||
|
||||
|
||||
blueprint = Blueprint('api', __name__, url_prefix='/api')
|
||||
|
@ -41,12 +41,12 @@ def file(file_name):
|
|||
abort(404)
|
||||
|
||||
return send_from_directory(current_app.config['UPLOAD_FOLDER'], file_name)
|
||||
|
||||
thumb = ImageGenerator.thumbnail(file_name, res)
|
||||
|
||||
|
||||
thumb = generate_thumbnail(file_name, res)
|
||||
|
||||
if not thumb:
|
||||
abort(404)
|
||||
|
||||
|
||||
return send_from_directory(os.path.dirname(thumb), os.path.basename(thumb))
|
||||
|
||||
|
||||
|
@ -126,8 +126,8 @@ def delete_image(image_id):
|
|||
# Delete cached files
|
||||
cache_path = os.path.join(platformdirs.user_config_dir('onlylegs'), 'cache')
|
||||
cache_name = img.file_name.rsplit('.')[0]
|
||||
for file in pathlib.Path(cache_path).glob(cache_name + '*'):
|
||||
os.remove(file)
|
||||
for cache_file in pathlib.Path(cache_path).glob(cache_name + '*'):
|
||||
os.remove(cache_file)
|
||||
|
||||
# Delete from database
|
||||
db_session.query(db.Posts).filter_by(id=image_id).delete()
|
||||
|
@ -209,40 +209,3 @@ def metadata(img_id):
|
|||
exif = mt.Metadata(img_path).yoink()
|
||||
|
||||
return jsonify(exif)
|
||||
|
||||
|
||||
@blueprint.route('/logfile')
|
||||
@login_required
|
||||
def logfile():
|
||||
"""
|
||||
Gets the log file and returns it as a JSON object
|
||||
"""
|
||||
log_dict = {}
|
||||
|
||||
with open('only.log', encoding='utf-8', mode='r') as file:
|
||||
for i, line in enumerate(file):
|
||||
line = line.split(' : ')
|
||||
|
||||
event = line[0].strip().split(' ')
|
||||
event_data = {
|
||||
'date': event[0],
|
||||
'time': event[1],
|
||||
'severity': event[2],
|
||||
'owner': event[3]
|
||||
}
|
||||
|
||||
message = line[1].strip()
|
||||
try:
|
||||
message_data = {
|
||||
'code': int(message[1:4]),
|
||||
'message': message[5:].strip()
|
||||
}
|
||||
except ValueError:
|
||||
message_data = {'code': 0, 'message': message}
|
||||
except Exception as err:
|
||||
logging.error('Could not parse log file: %s', err)
|
||||
abort(500)
|
||||
|
||||
log_dict[i] = {'event': event_data, 'message': message_data}
|
||||
|
||||
return jsonify(log_dict)
|
||||
|
|
|
@ -60,13 +60,18 @@ def group(group_id):
|
|||
for image in group_images:
|
||||
image = db_session.query(db.Posts).filter(db.Posts.id == image[0]).first()
|
||||
images.append(image)
|
||||
|
||||
|
||||
if images:
|
||||
text_colour = contrast.contrast(images[0].image_colours[0], 'rgb(var(--fg-black))', 'rgb(var(--fg-white))')
|
||||
text_colour = contrast.contrast(images[0].image_colours[0],
|
||||
'rgb(var(--fg-black))',
|
||||
'rgb(var(--fg-white))')
|
||||
else:
|
||||
text_colour = 'rgb(var(--fg-black))'
|
||||
|
||||
return render_template('groups/group.html', group=group_item, images=images, text_colour=text_colour)
|
||||
return render_template('groups/group.html',
|
||||
group=group_item,
|
||||
images=images,
|
||||
text_colour=text_colour)
|
||||
|
||||
|
||||
@blueprint.route('/<int:group_id>/<int:image_id>')
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
top: 0
|
||||
left: 0
|
||||
|
||||
background-color: RGB($fg-white)
|
||||
// background-image: linear-gradient(to right, RGB($bg-200) 15%, RGB($bg-400) 35%, RGB($bg-200) 50%)
|
||||
// background-size: 1000px 640px
|
||||
// animation: imgLoading 1.8s linear infinite forwards
|
||||
background-color: RGB($bg-300)
|
||||
background-image: linear-gradient(to right, RGB($bg-400) 15%, RGB($bg-200) 35%, RGB($bg-400) 50%)
|
||||
background-size: 1000px 640px
|
||||
animation: imgLoading 1.8s linear infinite forwards
|
||||
|
||||
user-select: none
|
||||
overflow: hidden
|
||||
|
|
|
@ -1,18 +1,22 @@
|
|||
"""
|
||||
Calculate the contrast between two colors
|
||||
"""
|
||||
|
||||
|
||||
def contrast(background, light, dark, threshold = 0.179):
|
||||
"""
|
||||
Calculate the contrast between two colors
|
||||
background: tuple of (r, g, b) values
|
||||
light: color to use if the background is light
|
||||
dark: color to use if the background is dark
|
||||
threshold: the threshold to use for determining lightness, the default is w3 recommended
|
||||
"""
|
||||
r = background[0]
|
||||
g = background[1]
|
||||
b = background[2]
|
||||
red = background[0]
|
||||
green = background[1]
|
||||
blue = background[2]
|
||||
|
||||
# Calculate contrast
|
||||
uicolors = [r / 255, g / 255, b / 255]
|
||||
c = [col / 12.92 if col <= 0.03928 else ((col + 0.055) / 1.055) ** 2.4 for col in uicolors]
|
||||
l = (0.2126 * c[0]) + (0.7152 * c[1]) + (0.0722 * c[2])
|
||||
|
||||
return light if l > threshold else dark
|
||||
uicolors = [red / 255, green / 255, blue / 255]
|
||||
cont = [col / 12.92 if col <= 0.03928 else ((col + 0.055) / 1.055) ** 2.4 for col in uicolors]
|
||||
lightness = (0.2126 * cont[0]) + (0.7152 * cont[1]) + (0.0722 * cont[2])
|
||||
|
||||
return light if lightness > threshold else dark
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
"""
|
||||
Tools for generating images and thumbnails
|
||||
"""
|
||||
|
||||
import os
|
||||
import platformdirs
|
||||
from PIL import Image, ImageOps #, ImageFilter
|
||||
|
@ -8,67 +12,66 @@ CACHE_PATH = platformdirs.user_config_dir('onlylegs') + '/cache'
|
|||
UPLOAD_PATH = platformdirs.user_config_dir('onlylegs') + '/uploads'
|
||||
|
||||
|
||||
class ImageGenerator:
|
||||
def thumbnail(name, 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_PATH):
|
||||
os.makedirs(CACHE_PATH)
|
||||
def generate_thumbnail(file_name, 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_PATH):
|
||||
os.makedirs(CACHE_PATH)
|
||||
|
||||
# no sussy business
|
||||
name, name_ext = secure_filename(name).rsplit('.')
|
||||
if not ext:
|
||||
ext = name_ext.strip('.')
|
||||
|
||||
# PIL doesnt like jpg so we convert it to jpeg
|
||||
if ext.lower() == "jpg":
|
||||
ext = "jpeg"
|
||||
|
||||
# Set resolution based on preset resolutions
|
||||
if resolution in ['thumb', 'thumbnail']:
|
||||
res_x, res_y = (400, 400)
|
||||
elif resolution in ['prev', 'preview']:
|
||||
res_x, res_y = (1920, 1080)
|
||||
elif len(resolution.split('x')) == 2:
|
||||
res_x, res_y = resolution.split('x')
|
||||
else:
|
||||
return None
|
||||
|
||||
# If image has been already generated, return it from the cache
|
||||
if os.path.exists(os.path.join(CACHE_PATH, f'{name}_{res_x}x{res_y}.{ext}')):
|
||||
return os.path.join(CACHE_PATH, f'{name}_{res_x}x{res_y}.{ext}')
|
||||
|
||||
# Check if image exists in the uploads directory
|
||||
if not os.path.exists(os.path.join(UPLOAD_PATH, f'{name}.{name_ext}')):
|
||||
return None
|
||||
|
||||
# Open image and rotate it based on EXIF data and get ICC profile so colors are correct
|
||||
image = Image.open(os.path.join(UPLOAD_PATH, f'{name}.{name_ext}'))
|
||||
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)
|
||||
# no sussy business
|
||||
file_name, file_ext = secure_filename(file_name).rsplit('.')
|
||||
if not ext:
|
||||
ext = file_ext.strip('.')
|
||||
|
||||
# Save image to cache directory
|
||||
try:
|
||||
image.save(os.path.join(CACHE_PATH,f'{name}_{res_x}x{res_y}.{ext}'),
|
||||
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
|
||||
image = image.convert('RGB')
|
||||
image.save(os.path.join(CACHE_PATH, f'{name}_{res_x}x{res_y}.{ext}'),
|
||||
icc_profile=image_icc)
|
||||
|
||||
# No need to keep the image in memory, learned the hard way
|
||||
image.close()
|
||||
|
||||
return os.path.join(CACHE_PATH, f'{name}_{res_x}x{res_y}.{ext}')
|
||||
# PIL doesnt like jpg so we convert it to jpeg
|
||||
if ext.lower() == "jpg":
|
||||
ext = "jpeg"
|
||||
|
||||
# Set resolution based on preset resolutions
|
||||
if resolution in ['thumb', 'thumbnail']:
|
||||
res_x, res_y = (400, 400)
|
||||
elif resolution in ['prev', 'preview']:
|
||||
res_x, res_y = (1920, 1080)
|
||||
elif len(resolution.split('x')) == 2:
|
||||
res_x, res_y = resolution.split('x')
|
||||
else:
|
||||
return None
|
||||
|
||||
# If image has been already generated, return it from the cache
|
||||
if os.path.exists(os.path.join(CACHE_PATH, f'{file_name}_{res_x}x{res_y}.{ext}')):
|
||||
return os.path.join(CACHE_PATH, f'{file_name}_{res_x}x{res_y}.{ext}')
|
||||
|
||||
# Check if image exists in the uploads directory
|
||||
if not os.path.exists(os.path.join(UPLOAD_PATH, f'{file_name}.{file_ext}')):
|
||||
return None
|
||||
|
||||
# Open image and rotate it based on EXIF data and get ICC profile so colors are correct
|
||||
image = Image.open(os.path.join(UPLOAD_PATH, f'{file_name}.{file_ext}'))
|
||||
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:
|
||||
image.save(os.path.join(CACHE_PATH,f'{file_name}_{res_x}x{res_y}.{ext}'),
|
||||
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
|
||||
image = image.convert('RGB')
|
||||
image.save(os.path.join(CACHE_PATH, f'{file_name}_{res_x}x{res_y}.{ext}'),
|
||||
icc_profile=image_icc)
|
||||
|
||||
# No need to keep the image in memory, learned the hard way
|
||||
image.close()
|
||||
|
||||
return os.path.join(CACHE_PATH, f'{file_name}_{res_x}x{res_y}.{ext}')
|
||||
|
|
Loading…
Reference in a new issue