From patchwork Thu Feb 6 15:04:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 2787 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 47CBB600FB for ; Thu, 6 Feb 2020 16:05:10 +0100 (CET) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C8978B7D; Thu, 6 Feb 2020 16:05:09 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1581001509; bh=UJkVQsVGvnWAUNkG0qoptPT5FM8CRgTpkacB4zCmKHw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=i6BJE5igwgb/Nt+nnItEBuQBRYSiVS23vfcZEZlY68rmcDUCa9Ut8QqF1y/3WRGNF vT8WiuZEB+lpzuakTRoXfzZXiY1ptx8RqMfGtqyNmGyDZrxndQ6kWAJZDBHRMMAsJi lUqPh1ehHqHRsbSC23r+BS47SQwNmpiNPswEdC44= From: Kieran Bingham To: LibCamera Devel Date: Thu, 6 Feb 2020 15:04:59 +0000 Message-Id: <20200206150504.24204-2-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200206150504.24204-1-kieran.bingham@ideasonboard.com> References: <20200206150504.24204-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/6] qcam: Tie FrameBufferAllocator to stream life 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: Thu, 06 Feb 2020 15:05:10 -0000 The FrameBufferAllocator must be deleted and reconstructed before performing any reconfiguration of the stream. Construct the allocator at startCapture, and destroy it during stopCapture so that we can successfully stop and restart the stream. Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/qcam/main_window.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index df51fa888342..38bc04a23b86 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -37,7 +37,6 @@ MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options) ret = openCamera(cm); if (!ret) { - allocator_ = FrameBufferAllocator::create(camera_); ret = startCapture(); } @@ -50,7 +49,6 @@ MainWindow::~MainWindow() { if (camera_) { stopCapture(); - delete allocator_; camera_->release(); camera_.reset(); } @@ -171,6 +169,7 @@ int MainWindow::startCapture() adjustSize(); + allocator_ = FrameBufferAllocator::create(camera_); ret = allocator_->allocate(stream); if (ret < 0) { std::cerr << "Failed to allocate capture buffers" << std::endl; @@ -255,6 +254,8 @@ void MainWindow::stopCapture() } mappedBuffers_.clear(); + delete allocator_; + isCapturing_ = false; config_.reset(); From patchwork Thu Feb 6 15:05:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 2788 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7A52E600FB for ; Thu, 6 Feb 2020 16:05:10 +0100 (CET) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 234F01227; Thu, 6 Feb 2020 16:05:10 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1581001510; bh=EK7IMDyzHjDuX4N6XYWlzj+eItFvFg/2ZwLUsobG3Dw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lu4b6BjRAQW96rGxPzczx0PkbsgAJn4qXpmCUhcXQM726xnfD/3pyQ2oh8C83Ozx4 OcdULQKQzllKUPCE8fxwSwoba7sWr6PihMmaS4SloKLZqT3UB6WCnLu4JW+q4uw9Un aojiD5BQSbnLaXhaj2dd2/H84Y1Qz2irovK0i1A8= From: Kieran Bingham To: LibCamera Devel Date: Thu, 6 Feb 2020 15:05:00 +0000 Message-Id: <20200206150504.24204-3-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200206150504.24204-1-kieran.bingham@ideasonboard.com> References: <20200206150504.24204-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/6] qcam: Expose quit method for MainWindow 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: Thu, 06 Feb 2020 15:05:10 -0000 Provide a method to facilitate clean shutdowns. Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/qcam/main_window.cpp | 9 +++++++-- src/qcam/main_window.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index 38bc04a23b86..b51a16de199d 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -41,8 +41,7 @@ MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options) } if (ret < 0) - QTimer::singleShot(0, QCoreApplication::instance(), - &QCoreApplication::quit); + quit(); } MainWindow::~MainWindow() @@ -54,6 +53,12 @@ MainWindow::~MainWindow() } } +void MainWindow::quit() +{ + QTimer::singleShot(0, QCoreApplication::instance(), + &QCoreApplication::quit); +} + void MainWindow::updateTitle() { unsigned int duration = frameRateInterval_.elapsed(); diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h index 04fb9e3ea869..a11443b30b37 100644 --- a/src/qcam/main_window.h +++ b/src/qcam/main_window.h @@ -41,6 +41,7 @@ public: ~MainWindow(); private Q_SLOTS: + void quit(); void updateTitle(); private: From patchwork Thu Feb 6 15:05:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 2789 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D18A7600FB for ; Thu, 6 Feb 2020 16:05:10 +0100 (CET) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 6C2C21291; Thu, 6 Feb 2020 16:05:10 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1581001510; bh=pgfhyHX8wYkZ26Ema3OsuMR/BT1/hG5NhNo2pPjP2Q0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=b64mPuiE/Kh+yDa1jjDC3h5WDe5RU3XET9L2wZjGZDenZxx+Nhm72s2MelFG//gWd IqPyJTwuM2qHhLb3ld0vBkbRYap5KO2hcMTGwRz2TrEc1TbhdQuYF3sfzLJp6PBbIo e1nUtsG6mqtIPqe14WovHNxcPaSJR0r5I746180c= From: Kieran Bingham To: LibCamera Devel Date: Thu, 6 Feb 2020 15:05:01 +0000 Message-Id: <20200206150504.24204-4-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200206150504.24204-1-kieran.bingham@ideasonboard.com> References: <20200206150504.24204-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 3/6] qcam: Introduce a toolbar and camera switching 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: Thu, 06 Feb 2020 15:05:11 -0000 Implement a quit button, and a list of cameras. Selecting a different camera from the Toolbar will stop the current stream, and start streaming the chosen camera device if it can be acquired. Signed-off-by: Kieran Bingham --- src/qcam/main_window.cpp | 60 ++++++++++++++++++++++++++++++++++++++++ src/qcam/main_window.h | 4 +++ 2 files changed, 64 insertions(+) diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index b51a16de199d..1c7260f32d0a 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include @@ -27,6 +29,8 @@ MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options) { int ret; + createToolbars(cm); + title_ = "QCam " + QString::fromStdString(CameraManager::version()); setWindowTitle(title_); connect(&titleTimer_, SIGNAL(timeout()), this, SLOT(updateTitle())); @@ -53,6 +57,31 @@ MainWindow::~MainWindow() } } +int MainWindow::createToolbars(CameraManager *cm) +{ + QAction *action; + + toolbar_ = addToolBar(""); + + action = toolbar_->addAction("Quit"); + connect(action, &QAction::triggered, this, &MainWindow::quit); + + QAction *cameraAction = new QAction("&Cameras", this); + toolbar_->addAction(cameraAction); + + QToolButton *cameraButton = dynamic_cast(toolbar_->widgetForAction(cameraAction)); + + cameraButton->setPopupMode(QToolButton::InstantPopup); + + for (const std::shared_ptr &cam : cm->cameras()) { + action = new QAction(QString::fromStdString(cam->name())); + cameraButton->addAction(action); + connect(action, &QAction::triggered, this, [=]() { this->setCamera(cam); }); + } + + return 0; +} + void MainWindow::quit() { QTimer::singleShot(0, QCoreApplication::instance(), @@ -72,6 +101,37 @@ void MainWindow::updateTitle() setWindowTitle(title_ + " : " + QString::number(fps, 'f', 2) + " fps"); } +int MainWindow::setCamera(const std::shared_ptr &cam) +{ + std::cout << "Chose " << cam->name() << std::endl; + + if (cam->acquire()) { + std::cout << "Failed to acquire camera" << std::endl; + return -EBUSY; + } + + std::cout << "Switching to camera " << cam->name() << std::endl; + + stopCapture(); + camera_->release(); + + /* + * If we don't disconnect this signal, it will persist (and get + * re-added and thus duplicated later if we ever switch back to an + * previously streamed camera). This causes all sorts of pain. + * + * Perhaps releasing a camera should disconnect all (public?) connected + * signals forcefully! + */ + camera_->requestCompleted.disconnect(this, &MainWindow::requestComplete); + camera_ = cam; + camera_->requestCompleted.connect(this, &MainWindow::requestComplete); + + startCapture(); + + return 0; +} + std::string MainWindow::chooseCamera(CameraManager *cm) { QStringList cameras; diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h index a11443b30b37..f7c96fdd5c30 100644 --- a/src/qcam/main_window.h +++ b/src/qcam/main_window.h @@ -44,7 +44,10 @@ private Q_SLOTS: void quit(); void updateTitle(); + int setCamera(const std::shared_ptr &cam); + private: + int createToolbars(CameraManager *cm); std::string chooseCamera(CameraManager *cm); int openCamera(CameraManager *cm); @@ -71,6 +74,7 @@ private: uint32_t previousFrames_; uint32_t framesCaptured_; + QToolBar *toolbar_; ViewFinder *viewfinder_; std::map> mappedBuffers_; }; From patchwork Thu Feb 6 15:05:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 2790 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2640260880 for ; Thu, 6 Feb 2020 16:05:11 +0100 (CET) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id BAF7A13C2; Thu, 6 Feb 2020 16:05:10 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1581001510; bh=G/WOaR9TW0B19g5vWaJa3w3u9HiHeSVXuXgaZFjFTLw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KNfhjh4bIlRJoHzOJIpMu1GKELx3gW1B8YNBOjATzcLJI8zU/W8z9EtMsw2EDNy+T w2WBx4SkuvSjgcCt1IliGiRRm3ZYvKEqcfkkIGKMdu8USi/uoaPUxcylksB6zO4CKQ UyMV0BJPK5EIgdpzQqX8j0K10qnqEvC1UiVOEVFc= From: Kieran Bingham To: LibCamera Devel Date: Thu, 6 Feb 2020 15:05:02 +0000 Message-Id: <20200206150504.24204-5-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200206150504.24204-1-kieran.bingham@ideasonboard.com> References: <20200206150504.24204-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 4/6] qcam: assets: Provide initial icon set 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: Thu, 06 Feb 2020 15:05:12 -0000 Provide simple clean icons from https://feathericons.com/ (https://github.com/feathericons/feather) These are provided under the MIT license. Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/qcam/assets/feathericons/README.md | 5 + src/qcam/assets/feathericons/feathericons.qrc | 288 ++++++++++++++++++ src/qcam/assets/feathericons/*.svg | + < Remaing icons chopped > diff --git a/src/qcam/assets/feathericons/README.md b/src/qcam/assets/feathericons/README.md new file mode 100644 index 000000000000..ce7664f6bf16 --- /dev/null +++ b/src/qcam/assets/feathericons/README.md @@ -0,0 +1,5 @@ +Icons from https://feathericons.com/ +License: MIT + +Generate the QRC file with: + rcc --project diff --git a/src/qcam/assets/feathericons/activity.svg b/src/qcam/assets/feathericons/activity.svg new file mode 100644 index 000000000000..669a57a772fa --- /dev/null +++ b/src/qcam/assets/feathericons/activity.svg @@ -0,0 +1 @@ + \ No newline at end of file From patchwork Thu Feb 6 15:05:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 2791 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6EF2E608A6 for ; Thu, 6 Feb 2020 16:05:11 +0100 (CET) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0EA409F0; Thu, 6 Feb 2020 16:05:11 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1581001511; bh=CG++kaOhv+WrNngzAWuFzVKnqHqhdEBC+W0BUpXRz/o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=F3HO4A6TaFv5sgbVIiugWjhUFBYyIojwNK+wGELksEULsr9hafZ7utcmzAIFob9Qr 2v4MgdgDU9uDZZzgjV5PR7NtVDsT8ZEQRVJ+xwyO/wE6Mgy7lsUFHs/YfZYNbZTcW4 lsW+iIyuSPJLqwY9OsGZ11R20TOsL3TbA9RMD79I= From: Kieran Bingham To: LibCamera Devel Date: Thu, 6 Feb 2020 15:05:03 +0000 Message-Id: <20200206150504.24204-6-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200206150504.24204-1-kieran.bingham@ideasonboard.com> References: <20200206150504.24204-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 5/6] qcam: Provide initial icon buttons "Play/Stop" 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: Thu, 06 Feb 2020 15:05:12 -0000 Provide Quit, Play, Pause, Stop icons. Utilise the provided QT resources to present icons for the toolbar. Update the Quit button with a 'cross', and implement Play/Pause/Stop buttons. 'Pause' is a no-op currently and likely could be removed, but I wanted an ability to distinguish between holding the stream and restarting it. Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/qcam/main_window.cpp | 12 +++++++++++- src/qcam/main_window.h | 7 +++---- src/qcam/meson.build | 8 +++++++- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index 1c7260f32d0a..0ae4c60b8699 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -63,7 +64,7 @@ int MainWindow::createToolbars(CameraManager *cm) toolbar_ = addToolBar(""); - action = toolbar_->addAction("Quit"); + action = toolbar_->addAction(QIcon(":x-circle.svg"), "Quit"); connect(action, &QAction::triggered, this, &MainWindow::quit); QAction *cameraAction = new QAction("&Cameras", this); @@ -79,6 +80,15 @@ int MainWindow::createToolbars(CameraManager *cm) connect(action, &QAction::triggered, this, [=]() { this->setCamera(cam); }); } + action = toolbar_->addAction(QIcon(":play-circle.svg"), "start"); + connect(action, &QAction::triggered, this, &MainWindow::startCapture); + + toolbar_->addAction(QIcon(":pause-circle.svg"), "pause"); + /* TODO: Connect an action to perform when 'pause' requested? or remove */ + + action = toolbar_->addAction(QIcon(":stop-circle.svg"), "stop"); + connect(action, &QAction::triggered, this, &MainWindow::stopCapture); + return 0; } diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h index f7c96fdd5c30..b0bf16dd2a09 100644 --- a/src/qcam/main_window.h +++ b/src/qcam/main_window.h @@ -46,14 +46,13 @@ private Q_SLOTS: int setCamera(const std::shared_ptr &cam); + int startCapture(); + void stopCapture(); + private: int createToolbars(CameraManager *cm); std::string chooseCamera(CameraManager *cm); int openCamera(CameraManager *cm); - - int startCapture(); - void stopCapture(); - void requestComplete(Request *request); int display(FrameBuffer *buffer); diff --git a/src/qcam/meson.build b/src/qcam/meson.build index 1e71f20fa15e..b6544dbf3f2b 100644 --- a/src/qcam/meson.build +++ b/src/qcam/meson.build @@ -11,6 +11,10 @@ qcam_moc_headers = files([ 'main_window.h', ]) +qcam_resources = files([ + 'assets/feathericons/feathericons.qrc', +]) + qt5 = import('qt5') qt5_dep = dependency('qt5', method : 'pkg-config', @@ -33,7 +37,9 @@ if qt5_dep.found() moc_files = qt5.preprocess(moc_headers: qcam_moc_headers, dependencies: qt5_dep) - qcam = executable('qcam', qcam_sources, moc_files, + resources = qt5.preprocess(qresources : qcam_resources) + + qcam = executable('qcam', qcam_sources, moc_files, resources, install : true, dependencies : [libcamera_dep, qt5_dep], cpp_args : qt5_cpp_args) From patchwork Thu Feb 6 15:05:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 2792 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AADE760902 for ; Thu, 6 Feb 2020 16:05:11 +0100 (CET) Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5784EB7D; Thu, 6 Feb 2020 16:05:11 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1581001511; bh=PtmplQqhe0wEuklPc8Jw/+DcHL1p5yhct/6PJlwZ0PY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DbE95t+YDa1mXtoFhsk5u637OdWjqJAtUhBt7GVoxkpsXPJWiopmJYOXxkMaJIsvN t50JPbRrIeC0esDnRApg1hMFNDbRmBbLtN5ed8THkE+c/Vy0h9QknsnEvSPRj5jmzR 4hFl0rWKqYv+o44xc0lhxfNQcp/OqZuP3Cc8Q4fA= From: Kieran Bingham To: LibCamera Devel Date: Thu, 6 Feb 2020 15:05:04 +0000 Message-Id: <20200206150504.24204-7-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200206150504.24204-1-kieran.bingham@ideasonboard.com> References: <20200206150504.24204-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 6/6] qcam: Provide save image functionality 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: Thu, 06 Feb 2020 15:05:12 -0000 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 --- src/qcam/main_window.cpp | 22 ++++++++++++++++++++++ src/qcam/main_window.h | 1 + src/qcam/viewfinder.cpp | 7 +++++++ src/qcam/viewfinder.h | 2 ++ 4 files changed, 32 insertions(+) diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index 0ae4c60b8699..0e994b1e9197 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -11,7 +11,10 @@ #include #include +#include #include +#include +#include #include #include #include @@ -89,6 +92,9 @@ int MainWindow::createToolbars(CameraManager *cm) action = toolbar_->addAction(QIcon(":stop-circle.svg"), "stop"); connect(action, &QAction::triggered, this, &MainWindow::stopCapture); + action = toolbar_->addAction(QIcon(":save.svg"), "save"); + connect(action, &QAction::triggered, this, &MainWindow::saveImage); + return 0; } @@ -339,6 +345,22 @@ void MainWindow::stopCapture() setWindowTitle(title_); } +void MainWindow::saveImage() +{ + /* Take a lock to prevent updating the backed image, copy, + * then ask where to save with lock released */ + + QImage image = viewfinder_->getCurrentImage(); + + QString filename = QFileDialog::getSaveFileName(this, "Save Image", "", + "Image Files (*.png *.jpg *.jpeg)"); + + std::cerr << "Save jpeg to " << filename.toStdString() << std::endl; + + 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 b0bf16dd2a09..fc85b6a46491 100644 --- a/src/qcam/main_window.h +++ b/src/qcam/main_window.h @@ -48,6 +48,7 @@ private Q_SLOTS: int startCapture(); void stopCapture(); + void saveImage(); private: int createToolbars(CameraManager *cm); diff --git a/src/qcam/viewfinder.cpp b/src/qcam/viewfinder.cpp index 6de284d1b782..3fa4a326c342 100644 --- a/src/qcam/viewfinder.cpp +++ b/src/qcam/viewfinder.cpp @@ -6,6 +6,7 @@ */ #include +#include #include #include "format_converter.h" @@ -27,6 +28,12 @@ void ViewFinder::display(const unsigned char *raw, size_t size) update(); } +QImage ViewFinder::getCurrentImage() +{ + /* Ideally need to lock, return/copy, then unlock... Can a scoped lock work? */ + return *image_; +} + 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 ef5fd45b264a..1da79d3e67aa 100644 --- a/src/qcam/viewfinder.h +++ b/src/qcam/viewfinder.h @@ -23,6 +23,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;