基于Qt大恒工业相机二次开发demo-C++

目录

1.新建工程

2.文件及属性配置

2.1文件拷贝

 2.2VS项目属性配置

2.2.1包含目录和库目录添加

 2.2.2附加依赖项添加

3.添加基于官方mfc代码改写的CGXBitmap类

3.1添加CGXBitmap类

 3.2编写CGXBitmap.h和.cpp文件

4.编写Qt .h和 .cpp文件

5.运行效果

6.下载链接

7.双相机代码移植Qt版


1.新建工程

该项目是通过阅读大恒官方C++项目的代码进行移植的一个Qt简单demo,废话不多说直接上步骤。

 ​​​​

 至此一个Qt项目创建完毕。

2.文件及属性配置

因为需要使用大恒官方的API,那么就需要使用官方提供的库文件和头文件。可以通过该步骤添加到项目中。(方法不唯一,这里为了移植到其他电脑才这样做的)

2.1文件拷贝

 2.2VS项目属性配置

2.2.1包含目录和库目录添加

 2.2.2附加依赖项添加

 至此整个项目的属性配置和文件就配置完成了。

3.添加基于官方mfc代码改写的CGXBitmap类

CGXBitmap类是我基于大恒官方提供的C++代码中mfc版CGXBitmap类改写的。具体功能有:显示图像、保存图像等功能。具体步骤如下:

3.1添加CGXBitmap类

 3.2编写CGXBitmap.h和.cpp文件

在添加的CGXBitmap.h 填写如下内容

//
/*CGXBitmap.h*/
/
#pragma once

#include <QWidget>
#include "ui_CGXBitmap.h"
#include <QLabel>
#include <iostream>
#include <GalaxyIncludes.h>

using namespace std;

#pragma execution_character_set("utf-8")

class CGXBitmap : public QWidget
{
	Q_OBJECT

public:
	CGXBitmap(QWidget *parent = Q_NULLPTR);
	~CGXBitmap();

private:
	Ui::CGXBitmap ui;
	bool               m_bIsColor;                       //是否支持彩色相机
	int64_t            m_nImageHeight;                   //原始图像高
	int64_t            m_nImageWidth;                    //原始图像宽
	BITMAPINFO         *m_pBmpInfo;	                     //BITMAPINFO 结构指针,显示图像时使用
	char               m_chBmpBuf[2048];	             //BIMTAPINFO 存储缓冲区,m_pBmpInfo即指向此缓冲区
	uchar              *m_pImageBuffer;                  //保存翻转后的图像用于显示
private:
	CGXBitmap& operator=(const CGXBitmap&);
	CGXBitmap(const CGXBitmap&);

public:

	QLabel			   *m_pLabel;
	QImage			   *m_pImage;
	//显示图像
	void Show(CImageDataPointer& objCImageDataPointer);

	//图像处理后并显示图像
	void ShowImageProcess(CImageProcessConfigPointer& objCfg, CImageDataPointer& objCImageDataPointer);

	//存储Bmp图像
	void SaveBmp(CImageDataPointer& objCImageDataPointer, const std::string& strFilePath);

	//存储Raw图像
	void SaveRaw(CImageDataPointer& objCImageDataPointer, const std::string& strFilePath);

	//通过GX_PIXEL_FORMAT_ENTRY获取最优Bit位
	GX_VALID_BIT_LIST GetBestValudBit(GX_PIXEL_FORMAT_ENTRY emPixelFormatEntry);

	LPCWSTR stringToLPCWSTR(std::string orig);

	void addDevicePtr(CGXDevicePointer& objCGXDevicePointer);

private:
	//判断PixelFormat是否为8位
	bool __IsPixelFormat8(GX_PIXEL_FORMAT_ENTRY emPixelFormatEntry);

	//为彩色相机图像显示准备资源
	void __ColorPrepareForShowImg();

	//为黑白相机图像显示准备资源
	void __MonoPrepareForShowImg();

	//判断是否兼容
	bool __IsCompatible(BITMAPINFO *pBmpInfo, uint64_t nWidth, uint64_t nHeight);

	//更新Bitmap的信息
	void __UpdateBitmap(CImageDataPointer& objCImageDataPointer);

	//将m_pBufferRGB中图像显示到界面
	void __DrawImg(uchar* pBuffer);

	//计算宽度所占的字节数
	int64_t __GetStride(int64_t nWidth, bool bIsColor);

	//是否支持彩色
	void __IsSupportColor(CGXDevicePointer& objCGXDevicePointer, bool &bIsColorFilter);

};

 在添加的CGXBitmap.cpp填写如下内容:

