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);
}