QCameraViewfinder的使用

目录

  • 引言
  • 核心代码
  • 完整代码

引言

本文是简单使用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 
#include 
#include 

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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

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 
#include 
#include 

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);
}

你可能感兴趣的:(数码相机)