#include "CGXBitmap.h"
//---------------------------------------------------------------------------------
/**
\brief   构造函数
\param   objCGXDevicePointer 图像设备指针
\param   parent 窗体指针
\return  无
*/
//----------------------------------------------------------------------------------
CGXBitmap::CGXBitmap(QWidget *parent)
	: QWidget(parent)
	, m_bIsColor(false)
	, m_nImageHeight(0)
	, m_nImageWidth(0)
	, m_pImage(NULL)
	, m_pBmpInfo(NULL)
	, m_pImageBuffer(NULL)
{
	ui.setupUi(this);
	//初始化绘图框
	m_pLabel = new QLabel(this);
	m_pLabel->move(0, 0);
	m_pLabel->resize(751, 551);

}

void CGXBitmap::addDevicePtr(CGXDevicePointer& objCGXDevicePointer)
{
	if (objCGXDevicePointer.IsNull())
	{
		throw std::runtime_error("Argument is error");
	}

	memset(m_chBmpBuf, 0, sizeof(m_chBmpBuf));
	gxstring strValue = "";

	//获得图像宽度、高度等

	m_nImageWidth = (int64_t)objCGXDevicePointer->GetRemoteFeatureControl()->GetIntFeature("Width")->GetValue();
	m_nImageHeight = (int64_t)objCGXDevicePointer->GetRemoteFeatureControl()->GetIntFeature("Height")->GetValue();

	//获取是否为彩色相机
	__IsSupportColor(objCGXDevicePointer, m_bIsColor);

	if (m_bIsColor)
	{
		__ColorPrepareForShowImg();
	}
	else
	{
		__MonoPrepareForShowImg();
	}
}
//---------------------------------------------------------------------------------
/**
\brief   析构函数

\return  无
*/
//----------------------------------------------------------------------------------
CGXBitmap::~CGXBitmap()
{

}

//----------------------------------------------------------------------------------
/**
\brief     判断PixelFormat是否为8位
\param     emPixelFormatEntry 图像数据格式
\return    true为8为数据,false为非8位数据
*/
//----------------------------------------------------------------------------------
bool CGXBitmap::__IsPixelFormat8(GX_PIXEL_FORMAT_ENTRY emPixelFormatEntry)
{
	bool bIsPixelFormat8 = false;
	const unsigned  PIXEL_FORMATE_BIT = 0x00FF0000;  ///<用于与当前的数据格式进行与运算得到当前的数据位数
	unsigned uiPixelFormatEntry = (unsigned)emPixelFormatEntry;
	if ((uiPixelFormatEntry & PIXEL_FORMATE_BIT) == GX_PIXEL_8BIT)
	{
		bIsPixelFormat8 = true;
	}
	return bIsPixelFormat8;
}

//----------------------------------------------------------------------------------
/**
\brief     通过GX_PIXEL_FORMAT_ENTRY获取最优Bit位
\param     emPixelFormatEntry 图像数据格式
\return    最优Bit位
*/
//----------------------------------------------------------------------------------
GX_VALID_BIT_LIST CGXBitmap::GetBestValudBit(GX_PIXEL_FORMAT_ENTRY emPixelFormatEntry)
{
	GX_VALID_BIT_LIST emValidBits = GX_BIT_0_7;
	switch (emPixelFormatEntry)
	{
	case GX_PIXEL_FORMAT_MONO8:
	case GX_PIXEL_FORMAT_BAYER_GR8:
	case GX_PIXEL_FORMAT_BAYER_RG8:
	case GX_PIXEL_FORMAT_BAYER_GB8:
	case GX_PIXEL_FORMAT_BAYER_BG8:
	{
		emValidBits = GX_BIT_0_7;
		break;
	}
	case GX_PIXEL_FORMAT_MONO10:
	case GX_PIXEL_FORMAT_BAYER_GR10:
	case GX_PIXEL_FORMAT_BAYER_RG10:
	case GX_PIXEL_FORMAT_BAYER_GB10:
	case GX_PIXEL_FORMAT_BAYER_BG10:
	{
		emValidBits = GX_BIT_2_9;
		break;
	}
	case GX_PIXEL_FORMAT_MONO12:
	case GX_PIXEL_FORMAT_BAYER_GR12:
	case GX_PIXEL_FORMAT_BAYER_RG12:
	case GX_PIXEL_FORMAT_BAYER_GB12:
	case GX_PIXEL_FORMAT_BAYER_BG12:
	{
		emValidBits = GX_BIT_4_11;
		break;
	}
	case GX_PIXEL_FORMAT_MONO14:
	{
		//暂时没有这样的数据格式待升级
		break;
	}
	case GX_PIXEL_FORMAT_MONO16:
	case GX_PIXEL_FORMAT_BAYER_GR16:
	case GX_PIXEL_FORMAT_BAYER_RG16:
	case GX_PIXEL_FORMAT_BAYER_GB16:
	case GX_PIXEL_FORMAT_BAYER_BG16:
	{
		//暂时没有这样的数据格式待升级
		break;
	}
	default:
		break;
	}
	return emValidBits;
}

