Skip to content

Commit

Permalink
Add a Remote Screenshot (#105)
Browse files Browse the repository at this point in the history
* Add ScreenshotAsBase64 Function this create a screenshot like the normal screenshot, except that it outputs the image as Base64 String
  • Loading branch information
53845714nF authored May 29, 2024
1 parent 18ab4db commit b948a34
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 1 deletion.
2 changes: 2 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ set(SOURCES
src/Commands/Quit.h
src/Commands/Screenshot.cpp
src/Commands/Screenshot.h
src/Commands/ScreenshotBase64.cpp
src/Commands/ScreenshotBase64.h
src/Commands/SetProperty.cpp
src/Commands/SetProperty.h
src/Commands/Wait.cpp
Expand Down
1 change: 1 addition & 0 deletions lib/include/Spix/TestServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class SPIX_EXPORT TestServer {
std::vector<std::string> getErrors();

void takeScreenshot(ItemPath targetItem, std::string filePath);
std::string takeScreenshotAsBase64(ItemPath targetItem);
void quit();

protected:
Expand Down
4 changes: 4 additions & 0 deletions lib/src/AnyRpcServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ AnyRpcServer::AnyRpcServer(int anyrpcPort)
return takeScreenshot(std::move(targetItem), std::move(filePath));
});

utils::AddFunctionToAnyRpc<std::string(std::string)>(methodManager, "takeScreenshotAsBase64",
"Take a screenshot of the object and send as base64 string | takeScreenshotAsBase64(string pathToTargetedItem)",
[this](std::string targetItem) { return takeScreenshotAsBase64(std::move(targetItem)); });

utils::AddFunctionToAnyRpc<void()>(methodManager, "quit", "Close the app | quit()", [this] { quit(); });

utils::AddFunctionToAnyRpc<void(std::string, std::string)>(methodManager, "command",
Expand Down
26 changes: 26 additions & 0 deletions lib/src/Commands/ScreenshotBase64.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/***
* Copyright (C) Falko Axmann. All rights reserved.
* Licensed under the MIT license.
* See LICENSE.txt file in the project root for full license information.
****/

#include "ScreenshotBase64.h"

#include <Scene/Scene.h>
namespace spix {
namespace cmd {

ScreenshotAsBase64::ScreenshotAsBase64(ItemPath targetItemPath, std::promise<std::string> promise)
: m_itemPath {std::move(targetItemPath)}
, m_promise(std::move(promise))
{
}

void ScreenshotAsBase64::execute(CommandEnvironment& env)
{
auto value = env.scene().takeScreenshotAsBase64(m_itemPath);
m_promise.set_value(value);
}

} // namespace cmd
} // namespace spix
23 changes: 23 additions & 0 deletions lib/src/Commands/ScreenshotBase64.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

#include "Command.h"
#include <Spix/Data/ItemPath.h>

#include <future>

namespace spix {
namespace cmd {

class ScreenshotAsBase64 : public Command {
public:
ScreenshotAsBase64(ItemPath targetItemPath, std::promise<std::string> promise);

void execute(CommandEnvironment& env) override;

private:
ItemPath m_itemPath;
std::promise<std::string> m_promise;
};

} // namespace cmd
} // namespace spix
5 changes: 5 additions & 0 deletions lib/src/Scene/Mock/MockScene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ void MockScene::takeScreenshot(const ItemPath&, const std::string&)
{
}

std::string MockScene::takeScreenshotAsBase64(const ItemPath&)
{
return "Base64 String";
}

void MockScene::addItemAtPath(MockItem item, const ItemPath& path)
{
m_items.emplace(std::make_pair(path.string(), std::move(item)));
Expand Down
2 changes: 1 addition & 1 deletion lib/src/Scene/Mock/MockScene.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class SPIX_EXPORT MockScene : public Scene {

// Tasks
void takeScreenshot(const ItemPath& targetItem, const std::string& filePath) override;

std::string takeScreenshotAsBase64(const ItemPath& targetItem);
// Mock stuff
void addItemAtPath(MockItem item, const ItemPath& path);
MockEvents& mockEvents();
Expand Down
30 changes: 30 additions & 0 deletions lib/src/Scene/Qt/QtScene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include <Scene/Qt/QtItemTools.h>
#include <Spix/Data/ItemPath.h>

#include <QBuffer>
#include <QByteArray>
#include <QGuiApplication>
#include <QObject>
#include <QQuickItem>
Expand Down Expand Up @@ -139,4 +141,32 @@ void QtScene::takeScreenshot(const ItemPath& targetItem, const std::string& file
image.save(QString::fromStdString(filePath));
}

std::string QtScene::takeScreenshotAsBase64(const ItemPath& targetItem)
{
auto item = getQQuickItemAtPath(targetItem);
if (!item) {
return "";
}

// take screenshot of the full window
auto windowImage = item->window()->grabWindow();

// get the rect of the item in window space in pixels, account for the device pixel ratio
QRectF imageCropRectItemSpace {0, 0, item->width(), item->height()};
auto imageCropRectF = item->mapRectToScene(imageCropRectItemSpace);
QRect imageCropRect(imageCropRectF.x() * windowImage.devicePixelRatio(),
imageCropRectF.y() * windowImage.devicePixelRatio(), imageCropRectF.width() * windowImage.devicePixelRatio(),
imageCropRectF.height() * windowImage.devicePixelRatio());

// crop the window image to the item rect
auto image = windowImage.copy(imageCropRect);
QByteArray byteArray;
QBuffer buffer(&byteArray);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "PNG");
buffer.close();

return byteArray.toBase64().toStdString();
}

} // namespace spix
2 changes: 2 additions & 0 deletions lib/src/Scene/Qt/QtScene.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#pragma once

#include <QByteArray>
#include <Scene/Qt/QtEvents.h>
#include <Scene/Scene.h>

Expand All @@ -28,6 +29,7 @@ class QtScene : public Scene {

// Tasks
void takeScreenshot(const ItemPath& targetItem, const std::string& filePath) override;
std::string takeScreenshotAsBase64(const ItemPath& targetItem);

private:
QtEvents m_events;
Expand Down
1 change: 1 addition & 0 deletions lib/src/Scene/Scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class Scene {

// Tasks
virtual void takeScreenshot(const ItemPath& targetItem, const std::string& filePath) = 0;
virtual std::string takeScreenshotAsBase64(const ItemPath& targetItem) = 0;
};

} // namespace spix
11 changes: 11 additions & 0 deletions lib/src/TestServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <Commands/InvokeMethod.h>
#include <Commands/Quit.h>
#include <Commands/Screenshot.h>
#include <Commands/ScreenshotBase64.h>
#include <Commands/SetProperty.h>
#include <Commands/Wait.h>

Expand Down Expand Up @@ -177,6 +178,16 @@ void TestServer::takeScreenshot(ItemPath targetItem, std::string filePath)
m_cmdExec->enqueueCommand<cmd::Screenshot>(targetItem, std::move(filePath));
}

std::string TestServer::takeScreenshotAsBase64(ItemPath targetItem)
{
std::promise<std::string> promise;
auto result = promise.get_future();
auto cmd = std::make_unique<cmd::ScreenshotAsBase64>(targetItem, std::move(promise));
m_cmdExec->enqueueCommand(std::move(cmd));

return result.get();
}

void TestServer::quit()
{
m_cmdExec->enqueueCommand<cmd::Quit>();
Expand Down

0 comments on commit b948a34

Please sign in to comment.