Profile Image Optimizations
made it as fast as i could, maybe there are faster solutions but I'm fine with this
This commit is contained in:
parent
be16821be2
commit
9d945f5edc
60
app.py
60
app.py
@ -1,7 +1,9 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
from PIL import Image
|
|
||||||
|
from PIL import Image, ImageSequence
|
||||||
|
import concurrent.futures
|
||||||
|
|
||||||
from flask import Flask, render_template, redirect, url_for, request, jsonify
|
from flask import Flask, render_template, redirect, url_for, request, jsonify
|
||||||
from flask_login import login_required, LoginManager, login_user, logout_user, current_user
|
from flask_login import login_required, LoginManager, login_user, logout_user, current_user
|
||||||
@ -782,43 +784,47 @@ def save_profile_image(image_file):
|
|||||||
|
|
||||||
# Get the filename from the image path saved in the user
|
# Get the filename from the image path saved in the user
|
||||||
filename = os.path.basename(current_user.profile_image)
|
filename = os.path.basename(current_user.profile_image)
|
||||||
image_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
|
||||||
os.remove(image_path)
|
|
||||||
|
|
||||||
# Check if the image is an animated gif
|
|
||||||
if file_extension == 'gif':
|
|
||||||
gif_path = os.path.join(app.config['UPLOAD_FOLDER'], filename.replace(".jpg", ".gif"))
|
|
||||||
image_file.save(gif_path)
|
|
||||||
|
|
||||||
current_user.profile_image = gif_path
|
|
||||||
current_user.update()
|
|
||||||
return
|
|
||||||
|
|
||||||
# Open the uploaded image
|
# Open the uploaded image
|
||||||
image = Image.open(image_file)
|
image = Image.open(image_file)
|
||||||
|
|
||||||
# Convert the image to RGB mode (required for JPEG)
|
# Function to crop and resize frames
|
||||||
image = image.convert('RGB')
|
def process_frame(frame, size):
|
||||||
|
new_size = min(frame.size)
|
||||||
|
left = (frame.width - new_size) // 2
|
||||||
|
top = (frame.height - new_size) // 2
|
||||||
|
right = left + new_size
|
||||||
|
bottom = top + new_size
|
||||||
|
cropped_frame = frame.crop((left, top, right, bottom))
|
||||||
|
return cropped_frame.resize(size)
|
||||||
|
|
||||||
# Determine the size of the square image
|
# Function to process frames in parallel
|
||||||
min_dimension = min(image.size)
|
def process_frames_parallel(frames, size):
|
||||||
square_size = (min_dimension, min_dimension)
|
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||||
|
resized_frames = list(executor.map(lambda f: process_frame(f, size), frames))
|
||||||
|
return resized_frames
|
||||||
|
|
||||||
# Calculate the coordinates for cropping
|
# Check if the image is an animated gif
|
||||||
left = (image.width - min_dimension) / 2
|
if file_extension == 'gif':
|
||||||
top = (image.height - min_dimension) / 2
|
# Process frames
|
||||||
right = (image.width + min_dimension) / 2
|
gif_frames = [frame.copy() for frame in ImageSequence.Iterator(image)]
|
||||||
bottom = (image.height + min_dimension) / 2
|
processed_frames = process_frames_parallel(gif_frames, size=(128, 128))
|
||||||
|
|
||||||
# Crop the image to a square and resize it
|
# Save the modified frames as a new GIF
|
||||||
image = image.crop((left, top, right, bottom))
|
output_gif_path = os.path.join(app.config['UPLOAD_FOLDER'], filename.replace(".jpg", ".gif"))
|
||||||
image.thumbnail(square_size)
|
processed_frames[0].save(output_gif_path, save_all=True, append_images=processed_frames[1:], loop=0)
|
||||||
image = image.resize((256, 256))
|
current_user.profile_image = output_gif_path
|
||||||
|
else:
|
||||||
|
# Process single image
|
||||||
|
processed_image = process_frame(image, size=(256, 256))
|
||||||
|
processed_image = processed_image.convert('RGB')
|
||||||
|
|
||||||
# Save the processed image
|
# Save the processed image
|
||||||
image_path = os.path.join(app.config['UPLOAD_FOLDER'], filename.replace(".gif", ".jpg"))
|
image_path = os.path.join(app.config['UPLOAD_FOLDER'], filename.replace(".gif", ".jpg"))
|
||||||
image.save(image_path, 'JPEG', quality=100)
|
processed_image.save(image_path, 'JPEG', quality=100)
|
||||||
current_user.profile_image = image_path
|
current_user.profile_image = image_path
|
||||||
|
|
||||||
|
# Update user profile
|
||||||
current_user.update()
|
current_user.update()
|
||||||
|
|
||||||
@app.route('/upload', methods=['POST'])
|
@app.route('/upload', methods=['POST'])
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<div class = "row">
|
<div class = "row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h1>
|
<h1>
|
||||||
{% if (current_user.is_authenticated) %}<img class="avatar avatar-xl" src="{{user.profile_image}}" alt="failed to load image"/>{% endif %}
|
{% if (current_user.is_authenticated) %}<img class="avatar avatar-xl" src="{{user.profile_image}}" alt="no image"/>{% endif %}
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</h1>
|
</h1>
|
||||||
<h3>{{ utc_dt }}</h3>
|
<h3>{{ utc_dt }}</h3>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user