//---------------------------------------------------------------------------------
/**
\brief   为彩色相机图像显示准备资源

\return  无
*/
//----------------------------------------------------------------------------------
void CGXBitmap::__ColorPrepareForShowImg()
{
	//--------------------------------------------------------------------
	//---------------------------初始化bitmap头---------------------------
	m_pBmpInfo = (BITMAPINFO *)m_chBmpBuf;
	m_pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	m_pBmpInfo->bmiHeader.biWidth = (LONG)m_nImageWidth;
	m_pBmpInfo->bmiHeader.biHeight = (LONG)m_nImageHeight;

	m_pBmpInfo->bmiHeader.biPlanes = 1;
	m_pBmpInfo->bmiHeader.biBitCount = 24;
	m_pBmpInfo->bmiHeader.biCompression = BI_RGB;
	m_pBmpInfo->bmiHeader.biSizeImage = 0;
	m_pBmpInfo->bmiHeader.biXPelsPerMeter = 0;
	m_pBmpInfo->bmiHeader.biYPelsPerMeter = 0;
	m_pBmpInfo->bmiHeader.biClrUsed = 0;
	m_pBmpInfo->bmiHeader.biClrImportant = 0;
}

//---------------------------------------------------------------------------------
/**
\brief   为黑白相机图像显示准备资源

\return  无
*/
//----------------------------------------------------------------------------------
void CGXBitmap::__MonoPrepareForShowImg()
{
	//---------------------------------------------------------------------
	//----------------------初始化bitmap头---------------------------------
	m_pBmpInfo = (BITMAPINFO *)m_chBmpBuf;
	m_pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	m_pBmpInfo->bmiHeader.biWidth = (LONG)m_nImageWidth;
	m_pBmpInfo->bmiHeader.biHeight = (LONG)m_nImageHeight;

	m_pBmpInfo->bmiHeader.biPlanes = 1;
	m_pBmpInfo->bmiHeader.biBitCount = 8; // 黑白图像为8
	m_pBmpInfo->bmiHeader.biCompression = BI_RGB;
	m_pBmpInfo->bmiHeader.biSizeImage = 0;
	m_pBmpInfo->bmiHeader.biXPelsPerMeter = 0;
	m_pBmpInfo->bmiHeader.biYPelsPerMeter = 0;
	m_pBmpInfo->bmiHeader.biClrUsed = 0;
	m_pBmpInfo->bmiHeader.biClrImportant = 0;

	// 黑白图像需要初始化调色板
	for (int i = 0; i < 256; i++)
	{
		m_pBmpInfo->bmiColors[i].rgbBlue = i;
		m_pBmpInfo->bmiColors[i].rgbGreen = i;
		m_pBmpInfo->bmiColors[i].rgbRed = i;
		m_pBmpInfo->bmiColors[i].rgbReserved = 0;
	}

	//为经过翻转后的图像数据分配空间
	if (m_pImageBuffer != NULL)
	{
		delete m_pImageBuffer;
		m_pImageBuffer = NULL;
	}

	m_pImageBuffer = new BYTE[(size_t)(m_nImageWidth * m_nImageHeight)];
	if (m_pImageBuffer == NULL)
	{
		throw std::runtime_error("Fail to allocate memory");
	}
}

//----------------------------------------------------------------------------------
/**
\brief     判断是否兼容
\param     pBmpInfo BITMAPINFO指针
\param     nWidth 图像宽
\param     nHeight 图像高
\return    true为一样,false不一样
*/
//----------------------------------------------------------------------------------
bool CGXBitmap::__IsCompatible(BITMAPINFO *pBmpInfo, uint64_t nWidth, uint64_t nHeight)
{
	if (pBmpInfo == NULL
		|| pBmpInfo->bmiHeader.biHeight != nHeight
		|| pBmpInfo->bmiHeader.biWidth != nWidth
		)
	{
		return false;
	}
	return true;
}

//----------------------------------------------------------------------------------
/**
\brief     检查图像是否改变并更新Buffer并为图像显示准备资源
\param     objCImageDataPointer  图像数据对象
\return    无
*/
//----------------------------------------------------------------------------------
void CGXBitmap::__UpdateBitmap(CImageDataPointer& objCImageDataPointer)
{
	if (!__IsCompatible(m_pBmpInfo, objCImageDataPointer->GetWidth(), objCImageDataPointer->GetHeight()))
	{
		m_nImageWidth = objCImageDataPointer->GetWidth();
		m_nImageHeight = objCImageDataPointer->GetHeight();
		if (m_bIsColor)
		{
			__ColorPrepareForShowImg();
		}
		else
		{
			__MonoPrepareForShowImg();
		}
	}
}

