Files
fn_registry/dev/issues/0036-cpp-image-canvas-webcam.md

161 lines
5.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: "0036"
title: "C++ image_canvas + webcam_texture"
status: pendiente
type: feature
domain:
- cpp-stack
scope: multi-app
priority: baja
depends: []
blocks: []
related: []
created: 2026-05-17
updated: 2026-05-17
tags: []
---
# 0036 — C++ image_canvas + webcam_texture
## APP Metadata
| Campo | Valor |
|-------|-------|
| **ID** | 0036 |
| **Estado** | pendiente |
| **Prioridad** | baja |
| **Tipo** | feature — C++ core/gfx (cpp/functions/core, cpp/functions/gfx) |
## Dependencias
`gl_texture_load_cpp_gfx` (issue 0026) — recomendado. `tokens_cpp_core`. Independiente de los demas.
**Desbloquea:** UIs para etiquetado/anotacion de imagenes (CV, OCR debugging) y entrada de webcam para `shaders_lab` reactivo a video.
---
## Objetivo
Dos primitivos:
1. **`image_canvas_cpp_core`** — viewer de imagen con pan/zoom + capa de anotaciones (rectangulos, puntos, polilineas, texto). Drag para crear nuevas anotaciones; click para seleccionar; tecla Del para borrar.
2. **`webcam_texture_cpp_gfx`** — captura de webcam (V4L2 en Linux, Media Foundation en Windows) → GL texture actualizada cada frame. API parejo a `audio_capture`.
## Contexto
Casos de uso identificados:
- Inspeccionar resultados de un detector (rectangulos overlay).
- Etiquetar manualmente datasets pequeños in-app.
- Pasar webcam a shaders en `shaders_lab` (filtros video en tiempo real).
Ningun primitivo del registry actual cubre estos casos.
## Arquitectura
```
cpp/functions/core/
├── image_canvas.h # NEW
├── image_canvas.cpp # NEW
└── image_canvas.md # NEW (impure component)
cpp/functions/gfx/
├── webcam_texture.h # NEW
├── webcam_texture.cpp # NEW
└── webcam_texture.md # NEW (impure)
cpp/apps/primitives_gallery/
├── demos_image_webcam.cpp # NEW
├── demos.h # MOD
├── main.cpp # MOD
└── CMakeLists.txt # MOD
```
### API propuesta
```cpp
namespace fn {
// --- image_canvas ---
struct Annotation {
enum Kind { Rect, Point, Polyline, Text } kind;
std::vector<ImVec2> points; // image-space coords (no screen)
ImU32 color = IM_COL32(255, 80, 80, 255);
std::string label;
};
struct ImageCanvasState {
GLuint texture = 0; // caller-owned
int img_w = 0, img_h = 0;
float zoom = 1.f;
ImVec2 pan = {0, 0};
std::vector<Annotation> annotations;
int selected = -1;
enum Tool { ToolNone, ToolRect, ToolPoint, ToolPolyline } tool = ToolNone;
};
void image_canvas(const char* id, ImageCanvasState&, ImVec2 size = {-1, -1});
// --- webcam_texture ---
struct WebcamTextureConfig { int width = 640; int height = 480; int fps = 30; int device = 0; };
struct WebcamTexture { GLuint id = 0; int w = 0; int h = 0; bool ok() const { return id != 0; } };
WebcamTexture webcam_texture_start(const WebcamTextureConfig&);
void webcam_texture_stop(WebcamTexture&);
bool webcam_texture_update(WebcamTexture&); // copia ultimo frame a GPU; true si hubo nuevo
const char* webcam_texture_last_error();
}
```
## Tareas
### Fase 1 — image_canvas
- 1.1 Render: `ImGui::Image(texture, ...)` con transform por pan/zoom. Drag con MMB para pan, wheel para zoom.
- 1.2 Tool == Rect: drag con LMB en image-space crea anotacion `Rect` con 2 puntos.
- 1.3 Tool == Point: click LMB anade un Point.
- 1.4 Tool == Polyline: click anade puntos; doble-click cierra.
- 1.5 Hit-test para selection; Del key elimina la seleccionada.
- 1.6 `.md`.
### Fase 2 — webcam_texture (Linux V4L2)
- 2.1 Abrir `/dev/video<device>`, MMAP buffers, VIDIOC_STREAMON.
- 2.2 En `update`, dequeue buffer, convert YUYV → RGBA (CPU), upload a GL texture, requeue.
- 2.3 `.md` (`kind: function`, `purity: impure`, `error_type`).
### Fase 3 — webcam_texture (Windows Media Foundation, opcional)
- 3.1 Si `_WIN32`, usar `IMFSourceReader`. Convert NV12 → RGBA.
- 3.2 Documentar que macOS no se soporta en MVP.
### Fase 4 — Gallery demo
- 4.1 `demos_image_webcam.cpp`:
- `demo_image_canvas()`: carga `assets/sample.png` (si existe — fallback a rendered placeholder), permite pintar rectangulos.
- `demo_webcam_texture()`: start cam, mostrar preview + sliders RGB sobre un shader fullscreen que samplea la cam.
- 4.2 Registrar.
### Fase 5 — Tests + docs
- 5.1 Tests puros de transform image-space ↔ screen-space.
- 5.2 Smoke test webcam (skip si no hay /dev/video0).
- 5.3 `./fn index`.
## Ejemplo de uso
```cpp
auto cam = fn::webcam_texture_start({});
if (!cam.ok()) std::fprintf(stderr, "%s\n", fn::webcam_texture_last_error());
fn::run_app("cam", [&]{
fn::webcam_texture_update(cam);
ImGui::Image((ImTextureID)(intptr_t)cam.id, {cam.w*1.f, cam.h*1.f});
});
```
## Decisiones de diseño
- **Anotaciones en image-space**: pan/zoom no afectan coordenadas guardadas. Permite serializar a JSON (issue futuro).
- **YUYV → RGBA en CPU**: simple, ~5ms/frame a 640×480. Si hace falta, hacer un compute shader (issue 0027).
- **macOS sin webcam por ahora**: AVFoundation requiere ObjC++; no compensa en MVP.
## Riesgos
- **Permisos webcam**: documentar troubleshooting (`/dev/video0` permisos en Linux).
- **Driver V4L2 raro**: algunos formatos de pixel no son YUYV. Documentar fallback a MJPEG (con stb_image decode) o error claro.
- **`ImTextureID` semantics** entre backends: documentar.