From 0f292e7821b809df77de443dd30148a609cc4f49 Mon Sep 17 00:00:00 2001
From: Kieran Bingham <kieran.bingham@ideasonboard.com>
Date: Wed, 5 Feb 2020 16:02:05 +0000
Subject: 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>
---
 src/qcam/assets/feathericons/feathericons.qrc |  1 +
 src/qcam/main_window.cpp                      | 22 ++++++++++++++++++++++
 src/qcam/main_window.h                        |  2 ++
 src/qcam/viewfinder.cpp                       | 17 +++++++++++++++++
 src/qcam/viewfinder.h                         |  5 +++++
 5 files changed, 47 insertions(+)

(limited to 'src')

diff --git a/src/qcam/assets/feathericons/feathericons.qrc b/src/qcam/assets/feathericons/feathericons.qrc
index b8e5c226..6ca3a846 100644
--- a/src/qcam/assets/feathericons/feathericons.qrc
+++ b/src/qcam/assets/feathericons/feathericons.qrc
@@ -1,6 +1,7 @@
 <!DOCTYPE RCC><RCC version="1.0">
 <qresource>
 <file>./play-circle.svg</file>
+<file>./save.svg</file>
 <file>./stop-circle.svg</file>
 <file>./x-circle.svg</file>
 </qresource>
diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp
index f76890e7..29eaba84 100644
--- a/src/qcam/main_window.cpp
+++ b/src/qcam/main_window.cpp
@@ -12,7 +12,10 @@
 
 #include <QComboBox>
 #include <QCoreApplication>
+#include <QFileDialog>
 #include <QIcon>
+#include <QImage>
+#include <QImageWriter>
 #include <QInputDialog>
 #include <QTimer>
 #include <QToolBar>
@@ -88,6 +91,9 @@ int MainWindow::createToolbars()
 	action = toolbar_->addAction(QIcon(":stop-circle.svg"), "stop");
 	connect(action, &QAction::triggered, this, &MainWindow::stopCapture);
 
+	action = toolbar_->addAction(QIcon(":save.svg"), "saveAs");
+	connect(action, &QAction::triggered, this, &MainWindow::saveImageAs);
+
 	return 0;
 }
 
@@ -339,6 +345,22 @@ void MainWindow::stopCapture()
 	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)
 {
 	if (request->status() == Request::RequestCancelled)
diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h
index 27ceed61..40aa10aa 100644
--- a/src/qcam/main_window.h
+++ b/src/qcam/main_window.h
@@ -49,6 +49,8 @@ private Q_SLOTS:
 	int startCapture();
 	void stopCapture();
 
+	void saveImageAs();
+
 private:
 	int createToolbars();
 	std::string chooseCamera();
diff --git a/src/qcam/viewfinder.cpp b/src/qcam/viewfinder.cpp
index 6de284d1..d51eebb1 100644
--- a/src/qcam/viewfinder.cpp
+++ b/src/qcam/viewfinder.cpp
@@ -6,6 +6,8 @@
  */
 
 #include <QImage>
+#include <QImageWriter>
+#include <QMutexLocker>
 #include <QPainter>
 
 #include "format_converter.h"
@@ -23,10 +25,25 @@ ViewFinder::~ViewFinder()
 
 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_);
 	update();
 }
 
+QImage ViewFinder::getCurrentImage()
+{
+	QMutexLocker locker(&mutex_);
+
+	return image_->copy();
+}
+
 int ViewFinder::setFormat(unsigned int format, unsigned int width,
 			  unsigned int height)
 {
diff --git a/src/qcam/viewfinder.h b/src/qcam/viewfinder.h
index ef5fd45b..2ba28b60 100644
--- a/src/qcam/viewfinder.h
+++ b/src/qcam/viewfinder.h
@@ -7,6 +7,7 @@
 #ifndef __QCAM_VIEWFINDER_H__
 #define __QCAM_VIEWFINDER_H__
 
+#include <QMutex>
 #include <QWidget>
 
 #include "format_converter.h"
@@ -23,6 +24,8 @@ public:
 		      unsigned int height);
 	void display(const unsigned char *rgb, size_t size);
 
+	QImage getCurrentImage();
+
 protected:
 	void paintEvent(QPaintEvent *) override;
 	QSize sizeHint() const override;
@@ -33,7 +36,9 @@ private:
 	unsigned int height_;
 
 	FormatConverter converter_;
+
 	QImage *image_;
+	QMutex mutex_; /* Prevent concurrent access to image_ */
 };
 
 #endif /* __QCAM_VIEWFINDER__ */
-- 
cgit v1.2.1