diff --git a/bindings/java/openshot.i b/bindings/java/openshot.i index 55cec262..b0a79348 100644 --- a/bindings/java/openshot.i +++ b/bindings/java/openshot.i @@ -170,6 +170,7 @@ %include "effects/Crop.h" %include "effects/Deinterlace.h" %include "effects/Hue.h" +%include "effects/LensFlare.h" %include "effects/Mask.h" %include "effects/Negate.h" %include "effects/Pixelate.h" diff --git a/bindings/python/openshot.i b/bindings/python/openshot.i index e673f3f1..a39df4c8 100644 --- a/bindings/python/openshot.i +++ b/bindings/python/openshot.i @@ -342,6 +342,7 @@ %include "effects/Crop.h" %include "effects/Deinterlace.h" %include "effects/Hue.h" +%include "effects/LensFlare.h" %include "effects/Mask.h" %include "effects/Negate.h" %include "effects/Pixelate.h" diff --git a/bindings/ruby/openshot.i b/bindings/ruby/openshot.i index a7ef11b4..be6fa19b 100644 --- a/bindings/ruby/openshot.i +++ b/bindings/ruby/openshot.i @@ -209,6 +209,7 @@ %include "effects/Crop.h" %include "effects/Deinterlace.h" %include "effects/Hue.h" +%include "effects/LensFlare.h" %include "effects/Mask.h" %include "effects/Negate.h" %include "effects/Pixelate.h" diff --git a/src/effects/LensFlare.h b/src/effects/LensFlare.h index f531a809..ef41846d 100644 --- a/src/effects/LensFlare.h +++ b/src/effects/LensFlare.h @@ -21,10 +21,12 @@ namespace openshot { - class LensFlare : public EffectBase { private: + void init_effect_details(); + + public: Keyframe x; Keyframe y; Keyframe brightness; @@ -32,9 +34,6 @@ namespace openshot Keyframe spread; Color color; - void init_effect_details(); - - public: LensFlare(); ~LensFlare() override; LensFlare(const Keyframe &xPos, diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index bcae500b..d0b6c827 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -45,6 +45,7 @@ set(OPENSHOT_TESTS # Effects ChromaKey Crop + LensFlare Sharpen SphericalEffect ) diff --git a/tests/LensFlare.cpp b/tests/LensFlare.cpp new file mode 100644 index 00000000..6e1c9cef --- /dev/null +++ b/tests/LensFlare.cpp @@ -0,0 +1,108 @@ +/** + * @file + * @brief Unit tests for Lens Flare effect + * @author Jonathan Thomas + * + * @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/LensFlare.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; +} + +// Create a small 5×5 grayscale frame +static std::shared_ptr makeGrayFrame() +{ + QImage img(5, 5, QImage::Format_ARGB32); + img.fill(QColor(100, 100, 100, 255)); + auto frame = std::make_shared(); + *frame->GetImage() = img; + return frame; +} + +TEST_CASE("LensFlare brightens center pixel", "[effect][lensflare]") +{ + LensFlare effect; + effect.x = Keyframe(0.0); + effect.y = Keyframe(0.0); + effect.brightness = Keyframe(1.0); + effect.size = Keyframe(1.0); + effect.spread = Keyframe(0.0); + + auto frame = makeGrayFrame(); + QColor before = frame->GetImage()->pixelColor(2, 2); + + auto out = effect.GetFrame(frame, 1); + QColor after = out->GetImage()->pixelColor(2, 2); + + CHECK(after != before); +} + +TEST_CASE("LensFlare size controls area of effect", "[effect][lensflare]") +{ + LensFlare small, large; + small.x = Keyframe(0.0); + large.x = Keyframe(0.0); + small.y = Keyframe(0.0); + large.y = Keyframe(0.0); + small.brightness = Keyframe(1.0); + large.brightness = Keyframe(1.0); + small.spread = Keyframe(0.0); + large.spread = Keyframe(0.0); + small.size = Keyframe(0.2); + large.size = Keyframe(1.0); + + auto frameSmall = makeGrayFrame(); + auto frameLarge = makeGrayFrame(); + QColor beforeSmall = frameSmall->GetImage()->pixelColor(2, 2); + QColor beforeLarge = frameLarge->GetImage()->pixelColor(2, 2); + + auto outSmall = small.GetFrame(frameSmall, 1); + auto outLarge = large.GetFrame(frameLarge, 1); + QColor afterSmall = outSmall->GetImage()->pixelColor(2, 2); + QColor afterLarge = outLarge->GetImage()->pixelColor(2, 2); + + CHECK(afterSmall == beforeSmall); + CHECK(afterLarge != beforeLarge); +} + +TEST_CASE("LensFlare brightness scales intensity", "[effect][lensflare]") +{ + LensFlare low, high; + low.x = Keyframe(0.0); + high.x = Keyframe(0.0); + low.y = Keyframe(0.0); + high.y = Keyframe(0.0); + low.size = Keyframe(1.0); + high.size = Keyframe(1.0); + low.spread = Keyframe(0.0); + high.spread = Keyframe(0.0); + low.brightness = Keyframe(0.2); + high.brightness= Keyframe(1.0); + + auto frameLow = makeGrayFrame(); + auto frameHigh = makeGrayFrame(); + auto outLow = low.GetFrame(frameLow, 1); + auto outHigh = high.GetFrame(frameHigh, 1); + QColor cLow = outLow->GetImage()->pixelColor(2, 2); + QColor cHigh = outHigh->GetImage()->pixelColor(2, 2); + + CHECK(cLow.red() < cHigh.red()); +} \ No newline at end of file