Files
HPPA/HPPA/SingleLensReflexCameraWindow.cpp
tangchao0503 e8ae6aa3b9 add
单反相机:实现1s拍照,并将照片传回控制电脑
2026-05-26 14:54:50 +08:00

545 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "SingleLensReflexCameraWindow.h"
#include <QMessageBox>
#include <QCoreApplication>
// 全局变量用于回调函数访问
static SingleLensReflexCameraOperation* g_cameraOperation = nullptr;
SingleLensReflexCameraWindow::SingleLensReflexCameraWindow(QWidget* parent)
: QDialog(parent)
{
ui.setupUi(this);
m_SLRCameraThread = new QThread();
m_SingleLensReflexCameraOperation = new SingleLensReflexCameraOperation();
m_SingleLensReflexCameraOperation->moveToThread(m_SLRCameraThread);
m_SLRCameraThread->start();
connect(ui.openSLRCamera_btn, &QPushButton::clicked, this, &SingleLensReflexCameraWindow::openSLRCamera);
connect(ui.closeSLRCamera_btn, &QPushButton::clicked, this, &SingleLensReflexCameraWindow::closeSLRCamera);
connect(this, &SingleLensReflexCameraWindow::closeSLRCameraSignal, m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CloseSLRCamera);
connect(this, &SingleLensReflexCameraWindow::openSLRCameraSignal, m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::OpenSLRCamera);
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CamOpenedSignal, this, &SingleLensReflexCameraWindow::onCamOpened);
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CamClosedSignal, this, &SingleLensReflexCameraWindow::onCamClosed);
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::PlotSignal, this, &SingleLensReflexCameraWindow::PlotSLRImageSignal);
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CamClosedSignal, this, &SingleLensReflexCameraWindow::SLRCamClosedSignal);
// 新增信号连接
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::ImageCapturedSignal, this, &SingleLensReflexCameraWindow::onImageCaptured);
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::ErrorSignal, this, &SingleLensReflexCameraWindow::onError);
// 初始化按钮状态
ui.closeSLRCamera_btn->setEnabled(false);
}
SingleLensReflexCameraWindow::~SingleLensReflexCameraWindow()
{
// 先停止拍照
if (m_SingleLensReflexCameraOperation->getRecordStatus())
{
m_SingleLensReflexCameraOperation->CloseSLRCamera();
}
m_SLRCameraThread->quit();
m_SLRCameraThread->wait();
delete m_SingleLensReflexCameraOperation;
m_SingleLensReflexCameraOperation = nullptr;
}
void SingleLensReflexCameraWindow::openSLRCamera()
{
if (!m_SingleLensReflexCameraOperation->getRecordStatus())
{
emit openSLRCameraSignal();
}
}
void SingleLensReflexCameraWindow::onCamOpened()
{
ui.openSLRCamera_btn->setEnabled(false);
ui.closeSLRCamera_btn->setEnabled(true);
ui.openSLRCamera_btn->setText(QString::fromLocal8Bit("已打开"));
}
void SingleLensReflexCameraWindow::closeSLRCamera()
{
emit closeSLRCameraSignal();
//m_SingleLensReflexCameraOperation->CloseSLRCamera();
}
void SingleLensReflexCameraWindow::onCamClosed()
{
ui.openSLRCamera_btn->setEnabled(true);
ui.closeSLRCamera_btn->setEnabled(false);
ui.openSLRCamera_btn->setText(QString::fromLocal8Bit("打 开"));
}
void SingleLensReflexCameraWindow::onImageCaptured(const QString& filePath)
{
std::cout << "Image captured: " << filePath.toStdString() << std::endl;
// 可以在这里更新UI显示最新拍摄的图片
}
void SingleLensReflexCameraWindow::onError(const QString& errorMsg)
{
QMessageBox::warning(this, QString::fromLocal8Bit("相机错误"), errorMsg);
}
//-------------------------------------------------------------------------------------------------------------------------------
// SingleLensReflexCameraOperation 实现
//-------------------------------------------------------------------------------------------------------------------------------
SingleLensReflexCameraOperation::SingleLensReflexCameraOperation()
{
m_func = nullptr;
record = false;
m_camera = nullptr;
m_isSDKInitialized = false;
m_isSessionOpen = false;
m_captureTimer = nullptr;
m_imageCounter = 0;
// 设置保存路径(可以根据需要修改)
m_savePath = QCoreApplication::applicationDirPath() + "/CapturedImages/";
// 创建保存目录
QDir dir;
if (!dir.exists(m_savePath))
{
dir.mkpath(m_savePath);
}
g_cameraOperation = this;
}
SingleLensReflexCameraOperation::~SingleLensReflexCameraOperation()
{
if (record)
{
CloseSLRCamera();
}
g_cameraOperation = nullptr;
}
EdsError SingleLensReflexCameraOperation::initializeSDK()
{
EdsError err = EdsInitializeSDK();
if (err == EDS_ERR_OK)
{
m_isSDKInitialized = true;
std::cout << "EDSDK initialized successfully" << std::endl;
}
else
{
std::cout << "Failed to initialize EDSDK, error: " << err << std::endl;
}
return err;
}
EdsError SingleLensReflexCameraOperation::terminateSDK()
{
if (m_isSDKInitialized)
{
EdsError err = EdsTerminateSDK();
m_isSDKInitialized = false;
std::cout << "EDSDK terminated" << std::endl;
return err;
}
return EDS_ERR_OK;
}
EdsError SingleLensReflexCameraOperation::openCamera()
{
EdsError err = EDS_ERR_OK;
EdsCameraListRef cameraList = nullptr;
EdsUInt32 count = 0;
// 获取相机列表
err = EdsGetCameraList(&cameraList);
if (err != EDS_ERR_OK)
{
std::cout << "Failed to get camera list, error: " << err << std::endl;
return err;
}
// 获取相机数量
err = EdsGetChildCount(cameraList, &count);
if (err != EDS_ERR_OK || count == 0)
{
std::cout << "No camera found" << std::endl;
EdsRelease(cameraList);
return EDS_ERR_DEVICE_NOT_FOUND;
}
std::cout << "Found " << count << " camera(s)" << std::endl;
// 获取第一台相机
err = EdsGetChildAtIndex(cameraList, 0, &m_camera);
if (err != EDS_ERR_OK)
{
std::cout << "Failed to get camera, error: " << err << std::endl;
EdsRelease(cameraList);
return err;
}
// 释放相机列表
EdsRelease(cameraList);
// 设置事件回调
err = EdsSetObjectEventHandler(m_camera, kEdsObjectEvent_All, handleObjectEvent, this);
if (err != EDS_ERR_OK)
{
std::cout << "Failed to set object event handler, error: " << err << std::endl;
}
err = EdsSetPropertyEventHandler(m_camera, kEdsPropertyEvent_All, handlePropertyEvent, this);
if (err != EDS_ERR_OK)
{
std::cout << "Failed to set property event handler, error: " << err << std::endl;
}
err = EdsSetCameraStateEventHandler(m_camera, kEdsStateEvent_All, handleStateEvent, this);
if (err != EDS_ERR_OK)
{
std::cout << "Failed to set state event handler, error: " << err << std::endl;
}
// 打开会话
err = EdsOpenSession(m_camera);
if (err != EDS_ERR_OK)
{
std::cout << "Failed to open session, error: " << err << std::endl;
EdsRelease(m_camera);
m_camera = nullptr;
return err;
}
m_isSessionOpen = true;
std::cout << "Camera session opened successfully" << std::endl;
return EDS_ERR_OK;
}
EdsError SingleLensReflexCameraOperation::closeCamera()
{
EdsError err = EDS_ERR_OK;
if (m_isSessionOpen && m_camera != nullptr)
{
err = EdsCloseSession(m_camera);
m_isSessionOpen = false;
std::cout << "Camera session closed" << std::endl;
}
if (m_camera != nullptr)
{
EdsRelease(m_camera);
m_camera = nullptr;
}
return err;
}
EdsError SingleLensReflexCameraOperation::setupSaveToHost()
{
EdsError err = EDS_ERR_OK;
// 设置保存到PC
EdsUInt32 saveTo = kEdsSaveTo_Host;
err = EdsSetPropertyData(m_camera, kEdsPropID_SaveTo, 0, sizeof(saveTo), &saveTo);
if (err != EDS_ERR_OK)
{
std::cout << "Failed to set SaveTo property, error: " << err << std::endl;
return err;
}
// 设置PC容量告诉相机PC有足够空间
EdsCapacity capacity;
capacity.numberOfFreeClusters = 0x7FFFFFFF;
capacity.bytesPerSector = 0x1000;
capacity.reset = true;
err = EdsSetCapacity(m_camera, capacity);
if (err != EDS_ERR_OK)
{
std::cout << "Failed to set capacity, error: " << err << std::endl;
return err;
}
std::cout << "Save to host configured successfully" << std::endl;
return EDS_ERR_OK;
}
EdsError SingleLensReflexCameraOperation::takePicture()
{
EdsError err = EDS_ERR_OK;
// 按下快门
err = EdsSendCommand(m_camera, kEdsCameraCommand_PressShutterButton, kEdsCameraCommand_ShutterButton_Completely);
if (err != EDS_ERR_OK)
{
std::cout << "Failed to press shutter button, error: " << err << std::endl;
return err;
}
// 释放快门
err = EdsSendCommand(m_camera, kEdsCameraCommand_PressShutterButton, kEdsCameraCommand_ShutterButton_OFF);
if (err != EDS_ERR_OK)
{
std::cout << "Failed to release shutter button, error: " << err << std::endl;
return err;
}
std::cout << "Picture taken" << std::endl;
return EDS_ERR_OK;
}
EdsError SingleLensReflexCameraOperation::downloadImage(EdsDirectoryItemRef directoryItem)
{
EdsError err = EDS_ERR_OK;
EdsStreamRef stream = nullptr;
EdsDirectoryItemInfo dirItemInfo;
// 获取文件信息
err = EdsGetDirectoryItemInfo(directoryItem, &dirItemInfo);
if (err != EDS_ERR_OK)
{
std::cout << "Failed to get directory item info, error: " << err << std::endl;
return err;
}
// 生成保存文件名(使用时间戳)
QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss_zzz");
QString fileName = m_savePath + "IMG_" + timestamp + "_" + QString::fromLocal8Bit(dirItemInfo.szFileName);
std::cout << "Downloading image to: " << fileName.toStdString() << std::endl;
// 创建文件流
err = EdsCreateFileStream(fileName.toLocal8Bit().constData(),
kEdsFileCreateDisposition_CreateAlways,
kEdsAccess_ReadWrite, &stream);
if (err != EDS_ERR_OK)
{
std::cout << "Failed to create file stream, error: " << err << std::endl;
return err;
}
// 下载图像
err = EdsDownload(directoryItem, dirItemInfo.size, stream);
if (err != EDS_ERR_OK)
{
std::cout << "Failed to download image, error: " << err << std::endl;
EdsRelease(stream);
return err;
}
// 通知下载完成
err = EdsDownloadComplete(directoryItem);
if (err != EDS_ERR_OK)
{
std::cout << "Failed to complete download, error: " << err << std::endl;
}
// 释放流
EdsRelease(stream);
std::cout << "Image downloaded successfully: " << fileName.toStdString() << std::endl;
// 发送信号通知图片已保存
emit ImageCapturedSignal(fileName);
return EDS_ERR_OK;
}
// 静态回调函数实现
EdsError EDSCALLBACK SingleLensReflexCameraOperation::handleObjectEvent(EdsObjectEvent event, EdsBaseRef object, EdsVoid* context)
{
SingleLensReflexCameraOperation* pThis = static_cast<SingleLensReflexCameraOperation*>(context);
switch (event)
{
case kEdsObjectEvent_DirItemRequestTransfer:
// 有图像需要传输
if (pThis != nullptr)
{
pThis->downloadImage(object);
}
break;
case kEdsObjectEvent_DirItemCreated:
std::cout << "New file created on camera" << std::endl;
break;
default:
break;
}
// 释放对象
if (object)
{
EdsRelease(object);
}
return EDS_ERR_OK;
}
EdsError EDSCALLBACK SingleLensReflexCameraOperation::handlePropertyEvent(EdsPropertyEvent event, EdsPropertyID property, EdsUInt32 param, EdsVoid* context)
{
switch (event)
{
case kEdsPropertyEvent_PropertyChanged:
// 属性已更改
break;
default:
break;
}
return EDS_ERR_OK;
}
EdsError EDSCALLBACK SingleLensReflexCameraOperation::handleStateEvent(EdsStateEvent event, EdsUInt32 parameter, EdsVoid* context)
{
SingleLensReflexCameraOperation* pThis = static_cast<SingleLensReflexCameraOperation*>(context);
switch (event)
{
case kEdsStateEvent_Shutdown:
std::cout << "Camera disconnected" << std::endl;
if (pThis != nullptr && pThis->record)
{
pThis->CloseSLRCamera();
}
break;
case kEdsStateEvent_WillSoonShutDown:
// 相机即将自动关机,延长计时器
if (pThis != nullptr && pThis->m_camera != nullptr)
{
EdsSendCommand(pThis->m_camera, kEdsCameraCommand_ExtendShutDownTimer, 0);
}
break;
default:
break;
}
return EDS_ERR_OK;
}
void SingleLensReflexCameraOperation::OpenSLRCamera()
{
std::cout << "SingleLensReflexCameraOperation::OpenSLRCamera, 打开单反相机" << std::endl;
EdsError err = EDS_ERR_OK;
// 初始化SDK
err = initializeSDK();
if (err != EDS_ERR_OK)
{
emit ErrorSignal(QString::fromLocal8Bit("初始化SDK失败错误码: %1").arg(err));
return;
}
// 打开相机
err = openCamera();
if (err != EDS_ERR_OK)
{
terminateSDK();
emit ErrorSignal(QString::fromLocal8Bit("打开相机失败,错误码: %1").arg(err));
return;
}
// 设置保存到PC
err = setupSaveToHost();
if (err != EDS_ERR_OK)
{
closeCamera();
terminateSDK();
emit ErrorSignal(QString::fromLocal8Bit("设置保存位置失败,错误码: %1").arg(err));
return;
}
record = true;
// 创建并启动定时器1秒拍一张
m_captureTimer = new QTimer(this);
connect(m_captureTimer, &QTimer::timeout, this, &SingleLensReflexCameraOperation::onCaptureTimer);
m_captureTimer->start(2000); // 1000毫秒 = 1秒
emit CamOpenedSignal();
std::cout << "Camera opened and timer started (1 photo per second)" << std::endl;
}
void SingleLensReflexCameraOperation::OpenSLRCamera_callback()
{
// 不使用信号而使用回调函数来通知界面刷新视频
}
void SingleLensReflexCameraOperation::setCallback(void(*func)())
{
m_func = func;
}
void SingleLensReflexCameraOperation::onCaptureTimer()
{
if (!record)
{
return;
}
QMutexLocker locker(&m_mutex);
// 处理相机事件(重要:需要定期调用以接收回调)
EdsGetEvent();
// 拍照
EdsError err = takePicture();
if (err != EDS_ERR_OK)
{
std::cout << "Failed to take picture, error: " << err << std::endl;
// 如果是设备忙,不发送错误信号,等待下次重试
if (err != EDS_ERR_DEVICE_BUSY)
{
emit ErrorSignal(QString::fromLocal8Bit("拍照失败,错误码: %1").arg(err));
}
}
m_imageCounter++;
std::cout << "Total pictures taken: " << m_imageCounter << std::endl;
}
void SingleLensReflexCameraOperation::CloseSLRCamera()
{
std::cout << "SingleLensReflexCameraOperation::CloseSLRCamera关闭单反相机" << std::endl;
QMutexLocker locker(&m_mutex);
record = false;
// 停止定时器
if (m_captureTimer != nullptr)
{
m_captureTimer->stop();
delete m_captureTimer;
m_captureTimer = nullptr;
}
// 处理剩余事件
for (int i = 0; i < 10; i++)
{
EdsGetEvent();
QThread::msleep(100);
}
// 关闭相机
closeCamera();
// 终止SDK
terminateSDK();
std::cout << "Camera closed, total pictures: " << m_imageCounter << std::endl;
m_imageCounter = 0;
emit CamClosedSignal();
}