""" Preview rendering for SSIM screenshot processor. Renders images properly in the browser instead of showing raw bytes. """ from loguru import logger def get_asset(asset_name, watch, datastore, request): """ Get processor-specific binary assets for preview streaming. This function supports serving images as separate HTTP responses instead of embedding them as base64 in the HTML template, solving memory issues with large screenshots. Supported assets: - 'screenshot': The screenshot for the specified version Args: asset_name: Name of the asset to retrieve ('screenshot') watch: Watch object datastore: Datastore object request: Flask request (for version query param) Returns: tuple: (binary_data, content_type, cache_control_header) or None if not found """ if asset_name != 'screenshot': return None versions = list(watch.history.keys()) if len(versions) == 0: return None # Get the version from query string (default: latest) preferred_version = request.args.get('version') timestamp = versions[-1] if preferred_version and preferred_version in versions: timestamp = preferred_version try: screenshot_bytes = watch.get_history_snapshot(timestamp=timestamp) # Convert to bytes if needed if isinstance(screenshot_bytes, str): screenshot_bytes = screenshot_bytes.encode('utf-8') # Detect image format if screenshot_bytes[:8] == b'\x89PNG\r\n\x1a\n': mime_type = 'image/png' elif screenshot_bytes[:3] == b'\xff\xd8\xff': mime_type = 'image/jpeg' elif screenshot_bytes[:6] in (b'GIF87a', b'GIF89a'): mime_type = 'image/gif' elif screenshot_bytes[:4] == b'RIFF' and screenshot_bytes[8:12] == b'WEBP': mime_type = 'image/webp' else: mime_type = 'image/png' # Default fallback return (screenshot_bytes, mime_type, 'public, max-age=3600') except Exception as e: logger.error(f"Failed to load screenshot for preview asset: {e}") return None def render(watch, datastore, request, url_for, render_template, flash, redirect): """ Render the preview page for screenshot watches. Args: watch: Watch object datastore: Datastore object request: Flask request url_for: Flask url_for function render_template: Flask render_template function flash: Flask flash function redirect: Flask redirect function Returns: Rendered template or redirect """ versions = list(watch.history.keys()) if len(versions) == 0: flash("Preview unavailable - No snapshots captured yet", "error") return redirect(url_for('watchlist.index')) # Get the version to display (default: latest) preferred_version = request.args.get('version') timestamp = versions[-1] if preferred_version and preferred_version in versions: timestamp = preferred_version # Render custom template for image preview # Screenshot is now served via separate /processor-asset/ endpoint instead of base64 # This significantly reduces memory usage by not embedding large images in HTML return render_template( 'image_ssim_diff/preview.html', watch=watch, uuid=watch.get('uuid'), versions=versions, timestamp=timestamp, current_diff_url=watch['url'] )