#<!
DOCTYPE html>
<html>
<head>
<title>Visualizador de Cámara OV7670</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; margin-top:
50px; }
canvas { border: 1px solid black; }
</style>
</head>
<body>
<h1>Cámara OV7670 en Tiempo Real</h1>
<canvas id="cameraCanvas"></canvas>
<p>Dimensiones: <span id="dimensions">N/A</span></p>
<script>
const canvas = document.getElementById('cameraCanvas');
const ctx = canvas.getContext('2d');
const dimensionsSpan = document.getElementById('dimensions');
// Asegúrate de que esta URL apunte a la IP de tu microcontrolador
ejecutando main.py
const SERVER_URL = "http://192.168.0.100:5000/get_image_json";
async function fetchImage() {
try {
const response = await fetch(SERVER_URL);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// Esperar una respuesta JSON
const jsonData = await response.json();
if (jsonData.status === "success") {
const width = jsonData.width;
const height = jsonData.height;
const encodedImage = jsonData.image_data; // Datos Base64 de la
imagen
dimensionsSpan.textContent = `${width}x${height}`;
canvas.width = width;
canvas.height = height;
// Decodificar Base64 a un ArrayBuffer
const binaryString = atob(encodedImage);
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
const buffer = bytes.buffer; // Esto es tu ArrayBuffer de datos
RGB565
const imageData = ctx.createImageData(width, height);
const pixels = new Uint8ClampedArray(imageData.data);
// Conversión de RGB565 a RGBA (similar a la anterior)
const dataView = new DataView(buffer);
let pixelIndex = 0;
for (let i = 0; i < buffer.byteLength; i += 2) {
const rgb565 = dataView.getUint16(i, false); // false para
big-endian (comprueba si tu cámara lo es)
const r = ((rgb565 >> 11) & 0x1F) << 3; // 5 bits para Rojo
const g = ((rgb565 >> 5) & 0x3F) << 2; // 6 bits para
Verde
const b = (rgb565 & 0x1F) << 3; // 5 bits para Azul
pixels[pixelIndex++] = r;
pixels[pixelIndex++] = g;
pixels[pixelIndex++] = b;
pixels[pixelIndex++] = 255; // Alpha (completamente opaco)
}
ctx.putImageData(imageData, 0, 0);
} else {
console.error("Error del servidor:", jsonData.message);
dimensionsSpan.textContent = `Error del servidor: $
{jsonData.message}`;
}
} catch (error) {
console.error("Error al obtener o procesar la imagen:", error);
dimensionsSpan.textContent = `Error: ${error.message}`;
}
}
// Obtener imagen repetidamente para el efecto en tiempo real
setInterval(fetchImage, 100); // Obtener cada 100ms
fetchImage(); // Primera obtención al cargar la página
</script>
</body>
</html>