//---------------------------------------------------------------------------------
/**
\brief   将m_pBufferRGB中图像显示到界面
\param   pBuffer  图像数据Buffer指针
\return  无
*/
//----------------------------------------------------------------------------------
void CGXBitmap::__DrawImg(uchar* pBuffer)
{
	if (m_pImage != NULL)
	{
		delete m_pImage;
		m_pImage = NULL;
	}
	//数据转换
	m_pImage = new QImage(pBuffer, m_nImageWidth, m_nImageHeight, QImage::Format_Indexed8);

	// 不失真缩放
	m_pImage->scaled(m_nImageWidth, m_nImageHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation);
	m_pLabel->setScaledContents(true);
	m_pLabel->setPixmap(QPixmap::fromImage(*m_pImage));
}
//----------------------------------------------------------------------------------
/**
\brief     计算宽度所占的字节数
\param     nWidth  图像宽度
\param     bIsColor  是否是彩色相机
\return    图像一行所占的字节数
*/
//----------------------------------------------------------------------------------
int64_t CGXBitmap::__GetStride(int64_t nWidth, bool bIsColor)
{
	return bIsColor ? nWidth * 3 : nWidth;
}

//----------------------------------------------------------------------------------
/**
\brief     用于显示图像
\param     objCImageDataPointer  图像数据对象
\return    无
*/
//----------------------------------------------------------------------------------
void CGXBitmap::Show(CImageDataPointer& objCImageDataPointer)
{
	GX_VALID_BIT_LIST emValidBits = GX_BIT_0_7;
	uchar* pBuffer = NULL;

	if (objCImageDataPointer.IsNull())
	{
		throw std::runtime_error("NULL pointer dereferenced");
	}

	//检查图像是否改变并更新Buffer
	__UpdateBitmap(objCImageDataPointer);

	emValidBits = GetBestValudBit(objCImageDataPointer->GetPixelFormat());
	if (m_bIsColor)
	{
		pBuffer = (uchar*)objCImageDataPointer->ConvertToRGB24(emValidBits, GX_RAW2RGB_NEIGHBOUR, true);
		__DrawImg(pBuffer);
	}
	else
	{
		if (__IsPixelFormat8(objCImageDataPointer->GetPixelFormat()))
		{
			pBuffer = (uchar*)objCImageDataPointer->GetBuffer();
		}
		else
		{
			pBuffer = (uchar*)objCImageDataPointer->ConvertToRaw8(emValidBits);
		}

		__DrawImg(pBuffer);
	}

}

