Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| # checker_pattern.py - Simple raw data checker pattern | |
| import numpy as np | |
| import time | |
| import os | |
| from flask import Flask, Response | |
| # ===== 1. SETUP ===== | |
| PORT = int(os.getenv('PORT', 7860)) | |
| WIDTH, HEIGHT = 400, 300 | |
| TILE_SIZE = 40 # Size of each checker tile | |
| print(f"π Starting checker pattern server on port {PORT}") | |
| # ===== 2. CREATE FLASK APP ===== | |
| app = Flask(__name__) | |
| # ===== 3. SIMPLE HTML WITH CANVAS ===== | |
| HTML = '''<!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Checker Pattern Test</title> | |
| <style> | |
| body { | |
| margin: 0; | |
| padding: 20px; | |
| background: #222; | |
| color: white; | |
| font-family: Arial, sans-serif; | |
| text-align: center; | |
| } | |
| h1 { color: #4CAF50; } | |
| #testCanvas { | |
| border: 5px solid #4CAF50; | |
| background: black; | |
| display: block; | |
| margin: 20px auto; | |
| image-rendering: pixelated; | |
| } | |
| .info { | |
| background: #333; | |
| padding: 15px; | |
| border-radius: 8px; | |
| display: inline-block; | |
| margin: 10px; | |
| text-align: left; | |
| } | |
| .success { color: #4CAF50; font-weight: bold; } | |
| .error { color: #f44336; font-weight: bold; } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>β CHECKER PATTERN TEST - MUST SHOW BELOW</h1> | |
| <div> | |
| <h3>If you see a black/white checker pattern below, it's WORKING!</h3> | |
| <canvas id="testCanvas" width="400" height="300"></canvas> | |
| </div> | |
| <div class="info"> | |
| <h3>Debug Info:</h3> | |
| <div>Server Time: <span id="serverTime">-</span></div> | |
| <div>Data Size: <span id="dataSize">0</span> bytes</div> | |
| <div>Status: <span id="status" class="success">Loading...</span></div> | |
| <div>Last Update: <span id="lastUpdate">Never</span></div> | |
| </div> | |
| <div style="margin-top: 20px;"> | |
| <button onclick="loadChecker()">Load Checker Pattern</button> | |
| <button onclick="testRaw()">Test Raw Data</button> | |
| <button onclick="testImage()">Test Image Format</button> | |
| </div> | |
| <script> | |
| const canvas = document.getElementById('testCanvas'); | |
| const ctx = canvas.getContext('2d'); | |
| // Create a simple checker pattern directly in JavaScript | |
| function drawLocalChecker() { | |
| console.log('π¨ Drawing local checker pattern...'); | |
| const tileSize = 40; | |
| const imageData = new ImageData(400, 300); | |
| const data = imageData.data; | |
| for (let y = 0; y < 300; y++) { | |
| for (let x = 0; x < 400; x++) { | |
| const i = (y * 400 + x) * 4; | |
| // Checker pattern logic | |
| const tileX = Math.floor(x / tileSize); | |
| const tileY = Math.floor(y / tileSize); | |
| if ((tileX + tileY) % 2 === 0) { | |
| // White tile | |
| data[i] = 255; // R | |
| data[i + 1] = 255; // G | |
| data[i + 2] = 255; // B | |
| } else { | |
| // Black tile | |
| data[i] = 0; // R | |
| data[i + 1] = 0; // G | |
| data[i + 2] = 0; // B | |
| } | |
| data[i + 3] = 255; // Alpha | |
| } | |
| } | |
| ctx.putImageData(imageData, 0, 0); | |
| console.log('β Local checker drawn'); | |
| } | |
| // Load checker pattern from Flask | |
| function loadChecker() { | |
| console.log('π₯ Loading checker from server...'); | |
| fetch('/checker') | |
| .then(response => { | |
| console.log('Response:', response.status, response.statusText); | |
| return response.arrayBuffer(); | |
| }) | |
| .then(buffer => { | |
| console.log(`π¦ Received ${buffer.byteLength} bytes`); | |
| if (buffer.byteLength === 0) { | |
| console.error('β Empty buffer!'); | |
| return; | |
| } | |
| // Create ImageData | |
| const imageData = new ImageData(400, 300); | |
| const rgba = imageData.data; | |
| const rgb = new Uint8Array(buffer); | |
| // Check size | |
| const expectedSize = 400 * 300 * 3; | |
| if (rgb.length !== expectedSize) { | |
| console.error(`β Wrong size! Got ${rgb.length}, expected ${expectedSize}`); | |
| return; | |
| } | |
| // Convert RGB to RGBA | |
| for (let i = 0, j = 0; i < rgba.length; i += 4, j += 3) { | |
| rgba[i] = rgb[j]; | |
| rgba[i + 1] = rgb[j + 1]; | |
| rgba[i + 2] = rgb[j + 2]; | |
| rgba[i + 3] = 255; | |
| } | |
| // Draw to canvas | |
| ctx.putImageData(imageData, 0, 0); | |
| // Update UI | |
| document.getElementById('dataSize').textContent = buffer.byteLength; | |
| document.getElementById('lastUpdate').textContent = new Date().toLocaleTimeString(); | |
| document.getElementById('status').textContent = 'Loaded β'; | |
| console.log('β Server checker drawn'); | |
| }) | |
| .catch(error => { | |
| console.error('β Load error:', error); | |
| document.getElementById('status').textContent = 'Error: ' + error.message; | |
| document.getElementById('status').className = 'error'; | |
| }); | |
| } | |
| function testRaw() { | |
| console.log('π§ͺ Testing raw data endpoint...'); | |
| fetch('/raw') | |
| .then(r => r.arrayBuffer()) | |
| .then(buffer => { | |
| console.log('Raw test:', buffer.byteLength, 'bytes'); | |
| alert(`Raw data test: ${buffer.byteLength} bytes received`); | |
| }); | |
| } | |
| function testImage() { | |
| console.log('πΌοΈ Testing image endpoint...'); | |
| const img = new Image(); | |
| img.onload = () => { | |
| console.log('Image loaded'); | |
| ctx.drawImage(img, 0, 0); | |
| alert('Image loaded successfully'); | |
| }; | |
| img.onerror = (e) => { | |
| console.error('Image failed:', e); | |
| alert('Image failed to load'); | |
| }; | |
| img.src = '/image?t=' + Date.now(); | |
| } | |
| // Initialize | |
| drawLocalChecker(); | |
| console.log('π’ Page ready'); | |
| </script> | |
| </body> | |
| </html>''' | |
| def index(): | |
| return HTML | |
| def get_checker(): | |
| """Return raw RGB bytes of a checker pattern""" | |
| print("π² Generating checker pattern...") | |
| # Create checker pattern using numpy | |
| pattern = np.zeros((HEIGHT, WIDTH, 3), dtype=np.uint8) | |
| # Create grid of tile indices | |
| y_indices, x_indices = np.mgrid[:HEIGHT, :WIDTH] | |
| tile_x = x_indices // TILE_SIZE | |
| tile_y = y_indices // TILE_SIZE | |
| # Checker pattern: (tile_x + tile_y) % 2 == 0 -> white, else black | |
| checker_mask = ((tile_x + tile_y) % 2 == 0) | |
| # White tiles: RGB = [255, 255, 255] | |
| pattern[checker_mask] = [255, 255, 255] | |
| # Black tiles: already [0, 0, 0] from zeros initialization | |
| # Convert to raw bytes | |
| raw_bytes = pattern.tobytes() | |
| print(f"π€ Serving checker pattern: {len(raw_bytes)} bytes") | |
| return Response( | |
| raw_bytes, | |
| mimetype='application/octet-stream', | |
| headers={ | |
| 'Cache-Control': 'no-cache, no-store, must-revalidate', | |
| 'Content-Type': 'application/octet-stream', | |
| 'X-Pattern': 'checker' | |
| } | |
| ) | |
| def get_image(): | |
| """Return the same checker pattern as a JPEG image""" | |
| print("πΌοΈ Generating checker image...") | |
| # Create checker pattern | |
| pattern = np.zeros((HEIGHT, WIDTH, 3), dtype=np.uint8) | |
| y_indices, x_indices = np.mgrid[:HEIGHT, :WIDTH] | |
| tile_x = x_indices // TILE_SIZE | |
| tile_y = y_indices // TILE_SIZE | |
| checker_mask = ((tile_x + tile_y) % 2 == 0) | |
| pattern[checker_mask] = [255, 255, 255] | |
| # Convert to JPEG using PIL | |
| from PIL import Image | |
| import io | |
| img = Image.fromarray(pattern, 'RGB') | |
| buffer = io.BytesIO() | |
| img.save(buffer, format='JPEG', quality=90) | |
| buffer.seek(0) | |
| print(f"π€ Serving JPEG image: {buffer.getbuffer().nbytes} bytes") | |
| return Response( | |
| buffer.getvalue(), | |
| mimetype='image/jpeg', | |
| headers={'Cache-Control': 'no-cache'} | |
| ) | |
| def get_raw(): | |
| """Simple raw data test - returns colored stripes""" | |
| print("π Generating colored stripes...") | |
| # Create colored stripes pattern | |
| pattern = np.zeros((HEIGHT, WIDTH, 3), dtype=np.uint8) | |
| # Red stripe | |
| pattern[:, :WIDTH//3, 0] = 255 | |
| # Green stripe | |
| pattern[:, WIDTH//3:2*WIDTH//3, 1] = 255 | |
| # Blue stripe | |
| pattern[:, 2*WIDTH//3:, 2] = 255 | |
| raw_bytes = pattern.tobytes() | |
| return Response( | |
| raw_bytes, | |
| mimetype='application/octet-stream', | |
| headers={'Cache-Control': 'no-cache'} | |
| ) | |
| def test(): | |
| """Simple test endpoint""" | |
| return { | |
| 'status': 'ok', | |
| 'time': time.time(), | |
| 'width': WIDTH, | |
| 'height': HEIGHT, | |
| 'tile_size': TILE_SIZE, | |
| 'data_size': WIDTH * HEIGHT * 3 | |
| } | |
| # ===== 4. MAIN ===== | |
| def main(): | |
| print("="*60) | |
| print("π― CHECKER PATTERN SERVER") | |
| print("="*60) | |
| print(f"π‘ Port: {PORT}") | |
| print(f"π¨ Resolution: {WIDTH}x{HEIGHT}") | |
| print(f"π§± Tile size: {TILE_SIZE}") | |
| print(f"π Data size per frame: {WIDTH * HEIGHT * 3} bytes") | |
| print("="*60) | |
| print("β Server ready! Open in browser:") | |
| print(f" http://localhost:{PORT}") | |
| print("="*60) | |
| try: | |
| app.run( | |
| host='0.0.0.0', | |
| port=PORT, | |
| debug=False, | |
| threaded=True, | |
| use_reloader=False | |
| ) | |
| except Exception as e: | |
| print(f"β Server error: {e}") | |
| if __name__ == "__main__": | |
| main() |