qcam: Provide save image functionality

Implement a save image button on the toolbar which will take a current
viewfinder image and present the user with a QFileDialog to allow them
to choose where to save the image.

Utilise the QImageWriter to perform the output task.

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
Kieran Bingham 2020-02-05 16:02:05 +00:00
parent 2dc85eabe1
commit 0f292e7821
5 changed files with 47 additions and 0 deletions

View file

@ -1,6 +1,7 @@
<!DOCTYPE RCC><RCC version="1.0"> <!DOCTYPE RCC><RCC version="1.0">
<qresource> <qresource>
<file>./play-circle.svg</file> <file>./play-circle.svg</file>
<file>./save.svg</file>
<file>./stop-circle.svg</file> <file>./stop-circle.svg</file>
<file>./x-circle.svg</file> <file>./x-circle.svg</file>
</qresource> </qresource>

View file

@ -12,7 +12,10 @@
#include <QComboBox> #include <QComboBox>
#include <QCoreApplication> #include <QCoreApplication>
#include <QFileDialog>
#include <QIcon> #include <QIcon>
#include <QImage>
#include <QImageWriter>
#include <QInputDialog> #include <QInputDialog>
#include <QTimer> #include <QTimer>
#include <QToolBar> #include <QToolBar>
@ -88,6 +91,9 @@ int MainWindow::createToolbars()
action = toolbar_->addAction(QIcon(":stop-circle.svg"), "stop"); action = toolbar_->addAction(QIcon(":stop-circle.svg"), "stop");
connect(action, &QAction::triggered, this, &MainWindow::stopCapture); connect(action, &QAction::triggered, this, &MainWindow::stopCapture);
action = toolbar_->addAction(QIcon(":save.svg"), "saveAs");
connect(action, &QAction::triggered, this, &MainWindow::saveImageAs);
return 0; return 0;
} }
@ -339,6 +345,22 @@ void MainWindow::stopCapture()
setWindowTitle(title_); setWindowTitle(title_);
} }
void MainWindow::saveImageAs()
{
QImage image = viewfinder_->getCurrentImage();
QString filename = QFileDialog::getSaveFileName(this, "Save Image", "",
"Image Files (*.png *.jpg *.jpeg)");
std::cout << "Save image to " << filename.toStdString() << std::endl;
if (filename.isEmpty())
return;
QImageWriter writer(filename);
writer.write(image);
}
void MainWindow::requestComplete(Request *request) void MainWindow::requestComplete(Request *request)
{ {
if (request->status() == Request::RequestCancelled) if (request->status() == Request::RequestCancelled)

View file

@ -49,6 +49,8 @@ private Q_SLOTS:
int startCapture(); int startCapture();
void stopCapture(); void stopCapture();
void saveImageAs();
private: private:
int createToolbars(); int createToolbars();
std::string chooseCamera(); std::string chooseCamera();

View file

@ -6,6 +6,8 @@
*/ */
#include <QImage> #include <QImage>
#include <QImageWriter>
#include <QMutexLocker>
#include <QPainter> #include <QPainter>
#include "format_converter.h" #include "format_converter.h"
@ -23,10 +25,25 @@ ViewFinder::~ViewFinder()
void ViewFinder::display(const unsigned char *raw, size_t size) void ViewFinder::display(const unsigned char *raw, size_t size)
{ {
QMutexLocker locker(&mutex_);
/*
* \todo We're not supposed to block the pipeline handler thread
* for long, implement a better way to save images without
* impacting performances.
*/
converter_.convert(raw, size, image_); converter_.convert(raw, size, image_);
update(); update();
} }
QImage ViewFinder::getCurrentImage()
{
QMutexLocker locker(&mutex_);
return image_->copy();
}
int ViewFinder::setFormat(unsigned int format, unsigned int width, int ViewFinder::setFormat(unsigned int format, unsigned int width,
unsigned int height) unsigned int height)
{ {

View file

@ -7,6 +7,7 @@
#ifndef __QCAM_VIEWFINDER_H__ #ifndef __QCAM_VIEWFINDER_H__
#define __QCAM_VIEWFINDER_H__ #define __QCAM_VIEWFINDER_H__
#include <QMutex>
#include <QWidget> #include <QWidget>
#include "format_converter.h" #include "format_converter.h"
@ -23,6 +24,8 @@ public:
unsigned int height); unsigned int height);
void display(const unsigned char *rgb, size_t size); void display(const unsigned char *rgb, size_t size);
QImage getCurrentImage();
protected: protected:
void paintEvent(QPaintEvent *) override; void paintEvent(QPaintEvent *) override;
QSize sizeHint() const override; QSize sizeHint() const override;
@ -33,7 +36,9 @@ private:
unsigned int height_; unsigned int height_;
FormatConverter converter_; FormatConverter converter_;
QImage *image_; QImage *image_;
QMutex mutex_; /* Prevent concurrent access to image_ */
}; };
#endif /* __QCAM_VIEWFINDER__ */ #endif /* __QCAM_VIEWFINDER__ */