fad4006f60
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.3 KiB
5.3 KiB
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 |
|
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:
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.webcam_texture_cpp_gfx— captura de webcam (V4L2 en Linux, Media Foundation en Windows) → GL texture actualizada cada frame. API parejo aaudio_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
Rectcon 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, usarIMFSourceReader. 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(): cargaassets/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/video0permisos en Linux). - Driver V4L2 raro: algunos formatos de pixel no son YUYV. Documentar fallback a MJPEG (con stb_image decode) o error claro.
ImTextureIDsemantics entre backends: documentar.