📄 mainfrm.cpp
字号:
// MainFrm.cpp : implementation of the CMainFrame class
//
#include "stdafx.h"
#include "LaserScan.h"
#include "MainFrm.h"
#include "CGVideo.h"
#include "CGVidEx.h"
//#include "Streams.h"
#include "ptSet.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define WIDTH_BYTES(bits) (((bits) + 31) / 32 * 4)
/////////////////////////////////////////////////////////////////////////////
// CMainFrame
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_COMMAND(ID_SCAN_START, OnScanStart)
ON_COMMAND(ID_SCAN_STOP, OnScanStop)
ON_UPDATE_COMMAND_UI(ID_SCAN_START, OnUpdateScanStart)
ON_WM_CLOSE()
ON_UPDATE_COMMAND_UI(ID_SCAN_STOP, OnUpdateScanStop)
ON_COMMAND(ID_SCAN_SETTINGS, OnScanSettings)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction
CMainFrame::CMainFrame()
{
// TODO: add member initialization code here
/*
* 初始化所有成员变量,同时打开图像卡
*/
nCount=0;
ctlCount=0;
CGSTATUS status = CG_OK;
nCptfrq=25;
m_bLive = FALSE;
// 打开图像卡 1
status = BeginCGCard(1, &m_hcg);
// 检验函数执行状态,如果失败,则返回错误状态消息框
m_bOpen=FALSE;
CG_VERIFY(status);
/*
* 初始化BITMAPINFO 结构,此结构在保存bmp文件、显示采集图像时使用
*/
BYTE *pMem;
int nTable = 256;
int a=sizeof(BITMAPINFOHEADER)+nTable * sizeof(RGBQUAD);
pMem=new BYTE[a];
pBmpInfo=(BITMAPINFO*) pMem;
pBmpInfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
/*
* 图像宽度,一般为输出窗口宽度
*/
pBmpInfo->bmiHeader.biWidth = 768;
/*
* 图像高度,根据扫描模式(FRAME/FIELD)的不同
* FRAME制下,一般为输出窗口高度
* FIELD制下,一般为输出窗口高度的一半
*/
pBmpInfo->bmiHeader.biHeight = 576;
/*
* 图像位深度,由视频格式确定,
* 采集图像视频格式有RGB565、RGB555、RGB888、ALL8BIT等,
* 如果使用CGDateTransfrom函数,则将15,16位数据转换为24位
*/
pBmpInfo->bmiHeader.biBitCount = 8;
/*
* 以下设置一般相同,
* 对于低于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;
/*
* 分配图像缓冲区,一般用来存储采集图像
* 用户可以将设备静态内存的图像数据直接通过指针或
* 用CGDataTransfrom函数拷贝到图像缓冲区,然后做进一步的处理,
* 一般图像缓冲区大小由输出窗口大小和视频格式确定。
*/
pImageBuffer = new BYTE[768 * 576 * 4];
FillMemory(pImageBuffer, 768 * 576 * 4, 0xff);
// bfh = {0};
bfh.bfType = (WORD)'M' << 8 | 'B'; //定义文件类型
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+nTable * sizeof(RGBQUAD); //定义文件头大小
// bfh.bfSize = bfh.bfOffBits + dwImageSize; //文件大小
}
CMainFrame::~CMainFrame()
{
CGSTATUS status = CG_OK;
// 关闭图像卡,释放图像卡内部资源
status = EndCGCard(m_hcg);
CG_VERIFY(status);
if (pImageBuffer) {
delete []pImageBuffer;
pImageBuffer = NULL;
}
if(pBmpInfo)
delete []pBmpInfo;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CMainFrame diagnostics
#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
CFrameWnd::AssertValid();
}
void CMainFrame::Dump(CDumpContext& dc) const
{
CFrameWnd::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CMainFrame message handlers
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
InitSystemInfo();
// TODO: Add your specialized creation code here
/*
* 初始化图像卡硬件状态,用户也可以在其他位置初始化图像卡,
* 但应保证图像卡已经打开,建议用户在应用程序初始化时,
* 同时初始化图像卡硬件。
*/
//设置视频制式(PAL / NTSC),由当前视频源制式决定
CGSetVideoStandard(m_hcg, PAL);
/*
* 视频格式,即采集图像数据描述方式,
* 包括YUV422、RGB888、RGB565、RGB555、RGB8888、ALL8BIT、LIMITED8BIT,
* 在采集图像到屏幕时,需要保证视频格式和当前系统屏幕位深度一致,而采集到内存没有此限制。
*/
CGSetVideoFormat(m_hcg, ALL8BIT);
//扫描模式,包括 FRAME、FIELD
CGSetScanMode(m_hcg, FRAME);
/*
* 晶振,包括CRY_OSC_35M、CRY_OSC_28M
* 对于DH-CG300图像卡,一般为CRY_OSC_35M,对于DH-QP300图像卡,一般为CRY_OSC_28M,
* 其他类型图像卡没有此硬件设置,但可以调用此接口,并返回CG_NOT_SUPPORT_INTERFACE信息
*/
CGSelectCryOSC(m_hcg, CRY_OSC_35M);
/*
* 设置视频源路,
* 视频源路VIDEO_SOURCE包括视频类型和序号,
* 各种图像卡支持的视频源路不尽相同,请参看相应硬件说明
*/
VIDEO_SOURCE source;
source.type = COMPOSITE_VIDEO; //视频类型为复合视频
source.nIndex = 1; //序号为0
CGSetVideoSource(m_hcg, source);
/*
* 视频输入窗口,即视频输入范围,输入窗口取值范围:
* 对于视频制式为PAL制,水平方向为0-768,垂直方向为0-576
* 对于视频制式为NTSC制,水平方向为0-768,垂直方向为0-576
* 视频窗口左上角X坐标和窗口宽度应为4的倍数,左上角Y坐标和窗口高度应为2的倍数
*/
CGSetInputWindow(m_hcg, 0, 0, 768, 576); //视频输入窗口取最大
/*
* 视频输出窗口,即视频输出范围,输出窗口取值范围必须在输入窗口范围以内,
* 视频窗口左上角X坐标和窗口宽度应为4的倍数,左上角Y坐标和窗口高度应为2的倍数
* 在采集到屏幕时,输出窗口的起始位置为图像屏幕输出位置的屏幕坐标,
* 在采集到内存时,输出窗口的起始位置设置为(0, 0)即可。
*/
CGSetOutputWindow(m_hcg, 0, 0, 768, 576);
return 0;
}
void CMainFrame::OnScanStart()
{
CGSTATUS status=CG_OK;
// TODO: Add your command handler code here
CGOpenSnapEx(m_hcg, SnapThreadCallback, this);
status = CGStartSnapEx(m_hcg, 0, TRUE, 2);
m_bOpen=TRUE;
CG_VERIFY(status);
}
int CALLBACK CMainFrame::SnapThreadCallback(SNAP_INFO *pInfo)
{
CMainFrame *pFrame = (CMainFrame *)(pInfo->pParam);
pFrame->SnapChange(pInfo->nNumber);
return 1;
}
BOOL CMainFrame::SnapChange(int nNumber)
{
CGSTATUS status=CG_OK;
pLinearAddr = NULL;//指向静态内存的指针
handle = NULL; //静态内存的句柄
/*
* 分配图像缓冲区,一般用来存储采集图像
* 用户可以将设备静态内存的图像数据直接通过指针或
* 用CGDataTransfrom函数拷贝到图像缓冲区,然后做进一步的处理,
* 一般图像缓冲区大小由输出窗口大小和视频格式确定。
*/
//pImageBuffer = new BYTE[768 * 576 * 3];
dwImageSize = 768 * 576 ;
if (pImageBuffer) {
/*
* 锁定指定位置的静态内存,
* 偏移由图像大小和图像序号确定,锁定大小为图像大小
* 用户可以在任何时候锁定指定位置的静态内存,然后通过pLinearAddr指针访问相应的内存。
*/
status = CGStaticMemLock(dwImageSize * nNumber, dwImageSize, &handle, (PVOID *)&pLinearAddr);
if (CG_SUCCESS(status)) {
/*
* 将静态内存中的图像传递到用户缓冲区,同时进行格式转换。
* 如果静态内存中图像为15、16、32位,则转换为24位。
* 由于图像卡采集到静态内存的图像数据是正向存放,
* 而Windows中处理的位图数据需要倒置,因此一般还要将图像倒置。
*/
CGDataTransform(pImageBuffer, //图像缓冲区
pLinearAddr, //静态内存
768, //图像宽度
576, //图像高度
8, //图像位深度
FALSE //是否倒置图像
);
CGStaticMemUnlock(handle); //解除静态内存锁定
//实时显示图像
ShowImg(pImageBuffer, pBmpInfo);
//每隔1秒采集一张图片
int a;
if (25 % nCptfrq != 0)
a= 25/nCptfrq+1;
else
a=25/nCptfrq;
ctlCount++;
if(ctlCount%a != 0)
return 1;
/*
* 以下保存BMP文件设置基本相同
*/
DWORD dwBytesRead = 0;
BOOL bRVal = TRUE;
bfh.bfSize = bfh.bfOffBits + dwImageSize; //文件大小
//定义文件名,每保存一张图片后加1
CString temp;
temp.Format("%d",nCount);
nCount++;
CString tempfilename;
tempfilename="c:\\temp\\"+temp+".bmp";
//tempfilename=strPath+temp+".bmp";
HANDLE hFile = ::CreateFile(tempfilename,
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 );
int dwSize;
dwSize = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
::WriteFile(hFile, pBmpInfo, dwSize, &dwBytesRead, NULL );
dwImageSize = WIDTH_BYTES(768 * 8) * 576;
::WriteFile(hFile, pImageBuffer, dwImageSize, &dwBytesRead, NULL );
CloseHandle(hFile);
}
}
}
//delete []pImageBuffer; //释放图像缓冲
//delete []pInfoBuffer; //释放文件信息缓冲
return true;
}
void CMainFrame::OnScanStop()
{
// TODO: Add your command handler code here
CGSTATUS status =CG_OK;
// 停止采集图像到内存,可以再次调用CGStartSnapEx启动图像卡采集
status = CGStopSnapEx(m_hcg);
CG_VERIFY(status);
if (CG_SUCCESS(status)) {
m_bOpen = FALSE;
}
}
void CMainFrame::OnUpdateScanStart(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable( !m_bOpen);
pCmdUI->SetCheck(m_bOpen);
}
void CMainFrame::OnClose()
{
// TODO: Add your message handler code here and/or call default
/*
* 用户在没有通过菜单项正常关闭图像卡采集,
* 而直接关闭应用程序时,应保证图像卡采集被关闭
*/
if (m_bOpen) {
CGCloseSnapEx(m_hcg);
}
CFrameWnd::OnClose();
}
void CMainFrame::OnUpdateScanStop(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bOpen);
}
BOOL CMainFrame::ShowImg(BYTE *pImageBuffer, BITMAPINFO *pBmpInfo)
{
CGSTATUS status = CG_OK;
CView *pView = GetActiveView(); //获取当前VIEW视图
CDC *pDC = pView->GetDC(); //得到VIEW的DC
dwImageSize = 768 * 576 ; //计算图像大小,由视频输出窗口和视频格式确定
//在视图客户区显示图像
if (m_hPalette && (pBmpInfo->bmiHeader.biBitCount == 8)) {
m_hOldPal = ::SelectPalette(pDC->GetSafeHdc(), m_hPalette, FALSE);
::RealizePalette(pDC->GetSafeHdc());
}
StretchDIBits(pDC->GetSafeHdc(),
0,
0,
768, //显示窗口宽度
576, //显示窗口高度
0,
0,
768, //图像宽度
576, //图像高度
pImageBuffer, //图像缓冲区
pBmpInfo, //BMP图像描述信息
DIB_RGB_COLORS,
SRCCOPY
);
if (m_hOldPal && (pBmpInfo->bmiHeader.biBitCount == 8)) {
::SelectPalette(pDC->GetSafeHdc(), m_hOldPal, FALSE);
::RealizePalette(pDC->GetSafeHdc());
}
//delete []pImageBuffer; //释放图像缓冲
pView->ReleaseDC(pDC);
return 1;
}
void CMainFrame::OnScanSettings()
{
// TODO: Add your command handler code here
CptSet dlg;
if(dlg.DoModal()==IDOK){
nCptfrq = dlg.m_Cptfrq;
strPath = dlg.m_Cptpath;
}
}
BOOL CMainFrame::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
// TODO: Add your specialized code here and/or call the base class
CRect windowrect(0,0,768,576);
return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, windowrect, pParentWnd, nID, pContext);
}
void CMainFrame::InitSystemInfo()
{
LOGPALETTE *pLGPal = NULL;
BYTE Palbuf[2048];
int i;
pLGPal = (LOGPALETTE *)Palbuf;
pLGPal->palVersion = 0x300;
pLGPal->palNumEntries = 256;
for ( i = 0; i < pLGPal->palNumEntries; i++){
pLGPal->palPalEntry[i].peRed = (BYTE)i ;
pLGPal->palPalEntry[i].peGreen = (BYTE)i ;
pLGPal->palPalEntry[i].peBlue = (BYTE)i ;
pLGPal->palPalEntry[i].peFlags = 0;//PC_NOCOLLAPSE;
}
m_hPalette = ::CreatePalette(pLGPal);
//初始化颜色表
for (i = 0; i < 256; i++){
pBmpInfo->bmiColors[i].rgbBlue = (BYTE)i;
pBmpInfo->bmiColors[i].rgbGreen = (BYTE)i;
pBmpInfo->bmiColors[i].rgbRed = (BYTE)i;
pBmpInfo->bmiColors[i].rgbReserved = 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -