Hi! Happy new year Nim men!
Question: is there any known possibility to acquire usb webcam image in Nim (eventually via an avicap wrapper or differently) Thanx
Hello,
I made a project in 2005 (in D language) where I used avicap32.dll to capture images from webcams, I remember that it worked very well but I guess that now there are better APIs to do it.
Anyway, I post here the relevant functions, you can use it as reference if you need it.
/*------------------------------------------------------------
  Obtiene el nombre y version de las camaras instaladas,
  en driver_index se indica el numero de dispositivo a
  inspeccionar, si no existe devuelve false.
  
  Usar esta funcion como comprobacion antes de crear ninguna
  ventana de captura.
------------------------------------------------------------*/
bool CameraGetDriverInfo(uint driver_index, out char[] driver_name, out char[] driver_version)
{
  HANDLE dll = LoadLibraryA(toMBSz("avicap32.dll"));
  
  if (!dll)
  {
    return false;
  }
  
  alias extern (Windows) BOOL function(UINT wDriverIndex, LPSTR lpszName, INT cbName, LPSTR lpszVer, INT cbVer)   DLL_capGetDriverDescriptionA;
  alias extern (Windows) BOOL function(UINT wDriverIndex, LPWSTR lpszName, INT cbName, LPWSTR lpszVer, INT cbVer) DLL_capGetDriverDescriptionW;
  
  DLL_capGetDriverDescriptionA pcapGetDriverDescriptionA = cast(DLL_capGetDriverDescriptionA)GetProcAddress(dll, toMBSz("capGetDriverDescriptionA"));
  DLL_capGetDriverDescriptionW pcapGetDriverDescriptionW = cast(DLL_capGetDriverDescriptionW)GetProcAddress(dll, toMBSz("capGetDriverDescriptionW"));
  
  if (useWfuncs)
  {
    // Version Unicode
    if (!pcapGetDriverDescriptionW)
    {
      FreeLibrary(dll);
      return false;
    }
  }
  else
  {
    // Version Ansi
    if (!pcapGetDriverDescriptionA)
    {
      FreeLibrary(dll);
      return false;
    }
  }
  
  if (useWfuncs)
  {
    // Version Unicode
    wchar[] tmp_driver_name    = new wchar[200];
    wchar[] tmp_driver_version = new wchar[200];
    
    if (pcapGetDriverDescriptionW(driver_index, tmp_driver_name.ptr, 200, tmp_driver_version.ptr, 200))
    {
      // Convertir a UTF8
      driver_name    = WinUTF16zToString(tmp_driver_name);
      driver_version = WinUTF16zToString(tmp_driver_version);
      
      FreeLibrary(dll);
      return true;
    }
  }
  else
  {
    // Version Ansi
    char[] tmp_driver_name    = new char[200];
    char[] tmp_driver_version = new char[200];
    
    if (pcapGetDriverDescriptionA(driver_index, tmp_driver_name.ptr, 200, tmp_driver_version.ptr, 200))
    {
      // Convertir a UTF8
      driver_name    = WinAnsizToString(tmp_driver_name.ptr);
      driver_version = WinAnsizToString(tmp_driver_version.ptr);
      
      FreeLibrary(dll);
      return true;
    }
  }
  
  FreeLibrary(dll);
  
  return false;
}
/*------------------------------------------------------------
  Crea una ventana de previa de la camara cam_index deseada,
  si no se especifica parent_hwnd se creara en una ventana
  propia (que usara win_title como titulo).
  
  Devuelve el HWND de la ventana de previa, o 0 si no existe
  la camara indicada.
  
  Tambien devuelve el handle de la avicap32.dll abierta, que
  sera usado en CameraClose() para cerrarla DLL.
  Despues de una llamada a esta funcion siempre se debe
  llamar a CameraClose() para que cierre la DLL.
------------------------------------------------------------*/
HWND CameraCreateWindow(uint cam_index, HWND parent_hwnd, out HANDLE dll, bool window_on_top, char[] win_title, uint frame_rate_fps, uint w, uint h, uint x=0, uint y=0)
{
  dll = LoadLibraryA(toMBSz("avicap32.dll"));
  
  if (!dll)
  {
    return (cast(HWND)0);
  }
  
  alias extern (Windows) HWND function(LPCSTR lpszWindowName, DWORD dwStyle, INT x, INT y, INT nWidth, INT nHeight, HWND hWnd, INT nID)  DLL_capCreateCaptureWindowA;
  alias extern (Windows) HWND function(LPCWSTR lpszWindowName, DWORD dwStyle, INT x, INT y, INT nWidth, INT nHeight, HWND hWnd, INT nID) DLL_capCreateCaptureWindowW;
  
  DLL_capCreateCaptureWindowA pcapCreateCaptureWindowA = cast(DLL_capCreateCaptureWindowA)GetProcAddress(dll, toMBSz("capCreateCaptureWindowA"));
  DLL_capCreateCaptureWindowW pcapCreateCaptureWindowW = cast(DLL_capCreateCaptureWindowW)GetProcAddress(dll, toMBSz("capCreateCaptureWindowW"));
  
  if (useWfuncs)
  {
    // Version Unicode
    if (!pcapCreateCaptureWindowW)
    {
      return (cast(HWND)0);
    }
  }
  else
  {
    // Version Ansi
    if (!pcapCreateCaptureWindowA)
    {
      return (cast(HWND)0);
    }
  }
  
  DWORD style;
  
  if (parent_hwnd == cast(HWND)0)
  {
    // Si no tiene ventana padre creara una ventana propia
    style = WS_VISIBLE;
  }
  else
  {
    // Tiene ventana padre
    style = WS_CHILD|WS_VISIBLE;
  }
  
  HWND cam_hwnd;
  
  if (useWfuncs)
  {
    // Version Unicode
    cam_hwnd = pcapCreateCaptureWindowW(toUTF16z(win_title), style, x, y, w, h, parent_hwnd, 0);
  }
  else
  {
    // Version Ansi
    cam_hwnd = pcapCreateCaptureWindowA(toMBSz(win_title), style, x, y, w, h, parent_hwnd, 0);
  }
  
  if (cam_hwnd == cast(HWND)0)
  {
    // No hay camara...
    return (cast(HWND)0);
  }
  
  // Fijar la ventana en top most?
  if (parent_hwnd == cast(HWND)0 && window_on_top)
  {
    SetWindowPos(cam_hwnd, cast(HWND)HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  }
  
  sys_SendMessage(cam_hwnd, WM_CAP_DRIVER_CONNECT, cam_index, 0);
  sys_SendMessage(cam_hwnd, WM_CAP_SET_SCALE, 1, 0);
  uint frame_rate = 1000 / frame_rate_fps;
  sys_SendMessage(cam_hwnd, WM_CAP_SET_PREVIEWRATE, frame_rate, 0);
  sys_SendMessage(cam_hwnd, WM_CAP_SET_PREVIEW, 1, 0);
  
  return cam_hwnd;
}
/*------------------------------------------------------------
  Captura un frame de la camara y lo graba como BMP.
------------------------------------------------------------*/
void CameraSaveBMP(HWND hwnd, char[] file_bmp)
{
  if (useWfuncs)
  {
    // Version Unicode
    wchar *file = toUTF16z(file_bmp);
    sys_SendMessage(hwnd, WM_CAP_FILE_SAVEDIBW, 0, cast(uint)file);
  }
  else
  {
    // Version Ansi
    char *file = toMBSz(file_bmp);
    sys_SendMessage(hwnd, WM_CAP_FILE_SAVEDIBW, 0, cast(uint)file);
  }
}
/*------------------------------------------------------------
  Desconecta el driver, destruye la ventana de la webcam y
  cierra la DLL de avicap32.dll.
------------------------------------------------------------*/
void CameraClose(uint cam_index, HWND hwnd, HANDLE dll)
{
  sys_SendMessage(hwnd, WM_CAP_DRIVER_DISCONNECT, cam_index, 0);
  DestroyWindow(hwnd);
  
  if (dll)
  {
    // Cerrar la avicap32.dll abierta en CameraCreateWindow()
    FreeLibrary(dll);
  }
}
/*------------------------------------------------------------
  Procesar mensajes pendientes.
  Si se especifica time_wait (en milisegundos) se forzara
  a que se procesen los mensajes pendientes durante al menos
  el tiempo indicado.
------------------------------------------------------------*/
void ProcessMessages(uint time_wait=0)
{
  clock_t end_time = clock() + time_wait * (CLOCKS_PER_SEC / 1000);
  MSG msg;
  
  while (true)
  {
    while (sys_PeekMessage(&msg, cast(HWND)0, 0, 0, PM_REMOVE))
    {
      TranslateMessage(&msg);
      sys_DispatchMessage(&msg);
    }
    
    if (clock() >= end_time)
    {
      break;
    }
  }
}
/*------------------------------------------------------------
  Inicializa el listado de webcams instaladas.
------------------------------------------------------------*/
void ListWebcams()
{
  m_cmbox_webcam_list.items.add("< Webcam disabled >");
  
  for (uint i=0; i < 16; i++)
  {
    char[] driver_name;
    char[] driver_version;
    if (CameraGetDriverInfo(i, driver_name, driver_version))
    {
      m_cmbox_webcam_list.items.add(driver_name ~ " - " ~ driver_version);
    }
  }
}
/*------------------------------------------------------------
  Captura la imagen (BMP) de la webcam indicada en cam_index.
------------------------------------------------------------*/
void CaptureWebcamImage(uint cam_index)
{
  // Verificar que realmente existe la webcam indicada
  char[] tmp_driver_name, tmp_driver_version;
  if (!CameraGetDriverInfo(cam_index, tmp_driver_name, tmp_driver_version))
  {
    throw(new Exception("Webcam not found"));
  }
  
  // Capturar imagen
  char[] file_bmp = m_tmp_directory ~ TMP_IMAG_WCAM;
  uint   w        = 250;
  uint   h        = 250;
  uint   x        = GetSystemMetrics(SM_CXSCREEN) - w;
  uint   y        = GetSystemMetrics(SM_CYSCREEN) - (h + 26);
  HANDLE cam_dll;
  HWND   cam_hwnd = CameraCreateWindow(cam_index, cast(HWND)0, cam_dll, true, "Photo...", 30, w, h, x, y);
  ProcessMessages(4000);
  CameraSaveBMP(cam_hwnd, file_bmp);
  CameraClose(cam_index, cam_hwnd, cam_dll);
}