diff options
author | Niklas Söderlund <niklas.soderlund@ragnatech.se> | 2020-04-29 16:59:15 +0200 |
---|---|---|
committer | Niklas Söderlund <niklas.soderlund@ragnatech.se> | 2020-05-02 14:46:20 +0200 |
commit | b20eb8ffb5f91788a1412928058cbc9304b8144b (patch) | |
tree | 6e351a0ed5835773425ec3e9e5f20448feeab4b6 | |
parent | db7235b7141aa4e2922827b4678e25da4faa8c5d (diff) |
qcam: Add RAW capture support
Add a toolbar button that captures RAW data to disk. The button is only
enabled if the camera is configured to provide a raw stream to the
application.
Only when the capture action is triggered will a request with a raw
buffer be queued to the camera.
Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r-- | src/qcam/assets/feathericons/feathericons.qrc | 1 | ||||
-rw-r--r-- | src/qcam/main_window.cpp | 68 | ||||
-rw-r--r-- | src/qcam/main_window.h | 4 |
3 files changed, 72 insertions, 1 deletions
diff --git a/src/qcam/assets/feathericons/feathericons.qrc b/src/qcam/assets/feathericons/feathericons.qrc index c4eb7a0b..fc821392 100644 --- a/src/qcam/assets/feathericons/feathericons.qrc +++ b/src/qcam/assets/feathericons/feathericons.qrc @@ -1,5 +1,6 @@ <!DOCTYPE RCC><RCC version="1.0"> <qresource> +<file>./aperture.svg</file> <file>./camera-off.svg</file> <file>./play-circle.svg</file> <file>./save.svg</file> diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index 0bd9f358..8720c6c6 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -27,6 +27,8 @@ #include <libcamera/camera_manager.h> #include <libcamera/version.h> +#include "dng_writer.h" + using namespace libcamera; /** @@ -48,7 +50,8 @@ public: }; MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options) - : options_(options), cm_(cm), allocator_(nullptr), isCapturing_(false) + : saveRaw_(nullptr), options_(options), cm_(cm), allocator_(nullptr), + isCapturing_(false), captureRaw_(false) { int ret; @@ -144,6 +147,16 @@ int MainWindow::createToolbars() action->setShortcut(QKeySequence::SaveAs); connect(action, &QAction::triggered, this, &MainWindow::saveImageAs); +#ifdef HAVE_DNG + /* Save Raw action. */ + action = toolbar_->addAction(QIcon::fromTheme("camera-photo", + QIcon(":aperture.svg")), + "Save Raw"); + action->setEnabled(false); + connect(action, &QAction::triggered, this, &MainWindow::captureRaw); + saveRaw_ = action; +#endif + return 0; } @@ -369,6 +382,10 @@ int MainWindow::startCapture() adjustSize(); + /* Configure the raw capture button. */ + if (saveRaw_) + saveRaw_->setEnabled(config_->size() == 2); + /* Allocate and map buffers. */ allocator_ = new FrameBufferAllocator(camera_); for (StreamConfiguration &config : *config_) { @@ -474,6 +491,9 @@ void MainWindow::stopCapture() return; viewfinder_->stop(); + if (saveRaw_) + saveRaw_->setEnabled(false); + captureRaw_ = false; int ret = camera_->stop(); if (ret) @@ -524,6 +544,32 @@ void MainWindow::saveImageAs() writer.write(image); } +void MainWindow::captureRaw() +{ + captureRaw_ = true; +} + +void MainWindow::processRaw(FrameBuffer *buffer) +{ +#ifdef HAVE_DNG + QString defaultPath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); + QString filename = QFileDialog::getSaveFileName(this, "Save DNG", defaultPath, + "DNG Files (*.dng)"); + + if (!filename.isEmpty()) { + const MappedBuffer &mapped = mappedBuffers_[buffer]; + DNGWriter::write(filename.toStdString().c_str(), camera_.get(), + rawStream_->configuration(), buffer, + mapped.memory); + } +#endif + + { + QMutexLocker locker(&mutex_); + freeBuffers_[rawStream_].enqueue(buffer); + } +} + /* ----------------------------------------------------------------------------- * Request Completion Handling */ @@ -566,6 +612,9 @@ void MainWindow::processCapture() /* Process buffers. */ if (buffers.count(vfStream_)) processViewfinder(buffers[vfStream_]); + + if (buffers.count(rawStream_)) + processRaw(buffers[rawStream_]); } void MainWindow::processViewfinder(FrameBuffer *buffer) @@ -598,5 +647,22 @@ void MainWindow::queueRequest(FrameBuffer *buffer) request->addBuffer(vfStream_, buffer); + if (captureRaw_) { + FrameBuffer *buffer = nullptr; + + { + QMutexLocker locker(&mutex_); + if (!freeBuffers_[rawStream_].isEmpty()) + buffer = freeBuffers_[rawStream_].dequeue(); + } + + if (buffer) { + request->addBuffer(rawStream_, buffer); + captureRaw_ = false; + } else { + qWarning() << "No free buffer available for RAW capture"; + } + } + camera_->queueRequest(request); } diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h index 4856ecc1..295ecc53 100644 --- a/src/qcam/main_window.h +++ b/src/qcam/main_window.h @@ -55,6 +55,8 @@ private Q_SLOTS: void toggleCapture(bool start); void saveImageAs(); + void captureRaw(); + void processRaw(FrameBuffer *buffer); void queueRequest(FrameBuffer *buffer); @@ -75,6 +77,7 @@ private: QToolBar *toolbar_; QAction *startStopAction_; QComboBox *cameraCombo_; + QAction *saveRaw_; ViewFinder *viewfinder_; QIcon iconPlay_; @@ -96,6 +99,7 @@ private: /* Capture state, buffers queue and statistics */ bool isCapturing_; + bool captureRaw_; Stream *vfStream_; Stream *rawStream_; std::map<Stream *, QQueue<FrameBuffer *>> freeBuffers_; |