From ec890fe74d07d5198e708dad68751af474e6d37b Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Wed, 21 May 2025 18:25:22 -0500 Subject: [PATCH] Adding unit tests for spherical project effect, using 2 PNG assets --- examples/eq_sphere.png | Bin 0 -> 635 bytes examples/fisheye.png | Bin 0 -> 1328 bytes tests/CMakeLists.txt | 1 + tests/SphericalEffect.cpp | 146 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+) create mode 100644 examples/eq_sphere.png create mode 100644 examples/fisheye.png create mode 100644 tests/SphericalEffect.cpp diff --git a/examples/eq_sphere.png b/examples/eq_sphere.png new file mode 100644 index 0000000000000000000000000000000000000000..53273886926c015dbeaeb5dcc06e67f617c2e180 GIT binary patch literal 635 zcmeAS@N?(olHy`uVBq!ia0y~yV9a1(VA#UJ#K6E{#-o_Tz`*3>>EaktG3V`-gS-t6 zJj{+x|81Rlf1iB0WG0u6ec8Tt-p4Ow`{F*%lViB!ZqeW~ibg{KH3Z(U3!Gp{_dO6L R&%nUI;OXk;vd$@?2><|f)209b literal 0 HcmV?d00001 diff --git a/examples/fisheye.png b/examples/fisheye.png new file mode 100644 index 0000000000000000000000000000000000000000..8b149821110d4a8b779c44bb82f1a25092d1e69d GIT binary patch literal 1328 zcmeAS@N?(olHy`uVBq!ia0y~yU^oH7983%h3`$m(Cm9%6zI(bjhE&XXd+YYJ#a2A7 z7bpDx|NIKGsfM_~f$6#4pJu(c?Q>lHbWX`M@qfQ->{9CsBByOrFU-AH9w-yA&a!#- ziq>pZu)g2omHRKJ!F~P>KbaeWmfX+4J))Jsa?(y5DPsTY=8OV{z`X`t%)1g zEm}1vCp02NH2Q4K>BEawNs9Q-JRdPZgQvUHw0~3N^cL69&6+bR$|6Ecm*3g>S(00* zGI8U&v}vZbW@0Kvhmv9+Rxf7W%zm2YX;zIG;4PPz!5kePSX1BDY)o5Z-=}T>k0~un{bYj*rZB z>=G7E-Kq-F+5$HD)1%4OEH@%1DCl?yfK3DogH)fL9ubg`?AWwH!4ZozZsCt{(^9`k z3J8E5!Fi~OB@to9p7{0R@u>^frbZ%Lxj*saPuaC=bT@8I3 z$#cHq@jDUB+sNO2TOhUU=?1W33(oG_0z3Q8ZrG?$C@1F4eSYq>L&rc?KFW@`(^l~) zS{)Lum!RRggR^^SYyP_13CWI+>~yAy_2sPwF#{uXbeGKga^P6gk;@w*q9SZ{6qA!L zip?_z#oL|@5mCmcXW2<}3*AiIxaHXt>+h3#U86x!|1i`e`m@Gt)A<_}0_DWKv)PUY zue%ko1(aa2*E`+nT2-{E=2(+U^M;71k5|rbIeTo;T8~*in{S4CM1#`Z>GKg=p2i;L zH2e3#FS>5)+}Pj$wU_Aj&+_;ERLY$DbJ2|Huc~!!eR49zT3n*FN%D-6zx4P%SLW$ie8Mlk^k3ML>OMd6%kNU=+{g>LT(R|L&e6$VYyKyz{ry?f z_NRRL)&J|i%#i=JaTh3ewf}9JvhA0|*LlbNr)LMIyota2aerlcsU}bT>c@wxBrCWN zMpVpy>_6dA)S48Fx@fk^QIfV{U3>gy z`evp6D$x9NOTs_v>4T1yCqEZWymIQSW3ceEry47#Zhri(MgL5!zx4X&eywLt=Lc!u zUw)r6V8-`(W{z^n$72%{t8Tee&y#)Jdh~Us@VA3~JuYGv%dUv + * + * @ref License + */ + +// Copyright (c) 2008-2025 OpenShot Studios, LLC +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include +#include +#include +#include "Frame.h" +#include "effects/SphericalProjection.h" +#include "openshot_catch.h" + +using namespace openshot; + +// allow Catch2 to print QColor on failure +static std::ostream& operator<<(std::ostream& os, QColor const& c) +{ + os << "QColor(" << c.red() << "," << c.green() + << "," << c.blue() << "," << c.alpha() << ")"; + return os; +} + +// load a PNG into a Frame +static std::shared_ptr loadFrame(const char* filename) +{ + QImage img(QString(TEST_MEDIA_PATH) + filename); + img = img.convertToFormat(QImage::Format_ARGB32); + auto f = std::make_shared(); + *f->GetImage() = img; + return f; +} + +// apply effect and sample center pixel +static QColor centerPixel(SphericalProjection& e, + std::shared_ptr f) +{ + auto img = e.GetFrame(f, 1)->GetImage(); + int cx = img->width() / 2; + int cy = img->height() / 2; + return img->pixelColor(cx, cy); +} + +TEST_CASE("sphere mode default and invert", "[effect][spherical]") +{ + SphericalProjection e; + e.projection_mode = 0; + e.yaw = Keyframe(45.0); + + { + auto f0 = loadFrame("eq_sphere.png"); + e.invert = 0; + e.interpolation = 0; + // eq_sphere.png has green stripe at center + CHECK(centerPixel(e, f0) == QColor(255,0,0,255)); + } + { + auto f1 = loadFrame("eq_sphere.png"); + e.yaw = Keyframe(-45.0); + e.invert = 0; + e.interpolation = 1; + // invert flips view 180°, center maps to blue stripe + CHECK(centerPixel(e, f1) == QColor(0,0,255,255)); + } + { + auto f1 = loadFrame("eq_sphere.png"); + e.yaw = Keyframe(0.0); + e.invert = 1; + e.interpolation = 0; + // invert flips view 180°, center maps to blue stripe + CHECK(centerPixel(e, f1) == QColor(0,255,0,255)); + } +} + +TEST_CASE("hemisphere mode default and invert", "[effect][spherical]") +{ + SphericalProjection e; + e.projection_mode = 1; + + { + auto f0 = loadFrame("eq_sphere.png"); + e.yaw = Keyframe(45.0); + e.invert = 0; + e.interpolation = 0; + // hemisphere on full pano still shows green at center + CHECK(centerPixel(e, f0) == QColor(255,0,0,255)); + } + { + auto f1 = loadFrame("eq_sphere.png"); + e.yaw = Keyframe(-45.0); + e.invert = 0; + e.interpolation = 1; + // invert=1 flips center to blue + CHECK(centerPixel(e, f1) == QColor(0,0,255,255)); + } + { + auto f1 = loadFrame("eq_sphere.png"); + e.yaw = Keyframe(-180.0); + e.invert = 0; + e.interpolation = 0; + // invert=1 flips center to blue + CHECK(centerPixel(e, f1) == QColor(0,255,0,255)); + } +} + +TEST_CASE("fisheye mode default and invert", "[effect][spherical]") +{ + SphericalProjection e; + e.projection_mode = 2; + e.fov = Keyframe(180.0); + + { + auto f0 = loadFrame("fisheye.png"); + e.invert = 0; + e.interpolation = 0; + // circular mask center remains white + CHECK(centerPixel(e, f0) == QColor(255,255,255,255)); + } + { + auto f1 = loadFrame("fisheye.png"); + e.invert = 1; + e.interpolation = 1; + e.fov = Keyframe(90.0); + // invert has no effect on center + CHECK(centerPixel(e, f1) == QColor(255,255,255,255)); + } +} + +TEST_CASE("fisheye mode yaw has no effect at center", "[effect][spherical]") +{ + SphericalProjection e; + e.projection_mode = 2; + e.interpolation = 0; + e.fov = Keyframe(180.0); + e.invert = 0; + + auto f = loadFrame("fisheye.png"); + e.yaw = Keyframe(45.0); + CHECK(centerPixel(e, f) == QColor(255,255,255,255)); +}