diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h
index 3b54112f6c..0167ec0035 100644
--- a/interface/src/scripting/WindowScriptingInterface.h
+++ b/interface/src/scripting/WindowScriptingInterface.h
@@ -334,9 +334,9 @@ public slots:
* dimensions is adjusted in order to match the aspect ratio.
* @param {string} [filename=""] - If a filename is not provided, the image is saved as "overte-snap-by-<user
* name>-on-YYYY-MM-DD_HH-MM-SS".
- *
Still images are saved in JPEG or PNG format according to the extension provided — ".jpg"
,
- * ".jpeg"
, or ".png"
— or if not provided then in JPEG format with an extension of
- * ".jpg"
. Animated images are saved in GIF format.
+ * Still images are saved in JPEG, PNG or WEBP format according to the extension provided — ".jpg"
,
+ * ".jpeg"
, ".png"
, or ".webp"
— or if not provided then in the format chosen in general settings,
+ * Default is PNG. Animated images are saved in GIF format.
*
* @example Using the snapshot function and signals.
* function onStillSnapshotTaken(path, notify) {
@@ -371,11 +371,11 @@ public slots:
* @function Window.takeSecondaryCameraSnapshot
* @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken}
* signal.
- * @param {string} [filename=""] - If a filename is not provided, the image is saved as "overte-snap-by-<user
+ * @param {string} [filename=""] - If a filename is not provided, the image is saved as "overte-snap-by-<user
* name>-on-YYYY-MM-DD_HH-MM-SS".
- * Images are saved in JPEG or PNG format according to the extension provided — ".jpg"
,
- * ".jpeg"
, or ".png"
— or if not provided then in JPEG format with an extension of
- * ".jpg"
.
+ * Still images are saved in JPEG, PNG or WEBP format according to the extension provided — ".jpg"
,
+ * ".jpeg"
, ".png"
, or ".webp"
— or if not provided then in the format chosen in general settings,
+ * Default is PNG. Animated images are saved in GIF format.
*/
void takeSecondaryCameraSnapshot(const bool& notify = true, const QString& filename = QString());
@@ -390,11 +390,11 @@ public slots:
* otherwise it is saved as an equirectangular image.
* @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken}
* signal.
- * @param {string} [filename=""] - If a filename is not provided, the image is saved as "overte-snap-by-<user
+ * @param {string} [filename=""] - If a filename is not provided, the image is saved as "overte-snap-by-<user
* name>-on-YYYY-MM-DD_HH-MM-SS".
- * Images are saved in JPEG or PNG format according to the extension provided — ".jpg"
,
- * ".jpeg"
, or ".png"
— or if not provided then in JPEG format with an extension of
- * ".jpg"
.
+ * Still images are saved in JPEG, PNG or WEBP format according to the extension provided — ".jpg"
,
+ * ".jpeg"
, ".png"
, or ".webp"
— or if not provided then in the format chosen in general settings,
+ * Default is PNG. Animated images are saved in GIF format.
*/
void takeSecondaryCamera360Snapshot(const glm::vec3& cameraPosition, const bool& cubemapOutputFormat = false, const bool& notify = true, const QString& filename = QString());
diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp
index adeb0d1dcd..6d13f586d4 100644
--- a/interface/src/ui/PreferencesDialog.cpp
+++ b/interface/src/ui/PreferencesDialog.cpp
@@ -238,15 +238,6 @@ void setupPreferences() {
auto preference = new BrowsePreference(SNAPSHOTS, "Put my snapshots here", getter, setter);
preferences->addPreference(preference);
}
- {
- auto getter = []()->float { return SnapshotAnimated::snapshotAnimatedDuration.get(); };
- auto setter = [](float value) { SnapshotAnimated::snapshotAnimatedDuration.set(value); };
- auto preference = new SpinnerPreference(SNAPSHOTS, "Animated Snapshot Duration", getter, setter);
- preference->setMin(1);
- preference->setMax(5);
- preference->setStep(1);
- preferences->addPreference(preference);
- }
{
auto getter = []()->bool {
@@ -258,6 +249,46 @@ void setupPreferences() {
preferences->addPreference(new CheckPreference(SNAPSHOTS, "Display snapshot notifications", getter, setter));
}
+ {
+ auto getter = []()->int {
+ if (!DependencyManager::get()->_snapshotFormat.isSet()) {
+ DependencyManager::get()->setSnapshotFormat(DependencyManager::get()->getAvailableSnapshotFormats()[0]);
+ }
+ return DependencyManager::get()->getAvailableSnapshotFormats().indexOf(DependencyManager::get()->getSnapshotFormat()); };
+ auto setter = [](int value) { DependencyManager::get()->setSnapshotFormat(DependencyManager::get()->getAvailableSnapshotFormats()[value]); };
+ auto preference = new RadioButtonsPreference(SNAPSHOTS, "Snapshot format", getter, setter);
+ QStringList items;
+ items << DependencyManager::get()->getAvailableSnapshotFormatsWithDescriptions();
+ preference->setHeading("Snapshot format");
+ preference->setItems(items);
+ preferences->addPreference(preference);
+ }
+
+ {
+ auto getter = []()->int {
+ if (!DependencyManager::get()->_animatedSnapshotFormat.isSet()) {
+ DependencyManager::get()->setAnimatedSnapshotFormat(DependencyManager::get()->getAvailableAnimatedSnapshotFormats()[0]);
+ }
+ return DependencyManager::get()->getAvailableAnimatedSnapshotFormats().indexOf(DependencyManager::get()->getAnimatedSnapshotFormat()); };
+ auto setter = [](int value) { DependencyManager::get()->setAnimatedSnapshotFormat(DependencyManager::get()->getAvailableAnimatedSnapshotFormats()[value]); };
+ auto preference = new RadioButtonsPreference(SNAPSHOTS, "Animated snapshot format", getter, setter);
+ QStringList items;
+ items << DependencyManager::get()->getAvailableAnimatedSnapshotFormatsWithDescriptions();
+ preference->setHeading("Animated snapshot format");
+ preference->setItems(items);
+ preferences->addPreference(preference);
+ }
+
+ {
+ auto getter = []()->float { return SnapshotAnimated::snapshotAnimatedDuration.get(); };
+ auto setter = [](float value) { SnapshotAnimated::snapshotAnimatedDuration.set(value); };
+ auto preference = new SpinnerPreference(SNAPSHOTS, "Animated Snapshot Duration", getter, setter);
+ preference->setMin(1);
+ preference->setMax(5);
+ preference->setStep(1);
+ preferences->addPreference(preference);
+ }
+
{
auto getter = []()->bool { return !Menu::getInstance()->isOptionChecked(MenuOption::DisableActivityLogger); };
auto setter = [](bool value) { Menu::getInstance()->setIsOptionChecked(MenuOption::DisableActivityLogger, !value); };
diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp
index e736ed9430..2884574767 100644
--- a/interface/src/ui/Snapshot.cpp
+++ b/interface/src/ui/Snapshot.cpp
@@ -4,6 +4,7 @@
//
// Created by Stojce Slavkovski on 1/26/14.
// Copyright 2014 High Fidelity, Inc.
+// Copyright 2022 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@@ -44,12 +45,13 @@
// filename format: overte-snap-by-%username%-on-%date%_%time%_@-%location%.png
// %1 <= username, %2 <= date and time, %3 <= current location
-const QString FILENAME_PATH_FORMAT = "overte-snap-by-%1-on-%2.png";
+const QString FILENAME_PATH_FORMAT = "overte-snap-by-%1-on-%2";
+const QString DEFAULT_FORMAT = "png";
const QString DATETIME_FORMAT = "yyyy-MM-dd_hh-mm-ss";
const QString SNAPSHOTS_DIRECTORY = "Snapshots";
const QString URL = "overte_url";
static const int SNAPSHOT_360_TIMER_INTERVAL = 350;
-static const QList SUPPORTED_IMAGE_FORMATS = { "jpg", "jpeg", "png" };
+static const QList SUPPORTED_IMAGE_FORMATS = { "jpg", "jpeg", "png", "webp" };
Snapshot::Snapshot() {
_snapshotTimer.setSingleShot(false);
@@ -110,6 +112,7 @@ QString Snapshot::saveSnapshot(QImage image, const QString& filename, const QStr
return "";
}
+
static const float CUBEMAP_SIDE_PIXEL_DIMENSION = 2048.0f;
static const float SNAPSHOT_360_FOV = 90.0f;
static const float SNAPSHOT_360_NEARCLIP = 0.3f;
@@ -389,7 +392,11 @@ QFile* Snapshot::savedFileForSnapshot(QImage& shot,
imageQuality = 50;
}
} else {
- filename = FILENAME_PATH_FORMAT.arg(username, now.toString(DATETIME_FORMAT));
+ QString selectedFormat(DEFAULT_FORMAT);
+ if (_snapshotFormat.get() != "") {
+ selectedFormat = _snapshotFormat.get();
+ }
+ filename = FILENAME_PATH_FORMAT.arg(username, now.toString(DATETIME_FORMAT)) + "." + selectedFormat;
QFileInfo snapshotFileInfo(filename);
QString filenameSuffix = snapshotFileInfo.suffix();
filenameSuffix = filenameSuffix.toLower();
@@ -516,3 +523,43 @@ QString Snapshot::getSnapshotsLocation() {
void Snapshot::setSnapshotsLocation(const QString& location) {
_snapshotsLocation.set(location);
}
+
+QString Snapshot::getSnapshotFormat(){
+ return _snapshotFormat.get();
+}
+
+void Snapshot::setSnapshotFormat(const QString& format){
+ if (getAvailableSnapshotFormats().contains(format)) {
+ _snapshotFormat.set(format);
+ } else {
+ qDebug() << "Snapshot format not supported: " << format;
+ }
+}
+
+QString Snapshot::getAnimatedSnapshotFormat(){
+ return _animatedSnapshotFormat.get();
+}
+
+void Snapshot::setAnimatedSnapshotFormat(const QString& format){
+ if (getAvailableAnimatedSnapshotFormats().contains(format)) {
+ _animatedSnapshotFormat.set(format);
+ } else {
+ qDebug() << "Snapshot format not supported: " << format;
+ }
+}
+
+QStringList Snapshot::getAvailableSnapshotFormats() {
+ return QStringList({"png", "jpg", "webp"});
+}
+
+QStringList Snapshot::getAvailableSnapshotFormatsWithDescriptions() {
+ return QStringList({"PNG - lossless, large file size", "JPG - lossy, fast compression", "WEBP - lossy, higher quality and file size than JPG"});
+}
+
+QStringList Snapshot::getAvailableAnimatedSnapshotFormats() {
+ return QStringList({"gif"});
+}
+
+QStringList Snapshot::getAvailableAnimatedSnapshotFormatsWithDescriptions() {
+ return QStringList({"GIF"});
+}
diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h
index f6c57b0e42..61af735af7 100644
--- a/interface/src/ui/Snapshot.h
+++ b/interface/src/ui/Snapshot.h
@@ -65,6 +65,8 @@ public:
Setting::Handle _snapshotsLocation{ "snapshotsLocation" };
Setting::Handle _snapshotNotifications{ "snapshotNotifications", true };
+ Setting::Handle _snapshotFormat{ "snapshotFormat" };
+ Setting::Handle _animatedSnapshotFormat{ "animatedSnapshotFormat" };
void uploadSnapshot(const QString& filename, const QUrl& href = QUrl(""));
signals:
@@ -97,6 +99,64 @@ public slots:
* @param {String} location - The path to save snapshots to.
*/
Q_INVOKABLE void setSnapshotsLocation(const QString& location);
+
+ /*@jsdoc
+ * Gets the currently selected snapshot format.
+ * @function Snapshot.getSnapshotFormat
+ * @returns {string} Currently selected snapshot format.
+ */
+ Q_INVOKABLE QString getSnapshotFormat();
+
+ /*@jsdoc
+ * Sets the snapshot format.
+ * @function Snapshot.setSnapshotFormat
+ * @param {String} format - one of the format names returned by Snapshot.getAvailableSnapshotFormats().
+ */
+ Q_INVOKABLE void setSnapshotFormat(const QString& format);
+
+ /*@jsdoc
+ * Gets the currently selected animated snapshot format.
+ * @function Snapshot.getAnimatedSnapshotFormat
+ * @returns {Array.} Currently selected snapshot format.
+ */
+ Q_INVOKABLE QString getAnimatedSnapshotFormat();
+
+ /*@jsdoc
+ * Sets the snapshot format.
+ * @function Snapshot.setAnimatedSnapshotFormat
+ * @param {String} format - one of the format names returned by Snapshot.getAvailableSnapshotFormats().
+ */
+ Q_INVOKABLE void setAnimatedSnapshotFormat(const QString& format);
+
+ /*@jsdoc
+ * Returns a list of supported snapshot formats.
+ * @function Snapshot.getAvailableSnapshotFormats
+ * @returns {Array.} List of supported snapshot formats.
+ */
+ Q_INVOKABLE QStringList getAvailableSnapshotFormats();
+
+ /*@jsdoc
+ * Returns a list of supported snapshot formats with short descriptions.
+ * @function Snapshot.getAvailableSnapshotFormatsWithDescriptions
+ * @returns {Array.} List of supported snapshot formats with short descriptions.
+ */
+ Q_INVOKABLE QStringList getAvailableSnapshotFormatsWithDescriptions();
+
+ /*@jsdoc
+ * Returns a list of supported animated snapshot formats.
+ * @function Snapshot.getAvailableAnimatedSnapshotFormats
+ * @returns {Array.} List of supported animated snapshot formats.
+ */
+ Q_INVOKABLE QStringList getAvailableAnimatedSnapshotFormats();
+
+ /*@jsdoc
+ * Returns a list of supported animated snapshot formats with short descriptions.
+ * @function Snapshot.getAvailableAnimatedSnapshotFormatsWithDescriptions
+ * @returns {Array.} List of supported animated snapshot formats with short descriptions.
+ */
+ Q_INVOKABLE QStringList getAvailableAnimatedSnapshotFormatsWithDescriptions();
+
+
private slots:
void takeNextSnapshot();