radiant_ai / app.py
arshvir's picture
Fix indentation after NBSP cleanup in app.py
14e5cba
import os
import time
from flask import Flask, render_template, request, jsonify, send_from_directory
from werkzeug.utils import secure_filename
# Import Services (We will create these next)
# Note: Ensure empty __init__.py exists in services/ folder
from services.studio import StudioService
from services.vision import VisionService
from services.ai_studio import AIStudioService
from services.utilities import UtilitiesService
# Initialize Flask App
app = Flask(__name__)
# --- Configuration ---
UPLOAD_FOLDER = 'static/uploads'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'webp', 'bmp'}
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 32 * 1024 * 1024
app.secret_key = 'radiant_secret_key_dev'
# Ensure upload directory exists
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
# Initialize Service Instances
studio_service = StudioService()
vision_service = VisionService()
ai_service = AIStudioService()
utilities_service = UtilitiesService()
# --- Helpers ---
def allowed_file(filename):
return (
'.' in filename and
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
)
def get_file_path(filename):
return os.path.join(app.config['UPLOAD_FOLDER'], secure_filename(filename))
def generate_output_filename(original_filename, prefix="processed"):
timestamp = int(time.time())
name, ext = os.path.splitext(original_filename)
return f"{prefix}_{timestamp}_{name}{ext}"
# --- Page Routes (Frontend) ---
@app.route('/')
def index():
return render_template('onboarding.html')
@app.route('/studio')
def studio():
return render_template('studio.html')
@app.route('/vision')
def vision():
return render_template('vision.html')
@app.route('/ai-studio')
def ai_studio():
return render_template('ai_studio.html')
@app.route('/utilities')
def utilities():
return render_template('utilities.html')
@app.route('/about')
def about():
return render_template('about.html')
#@app.route('/products')
#def products():
# return render_template('products.html')
@app.route('/docs')
def docs():
return render_template('docs.html')
@app.route('/download')
def download():
return render_template('download.html')
# --- API: Core Upload ---
@app.route('/api/upload', methods=['POST'])
def upload_file():
if 'file' not in request.files:
return jsonify({'success': False, 'error': 'No file part'}), 400
file = request.files['file']
if file.filename == '':
return jsonify({'success': False, 'error': 'No selected file'}), 400
if file and allowed_file(file.filename):
# Create unique filename
filename = secure_filename(f"{int(time.time())}_{file.filename}")
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(filepath)
return jsonify({
'success': True,
'filename': filename,
'url': f"/static/uploads/{filename}"
})
return jsonify({'success': False, 'error': 'Invalid file type'}), 400
# --- API: Studio (Image Editing) ---
@app.route('/api/process-studio', methods=['POST'])
def process_studio():
try:
data = request.json
filename = data.get('filename')
options = data.get('options') # Contains brightness, contrast, filter, etc.
if not filename or not options:
return jsonify({'success': False, 'error': 'Missing parameters'}), 400
input_path = get_file_path(filename)
output_filename = generate_output_filename(filename, "edit")
output_path = os.path.join(app.config['UPLOAD_FOLDER'], output_filename)
# Call Service
success, result = studio_service.process_request(input_path, output_path, options)
if success:
return jsonify({
'success': True,
'url': f"/static/uploads/{output_filename}",
'filename': output_filename
})
else:
return jsonify({'success': False, 'error': str(result)}), 500
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
# --- API: Vision (YOLO, BG Remove) ---
@app.route('/api/process-vision', methods=['POST'])
def process_vision():
try:
data = request.json
filename = data.get('filename')
task = data.get('task')
# extra options like 'color' for bg replacement or 'value' for blur intensity
options = data
if not filename or not task:
return jsonify({'success': False, 'error': 'Missing parameters'}), 400
input_path = get_file_path(filename)
output_filename = generate_output_filename(filename, f"vision_{task}")
output_path = os.path.join(app.config['UPLOAD_FOLDER'], output_filename)
success, result_meta = vision_service.process_request(input_path, output_path, task, options)
if success:
response = {
'success': True,
'url': f"/static/uploads/{output_filename}",
'filename': output_filename
}
# Add detections if they exist (for YOLO)
if isinstance(result_meta, dict) and 'detections' in result_meta:
response['detections'] = result_meta['detections']
return jsonify(response)
else:
return jsonify({'success': False, 'error': str(result_meta)}), 500
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
# --- API: AI Studio (Colorize, Upscale) ---
@app.route('/api/process-ai', methods=['POST'])
def process_ai():
try:
data = request.json
filename = data.get('filename')
task = data.get('task')
if not filename or not task:
return jsonify({'success': False, 'error': 'Missing parameters'}), 400
input_path = get_file_path(filename)
output_filename = generate_output_filename(filename, f"ai_{task}")
output_path = os.path.join(app.config['UPLOAD_FOLDER'], output_filename)
success, result = ai_service.process_request(input_path, output_path, task)
if success:
return jsonify({
'success': True,
'url': f"/static/uploads/{output_filename}",
'filename': output_filename
})
else:
return jsonify({'success': False, 'error': str(result)}), 500
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
# --- API: Utilities (Convert, Resize) ---
@app.route('/api/process-utility', methods=['POST'])
def process_utility():
try:
data = request.json
filename = data.get('filename')
# Service handles specific logic internally
input_path = get_file_path(filename)
# Output directory is passed so service can generate name based on format
output_dir = app.config['UPLOAD_FOLDER']
success, result = utilities_service.process_request(input_path, output_dir, data)
if success:
if data.get('action') == 'metadata':
return jsonify({'success': True, 'metadata': result})
else:
return jsonify({
'success': True,
'url': f"/static/uploads/{result}",
'filename': result
})
else:
return jsonify({'success': False, 'error': str(result)}), 500
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
# --- Serve Static Files (Images) ---
@app.route('/static/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
if __name__ == '__main__':
#print("Radiant AI Server (local dev)")
app.run(host='0.0.0.0', port=7860)