mardi 21 juin 2016

Qt and C++ - has any human ever made a program that successfully reads buffer info from a camera?

I have one particular part of a Qt application that is simply supposed to take a photo from a camera and decode a QR code using the qzxing library. However, I for the LIFE of me cannot get the stupid photo out of the stupid buffer! I know the decoding is working well, because if I save the photo to a file and then immediately reload it as a QImage, everything works (except, of course, that the program doesn't block until the image is fully saved, so it'll try to decode a half-image, then on the second attempt, decode the first image... AUGH)!

There are plenty of people out there asking this question, but nobody seems to have a COMPLETE answer. I've been researching and guessing-and-testing for the last six hours and I'm about to pull my hair out. Qt documentation for QCameraImageCapture exists, but doesn't talk about passing the buffer or casting in QImage at all. There are a few answers on SO that have a couple guesses at casting the image into a QImage, and a couple more that talk about finding the buffer, but nobody ANYWHERE has a complete answer - it's all piecemeal. The Qt example documentation isn't even complete, and their example project (broken links abound throughout the web) doesn't discuss WHAT its doing.

Here's a sample of some test code that runs and compiles using a mainwindow.ui with a pushbutton called "pushButton" and a vertical layout called "verticalLayout." What am I doing so wrong?

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QImage>
#include <QCamera>
#include <QCameraInfo>
#include <QCameraViewfinder>
#include <QCameraImageCapture>
#include <qzxing/QZXing.h>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void cameraReceiver(int f,QVideoFrame u);
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
    QCameraViewfinder   *viewfinder;
    QCamera             *invCam;
    QCameraImageCapture *rawImage;
    QZXing              *decoder;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //build camera
    QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
    foreach (const QCameraInfo &cameraInfo, cameras) {
        if (cameraInfo.deviceName() == "/dev/video0")
            invCam = new QCamera(cameraInfo);

    }

    //build decoder
    decoder = new QZXing;
    decoder->setDecoder(QZXing::DecoderFormat_QR_CODE);

    //build viewfinder and link to camera
    viewfinder = new QCameraViewfinder(this);
    viewfinder->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    ui->verticalLayout->addWidget(viewfinder);
    invCam->setViewfinder(viewfinder);

    //build image buffer, set camera mode to capture
    rawImage = new QCameraImageCapture(invCam);
    invCam->setCaptureMode(QCamera::CaptureStillImage);
    invCam->start();
    viewfinder->show();

    connect(rawImage,SIGNAL(imageAvailable(int,QVideoFrame)),this,SLOT(cameraReceiver(int,QVideoFrame)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::cameraReceiver(int f,QVideoFrame u) {

    QImage currentImage(u.bits(), u.width(), u.height(), u.bytesPerLine(), QVideoFrame::imageFormatFromPixelFormat(u.pixelFormat()));
    QString output = decoder->decodeImage(currentImage);
    qDebug() << output;

}

void MainWindow::on_pushButton_clicked()
{
    rawImage->setCaptureDestination(QCameraImageCapture::CaptureToBuffer);
    rawImage->capture();
}

EDIT: Currently on a Linux environment, camera is embedded. The viewfinder displays just fine, and like I said, I can capture image to FILE no problem - the camera is working nicely

EDIT 2: as soon as I post on SO I find the flippin answer:. The "connect" call should use the "imageCaptured" signal: connect(rawImage,SIGNAL(imageCaptured(int,QImage)),this,SLOT(cameraReceiver(int,QImage)));

Then, the buffer has a QImage sitting right in it.

void MainWindow::cameraReceiver(int f,QImage u) {

    QString output = decoder->decodeImage(u);
    qDebug() << output;

}

Aucun commentaire:

Enregistrer un commentaire