我们都知道,LabWindows/CVI的强大功能实际上不只是在测控领域,在其它方面,也显示着无与伦比的优势。 你的电脑有没有摄像头?看到别人用QQ玩视屏你会不会去想怎么实现的? 一般来说,所有的摄像头都会包括一个AVICAP32.DLL动态链接库文件,而动态库里面必有capCreateCaptureWindow和capCreateCaptureWindowA这两个函数,我们就是利用这些函数实现图像采集的! 这里介绍使用AVICAP32.DLL就可轻松的实现对摄像头编程,如果再加上你的网络编程水平,实现一个视屏聊天就不成什么问题了。如果电脑没有摄像头,但又想看看程序的效果,可以么?呵呵,当然可以,找个虚拟摄像头就可以搞定了,大家可以试试“SoftCam”这个软件,它是一个名副其实的软件摄像机,能模拟成为“真实的”摄像机,提醒一下各位,大家可不要用这个东东用在QQ,MSN等聊天软件上欺骗MM或GG啊。 本例能实现图片的保存,浏览以及录像功能,在界面上都能显示出来,大家仔细瞧瞧吧! 界面如下: 图中的景像就是我的实验室,情况有点糟糕,哈哈,还能凑合着过! 代码如下: #include "windows.h" #include "avicap32.h" #include #include #include "cam.h" //设置所需要摄像头的常量 #define WM_CAP_START WM_USER //开始 #define WM_CAP_STOP WM_CAP_START + 68 //停止 #define WM_CAP_DRIVER_CONNECT WM_CAP_START + 10 //连接 #define WM_CAP_DRIVER_DISCONNECT WM_CAP_START + 11 //断开 #define WM_CAP_SAVEDIB WM_CAP_START + 25 #define WM_CAP_GRAB_FRAME WM_CAP_START + 60 #define WM_CAP_SEQUENCE WM_CAP_START + 62 #define WM_CAP_FILE_SET_CAPTURE_FILEA WM_CAP_START + 20 //保存至文件 #define WM_CAP_SEQUENCE_NOFILE WM_CAP_START + 63 #define WM_CAP_SET_OVERLAY WM_CAP_START + 51 #define WM_CAP_SET_PREVIEW WM_CAP_START + 50 #define WM_CAP_SET_CALLBACK_VIDEOSTREAM WM_CAP_START +6 #define WM_CAP_SET_CALLBACK_ERROR WM_CAP_START +2 #define WM_CAP_SET_CALLBACK_STATUSA WM_CAP_START +3 #define WM_CAP_SET_CALLBACK_FRAME WM_CAP_START +5 #define WM_CAP_SET_SCALE WM_CAP_START+ 53 #define WM_CAP_SET_PREVIEWRATE WM_CAP_START+ 52 #define WM_CAP_COPYDIB WM_CAP_START + 30 //复制图片
//定义面板句柄 static int handle; //定义摄像头句柄 static int result; static int panelHandle; int main (int argc, char *argv[]) { if (InitCVIRTE (0, argv, 0) == 0) return -1; /* out of memory */ if ((panelHandle = LoadPanel (0, "cam.uir", PANEL)) < 0) return -1; DisplayPanel (panelHandle); RunUserInterface (); DiscardPanel (panelHandle); return 0; } //退出按钮 int CVICALLBACK QuitCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_COMMIT: QuitUserInterface (0); break; } return 0; } //开始按钮 int CVICALLBACK startCB (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { int width; int height; int top; int left; switch (event) { case EVENT_COMMIT: //获得面板句柄 GetPanelAttribute (panelHandle, ATTR_SYSTEM_WINDOW_HANDLE, &handle); //获得屏幕中图像要显示的位置 GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_LEFT, &left); GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_TOP, &top); GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, &height); GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, &width); //打开摄像头 result = capCreateCaptureWindowA("",WS_CHILD | WS_VISIBLE ,left,top,width,height,handle,0); //设置摄像头函数 SendMessage((HWND)result, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0); SendMessage((HWND)result, WM_CAP_SET_CALLBACK_ERROR, 0, 0); SendMessage((HWND)result, WM_CAP_SET_CALLBACK_STATUSA, 0, 0); SendMessage((HWND)result, WM_CAP_DRIVER_CONNECT, 0, 0); SendMessage((HWND)result, WM_CAP_SET_SCALE, 1, 0); SendMessage((HWND)result, WM_CAP_SET_PREVIEWRATE, 66, 0); SendMessage((HWND)result, WM_CAP_SET_OVERLAY, 1, 0); SendMessage((HWND)result, WM_CAP_SET_PREVIEW, 1, 0); break; } return 0; } //停止按钮 int CVICALLBACK stopCB (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_COMMIT: if (result != 0) { //断开连接 SendMessage((HWND)result, WM_CAP_DRIVER_DISCONNECT, 0, 0); } break; } return 0; } //保存BMP按钮 int CVICALLBACK recordbmp (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { // int available; //定义BMP位图ID号 int bitmapID; //定义文件存储路径 char path[MAX_PATHNAME_LEN]; //定义静态变量,设置循环次数 static int i; switch (event) { case EVENT_COMMIT: /* 此代码为将图片存入剪切板 if (result != 0) { SendMessage((HWND)result, WM_CAP_GRAB_FRAME, 0, 0); SendMessage((HWND)result, WM_CAP_COPYDIB, 0, 0); ClipboardGetBitmap (&bitmapID, &available); if (available ==1) { CanvasClear (panelHandle, PANEL_CANVAS, VAL_ENTIRE_OBJECT); CanvasDrawBitmap (panelHandle, PANEL_CANVAS, bitmapID, VAL_ENTIRE_OBJECT, VAL_ENTIRE_OBJECT); } DiscardBitmap (bitmapID); } */ //保存位图 if (FileSelectPopup ("", "*.bmp", "*.bmp", "保存", VAL_SAVE_BUTTON, 0, 0, 1, 1, path) > 0) { SendMessage((HWND)result,WM_CAP_SAVEDIB,0,(LPARAM)path); //获得BMP位图ID GetBitmapFromFile (path, &bitmapID); switch (i) { //设置三个位图浏览器 case 0: CanvasDrawBitmap (panelHandle, PANEL_CANVAS_SNAP0, bitmapID, VAL_ENTIRE_OBJECT, VAL_ENTIRE_OBJECT); break; case 1: CanvasDrawBitmap (panelHandle, PANEL_CANVAS_SNAP1, bitmapID, VAL_ENTIRE_OBJECT, VAL_ENTIRE_OBJECT); break; case 2: CanvasDrawBitmap (panelHandle, PANEL_CANVAS_SNAP2, bitmapID, VAL_ENTIRE_OBJECT, VAL_ENTIRE_OBJECT); break; } //删除BMP位图ID DiscardBitmap (bitmapID); //循环累加,共三次,三次之后回零 i++; if (i == 3) { i = 0; } } break; } return 0; } //开始录像按钮 int CVICALLBACK recordstream (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { char path[MAX_PATHNAME_LEN]; switch (event) { case EVENT_COMMIT: //保存录像 if (FileSelectPopup ("", "*.avi", "*.avi", "保存", VAL_SAVE_BUTTON, 0, 0, 1, 1, path) > 0) { SendMessage((HWND)result,WM_CAP_FILE_SET_CAPTURE_FILEA,0,(LPARAM)path); SendMessage((HWND)result, WM_CAP_SEQUENCE, 0, 0); } break; } return 0; } //停止录像按钮 int CVICALLBACK stopstream (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_COMMIT: SendMessage((HWND)result, WM_CAP_STOP, 0, 0); break; } return 0; } //显示制式设置 int CVICALLBACK method (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { int kind; int width; int height; int top; int left; switch (event) { case EVENT_COMMIT: //获得制式种类 GetCtrlVal (panelHandle, PANEL_RING, &kind); switch (kind) { case 0: //160*120制式 SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, 160); SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, 120); break; case 1: //1176*144制式 SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, 176); SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, 144); break; case 2: //320*240制式 SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, 320); SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, 240); break; case 3: //352*288制式 SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, 352); SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, 288); break; case 4: //1默认制式 SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, 592); SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, 333); break; } //获得屏幕中图像要显示的位置 GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_LEFT, &left); GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_TOP, &top); GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, &height); GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, &width); //重新定位 SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_TOP, (333-height)/2+55); SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_LEFT, (592-width)/2+53); //断开连接 SendMessage((HWND)result, WM_CAP_DRIVER_DISCONNECT, 0, 0); //调用开始按钮事件 startCB(panel, PANEL_CANVAS_TV, EVENT_COMMIT, NULL, 0, 0); break; } return 0; }
|