目录
- 引言
- 核心代码
- 完整代码
引言
本文是简单使用Qt快速使用摄像头完成截图等工作,主要涉及QCamera、QCameraViewfinder、QCameraImageCapture这三个类。QCamera通过相机的信息创建,用于控制开始接收图形、停止接收图像。QCameraViewfinder则是图像的展示窗口,相当于View的作用。QCameraImageCapture用于截图操作,也是本文的主要目的。
核心代码
首先肯定是获取可使用的相机列表,可以通过静态函数获取,如下所示:
// 初始化设备列表
const QList<QCameraInfo> availableCameras = QCameraInfo::availableCameras();
for(int i=0; i< availableCameras.count(); i++){
QCameraInfo cameraInfo = availableCameras.at(i);
m_combox->addItem(cameraInfo.description(), QVariant::fromValue(cameraInfo));
if (cameraInfo == QCameraInfo::defaultCamera())
m_combox->setCurrentIndex(i);
}
然后就是通过获取的QCameraInfo去初始化QCamera,不同的相机信息都需要重写构造一个QCamera对象,建议使用智能指针,避免出现内存问题,如下所示:
void UsbCameraDialog::setCamera(const QCameraInfo &cameraInfo)
{
m_camera.reset(new QCamera(cameraInfo));
m_camera->setViewfinder(m_viewfinder);
// 截图
m_imageCapture.reset(new QCameraImageCapture(m_camera.data()));
connect(m_imageCapture.data(), &QCameraImageCapture::readyForCaptureChanged, this, &UsbCameraDialog::readyForCapture);
connect(m_imageCapture.data(), &QCameraImageCapture::imageCaptured, this, &UsbCameraDialog::processCapturedImage);
connect(m_imageCapture.data(), &QCameraImageCapture::imageSaved, this, &UsbCameraDialog::imageSaved);
connect(m_imageCapture.data(), QOverload<int, QCameraImageCapture::Error, const QString &>::of(&QCameraImageCapture::error),
this, &UsbCameraDialog::displayCaptureError);
}
完整代码
#include <QDialog>
#include <QScopedPointer>
#include <QCameraImageCapture>
class QPushButton;
class QComboBox;
class QCamera;
class QCameraViewfinder;
class QCameraInfo;
class UsbCameraDialog : public QDialog
{
Q_OBJECT
public:
explicit UsbCameraDialog(QWidget *parent = nullptr);
~UsbCameraDialog();
signals:
void sig_processCapturedImage(const QImage& img);
protected:
void showEvent(QShowEvent *event) override;
void hideEvent(QHideEvent *event) override;
private:
void setCamera(const QCameraInfo &cameraInfo);
private slots:
void readyForCapture(bool ready);
void processCapturedImage(int requestId, const QImage &img);
void imageSaved(int id, const QString &fileName);
void displayCaptureError(int, QCameraImageCapture::Error, const QString &errorString);
private:
QCameraViewfinder *m_viewfinder;
QPushButton *m_startBtn;
QPushButton *m_stopBtn;
QComboBox *m_combox;
QPushButton *m_snapBtn;
QScopedPointer<QCamera> m_camera;
QScopedPointer<QCameraImageCapture> m_imageCapture;
};
#include <QCameraViewfinder>
#include <QCamera>
#include <QCameraInfo>
#include <QPushButton>
#include <QComboBox>
#include <QVBoxLayout>
#include <QAction>
#include <QMessageBox>
#include <QDir>
#include <QDebug>
Q_DECLARE_METATYPE(QCameraInfo)
UsbCameraDialog::UsbCameraDialog(QWidget *parent) : QDialog(parent)
{
setFixedSize(600, 450);
m_viewfinder = new QCameraViewfinder(this);
m_startBtn = new QPushButton("start", this);
connect(m_startBtn, &QPushButton::clicked, this, [this] {
m_camera->start();
});
m_stopBtn = new QPushButton("stop", this);
connect(m_stopBtn, &QPushButton::clicked, this, [this] {
m_camera->stop();
});
m_combox = new QComboBox(this);
connect(m_combox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](){
setCamera(m_combox->currentData().value<QCameraInfo>());
});
// 初始化设备列表
const QList<QCameraInfo> availableCameras = QCameraInfo::availableCameras();
for(int i=0; i< availableCameras.count(); i++){
QCameraInfo cameraInfo = availableCameras.at(i);
m_combox->addItem(cameraInfo.description(), QVariant::fromValue(cameraInfo));
if (cameraInfo == QCameraInfo::defaultCamera())
m_combox->setCurrentIndex(i);
}
m_snapBtn = new QPushButton("snap", this);
connect(m_snapBtn, &QPushButton::clicked, this, [this] {
m_imageCapture->capture("capture.jpg");
});
// 布局
auto buttonLayout = new QHBoxLayout;
buttonLayout->addWidget(m_combox);
buttonLayout->addWidget(m_startBtn);
buttonLayout->addWidget(m_stopBtn);
auto mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(m_viewfinder);
mainLayout->addLayout(buttonLayout);
mainLayout->addWidget(m_snapBtn);
}
UsbCameraDialog::~UsbCameraDialog()
{
}
void UsbCameraDialog::showEvent(QShowEvent *)
{
if(m_combox->count()){
setCamera(m_combox->currentData().value<QCameraInfo>());
m_camera->start();
}
}
void UsbCameraDialog::hideEvent(QHideEvent *)
{
if(m_camera){
m_camera->stop();
}
}
void UsbCameraDialog::setCamera(const QCameraInfo &cameraInfo)
{
m_camera.reset(new QCamera(cameraInfo));
m_camera->setViewfinder(m_viewfinder);
m_imageCapture.reset(new QCameraImageCapture(m_camera.data()));
connect(m_imageCapture.data(), &QCameraImageCapture::readyForCaptureChanged, this, &UsbCameraDialog::readyForCapture);
connect(m_imageCapture.data(), &QCameraImageCapture::imageCaptured, this, &UsbCameraDialog::processCapturedImage);
connect(m_imageCapture.data(), &QCameraImageCapture::imageSaved, this, &UsbCameraDialog::imageSaved);
connect(m_imageCapture.data(), QOverload<int, QCameraImageCapture::Error, const QString &>::of(&QCameraImageCapture::error),
this, &UsbCameraDialog::displayCaptureError);
}
void UsbCameraDialog::readyForCapture(bool ready)
{
m_snapBtn->setEnabled(ready);
}
void UsbCameraDialog::processCapturedImage(int requestId, const QImage &img)
{
Q_UNUSED(requestId);
emit sig_processCapturedImage(img);
close();
}
void UsbCameraDialog::imageSaved(int id, const QString &fileName)
{
Q_UNUSED(id);
qDebug() << fileName;
}
void UsbCameraDialog::displayCaptureError(int id, QCameraImageCapture::Error error, const QString &errorString)
{
Q_UNUSED(id);
Q_UNUSED(error);
QMessageBox::warning(this, QString("Image Capture Error"), errorString);
}
#include <QLabel>
#include <QPushButton>
#include <QHBoxLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
auto label = new QLabel("This is label", this);
label->setFixedSize(150, 200);
label->setStyleSheet("QLabel {border: 1px solid black;}");
m_cameraDlg = new UsbCameraDialog(this);
connect(m_cameraDlg, &UsbCameraDialog::sig_processCapturedImage, this, [=](const QImage &img) {
QImage scaledImage = img.scaled(label->size(),
Qt::KeepAspectRatio,
Qt::SmoothTransformation);
label->setPixmap(QPixmap::fromImage(scaledImage));
});
auto btn = new QPushButton("+", label);
btn->setFixedSize(40, 40);
btn->move(0, label->height() - btn->height());
connect(btn, &QPushButton::clicked, this, [this] {
m_cameraDlg->show();
});
auto main_widget = new QWidget(this);
main_widget->setLayout(new QHBoxLayout);
main_widget->layout()->addWidget(label);
setCentralWidget(main_widget);
}