//----------------------------------------------------------------------------------
/**
\brief     用于图像处理后并显示图像
\param     objCfg  图像处理调节参数对象
\param     objCImageDataPointer  图像数据对象
\return    无
*/
//----------------------------------------------------------------------------------
void CGXBitmap::ShowImageProcess(CImageProcessConfigPointer& objCfg, CImageDataPointer& objCImageDataPointer)
{
	if ((objCfg.IsNull()) || (objCImageDataPointer.IsNull()))
	{
		throw std::runtime_error("NULL pointer dereferenced");
	}

	//检查图像是否改变并更新Buffer
	__UpdateBitmap(objCImageDataPointer);

	BYTE* pBuffer = (BYTE*)objCImageDataPointer->ImageProcess(objCfg);

	if (m_bIsColor)
	{
		__DrawImg(pBuffer);
	}
	else
	{
		// 黑白相机需要翻转数据后显示
		for (int i = 0; i < m_nImageHeight; i++)
		{
			memcpy(m_pImageBuffer + i * m_nImageWidth, pBuffer + (m_nImageHeight - i - 1) * m_nImageWidth, (size_t)m_nImageWidth);
		}

		__DrawImg(m_pImageBuffer);
	}
}
//----------------------------------------------------------------------------------
/**
\brief     存储Bmp图像
\param     objCImageDataPointer  图像数据对象
\param     strFilePath  显示图像文件名
\return    无
*/
//----------------------------------------------------------------------------------
void CGXBitmap::SaveBmp(CImageDataPointer& objCImageDataPointer, const std::string& strFilePath)
{
	GX_VALID_BIT_LIST emValidBits = GX_BIT_0_7;
	uchar* pBuffer = NULL;

	if ((objCImageDataPointer.IsNull()) || (strFilePath == ""))
	{
		throw std::runtime_error("Argument is error");
	}

	//检查图像是否改变并更新Buffer
	__UpdateBitmap(objCImageDataPointer);

	emValidBits = GetBestValudBit(objCImageDataPointer->GetPixelFormat());

	if (m_bIsColor)
	{
		pBuffer = (uchar*)objCImageDataPointer->ConvertToRGB24(emValidBits, GX_RAW2RGB_NEIGHBOUR, true);
	}
	else
	{
		if (__IsPixelFormat8(objCImageDataPointer->GetPixelFormat()))
		{
			pBuffer = (uchar*)objCImageDataPointer->GetBuffer();
		}
		else
		{
			pBuffer = (uchar*)objCImageDataPointer->ConvertToRaw8(emValidBits);
		}
		// 黑白相机需要翻转数据后显示
		for (int i = 0; i < m_nImageHeight; i++)
		{
			memcpy(m_pImageBuffer + i * m_nImageWidth, pBuffer + (m_nImageHeight - i - 1) * m_nImageWidth, (size_t)m_nImageWidth);
		}
		pBuffer = m_pImageBuffer;
	}

	DWORD		         dwImageSize = (DWORD)(__GetStride(m_nImageWidth, m_bIsColor) * m_nImageHeight);
	BITMAPFILEHEADER     stBfh = { 0 };
	DWORD		         dwBytesRead = 0;

	stBfh.bfType = (WORD)'M' << 8 | 'B';			 //定义文件类型
	stBfh.bfOffBits = m_bIsColor ? sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
		: sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (256 * 4);	//定义文件头大小true为彩色,false为黑白
	stBfh.bfSize = stBfh.bfOffBits + dwImageSize; //文件大小

	DWORD dwBitmapInfoHeader = m_bIsColor ? sizeof(BITMAPINFOHEADER)
		: sizeof(BITMAPINFOHEADER) + (256 * 4);	//定义BitmapInfoHeader大小true为彩色,false为黑白

	//创建文件
	HANDLE hFile = ::CreateFile(stringToLPCWSTR(strFilePath),
		GENERIC_WRITE,
		0,
		NULL,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL,
		NULL);

	if (hFile == INVALID_HANDLE_VALUE)
	{
		throw std::runtime_error("Handle is invalid");
	}

	::WriteFile(hFile, &stBfh, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL);
	::WriteFile(hFile, m_pBmpInfo, dwBitmapInfoHeader, &dwBytesRead, NULL); //黑白和彩色自适应
	::WriteFile(hFile, pBuffer, dwImageSize, &dwBytesRead, NULL);

	CloseHandle(hFile);
}
//----------------------------------------------------------------------------------
/**
\brief     存储Raw图像
\param     objCImageDataPointer  图像数据对象
\param     strFilePath  显示图像文件名
\return    无
*/
//----------------------------------------------------------------------------------
void CGXBitmap::SaveRaw(CImageDataPointer& objCImageDataPointer, const std::string& strFilePath)
{
	if ((objCImageDataPointer.IsNull()) || (strFilePath == ""))
	{
		throw std::runtime_error("Argument is error");
	}

	//检查图像是否改变并更新Buffer
	__UpdateBitmap(objCImageDataPointer);

	DWORD   dwImageSize = (DWORD)objCImageDataPointer->GetPayloadSize();  // 写入文件的长度
	DWORD   dwBytesRead = 0;                // 文件读取的长度

	BYTE* pbuffer = (BYTE*)objCImageDataPointer->GetBuffer();
	if (!m_bIsColor)
	{
		// 黑白相机需要翻转数据后显示
		for (int i = 0; i < m_nImageHeight; i++)
		{
			memcpy(m_pImageBuffer + i * m_nImageWidth, pbuffer + (m_nImageHeight - i - 1) * m_nImageWidth, (size_t)m_nImageWidth);
		}
		pbuffer = m_pImageBuffer;
	}

	// 创建文件
	HANDLE hFile = ::CreateFile(stringToLPCWSTR(strFilePath),
		GENERIC_WRITE,
		FILE_SHARE_READ,
		NULL,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL,
		NULL);

	if (hFile == INVALID_HANDLE_VALUE)   // 创建失败则返回
	{
		throw std::runtime_error("Handle is invalid");
	}
	else                                 // 保存Raw图像          
	{
		::WriteFile(hFile, pbuffer, dwImageSize, &dwBytesRead, NULL);
		CloseHandle(hFile);
	}
}
//----------------------------------------------------------------------------------
/**
\brief     是否支持彩色
\param     objCGXDevicePointer  [in]    设备句柄
\param     bIsColorFilter       [out]   是否支持彩色

\return
*/
//----------------------------------------------------------------------------------
void CGXBitmap::__IsSupportColor(CGXDevicePointer& objCGXDevicePointer, bool &bIsColorFilter)
{
	GX_STATUS emStatus = GX_STATUS_SUCCESS;
	bool      bIsImplemented = false;
	bool      bIsMono = false;
	gxstring  strPixelFormat = "";

	strPixelFormat = objCGXDevicePointer->GetRemoteFeatureControl()->GetEnumFeature("PixelFormat")->GetValue();
	strPixelFormat.substr(0, 4);

	if (0 == memcmp(strPixelFormat.c_str(), "Mono", 4))
	{
		bIsMono = true;
	}
	else
	{
		bIsMono = false;
	}

	bIsImplemented = objCGXDevicePointer->GetRemoteFeatureControl()->IsImplemented("PixelColorFilter");

	// 若当前为非黑白且支持PixelColorFilter则为彩色
	if ((!bIsMono) && (bIsImplemented))
	{
		bIsColorFilter = true;
	}
	else
	{
		bIsColorFilter = false;
	}
}

LPCWSTR CGXBitmap::stringToLPCWSTR(std::string orig)
{
	size_t origsize = orig.length() + 1;
	const size_t newsize = 100;
	size_t convertedChars = 0;
	wchar_t* wcstring = (wchar_t*)malloc(sizeof(wchar_t) * (orig.length() - 1));
	mbstowcs_s(&convertedChars, wcstring, origsize, orig.c_str(), _TRUNCATE);

	return wcstring;
}

 CGXBitmap.ui不做修改

