From 0f292e7821b809df77de443dd30148a609cc4f49 Mon Sep 17 00:00:00 2001 From: Kieran Bingham 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 Reviewed-by: Laurent Pinchart --- 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/qcam') 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 @@ ./play-circle.svg +./save.svg ./stop-circle.svg ./x-circle.svg 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 #include +#include #include +#include +#include #include #include #include @@ -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 +#include +#include #include #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 #include #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