user-0 提问: 求助，C语言控制自己的摄像头，使其只输出一张图片。

回复:
user: user-1
content: 引用 3 楼 Johnny14117 的回复:@liups，是的呢，你怎么知道 想过这种方式。 那么楼主是应该研究一下驱动的编写，最后给假的摄像头编写一个驱动就行了

user: user-0
content: @liups，是的呢，你怎么知道

user: user-1
content: 可能楼主需要的是一个虚假的摄像头，提供一个假的画面吧？

user: user-2
content: 网上凑了些代码，你可以参考一下：(效果：打开一个控制台和窗口，控制台显示摄像头名称，窗口显示摄像头参数及预览图像。程序会在打开摄像头一秒后将下一帧保存在同目录 output.bmp 中)  // gcc WinMain.c -o WinMain -luser32 -lgdi32 -lvfw32  #include <stdio.h> #include <Windows.h> #include <vfw.h>  // 转载来源: https://github.com/godspeed1989/Win32CameraCapture  #define MAX_CAMERA_INDEX 10  static HWND m_hCapWnd[MAX_CAMERA_INDEX]; static CAPDRIVERCAPS m_CapDrvCap[MAX_CAMERA_INDEX]; static CAPSTATUS m_CapStatus[MAX_CAMERA_INDEX]; static CAPTUREPARMS m_Parms[MAX_CAMERA_INDEX];  UINT cm_print_driver_list() { 	UINT wIndex, wCameraCnt; 	WCHAR szDriverName[80]; 	WCHAR szDriverVersion[80]; 	wCameraCnt = 0; 	for (wIndex = 0; wIndex < MAX_CAMERA_INDEX; wIndex++) 	{ 		if( TRUE == capGetDriverDescriptionW (wIndex, 					szDriverName, sizeof(szDriverName), 					szDriverVersion, sizeof(szDriverVersion)) ) 		{ 			wprintf(L"[%d] %s - %s\n", wIndex, szDriverName, szDriverVersion); 			wCameraCnt++; 		} 	} 	return wCameraCnt; }  static BOOL cm_open_internal(UINT idx, HWND hwParent) { 	// 创建窗口句柄 	m_hCapWnd[idx] = capCreateCaptureWindow("Camera Preview Window", WS_CHILD | WS_VISIBLE, 0, 0, 20000, 20000, hwParent, 0); 	if (!m_hCapWnd) 	{ 		printf("m_hCapWnd failed !!!\n"); 		return FALSE; 	} 	// 连接第idx号驱动器 	else if (TRUE == capDriverConnect(m_hCapWnd[idx], idx)) 	{ 		capOverlay(m_hCapWnd[idx], FALSE); 		capPreview(m_hCapWnd[idx], FALSE); 		// 得到驱动器的性能 		memset(&m_CapDrvCap[idx], 0, sizeof(CAPDRIVERCAPS)); 		if (FALSE == capDriverGetCaps(m_hCapWnd[idx], &m_CapDrvCap[idx], sizeof(CAPDRIVERCAPS))) 		{ 			printf("capDriverGetCaps failed !!!\n"); 		} 		else if (m_CapDrvCap[idx].fCaptureInitialized) 		{ 			// 初始化成功 			return TRUE; 		} 		else 		{ 			printf("fCaptureInitialized failed !!!\n"); 		} 	} 	else 	{ 		printf("connect failed !!!\n"); 	} 	//capCaptureStop(m_hCapWnd[idx]); // 停止捕捉 	//capDriverDisconnect(m_hCapWnd[idx]); 	//DestroyWindow(m_hCapWnd[idx]); 	return FALSE; }  void cm_close(UINT idx) { 	capCaptureStop(m_hCapWnd[idx]); 	capCaptureAbort(m_hCapWnd[idx]); // 停止捕获 	capDriverDisconnect(m_hCapWnd[idx]); // 断开捕捉器与驱动器的连接 	DestroyWindow(m_hCapWnd[idx]); }  BOOL cm_open(UINT idx, HWND hwParent) { 	BOOL ret = TRUE; 	int n = 0; 	do 	{ 		printf("%d try to open %d\n", n, idx); 		Sleep(500); 		ret = cm_open_internal(idx, hwParent); 		n++; 	} while(FALSE == ret && n < 5); 	if (FALSE == ret) 	{ 		printf("open failed !!!\n"); 	} 	return ret; }  BOOL cm_get_param(UINT idx, int *width, int *height, int *frame_rate) { 	BOOL ret = TRUE; 	// 得到设置参数 	ret = capCaptureGetSetup(m_hCapWnd[idx], &m_Parms[idx], sizeof(CAPTUREPARMS)); 	if (FALSE == ret) 	{ 		printf("capCaptureGetSetup failed !!!\n"); 		return ret; 	} 	// 得到驱动器状态 	ret = capGetStatus(m_hCapWnd[idx], &m_CapStatus[idx], sizeof(CAPSTATUS)); 	if (FALSE == ret) 	{ 		printf("capGetStatus failed !!!\n"); 		return ret; 	} 	*width = (int)m_CapStatus[idx].uiImageWidth; 	*height = (int)m_CapStatus[idx].uiImageHeight; 	*frame_rate = (int)1000000 / (int)m_Parms[idx].dwRequestMicroSecPerFrame;  	return ret; }  BOOL cm_grab_to_bmp(UINT idx, WCHAR *file) { 	BOOL ret = TRUE; 	// 截获当前图像 	ret = capGrabFrame(m_hCapWnd[idx]); 	if (FALSE == ret) 	{ 		printf("capGrabFrame failed !!!\n"); 		return ret; 	} 	// 保存到文件 	ret = capFileSaveDIB(m_hCapWnd[idx], file); 	if (FALSE == ret) 	{ 		printf("capFileSaveDIB failed !!!\n"); 		return ret; 	} 	return ret; }  BOOL cm_grab_to_clipboard(UINT idx) { 	BOOL ret = TRUE; 	// 截获当前图像 	ret = capGrabFrame(m_hCapWnd[idx]); 	if (FALSE == ret) 	{ 		printf("capGrabFrame failed !!!\n"); 		return ret; 	} 	// 保存到剪贴板 	ret = capEditCopy(m_hCapWnd[idx]); 	if (FALSE == ret) 	{ 		printf("capEditCopy failed !!!\n"); 		return ret; 	} 	return ret; }  //LRESULT CALLBACK StreamCallbackProc(HWND hCapWnd, LPVIDEOHDR lphdr) //{ //	return (LRESULT)TRUE; //}  BOOL cm_start_record(UINT idx, WCHAR *file) { 	BOOL ret = TRUE; 	// 视频流回调函数 	//ret = capSetCallbackOnVideoStream(m_hCapWnd[idx], StreamCallbackProc); 	//if (FALSE == ret) 	//{ 	//	printf("capSetCallbackOnVideoStream failed !!!\n"); 	//	return ret; 	//} 	// 设置捕获参数 	capCaptureGetSetup(m_hCapWnd[idx], &m_Parms[idx], sizeof(CAPTUREPARMS)); 	m_Parms[idx].fYield = TRUE; // 后台运行 	m_Parms[idx].fCaptureAudio = FALSE; // 无声音 	m_Parms[idx].wTimeLimit = FALSE; // 无时间限制 	capCaptureSetSetup(m_hCapWnd[idx], &m_Parms[idx], sizeof(CAPTUREPARMS)); 	// 设置捕获视频的文件 	capFileSetCaptureFile(m_hCapWnd[idx], file); 	// 开始录像线程 	ret = capCaptureSequence(m_hCapWnd[idx]); 	if (FALSE == ret) 	{ 		printf("capCaptureSequence failed !!!\n"); 		return ret; 	} 	return ret; }  void cm_stop_record(UINT idx) { 	//capSetCallbackOnVideoStream(m_hCapWnd[idx], NULL); 	capCaptureStop(m_hCapWnd[idx]); 	capCaptureAbort(m_hCapWnd[idx]); }  // 转载部分结束  void cm_update_frame(UINT idx) { 	capGrabFrame(m_hCapWnd[idx]); }  #define BASE_WINDOW_CLASS_NAME "CameraCaptureWindowClass" #define BASE_WINDOW_NAME "Camera Capture Window"  LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { 	switch (msg) { 	case WM_DESTROY: 		PostQuitMessage(EXIT_SUCCESS); 		break; 	case WM_TIMER: 		cm_update_frame(0); 		break; 	} 	return DefWindowProc(hwnd, msg, wParam, lParam); }  ATOM My_RegisterClass(HINSTANCE hInstance) { 	WNDCLASSA WndClass; 	WndClass.cbClsExtra = 0; 	WndClass.cbWndExtra = 0; 	WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); 	WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 	WndClass.hInstance = hInstance; 	WndClass.lpfnWndProc = WndProc; 	WndClass.lpszClassName = BASE_WINDOW_CLASS_NAME; 	WndClass.lpszMenuName = NULL; 	WndClass.style = 0; 	return RegisterClassA(&WndClass); }  HWND My_CreateWindow(HINSTANCE hInstance) { 	return CreateWindowA( 		BASE_WINDOW_CLASS_NAME, 		BASE_WINDOW_NAME, 		WS_OVERLAPPEDWINDOW | WS_VISIBLE, 		CW_USEDEFAULT, CW_USEDEFAULT, 		CW_USEDEFAULT, CW_USEDEFAULT, 		NULL, 		NULL, 		hInstance, 		NULL 	); }  int My_CycleMessage(void) { 	MSG msg; 	while (GetMessageA(&msg, NULL, 0, 0)) { 		TranslateMessage(&msg); 		DispatchMessageA(&msg); 	} 	return (int)msg.wParam; }  int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { 	HWND hwnd; 	int nRet; 	 	My_RegisterClass(hInstance); 	hwnd = My_CreateWindow(hInstance); 	UpdateWindow(hwnd); 	{ 		cm_print_driver_list(); 		cm_open(0, hwnd); 		{ 			char str[128]; 			int nWidth, nHeight, nFramerate; 			cm_get_param(0, &nWidth, &nHeight, &nFramerate); 			sprintf(str, BASE_WINDOW_NAME " - (%d x %d) %d Hz", nWidth, nHeight, nFramerate); 			SetWindowTextA(hwnd, str); 		} 		UpdateWindow(hwnd); 		Sleep(1000); 		cm_grab_to_bmp(0, "output.bmp"); 		SetTimer(hwnd, 123, 200, NULL); 		//cm_close(0); 	} 	 	nRet = My_CycleMessage(); 	 	cm_close(0); 	 	return nRet; }