15.3.6 远程摄像头--创建客户方工程(3)
【代码解析】
以上代码中IplImage结构用到的主要成员变量有:width图片宽,height图片高,*imageData以4字节对齐的图像数据,widthStep对齐图像每行大小。代码中第5、6行根据图片宽计算8位色或24位色图片下,每行4字节对齐所需的字节数,第13~24行检查是否是8位色或24位色图片格式,其他格式图片不处理。第25~53行根据图片格式,循环行和列转换每像素字节数据到BMP图片缓冲中。
(7)为CVideoClientDlg类添加Timer消息处理函数,并在该函数中添加如下代码,其作用是不断从摄像头采集视频数据,将这些数据转换成BMP图像数据后,再转为JPG图像数据,发送到服务器方,代码如下:
- 01 void CVideoClientDlg::OnTimer(UINT nIDEvent)
- 02 {
- 03 int n = m_CameraDS.CameraCount();//取得摄像头量
- 04 CString s;
- 05 s.Format("本机共%d个摄像头", n);
- 06 GetDlgItem(IDC_STATIC_VIDEO_STATE)->SetWindowText(s);
- 07 //取得摄像头1帧视频数据
- 08 IplImage *pIplImage = m_CameraDS.QueryFrame();
- 09 if(NULL != pIplImage)
- 10 {
- 11 VIDEODATADIB *bmp;
- 12 //转为BMP图片格式
- 13 IplImage2Bmp(pIplImage, bmp);
- 14 char *JpgMemData = NULL;
- 15 DWORD JpgMemDataSize=0;
- 16 //将BMP图片转为JPG图片格式
- 17 BOOL bOK = m_PictureConvert.ConvertPictrue((char *)bmp->pData,
- 18 bmp->totalSize, bmp->width, bmp->height, &JpgMemData,&JpgMem-
- DataSize);
- 19 if(bOK)
- 20 {
- 21 CNetPackage *pSendPack = m_videoClient.GetSendIdle Package();
- 22 if(NULL != pSendPack)
- 23 { //向服务方发送此帧数据
- 24 pSendPack->WriteProc(MSG_VIDEO_DATA_C2S);//写消息
- 25 pSendPack->WriteInt32(JpgMemDataSize);
- //消息内容(JPG数据大小)
- 26 //写JPG数据
- 27 pSendPack->WriteStruct(JpgMemData, JpgMemDataSize);
- 28 pSendPack->SendMSG_Client(); //发送此数据包到服务方
- 29 }
- 30 }
- 31 Delete bmp;
- 32 }
- 33 }
【代码解析】
第8行取得1帧摄像头视频数据。第13行调用IplImage2Bmp()函数将摄像头视频数据转为BMP数据。第17、18行将BMP数据转为JPG数据。第21~29行取一个空闲网络发送包,将JPG视频数据发送到服务方。
(8)为采集视频按钮添加单击事件处理函数,并在该函数中添加如下代码,其作用是根据设置的服务方IP及端口连接服务器,连接成功后打开视频摄像头,并启动定时器,代码如下:
- 01 void CVideoClientDlg::OnBtnGetvideo()
- 02 {
- 03 char ip[16]={0}, portStr[16]={0};
- 04 __int16 nPort=0;
- 05 GetDlgItem(IDC_EDIT_SVR_IP)->GetWindowText(ip, 16);
- 06 GetDlgItem(IDC_EDIT_SVR_PORT)->GetWindowText(portStr, 16);
- 07 nPort = atoi(portStr);
- 08 if(m_pVideoClient.ConnectServer(ip, nPort) == true)
- 09 {//连接服务方成功
- 10 m_CameraDS.OpenCamera(0); //打开第1个摄像头
- 11 SetTimer(1, 200, NULL);
- 12 GetDlgItem(IDC_BTN_GETVIDEO)->EnableWindow(FALSE);
- 13 }
- 14 }
【代码解析】
CVideoClientDlg::OnBtnGetvideo()函数连接服务方,打开摄像头并启动定时器,定时获取视频数据帧。代码第5~7行获取界面输入的服务器IP,第8行连接服务器,第10行打开摄像头,这里打开的是第1个摄像头。第11行启动定时器。
(9)为停止视频采集按钮添加单击事件处理函数,其作用是关闭定时器,停止视频采集,代码如下:
- 01 void CVideoClientDlg::OnBtnStop()
- 02 {
- 03 KillTimer(1); //关闭定时器
- 04 GetDlgItem(IDC_BTN_GETVIDEO)->EnableWindow(TRUE);
- 05 }