4.编写Qt .h和 .cpp文件

 接下来编写最后的核心文件,具体文件以自己命名为主。

 编写daheng_SingleCam_for_qt.h(我的界面是用代码生成的,没有使用拖曳的方式生成,目的是为了提供更好的代码观感)

#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_daheng_SingleCam_for_qt.h"
#include <GalaxyIncludes.h>
#include <iostream>
#include "CGXBitmap.h"
#include <QPushButton>
#include <QLabel>
#include <QCloseEvent>

using namespace std;

#pragma execution_character_set("utf-8")

class daheng_SingleCam_for_qt : public QMainWindow
{
    Q_OBJECT

	//用户继承采集事件处理类
	class CSampleCaptureEventHandler : public ICaptureEventHandler
	{
	public:
		//---------------------------------------------------------------------------------
		/**
		\brief   采集回调函数
		\param   objImageDataPointer      图像处理参数
		\param   pFrame                   用户参数

		\return  无
		*/
		//----------------------------------------------------------------------------------
		void DoOnImageCaptured(CImageDataPointer&objImageDataPointer, void* pUserParam)
		{
			try
			{
				daheng_SingleCam_for_qt* pSingleCamDlg = (daheng_SingleCam_for_qt*)pUserParam;

				//显示图像
				pSingleCamDlg->m_pBitmap->Show(objImageDataPointer);
				//判断是否需要保存图像
				//if (pSingleCamDlg->m_pBitmap->m_bSaveImage == true)
				//{
				//	pSingleCamDlg->m_pBitmap->SavePicture(objImageDataPointer);
				//	pSingleCamDlg->m_pBitmap->m_bSaveImage = false;
				//}
			}
			catch (CGalaxyException)
			{
			}
			catch (std::exception)
			{
			}
		}
	};
public:
    daheng_SingleCam_for_qt(QWidget *parent = Q_NULLPTR);
	CGXBitmap	*m_pBitmap;				//图像操作类

private:
    Ui::daheng_SingleCam_for_qtClass ui;
	//Qt控件
	QPushButton *m_pBtnOpenDevice;		//打开设备按钮
	QPushButton *m_pBtnCloseDevice;		//关闭设备按钮
	QPushButton *m_pBtnStartSnap;		//开始采集按钮
	QPushButton *m_pBtnStopSnap;		//停止采集按钮
	QLabel		*m_pLabel;				//状态栏显示文字
	//用于界面更新的标识
	bool		m_bIsOpen;				//打开设备标识
	bool		m_bIsSnap;				//采集图像标识
	//大恒相机API
	CGXFeatureControlPointer			*m_pFeatureEventHandler;				//远端设备事件回调对象
	CSampleCaptureEventHandler			*m_pCaptureEventHandler;				//采集回调对象
	CGXDevicePointer					m_ObjDevicePtr;							//设备句柄
	CGXStreamPointer					m_ObjStreamPtr;							//设备流
	CGXFeatureControlPointer			m_ObjFeatureControlPtr;					//属性控制器
	CGXFeatureControlPointer			m_ObjStreamFeatureControlPtr;			//流层控制器
	//槽函数
	void on_Btn_OpenDevice_clicked();
	void on_Btn_CloseDevice_clicked();
	void on_Btn_StartSnap_clicked();
	void on_Btn_StopSnap_clicked();

	//关闭窗口事件重写
	void closeEvent(QCloseEvent *event);

	//更新界面
	void UpdateUI();

};

 daheng_SingleCam_for_qt.cpp

#include "daheng_SingleCam_for_qt.h"

