进行设置
在Doc类头文件添加
// WebCameraDoc.h : interface of the CWebCameraDoc class // ///////////////////////////////////////////////////////////////////////////// #if !defined(AFX_WEBCAMERADOC_H__46D2072D_8159_46E5_BCA4_C91FE67DE31A__INCLUDED_) #define AFX_WEBCAMERADOC_H__46D2072D_8159_46E5_BCA4_C91FE67DE31A__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "HVDAILT.h" //定义自己的0 #define MY_ZERO 0.000000001 #include "Raw2Rgb.h" //const const int DeviceNum = 1; //设备编号 const HV_RESOLUTION Resolution = RES_MODE0;//分辨率 const HV_SNAP_MODE SnapMode = CONTINUATION; const HV_BAYER_LAYOUT Layout = BAYER_GR; const HV_BAYER_CONVERT_TYPE ConvertType = BAYER2RGB_NEIGHBOUR; const long Gain = 8; const long ExposureTint_Upper = 60; const long ExposureTint_Lower = 1000; const long ShutterDelay = 0; const long ADCLevel = ADC_LEVEL2; const int XStart = 0; const int YStart = 0; const int Width = 752; const int Height = 480;
protected: void SaveBmp();
private: void SetExposureTime(HHV hhv,int nWindWidth,long lTintUpper,long lTintLower);
在cpp文件添加实现代码
///////////////////////////////////////////////////////////////////////////// // CWebCameraDoc commands //根据卡的其他参数设置曝光时间 //其他的参数如摄像机时钟频率,消隐值都取默认值, //参数: //nWindWidth:当前图像宽度 //lTintUpper:曝光时间的分子, lTintUpper/lTintLower 组成实际的曝光时间 //lTintLower:曝光时间的分母,lTintUpper/lTintLower 组成实际的曝光时间 void CWebCameraDoc::SetExposureTime(HHV hhv, int nWindWidth, long lTintUpper, long lTintLower) { int size = sizeof(HVTYPE); HVTYPE type; HVGetDeviceInfo(hhv,DESC_DEVICE_TYPE, &type, &size); //When outputwindow changes, change the exposure //请参考曝光系数转换公式 long lClockFreq; int nOutputWid; double dExposure = 0.0; double dTint = max((double)lTintUpper/(double)lTintLower,MY_ZERO); if (type == GV400UMTYPE || type == GV400UCTYPE) { long rate = 0; switch(Resolution) { case 0: rate = 1; break; case 1: rate = 2; break; case 2: rate = 4; break; default: break; } nOutputWid = nWindWidth*rate; lClockFreq = 26600000; long lTb = 0x5e; if (dTint* lClockFreq <= ((double)nOutputWid + lTb - 255)) { dExposure = 1; } dExposure = (dTint* lClockFreq - ((double)nOutputWid + lTb - 255))/((double)nOutputWid + lTb); if (dExposure > 32767) dExposure = 32767; } else { nOutputWid = nWindWidth; lClockFreq = 24000000; if(type == HV1300UCTYPE || type == HV1301UCTYPE) { long lTb = 0; dExposure = (dTint* lClockFreq + 180.0)/((double)nOutputWid + 244.0 + lTb); } else { long lTb = 0; dExposure = (dTint* lClockFreq + 180.0)/((double)nOutputWid + 305.0 + lTb) + 1 ; } if (dExposure > 16383) dExposure = 16383; } HVAECControl(hhv, AEC_EXPOSURE_TIME, (long)dExposure); } void CWebCameraDoc::SaveBmp() { // TODO: Add your control notification handler code here HVSTATUS status = STATUS_OK; HHV hhv = NULL; /* * 初始化所有成员变量,同时打开数字摄像机 */ // 打开数字摄像机 1,返回状态值 status = BeginHVDevice(DeviceNum, &hhv); // 检验函数执行状态,如果失败,则返回错误状态消息框 HV_VERIFY(status); /* * 初始化数字摄像机硬件状态,用户也可以在其他位置初始化数字摄像机, * 但应保证数字摄像机已经打开,建议用户在应用程序初始化时, * 同时初始化数字摄像机硬件。 */ // 设置数字摄像机分辨率 HVSetResolution(hhv, Resolution); // 采集模式,包括 CONTINUATION(连续)、TRIGGER(外触发) HVSetSnapMode(hhv, SnapMode); // 设置各个分量的增益 for (int i = 0; i < 4; i++){ HVAGCControl(hhv, RED_CHANNEL + i, Gain); } // 设置曝光时间 SetExposureTime(hhv,Width,ExposureTint_Upper,ExposureTint_Lower); // 设置ADC的级别 HVADCControl(hhv, ADC_BITS, ADCLevel); /* * 视频输出窗口,即视频输出范围,输出窗口取值范围必须在输入窗口范围以内, * 视频窗口左上角X坐标和窗口宽度应为4的倍数,左上角Y坐标和窗口高度应为2的倍数 * 输出窗口的起始位置一般设置为(0, 0)即可。 */ HVSetOutputWindow(hhv, XStart, YStart, Width, Height); /* * 分配原始图像缓冲区,一般用来存储采集图像原始数据 * 一般图像缓冲区大小由输出窗口大小和视频格式确定。 */ BYTE *pRawBuffer = new BYTE[Width * Height]; ASSERT(pRawBuffer); /* 分配Bayer转换后图像数据缓冲 */ BYTE *pImageBuffer = new BYTE[Width * Height * 3]; ASSERT(pImageBuffer); // 分配BITMAPINFO缓冲 BYTE *pInfoBuffer = new BYTE[sizeof(BITMAPINFO)]; ASSERT(pInfoBuffer); /* * 初始化BITMAPINFO 结构,此结构在保存bmp文件、显示采集图像时使用 */ // m_pBmpInfo即指向m_chBmpBuf缓冲区,用户可以自己分配BTIMAPINFO缓冲区 BITMAPINFO *pBmpInfo = (BITMAPINFO *)pInfoBuffer; pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); // 图像宽度,一般为输出窗口宽度 pBmpInfo->bmiHeader.biWidth = Width; // 图像宽度,一般为输出窗口高度 pBmpInfo->bmiHeader.biHeight = Height; // 图像位深度,数字摄像机采集的原始数据为8位,Bayer转换后为24位 pBmpInfo->bmiHeader.biBitCount = 24; // 以下设置一般相同,对于低于8位的位图,还应设置相应的位图调色板 pBmpInfo->bmiHeader.biPlanes = 1; pBmpInfo->bmiHeader.biCompression = BI_RGB; pBmpInfo->bmiHeader.biSizeImage = 0; pBmpInfo->bmiHeader.biXPelsPerMeter = 0; pBmpInfo->bmiHeader.biYPelsPerMeter = 0; pBmpInfo->bmiHeader.biClrUsed = 0; pBmpInfo->bmiHeader.biClrImportant = 0; // 采集1帧图像到内存,采集完成后停止 BYTE *ppBuf[1]; ppBuf[0] = pRawBuffer; status = HVSnapShot(hhv, ppBuf,1); HV_VERIFY(status); if (HV_SUCCESS(status)) { // 将原始图像数据进行Bayer转换,转换后为24位。 //同时将原始数据进行上下翻转 //颜色查找表 BYTE pLutR[256] ; BYTE pLutG[256] ; BYTE pLutB[256] ; for(int i=0;i<256;i++) { pLutR[i] = i; pLutG[i] = i; pLutB[i] = i; } ConvertBayer2Rgb(pImageBuffer,pRawBuffer,Width,Height,ConvertType,pLutR,pLutG,pLutB,true,Layout); /* * 以下保存BMP文件设置基本相同 */ CFileDialog dlg(FALSE , "*.bmp", NULL ,OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY, "Bitmap Files(*.bmp)|*.bmp", NULL); if (dlg.DoModal() == IDOK) { BITMAPFILEHEADER bfh = {0}; DWORD dwImageSize = 0; DWORD dwBytesRead = 0; BOOL bRVal = TRUE; dwImageSize = Width * Height * 3; //计算图像大小,由视频输出窗口和视频格式确定 bfh.bfType = (WORD)'M' << 8 | 'B'; //定义文件类型 bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); //定义文件头大小 bfh.bfSize = bfh.bfOffBits + dwImageSize; //文件大小 HANDLE hFile = ::CreateFile(dlg.GetPathName(), GENERIC_WRITE , 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile == INVALID_HANDLE_VALUE) { bRVal = FALSE; } else{ ::WriteFile(hFile, &bfh, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL ); ::WriteFile(hFile, pBmpInfo, sizeof(BITMAPINFOHEADER), &dwBytesRead, NULL ); ::WriteFile(hFile, pImageBuffer, dwImageSize, &dwBytesRead, NULL ); CloseHandle(hFile); } } } delete []pRawBuffer; delete []pImageBuffer; delete []pInfoBuffer; // 关闭数字摄像机1 status = EndHVDevice(hhv); HV_VERIFY(status); }
添加菜单或工具栏进行处理,调用SaveBmp函数。调试,运行。
void CWebCameraDoc::OnSaveBmp() { // TODO: Add your command handler code here SaveBmp(); }