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

5.3 KiB
Raw Blame History

id, title, status, type, domain, scope, priority, depends, blocks, related, created, updated, tags
id title status type domain scope priority depends blocks related created updated tags
0036 C++ image_canvas + webcam_texture pendiente feature
cpp-stack
multi-app baja
2026-05-17 2026-05-17

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

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.
  • 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

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.