daheng_SingleCam_for_qt::daheng_SingleCam_for_qt(QWidget *parent)
    : QMainWindow(parent)
	, m_bIsOpen(false)
	, m_bIsSnap(false)
{
    ui.setupUi(this);

	//控件初始化
	m_pBtnOpenDevice = new QPushButton(this);
	m_pBtnOpenDevice->setText("打开设备");
	m_pBtnOpenDevice->move(0, 0);

	m_pBtnCloseDevice = new QPushButton(this);
	m_pBtnCloseDevice->setText("关闭设备");
	m_pBtnCloseDevice->move(0, 50);

	m_pBtnStartSnap = new QPushButton(this);
	m_pBtnStartSnap->setText("开始采集");
	m_pBtnStartSnap->move(0, 100);

	m_pBtnStopSnap = new QPushButton(this);
	m_pBtnStopSnap->setText("停止采集");
	m_pBtnStopSnap->move(0, 150);

	m_pBitmap = new CGXBitmap(this);
	m_pBitmap->move(100, 0);
	m_pBitmap->resize(800, 607);

	m_pLabel = new QLabel(this);
	m_pLabel->setText("欢迎使用大恒相机[for Qt]");
	statusBar()->addWidget(m_pLabel);//将label控件添加到状态栏

	//连接信号和槽函数
	connect(m_pBtnOpenDevice, &QPushButton::clicked, this, &daheng_SingleCam_for_qt::on_Btn_OpenDevice_clicked);
	connect(m_pBtnCloseDevice, &QPushButton::clicked, this, &daheng_SingleCam_for_qt::on_Btn_CloseDevice_clicked);
	connect(m_pBtnStartSnap, &QPushButton::clicked, this, &daheng_SingleCam_for_qt::on_Btn_StartSnap_clicked);
	connect(m_pBtnStopSnap, &QPushButton::clicked, this, &daheng_SingleCam_for_qt::on_Btn_StopSnap_clicked);

	//大恒API库调用
	try
	{
		//初始化设备
		IGXFactory::GetInstance().Init();

		m_pCaptureEventHandler = new CSampleCaptureEventHandler();

		//更新界面
		UpdateUI();
	}
	catch (CGalaxyException& e)
	{
		if (m_pCaptureEventHandler != NULL)
		{
			delete m_pCaptureEventHandler;
			m_pCaptureEventHandler = NULL;
		}
		m_pLabel->setText(QString::fromStdString(e.what()));

		return;

	}
	catch (std::exception& e)
	{
		if (m_pCaptureEventHandler != NULL)
		{
			delete m_pCaptureEventHandler;
			m_pCaptureEventHandler = NULL;
		}

		m_pLabel->setText(QString::fromStdString(e.what()));
		return;

	}
}
//---------------------------------------------------------------------------------
/**
\brief   更新界面

\return  无
*/
//----------------------------------------------------------------------------------
void daheng_SingleCam_for_qt::UpdateUI()
{
	m_pBtnOpenDevice->setEnabled(!m_bIsOpen);
	m_pBtnCloseDevice->setEnabled(m_bIsOpen);
	m_pBtnStartSnap->setEnabled(m_bIsOpen && !m_bIsSnap);
	m_pBtnStopSnap->setEnabled(m_bIsOpen && m_bIsSnap);
}

void daheng_SingleCam_for_qt::on_Btn_OpenDevice_clicked()
{
	bool bIsDeviceOpen = false;		//设备是否打开标识
	bool bIsStreamOpen = false;		//设备流是否打开标识
	try
	{
		//枚举设备
		GxIAPICPP::gxdeviceinfo_vector vectorDeviceInfo;
		IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo);

		if (vectorDeviceInfo.size() == 0)
		{
			m_bIsOpen = false;
			bIsDeviceOpen = false;
			m_pLabel->setText("无可用设备!");
			return;
		}

		//打开第一个设备以及设备下面第一个流
		m_ObjDevicePtr = IGXFactory::GetInstance().OpenDeviceBySN(vectorDeviceInfo[0].GetSN(), GX_ACCESS_EXCLUSIVE);//打开方式:独占
		m_bIsOpen = true;
		bIsDeviceOpen = true;

		//获取远端设备属性控制器
		m_ObjFeatureControlPtr = m_ObjDevicePtr->GetRemoteFeatureControl();

		//为画图对象分配设备指针
		m_pBitmap->addDevicePtr(m_ObjDevicePtr);

		//判断设备流是否大于零,如果大于零则打开流
		int nStreamCount = m_ObjDevicePtr->GetStreamCount();

		if (nStreamCount)
		{
			m_ObjStreamPtr = m_ObjDevicePtr->OpenStream(0);
			//获取流层属性控制器
			m_ObjStreamFeatureControlPtr = m_ObjStreamPtr->GetFeatureControl();
			bIsStreamOpen = true;
		}
		else
		{
			throw exception("未发现设备流!");
		}

		//提高网络相机的采集性能,设置方法如下(目前只有千兆网系列相机支持设置最优包长)
		GX_DEVICE_CLASS_LIST ObjDeviceClass =
			m_ObjDevicePtr->GetDeviceInfo().GetDeviceClass();
		if (ObjDeviceClass == GX_DEVICE_CLASS_GEV)
		{
			//判断设备是否支持流通道数据包功能
			if (m_ObjStreamFeatureControlPtr->IsImplemented("GevSCPSPacketSize"))
			{
				//获取当前网络环境的最优包长值
				int nPacketSize = m_ObjStreamPtr->GetOptimalPacketSize();
				//将最优包长值设置为当前设备的流通道包长值
				m_ObjFeatureControlPtr->GetIntFeature(
					"GevSCPSPacketSize")->SetValue(nPacketSize);
			}
		}

		//更新界面
		UpdateUI();

		m_pLabel->setText(QString("打开设备成功!"));

	}
	catch (CGalaxyException& e)
	{
		//判断设备流是否已打开
		if (bIsStreamOpen)
		{
			m_ObjStreamPtr->Close();
		}

		//判断设备是否已打开
		if (bIsDeviceOpen)
		{
			m_ObjDevicePtr->Close();
		}

		m_pLabel->setText(QString::fromStdString(e.what()));

		return;
	}
	catch (exception& e)
	{
		//判断设备流是否已打开
		if (bIsStreamOpen)
		{
			m_ObjStreamPtr->Close();
		}

		//判断设备是否已打开
		if (bIsDeviceOpen)
		{
			m_ObjDevicePtr->Close();
		}

		m_pLabel->setText(QString::fromStdString(e.what()));
		return;
	}
}

