summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Larrosa <[email protected]>2016-11-02 13:01:51 +0100
committerAntonio Larrosa <[email protected]>2016-11-04 09:57:41 +0100
commitc309f1eaeb6993d6e49ba04db7a874f952ce02bc (patch)
tree9c33b4177f9690409b9ceff7f5395aea976c9414
parentd1133288c3357681b4a9c9976469df07d0802793 (diff)
Modified distance function to keep aspect ratio as close as possible
Summary: This new version of the distance function simplifies the findPreferredImageInPackage method by using the aspect ratio in the calculation. Now, it won't only search for a wallpaper with the same aspect ratio, but will also choose one with the closest possible aspect ratio when a perfect match is not found. Also, I separated the method that chooses the preferred image to not use KPackage in order to use it from a test application that tests the distance algorithm with all possible resolutions. Test application that tests the Image::findPreferredImage method The test initializes a list of available wallpaper image sizes, then a list of screen resolutions, and then executes Image::findPreferredImage to find out which is the preferred image in each case. Test Plan: I tested with different screen resolutions on a virtual machine with openSUSE Leap 42.2 RC1 and also included a commit that adds a test application (not built by default) that tests all possible resolutions. Reviewers: #plasma, mart Reviewed By: mart Subscribers: mart, plasma-devel Tags: #plasma Differential Revision: https://phabricator.kde.org/D3188
-rw-r--r--wallpapers/image/CMakeLists.txt4
-rw-r--r--wallpapers/image/autotests/CMakeLists.txt11
-rw-r--r--wallpapers/image/autotests/testfindpreferredimage.cpp106
-rw-r--r--wallpapers/image/image.cpp59
-rw-r--r--wallpapers/image/image.h1
5 files changed, 147 insertions, 34 deletions
diff --git a/wallpapers/image/CMakeLists.txt b/wallpapers/image/CMakeLists.txt
index 21e9740..e226526 100644
--- a/wallpapers/image/CMakeLists.txt
+++ b/wallpapers/image/CMakeLists.txt
@@ -6,8 +6,8 @@ set(image_SRCS
backgroundlistmodel.cpp
)
-
add_library(plasma_wallpaper_imageplugin SHARED ${image_SRCS})
+
target_link_libraries(plasma_wallpaper_imageplugin
Qt5::Core
Qt5::Quick
@@ -22,6 +22,8 @@ target_link_libraries(plasma_wallpaper_imageplugin
KF5::GuiAddons
)
+add_subdirectory(autotests)
+
install(TARGETS plasma_wallpaper_imageplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/wallpapers/image)
install(FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/wallpapers/image)
diff --git a/wallpapers/image/autotests/CMakeLists.txt b/wallpapers/image/autotests/CMakeLists.txt
new file mode 100644
index 0000000..6d9e7a5
--- /dev/null
+++ b/wallpapers/image/autotests/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(testfindpreferredimage_SRCS
+ testfindpreferredimage.cpp
+ ../image.cpp
+ ../backgroundlistmodel.cpp
+ )
+
+add_executable(testfindpreferredimage EXCLUDE_FROM_ALL ${testfindpreferredimage_SRCS})
+
+target_link_libraries(testfindpreferredimage
+ plasma_wallpaper_imageplugin
+ Qt5::Test)
diff --git a/wallpapers/image/autotests/testfindpreferredimage.cpp b/wallpapers/image/autotests/testfindpreferredimage.cpp
new file mode 100644
index 0000000..e6b1a9d
--- /dev/null
+++ b/wallpapers/image/autotests/testfindpreferredimage.cpp
@@ -0,0 +1,106 @@
+/***************************************************************************
+ * Copyright 2016 Antonio Larrosa <[email protected]> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
+ ***************************************************************************/
+#include "image.h"
+#include <QtTest/QtTest>
+#include <QDebug>
+
+extern QSize resSize(const QString &str);
+
+QString formatResolution(const QString &str)
+{
+ QSize size = resSize(str);
+ float aspectRatio = (size.height() > 0 ) ? size.width() / (float)size.height() : 0;
+ return QString("%1 (%2)").arg(str, 9).arg(aspectRatio, 7);
+}
+
+class TestResolutions: public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testResolutions_data();
+ void testResolutions();
+
+protected:
+ Image m_image;
+ QStringList m_images;
+};
+
+void TestResolutions::testResolutions_data()
+{
+ // The list of available wallpaper image sizes
+ m_images << QStringLiteral("1280x1024")
+ << QStringLiteral("1350x1080")
+ << QStringLiteral("1440x1080")
+ << QStringLiteral("1600x1200")
+ << QStringLiteral("1920x1080")
+ << QStringLiteral("1920x1200")
+ << QStringLiteral("3840x2400");
+ qDebug() << "Available images:";
+ foreach( auto image, m_images) {
+ qDebug() << formatResolution(image);
+ }
+
+ // The list of possible screen resolutions to test and the appropiate images that should be chosen
+ QTest::addColumn<QString>("resolution");
+ QTest::addColumn<QString>("expected");
+ QTest::newRow("1280x1024") << QStringLiteral("1280x1024") << QStringLiteral("1280x1024");
+ QTest::newRow("1350x1080") << QStringLiteral("1350x1080") << QStringLiteral("1350x1080");
+ QTest::newRow("1440x1080") << QStringLiteral("1440x1080") << QStringLiteral("1440x1080");
+ QTest::newRow("1600x1200") << QStringLiteral("1600x1200") << QStringLiteral("1600x1200");
+ QTest::newRow("1920x1080") << QStringLiteral("1920x1080") << QStringLiteral("1920x1080");
+ QTest::newRow("1920x1200") << QStringLiteral("1920x1200") << QStringLiteral("1920x1200");
+ QTest::newRow("3840x2400") << QStringLiteral("3840x2400") << QStringLiteral("3840x2400");
+ QTest::newRow("4096x2160") << QStringLiteral("4096x2160") << QStringLiteral("1920x1080");
+ QTest::newRow("3840x2160") << QStringLiteral("3840x2160") << QStringLiteral("1920x1080");
+ QTest::newRow("3200x1800") << QStringLiteral("3200x1800") << QStringLiteral("1920x1080");
+ QTest::newRow("2048x1080") << QStringLiteral("2048x1080") << QStringLiteral("1920x1080");
+ QTest::newRow("1680x1050") << QStringLiteral("1680x1050") << QStringLiteral("1920x1200");
+ QTest::newRow("1400x1050") << QStringLiteral("1400x1050") << QStringLiteral("1440x1080");
+ QTest::newRow("1440x900") << QStringLiteral("1440x900") << QStringLiteral("1920x1200");
+ QTest::newRow("1280x960") << QStringLiteral("1280x960") << QStringLiteral("1440x1080");
+ QTest::newRow("1280x854") << QStringLiteral("1280x854") << QStringLiteral("1920x1200");
+ QTest::newRow("1280x800") << QStringLiteral("1280x800") << QStringLiteral("1920x1200");
+ QTest::newRow("1280x720") << QStringLiteral("1280x720") << QStringLiteral("1920x1080");
+ QTest::newRow("1152x768") << QStringLiteral("1152x768") << QStringLiteral("1920x1200");
+ QTest::newRow("1024x768") << QStringLiteral("1024x768") << QStringLiteral("1440x1080");
+ QTest::newRow("800x600") << QStringLiteral("800x600") << QStringLiteral("1440x1080");
+ QTest::newRow("848x480") << QStringLiteral("848x480") << QStringLiteral("1920x1080");
+ QTest::newRow("720x480") << QStringLiteral("720x480") << QStringLiteral("1920x1200");
+ QTest::newRow("640x480") << QStringLiteral("640x480") << QStringLiteral("1440x1080");
+ QTest::newRow("1366x768") << QStringLiteral("1366x768") << QStringLiteral("1920x1080");
+ QTest::newRow("1600x814") << QStringLiteral("1600x814") << QStringLiteral("1920x1080");
+}
+
+void TestResolutions::testResolutions()
+{
+ QFETCH(QString, resolution);
+ QFETCH(QString, expected);
+
+ m_image.setTargetSize( resSize( resolution ) );
+ QString preferred = m_image.findPreferedImage(m_images);
+
+ qDebug() << "For a screen size of " << formatResolution(resolution)
+ << " the " << formatResolution(preferred) << " wallpaper was preferred";
+
+ QCOMPARE(preferred, expected);
+}
+
+QTEST_MAIN(TestResolutions)
+#include "testfindpreferredimage.moc"
diff --git a/wallpapers/image/image.cpp b/wallpapers/image/image.cpp
index 517915c..d481243 100644
--- a/wallpapers/image/image.cpp
+++ b/wallpapers/image/image.cpp
@@ -156,13 +156,14 @@ void Image::setRenderingMode(RenderingMode mode)
float distance(const QSize& size, const QSize& desired)
{
// compute difference of areas
- float delta = size.width() * size.height() -
- desired.width() * desired.height();
- // scale down to about 1.0
- delta /= ((desired.width() * desired.height())+(size.width() * size.height()))/2;
+ float desiredAspectRatio = ( desired.height() > 0 ) ? desired.width() / (float)desired.height() : 0;
+ float candidateAspectRatio = ( size.height() > 0 ) ? size.width() / (float)size.height() : FLT_MAX;
+
+ float delta = size.width() - desired.width();
+ delta = (delta >= 0.0 ? delta : -delta*2 ); // Penalize for scaling up
+
+ return qAbs(candidateAspectRatio - desiredAspectRatio)*25000 + delta;
- // Difference of areas, slight preference to scale down
- return delta >= 0.0 ? delta : -delta + 2.0;
}
QSize resSize(const QString &str)
@@ -176,56 +177,48 @@ QSize resSize(const QString &str)
return QSize();
}
-void Image::findPreferedImageInPackage(KPackage::Package &package)
+QString Image::findPreferedImage(const QStringList &images)
{
- if (!package.isValid() || !package.filePath("preferred").isEmpty()) {
- return;
- }
-
- QStringList images = package.entryList("images");
if (images.empty()) {
- return;
+ return QString();
}
- //qDebug() << "wanted" << m_targetSize << "options" << images;
-
- // choose the nearest resolution, always preferring images with the same aspect ratio
+ //float targetAspectRatio = (m_targetSize.height() > 0 ) ? m_targetSize.width() / (float)m_targetSize.height() : 0;
+ //qDebug() << "wanted" << m_targetSize << "options" << images << "aspect ratio" << targetAspectRatio;
float best = FLT_MAX;
- float bestWithSameAspectRatio = FLT_MAX;
- float targetAspectRatio = ( m_targetSize.height() > 0 ) ? m_targetSize.width() / (float)m_targetSize.height() : 0;
QString bestImage;
- QString bestImageWithSameAspectRatio;
foreach (const QString &entry, images) {
QSize candidate = resSize(QFileInfo(entry).baseName());
if (candidate == QSize()) {
continue;
}
- float candidateAspectRatio = (candidate.height() > 0 ) ? candidate.width() / (float)candidate.height() : FLT_MAX;
+ //float candidateAspectRatio = (candidate.height() > 0 ) ? candidate.width() / (float)candidate.height() : FLT_MAX;
- double dist = distance(candidate, m_targetSize);
+ float dist = distance(candidate, m_targetSize);
//qDebug() << "candidate" << candidate << "distance" << dist << "aspect ratio" << candidateAspectRatio;
- if ( candidateAspectRatio == targetAspectRatio && (bestImageWithSameAspectRatio.isEmpty() || dist < bestWithSameAspectRatio) ) {
- bestImageWithSameAspectRatio = entry;
- bestWithSameAspectRatio = dist;
- //qDebug() << "bestWithSameAspectRatio" << bestImageWithSameAspectRatio;
- if (dist == 0) {
- break;
- }
- } else if (bestImage.isEmpty() || dist < best) {
+ if (bestImage.isEmpty() || dist < best) {
bestImage = entry;
best = dist;
//qDebug() << "best" << bestImage;
}
}
- if (!bestImageWithSameAspectRatio.isEmpty()) // Always prefer an image with the same aspect ratio as the target (if available)
- bestImage=bestImageWithSameAspectRatio;
-
//qDebug() << "best image" << bestImage;
+ return bestImage;
+}
+
+void Image::findPreferedImageInPackage(KPackage::Package &package)
+{
+ if (!package.isValid() || !package.filePath("preferred").isEmpty()) {
+ return;
+ }
+
+ QString preferred = findPreferedImage( package.entryList("images") );
+
package.removeDefinition("preferred");
- package.addFileDefinition("preferred", "images/" + bestImage, i18n("Recommended wallpaper file"));
+ package.addFileDefinition("preferred", "images/" + preferred, i18n("Recommended wallpaper file"));
}
QSize Image::targetSize() const
diff --git a/wallpapers/image/image.h b/wallpapers/image/image.h
index 6b9f63c..0f50959 100644
--- a/wallpapers/image/image.h
+++ b/wallpapers/image/image.h
@@ -114,6 +114,7 @@ class Image : public QObject, public QQmlParserStatus
void setSlidePaths(const QStringList &slidePaths);
void findPreferedImageInPackage(KPackage::Package &package);
+ QString findPreferedImage(const QStringList &images);
void classBegin() override;
void componentComplete() override;