GIF / app.py
yangtb24's picture
Update app.py
aaaba76 verified
import os
from flask import Flask, request, jsonify, render_template
from io import BytesIO
from PIL import Image
from imageio import mimwrite
import base64
app = Flask(__name__)
HTML_CONTENT = """
<!DOCTYPE html>
<html>
<head>
<title>GIF Generator</title>
<style>
body { font-family: sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; background-color: #f4f4f4; }
.container { background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0,0,0,0.1); text-align: center; }
input[type="file"] { margin-bottom: 10px; display: block; margin-left: auto; margin-right: auto; }
input[type="number"] { margin-bottom: 10px; display: block; margin-left: auto; margin-right: auto; }
button { background-color: #007bff; color: white; padding: 10px 15px; border: none; border-radius: 5px; cursor: pointer; }
button:hover { background-color: #0056b3; }
#gif-container { margin-top: 20px; }
#gif-image { max-width: 100%; }
</style>
</head>
<body>
<div class="container">
<h1>GIF Generator</h1>
<form id="upload-form" enctype="multipart/form-data">
<input type="file" name="images" accept="image/*" multiple>
<input type="number" name="delay" placeholder="Delay (ms)" value="100" min="1" >
<button type="button" id="generate-button">Generate GIF</button>
</form>
<div id="gif-container" style="display:none;">
<a id="download-link" href="#" download="animated.gif">
<button>Download GIF</button>
</a>
</div>
</div>
<script>
document.getElementById('generate-button').addEventListener('click', async () => {
const form = document.getElementById('upload-form');
const formData = new FormData(form);
try {
const response = await fetch('/upload', {
method: 'POST',
body: formData
});
if (response.ok) {
const data = await response.json();
const gifContainer = document.getElementById('gif-container');
const downloadLink = document.getElementById('download-link');
downloadLink.href = data.gif_url;
gifContainer.style.display = 'block';
} else {
const errorText = await response.text();
alert('Error generating GIF: ' + errorText);
}
} catch (error) {
console.error('Fetch error:', error);
alert('An error occurred during the request.');
}
});
</script>
</body>
</html>
"""
@app.route('/', methods=['GET'])
def index():
return HTML_CONTENT
@app.route('/upload', methods=['POST'])
def upload():
try:
files = request.files.getlist('images')
delay_ms = int(request.form.get('delay', 100))
if not files:
return "No images uploaded", 400
images = []
max_width = 0
max_height = 0
# 1. Read images and find *maximum* dimensions
for file in files:
if file:
try:
img = Image.open(BytesIO(file.read()))
max_width = max(max_width, img.width)
max_height = max(max_height, img.height)
images.append(img)
except Exception as e:
print(f"Error opening image: {e}")
return f"Error opening image: {e}", 500
if not images:
return "No valid images processed", 400
# 2. Resize *ALL* images to the *EXACT* maximum dimensions and convert to RGB
resized_images = []
for img in images:
# Convert to RGB to avoid mode issues (RGBA vs RGB)
img = img.convert("RGB") # CRUCIAL: Handle different image modes!
resized_img = img.resize((max_width, max_height), Image.LANCZOS)
resized_images.append(resized_img)
# 3. Generate GIF using imageio
gif_bytes = BytesIO()
mimwrite(gif_bytes, resized_images, format='GIF', loop=0, duration=delay_ms / 1000)
gif_bytes.seek(0)
gif_base64 = base64.b64encode(gif_bytes.read()).decode('utf-8')
gif_url = f'data:image/gif;base64,{gif_base64}'
return jsonify({'gif_url': gif_url})
except Exception as e:
print(f"Error during upload: {e}")
return f"Error: {e}", 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 7860)), debug=True)