Spaces:
Sleeping
Sleeping
| import os | |
| import io | |
| import zipfile | |
| import json | |
| from flask import Flask, render_template, request, send_file, jsonify | |
| from PIL import Image, ImageOps, ImageColor | |
| app = Flask(__name__) | |
| app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 | |
| ICO_SIZES = [(16, 16), (32, 32), (48, 48), (64, 64)] | |
| APPLE_ICON_SIZE = (180, 180) | |
| ANDROID_192_SIZE = (192, 192) | |
| ANDROID_512_SIZE = (512, 512) | |
| def index(): | |
| return render_template('index.html') | |
| def make_square(im, min_size=256, fill_color=(255, 255, 255, 0)): | |
| """ | |
| Pads the image to make it square without distorting aspect ratio. | |
| """ | |
| x, y = im.size | |
| size = max(min_size, x, y) | |
| new_im = Image.new('RGBA', (size, size), fill_color) | |
| paste_x = (size - x) // 2 | |
| paste_y = (size - y) // 2 | |
| new_im.paste(im, (paste_x, paste_y)) | |
| return new_im | |
| def generate(): | |
| if 'file' not in request.files: | |
| return jsonify({'error': 'No file part'}), 400 | |
| file = request.files['file'] | |
| if file.filename == '': | |
| return jsonify({'error': 'No selected file'}), 400 | |
| bg_color_hex = request.form.get('bgColor', '') | |
| site_name = request.form.get('siteName', 'My Website') or 'My Website' | |
| short_name = request.form.get('shortName', 'Website') or 'Website' | |
| fill_color = (255, 255, 255, 0) | |
| theme_color = "#ffffff" | |
| if bg_color_hex and bg_color_hex != 'transparent': | |
| try: | |
| rgb = ImageColor.getrgb(bg_color_hex) | |
| fill_color = rgb + (255,) | |
| theme_color = bg_color_hex | |
| except Exception: | |
| pass | |
| try: | |
| img = Image.open(file.stream) | |
| if img.mode != 'RGBA': | |
| img = img.convert('RGBA') | |
| img_square = make_square(img, fill_color=fill_color) | |
| if bg_color_hex and bg_color_hex != 'transparent': | |
| bg_layer = Image.new('RGBA', img_square.size, fill_color) | |
| bg_layer.paste(img_square, (0, 0), img_square) | |
| img_square = bg_layer | |
| memory_file = io.BytesIO() | |
| with zipfile.ZipFile(memory_file, 'w', zipfile.ZIP_DEFLATED) as zf: | |
| ico_io = io.BytesIO() | |
| img_square.save(ico_io, format='ICO', sizes=ICO_SIZES) | |
| ico_io.seek(0) | |
| zf.writestr('favicon.ico', ico_io.read()) | |
| apple_io = io.BytesIO() | |
| img_apple = img_square.resize(APPLE_ICON_SIZE, Image.Resampling.LANCZOS) | |
| img_apple.save(apple_io, format='PNG') | |
| apple_io.seek(0) | |
| zf.writestr('apple-touch-icon.png', apple_io.read()) | |
| android192_io = io.BytesIO() | |
| img_192 = img_square.resize(ANDROID_192_SIZE, Image.Resampling.LANCZOS) | |
| img_192.save(android192_io, format='PNG') | |
| android192_io.seek(0) | |
| zf.writestr('android-chrome-192x192.png', android192_io.read()) | |
| favicon32_io = io.BytesIO() | |
| img_32 = img_square.resize((32, 32), Image.Resampling.LANCZOS) | |
| img_32.save(favicon32_io, format='PNG') | |
| favicon32_io.seek(0) | |
| zf.writestr('favicon-32x32.png', favicon32_io.read()) | |
| favicon16_io = io.BytesIO() | |
| img_16 = img_square.resize((16, 16), Image.Resampling.LANCZOS) | |
| img_16.save(favicon16_io, format='PNG') | |
| favicon16_io.seek(0) | |
| zf.writestr('favicon-16x16.png', favicon16_io.read()) | |
| android512_io = io.BytesIO() | |
| img_512 = img_square.resize(ANDROID_512_SIZE, Image.Resampling.LANCZOS) | |
| img_512.save(android512_io, format='PNG') | |
| android512_io.seek(0) | |
| zf.writestr('android-chrome-512x512.png', android512_io.read()) | |
| manifest = { | |
| "name": site_name, | |
| "short_name": short_name, | |
| "icons": [ | |
| { | |
| "src": "/android-chrome-192x192.png", | |
| "sizes": "192x192", | |
| "type": "image/png" | |
| }, | |
| { | |
| "src": "/android-chrome-512x512.png", | |
| "sizes": "512x512", | |
| "type": "image/png" | |
| } | |
| ], | |
| "theme_color": theme_color, | |
| "background_color": theme_color, | |
| "display": "standalone" | |
| } | |
| zf.writestr('site.webmanifest', json.dumps(manifest, indent=2)) | |
| memory_file.seek(0) | |
| return send_file( | |
| memory_file, | |
| mimetype='application/zip', | |
| as_attachment=True, | |
| download_name='favicons.zip' | |
| ) | |
| except Exception as e: | |
| return jsonify({'error': str(e)}), 500 | |
| if __name__ == '__main__': | |
| port = int(os.environ.get('PORT', 7860)) | |
| app.run(host='0.0.0.0', port=port) | |