From patchwork Sat May 2 02:10:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 3660 Return-Path: Received: from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net [195.74.38.228]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 361CF61459 for ; Sat, 2 May 2020 04:11:24 +0200 (CEST) X-Halon-ID: 3806cd68-8c1a-11ea-aeed-005056917f90 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (p4fca2392.dip0.t-ipconnect.de [79.202.35.146]) by bin-vsp-out-02.atm.binero.net (Halon) with ESMTPA id 3806cd68-8c1a-11ea-aeed-005056917f90; Sat, 02 May 2020 04:11:22 +0200 (CEST) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 2 May 2020 04:10:45 +0200 Message-Id: <20200502021045.785979-4-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200502021045.785979-1-niklas.soderlund@ragnatech.se> References: <20200502021045.785979-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 3/3] qcam: Add RAW capture support X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 02 May 2020 02:11:25 -0000 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 Reviewed-by: Laurent Pinchart --- * Changes since v2 - Use a file dialog - Make DNG optional depending on libtiff --- src/qcam/assets/feathericons/feathericons.qrc | 1 + src/qcam/main_window.cpp | 64 ++++++++++++++++++- src/qcam/main_window.h | 4 ++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/qcam/assets/feathericons/feathericons.qrc b/src/qcam/assets/feathericons/feathericons.qrc index c4eb7a0be6884373..fc8213928ece70ea 100644 --- a/src/qcam/assets/feathericons/feathericons.qrc +++ b/src/qcam/assets/feathericons/feathericons.qrc @@ -1,5 +1,6 @@ +./aperture.svg ./camera-off.svg ./play-circle.svg ./save.svg diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index 0bd9f3583ea4f6d4..458da479a9b21b73 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -27,6 +27,10 @@ #include #include +#if HAVE_TIFF +#include "dng_writer.h" +#endif + using namespace libcamera; /** @@ -48,7 +52,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 +149,16 @@ int MainWindow::createToolbars() action->setShortcut(QKeySequence::SaveAs); connect(action, &QAction::triggered, this, &MainWindow::saveImageAs); +#if HAVE_TIFF + /* 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 +384,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 +493,9 @@ void MainWindow::stopCapture() return; viewfinder_->stop(); + if (saveRaw_) + saveRaw_->setEnabled(false); + captureRaw_ = false; int ret = camera_->stop(); if (ret) @@ -524,6 +546,31 @@ void MainWindow::saveImageAs() writer.write(image); } +void MainWindow::captureRaw() +{ + captureRaw_ = true; +} + +void MainWindow::processRaw(FrameBuffer *buffer) +{ +#if HAVE_TIFF + QString defaultPath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); + QString filename = QFileDialog::getSaveFileName(this, "Save DNG", defaultPath, + "DNG Files (*.dng)"); + + if (filename != "") { + 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 +613,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 +648,17 @@ void MainWindow::queueRequest(FrameBuffer *buffer) request->addBuffer(vfStream_, buffer); + if (captureRaw_) { + QMutexLocker locker(&mutex_); + + if (!freeBuffers_[rawStream_].isEmpty()) { + request->addBuffer(rawStream_, + freeBuffers_[rawStream_].dequeue()); + 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 4856ecc10729159c..295ecc537e9d45bf 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> freeBuffers_;