mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-21 03:15:06 +03:00
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:
parent
2dc85eabe1
commit
0f292e7821
5 changed files with 47 additions and 0 deletions
|
@ -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>
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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__ */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue