""" Visualization Display Component Displays AI-generated architectural sketches with metadata and download functionality """ import base64 import logging import tempfile import os from pathlib import Path from typing import Optional, Tuple from datetime import datetime logger = logging.getLogger(__name__) def format_visualization_display(visualization_data) -> Tuple[str, Optional[str], Optional[str]]: """ Format visualization data for display with image and metadata Args: visualization_data: Visualization data (dict or VisualizationData object) Returns: Tuple of (HTML string, image path for gr.Image component, download path) """ # Handle missing or empty visualization data if not visualization_data: return _format_no_visualization(), None, None # Handle both dict and object formats if isinstance(visualization_data, dict): success = visualization_data.get('success', True) if not success: error = visualization_data.get('error', {}) return _format_visualization_error(error), None, None image_base64 = visualization_data.get('image_base64', '') prompt_used = visualization_data.get('prompt_used', '') model_version = visualization_data.get('model_version', 'Unknown') generation_timestamp = visualization_data.get('generation_timestamp', 'Unknown') image_format = visualization_data.get('image_format', 'PNG') resolution = visualization_data.get('resolution', 'Unknown') features_included = visualization_data.get('features_included', []) else: image_base64 = getattr(visualization_data, 'image_base64', '') prompt_used = getattr(visualization_data, 'prompt_used', '') model_version = getattr(visualization_data, 'model_version', 'Unknown') generation_timestamp = getattr(visualization_data, 'generation_timestamp', 'Unknown') image_format = getattr(visualization_data, 'image_format', 'PNG') resolution = getattr(visualization_data, 'resolution', 'Unknown') features_included = getattr(visualization_data, 'features_included', []) # Validate image data if not image_base64: return _format_no_visualization(), None, None # Convert base64 to temporary file for Gradio Image component image_path = None download_path = None try: # Decode base64 image image_bytes = base64.b64decode(image_base64) # Create temporary file for display temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.png', mode='wb') temp_file.write(image_bytes) temp_file.close() image_path = temp_file.name # Create a downloadable file with a meaningful name download_dir = Path("gradio-ui/downloads") download_dir.mkdir(exist_ok=True) # Generate filename with timestamp including microseconds for uniqueness timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f") download_filename = f"construction_visualization_{timestamp}.png" download_path = download_dir / download_filename # Write image to download location with open(download_path, 'wb') as f: f.write(image_bytes) logger.info(f"Created temporary image file: {image_path}") logger.info(f"Created downloadable image file: {download_path}") except Exception as e: logger.error(f"Error converting base64 to image file: {e}") return _format_no_visualization(), None, None # Build HTML output html = f"""
Model: {model_version}
Generated: {generation_timestamp}
Format: {image_format}
Resolution: {resolution}
Download: Use the download button below the image to save
{prompt_used}
âšī¸ This visualization is AI-generated and represents a conceptual design. Consult with licensed architects and engineers for actual construction plans.
The visualization agent did not generate an image for this construction plan. This may occur if the visualization service is unavailable or if there was an error during generation.
Error Code: {code}
Message: {message}
{f"Retry Possible: {'Yes' if retry_possible else 'No'}
" if retry_possible is not None else ''}