void daheng_SingleCam_for_qt::on_Btn_CloseDevice_clicked()
{
	try
	{
		//判断是否已停止采集
		if (m_bIsSnap)
		{
			//发送停采命令
			m_ObjFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();

			//关闭流层采集
			m_ObjStreamPtr->StopGrab();

			//注销采集回调
			m_ObjStreamPtr->UnregisterCaptureCallback();
		}
	}
	catch (CGalaxyException)
	{
		//do noting
	}

	try
	{
		//关闭流对象
		m_ObjStreamPtr->Close();

	}
	catch (CGalaxyException)
	{
		//do noting
	}
	try
	{
		//关闭设备
		m_ObjDevicePtr->Close();
		m_pLabel->setText(QString("关闭设备成功!"));
	}
	catch (CGalaxyException)
	{
		//do noting
	}

	m_bIsOpen = false;
	m_bIsSnap = false;

	//更新界面
	UpdateUI();
}

void daheng_SingleCam_for_qt::on_Btn_StartSnap_clicked()
{
	// TODO: Add your control notification handler code here
	try
	{
		try
		{
			//设置Buffer处理模式
			m_ObjStreamFeatureControlPtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("OldestFirst");
		}
		catch (...)
		{
		}

		//注册回调函数
		m_ObjStreamPtr->RegisterCaptureCallback(m_pCaptureEventHandler, this);

		//开启流层通道
		m_ObjStreamPtr->StartGrab();

		//发送开采命令
		m_ObjFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute();
		m_bIsSnap = true;

		//更新界面
		UpdateUI();
		m_pLabel->setText(QString("开始采集!"));
	}
	catch (CGalaxyException& e)
	{
		m_pLabel->setText(QString::fromStdString(e.what()));

		return;
	}
	catch (std::exception& e)
	{
		m_pLabel->setText(QString::fromStdString(e.what()));

		return;
	}
}

void daheng_SingleCam_for_qt::on_Btn_StopSnap_clicked()
{
	// TODO: Add your control notification handler code here
	try
	{
		//发送停采命令
		m_ObjFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();

		//关闭流层通道
		m_ObjStreamPtr->StopGrab();

		//注销采集回调
		m_ObjStreamPtr->UnregisterCaptureCallback();
		m_bIsSnap = false;

		//更新界面
		UpdateUI();
		m_pLabel->setText(QString("停止采集!"));

	}
	catch (CGalaxyException& e)
	{
		m_pLabel->setText(QString::fromStdString(e.what()));

		return;
	}
	catch (std::exception& e)
	{
		m_pLabel->setText(QString::fromStdString(e.what()));

		return;
	}
}

void daheng_SingleCam_for_qt::closeEvent(QCloseEvent *event)
{
	try
	{
		//判断是否停止采集
		if (m_bIsSnap)
		{
			//发送停采命令
			m_ObjFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();

			//关闭流层通道
			m_ObjStreamPtr->StopGrab();

			//注销采集回调
			m_ObjStreamPtr->UnregisterCaptureCallback();

			m_bIsSnap = false;
		}
	}
	catch (CGalaxyException& e)
	{

	}
	catch (exception& e)
	{
	}

	try
	{
		//判断是否关闭设备
		if (m_bIsOpen)
		{
			//关闭流对象
			m_ObjStreamPtr->Close();

			//关闭设备
			m_ObjDevicePtr->Close();

			m_bIsOpen = false;
		}
	}
	catch (CGalaxyException& e)
	{
	}
	catch (exception& e)
	{
	}

	try
	{
		//释放设备资源
		IGXFactory::GetInstance().Uninit();
	}
	catch (CGalaxyException& e)
	{
	}
	catch (exception& e)
	{
	}

	if (m_pCaptureEventHandler != NULL)
	{
		delete m_pCaptureEventHandler;
		m_pCaptureEventHandler = NULL;
	}

	event->accept();
}

5.运行效果

 因为目前我只有一个黑白相机,没办法测试彩色相机是否可行。

6.下载链接

基于Qt大恒工业相机二次开发demo-C++-QT文档类资源-CSDN下载基于Qt大恒工业相机二次开发demo-C++,重写的CGXBitmap类,移植性强更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/qq_42816065/85043886

7.双相机代码移植Qt版

 可以实现两个相机的同步采集和图片保存,有兴趣的也可以下载查看使用,该项目需要自己重新配置属性。

大恒双相机C++QT工程文件建议使用Release调试-QT文档类资源-CSDN下载大恒双相机C++QT工程文件建议使用Release调试更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/qq_42816065/85043927

  • 11
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值