From cd887c7e8e9f89e2b71b3dbe37707e32bcf156aa Mon Sep 17 00:00:00 2001 From: HaiVQ Date: Tue, 10 Dec 2024 17:13:34 +0700 Subject: [PATCH 01/16] Add Outline effect class and integrate into OpenShot --- bindings/python/openshot.i | 2 + src/CMakeLists.txt | 1 + src/Effects.h | 1 + src/effects/Outline.cpp | 177 +++++++++++++++++++++++++++++++++++++ src/effects/Outline.h | 99 +++++++++++++++++++++ 5 files changed, 280 insertions(+) create mode 100644 src/effects/Outline.cpp create mode 100644 src/effects/Outline.h diff --git a/bindings/python/openshot.i b/bindings/python/openshot.i index 2bca526a..e673f3f1 100644 --- a/bindings/python/openshot.i +++ b/bindings/python/openshot.i @@ -114,6 +114,7 @@ #include "effects/Stabilizer.h" #include "effects/Tracker.h" #include "effects/ObjectDetection.h" + #include "effects/Outline.h" #include "TrackedObjectBase.h" #include "TrackedObjectBBox.h" %} @@ -351,4 +352,5 @@ %include "effects/Stabilizer.h" %include "effects/Tracker.h" %include "effects/ObjectDetection.h" + %include "effects/Outline.h" #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3e541cc2..54f196c6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -99,6 +99,7 @@ set(OPENSHOT_CV_SOURCES effects/Stabilizer.cpp effects/Tracker.cpp effects/ObjectDetection.cpp + effects/Outline.cpp ./sort_filter/sort.cpp ./sort_filter/Hungarian.cpp ./sort_filter/KalmanTracker.cpp) diff --git a/src/Effects.h b/src/Effects.h index c1005c59..bfc3fcf0 100644 --- a/src/Effects.h +++ b/src/Effects.h @@ -43,6 +43,7 @@ /* OpenCV Effects */ #ifdef USE_OPENCV +#include "effects/Outline.h" #include "effects/ObjectDetection.h" #include "effects/Tracker.h" #include "effects/Stabilizer.h" diff --git a/src/effects/Outline.cpp b/src/effects/Outline.cpp new file mode 100644 index 00000000..5f6c3717 --- /dev/null +++ b/src/effects/Outline.cpp @@ -0,0 +1,177 @@ +/** + * @file + * @brief Source file for Outline effect class + * @author Jonathan Thomas , Hai Vu + * + * @ref License + */ + +// Copyright (c) 2008-2019 OpenShot Studios, LLC +// +// SPDX-License-Identifier: LGPL-3.0-or-later +#include +#include "Outline.h" +#include "Exceptions.h" + +using namespace openshot; + +/// Blank constructor, useful when using Json to load the effect properties +Outline::Outline() : width(3.0), red(0.0), green(0.0), blue(0.0), alpha(255.0) { + // Init effect properties + init_effect_details(); +} + +// Default constructor +Outline::Outline(Keyframe width, Keyframe red, Keyframe green, Keyframe blue, Keyframe alpha) : + width(width), red(red), green(green), blue(blue), alpha(alpha) +{ + // Init effect properties + init_effect_details(); +} + +// Init effect settings +void Outline::init_effect_details() +{ + /// Initialize the values of the EffectInfo struct. + InitEffectInfo(); + + /// Set the effect info + info.class_name = "Outline"; + info.name = "Outline"; + info.description = "Add outline around the image with transparent background."; + info.has_audio = false; + info.has_video = true; +} + +// This method is required for all derived classes of EffectBase, and returns a +// modified openshot::Frame object +std::shared_ptr Outline::GetFrame(std::shared_ptr frame, int64_t frame_number) +{ + // Get the frame's image + std::shared_ptr frame_image = frame->GetImage(); + + int sigmaValue = width.GetValue(frame_number) / 3; + int redValue = red.GetValue(frame_number); + int greenValue = green.GetValue(frame_number); + int blueValue = blue.GetValue(frame_number); + int alphaValue = alpha.GetValue(frame_number); + + // Get ARGB image from QImage + cv::Mat cv_image = QImageToARGBCvMat(frame_image); + + // extract alpha channel to create the alpha mask from the image + std::vector channels(4); + cv::split(cv_image, channels); + cv::Mat alpha_mask = channels[3].clone(); + cv::threshold(alpha_mask, alpha_mask, 254, 255, cv::ThresholdTypes::THRESH_BINARY); // threshold the alpha channel to remove aliased edges + + + // Create the outline mask + cv::Mat outline_mask; + cv::GaussianBlur(alpha_mask, outline_mask, cv::Size(0, 0), sigmaValue, sigmaValue, cv::BorderTypes::BORDER_DEFAULT); + cv::threshold(outline_mask, outline_mask, 0, 255, cv::ThresholdTypes::THRESH_BINARY); + + cv::Mat final_image; + + // create solid color source mat + cv::Mat solid_color_mat(cv::Size(cv_image.cols, cv_image.rows), CV_8UC4, cv::Scalar(blueValue, greenValue, redValue, alphaValue)); + + // place outline image first, then place the original image (de-antialiased) on top + solid_color_mat.copyTo(final_image, outline_mask); + cv_image.copyTo(final_image, alpha_mask); + + std::shared_ptr new_frame_image = ARGBCvMatToQImage(final_image); + + // FIXME: The shared_ptr::swap does not work somehow + // frame_image.swap(new_frame_image); + *frame_image = *new_frame_image; + + // return the modified frame + return frame; +} + +cv::Mat Outline::QImageToARGBCvMat(std::shared_ptr& qimage) { + return cv::Mat(qimage->height(), qimage->width(), CV_8UC4, (uchar*)qimage->constBits(), qimage->bytesPerLine()); +} + +std::shared_ptr Outline::ARGBCvMatToQImage(cv::Mat img) { + QImage qimage(img.data, img.cols, img.rows, img.step, QImage::Format_ARGB32); + std::shared_ptr imgIn = std::make_shared(qimage.convertToFormat(QImage::Format_RGBA8888_Premultiplied)); + return imgIn; +} + +// Generate JSON string of this object +std::string Outline::Json() const { + + // Return formatted string + return JsonValue().toStyledString(); +} + +// Generate Json::Value for this object +Json::Value Outline::JsonValue() const { + + // Create root json object + Json::Value root = EffectBase::JsonValue(); // get parent properties + root["type"] = info.class_name; + root["width"] = width.JsonValue(); + root["red"] = red.JsonValue(); + root["green"] = green.JsonValue(); + root["blue"] = blue.JsonValue(); + root["alpha"] = alpha.JsonValue(); + + // return JsonValue + return root; +} + +// Load JSON string into this object +void Outline::SetJson(const std::string value) { + + // Parse JSON string into JSON objects + try + { + const Json::Value root = openshot::stringToJson(value); + // Set all values that match + SetJsonValue(root); + } + catch (const std::exception& e) + { + // Error parsing JSON (or missing keys) + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); + } +} + +// Load Json::Value into this object +void Outline::SetJsonValue(const Json::Value root) { + + // Set parent data + EffectBase::SetJsonValue(root); + + // Set data from Json (if key is found) + if (!root["width"].isNull()) + width.SetJsonValue(root["width"]); + if (!root["red"].isNull()) + red.SetJsonValue(root["red"]); + if (!root["green"].isNull()) + green.SetJsonValue(root["green"]); + if (!root["blue"].isNull()) + blue.SetJsonValue(root["blue"]); + if (!root["alpha"].isNull()) + alpha.SetJsonValue(root["alpha"]); +} + +// Get all properties for a specific frame +std::string Outline::PropertiesJSON(int64_t requested_frame) const { + + // Generate JSON properties list + Json::Value root = BasePropertiesJSON(requested_frame); + + // Keyframes + root["width"] = add_property_json("Width", width.GetValue(requested_frame), "float", "", &width, 0, 1000, false, requested_frame); + root["red"] = add_property_json("Red", red.GetValue(requested_frame), "float", "", &red, 0, 255, false, requested_frame); + root["green"] = add_property_json("Green", green.GetValue(requested_frame), "float", "", &green, 0, 255, false, requested_frame); + root["blue"] = add_property_json("Blue", blue.GetValue(requested_frame), "float", "", &blue, 0, 255, false, requested_frame); + root["alpha"] = add_property_json("Alpha", alpha.GetValue(requested_frame), "float", "", &alpha, 0, 255, false, requested_frame); + + // Return formatted string + return root.toStyledString(); +} diff --git a/src/effects/Outline.h b/src/effects/Outline.h new file mode 100644 index 00000000..5345e12d --- /dev/null +++ b/src/effects/Outline.h @@ -0,0 +1,99 @@ +/** + * @file + * @brief Header file for Outline effect class + * @author Jonathan Thomas , Hai Vu + * + * @ref License + */ + +// Copyright (c) 2008-2019 OpenShot Studios, LLC +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef OPENSHOT_OUTLINE_EFFECT_H +#define OPENSHOT_OUTLINE_EFFECT_H + +#include "../EffectBase.h" + +#include "../Frame.h" +#include "../Json.h" +#include "../KeyFrame.h" + +#include +#include + + +namespace openshot +{ + + /** + * @brief This class add the outline around image with transparent background and can be animated + * with openshot::Keyframe curves over time. + * + * Since outline effect is pretty useful in many cases, this effect is added to libopenshot. + */ + class Outline : public EffectBase + { + private: + /// Init effect settings + void init_effect_details(); + + // Convert QImage to cv::Mat and vice versa + // Although Frame class has GetImageCV, but it does not include alpha channel + // so we need a separate methods which preserve alpha channel + // Idea from: https://stackoverflow.com/a/78480103 + cv::Mat QImageToARGBCvMat(std::shared_ptr& qimage); + std::shared_ptr ARGBCvMatToQImage(cv::Mat img); + + public: + Keyframe width; ///< Width of the outline + Keyframe red; ///< Red channel of the outline + Keyframe green; ///< Green of the outline + Keyframe blue; ///< Blue of the outline + Keyframe alpha; ///< Alpha of the outline + + /// Blank constructor, useful when using Json to load the effect properties + Outline(); + + /// Default constructor, which require width + /// + /// @param width the width of the outline (between 0 and 1000, rounded to int) + /// @param red the red channel of the outline (between 0 and 255, rounded to int) + /// @param green the green channel of the outline (between 0 and 255, rounded to int) + /// @param blue the blue channel of the outline (between 0 and 255, rounded to int) + /// @param alpha the alpha channel of the outline (between 0 and 255, rounded to int) + Outline(Keyframe width, Keyframe red, Keyframe green, Keyframe blue, Keyframe alpha); + + /// @brief This method is required for all derived classes of ClipBase, and returns a + /// new openshot::Frame object. All Clip keyframes and effects are resolved into + /// pixels. + /// + /// @returns A new openshot::Frame object + /// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline. + std::shared_ptr GetFrame(int64_t frame_number) override { return GetFrame(std::make_shared(), frame_number); } + + /// @brief This method is required for all derived classes of ClipBase, and returns a + /// modified openshot::Frame object + /// + /// The frame object is passed into this method and used as a starting point (pixels and audio). + /// All Clip keyframes and effects are resolved into pixels. + /// + /// @returns The modified openshot::Frame object + /// @param frame The frame object that needs the clip or effect applied to it + /// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline. + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; + + // Get and Set JSON methods + std::string Json() const override; ///< Generate JSON string of this object + void SetJson(const std::string value) override; ///< Load JSON string into this object + Json::Value JsonValue() const override; ///< Generate Json::Value for this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object + + /// Get all properties for a specific frame (perfect for a UI to display the current state + /// of all properties at any time) + std::string PropertiesJSON(int64_t requested_frame) const override; + }; + +} + +#endif From 8bee172ff60e637a7e1678113f0df8fea41d10a1 Mon Sep 17 00:00:00 2001 From: HaiVQ Date: Tue, 10 Dec 2024 19:01:53 +0700 Subject: [PATCH 02/16] Fix author name formatting in Outline effect class documentation and remove unused include --- src/effects/Outline.cpp | 4 ++-- src/effects/Outline.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/effects/Outline.cpp b/src/effects/Outline.cpp index 5f6c3717..664dcd6d 100644 --- a/src/effects/Outline.cpp +++ b/src/effects/Outline.cpp @@ -1,7 +1,7 @@ /** * @file * @brief Source file for Outline effect class - * @author Jonathan Thomas , Hai Vu + * @author Jonathan Thomas , HaiVQ * * @ref License */ @@ -9,7 +9,7 @@ // Copyright (c) 2008-2019 OpenShot Studios, LLC // // SPDX-License-Identifier: LGPL-3.0-or-later -#include + #include "Outline.h" #include "Exceptions.h" diff --git a/src/effects/Outline.h b/src/effects/Outline.h index 5345e12d..23c3b15c 100644 --- a/src/effects/Outline.h +++ b/src/effects/Outline.h @@ -1,7 +1,7 @@ /** * @file * @brief Header file for Outline effect class - * @author Jonathan Thomas , Hai Vu + * @author Jonathan Thomas , HaiVQ * * @ref License */ From 975041d82dab5503de0863e9e525219d34e2a8b3 Mon Sep 17 00:00:00 2001 From: HaiVQ Date: Tue, 10 Dec 2024 20:18:12 +0700 Subject: [PATCH 03/16] Enhance Outline effect by adding antialiasing to the edge detection process and combining masks for improved output quality --- src/effects/Outline.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/effects/Outline.cpp b/src/effects/Outline.cpp index 664dcd6d..36e7e01f 100644 --- a/src/effects/Outline.cpp +++ b/src/effects/Outline.cpp @@ -71,6 +71,19 @@ std::shared_ptr Outline::GetFrame(std::shared_ptr Date: Tue, 10 Dec 2024 20:47:26 +0700 Subject: [PATCH 04/16] Remove debug image output in Outline effect processing --- src/effects/Outline.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/effects/Outline.cpp b/src/effects/Outline.cpp index 36e7e01f..01f7fc4e 100644 --- a/src/effects/Outline.cpp +++ b/src/effects/Outline.cpp @@ -83,7 +83,7 @@ std::shared_ptr Outline::GetFrame(std::shared_ptr Date: Tue, 10 Dec 2024 23:28:15 +0700 Subject: [PATCH 05/16] Disable alpha channel thresholding in Outline effect to prevent removal of aliased edges --- src/effects/Outline.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/effects/Outline.cpp b/src/effects/Outline.cpp index 01f7fc4e..e570c90e 100644 --- a/src/effects/Outline.cpp +++ b/src/effects/Outline.cpp @@ -63,7 +63,9 @@ std::shared_ptr Outline::GetFrame(std::shared_ptr channels(4); cv::split(cv_image, channels); cv::Mat alpha_mask = channels[3].clone(); - cv::threshold(alpha_mask, alpha_mask, 254, 255, cv::ThresholdTypes::THRESH_BINARY); // threshold the alpha channel to remove aliased edges + + // Disable de-antialiased + // cv::threshold(alpha_mask, alpha_mask, 254, 255, cv::ThresholdTypes::THRESH_BINARY); // threshold the alpha channel to remove aliased edges // Create the outline mask From 3b107890adfdccf0ebfe509c1944635e7b4ac325 Mon Sep 17 00:00:00 2001 From: HaiVQ Date: Wed, 11 Dec 2024 16:46:54 +0700 Subject: [PATCH 06/16] Rename ARGB conversion functions to BGRA for consistency and clarity --- src/effects/Outline.cpp | 10 +++++----- src/effects/Outline.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/effects/Outline.cpp b/src/effects/Outline.cpp index e570c90e..ddbc813a 100644 --- a/src/effects/Outline.cpp +++ b/src/effects/Outline.cpp @@ -56,8 +56,8 @@ std::shared_ptr Outline::GetFrame(std::shared_ptr channels(4); @@ -95,7 +95,7 @@ std::shared_ptr Outline::GetFrame(std::shared_ptr new_frame_image = ARGBCvMatToQImage(final_image); + std::shared_ptr new_frame_image = BGRACvMatToQImage(final_image); // FIXME: The shared_ptr::swap does not work somehow // frame_image.swap(new_frame_image); @@ -105,11 +105,11 @@ std::shared_ptr Outline::GetFrame(std::shared_ptr& qimage) { +cv::Mat Outline::QImageToBGRACvMat(std::shared_ptr& qimage) { return cv::Mat(qimage->height(), qimage->width(), CV_8UC4, (uchar*)qimage->constBits(), qimage->bytesPerLine()); } -std::shared_ptr Outline::ARGBCvMatToQImage(cv::Mat img) { +std::shared_ptr Outline::BGRACvMatToQImage(cv::Mat img) { QImage qimage(img.data, img.cols, img.rows, img.step, QImage::Format_ARGB32); std::shared_ptr imgIn = std::make_shared(qimage.convertToFormat(QImage::Format_RGBA8888_Premultiplied)); return imgIn; diff --git a/src/effects/Outline.h b/src/effects/Outline.h index 23c3b15c..2cdb3392 100644 --- a/src/effects/Outline.h +++ b/src/effects/Outline.h @@ -42,8 +42,8 @@ namespace openshot // Although Frame class has GetImageCV, but it does not include alpha channel // so we need a separate methods which preserve alpha channel // Idea from: https://stackoverflow.com/a/78480103 - cv::Mat QImageToARGBCvMat(std::shared_ptr& qimage); - std::shared_ptr ARGBCvMatToQImage(cv::Mat img); + cv::Mat QImageToBGRACvMat(std::shared_ptr& qimage); + std::shared_ptr BGRACvMatToQImage(cv::Mat img); public: Keyframe width; ///< Width of the outline From fc3f76732b40fbe1e43b52f9622b05e438928408 Mon Sep 17 00:00:00 2001 From: HaiVQ Date: Wed, 11 Dec 2024 13:21:44 +0000 Subject: [PATCH 07/16] Update Outline class documentation to clarify parameters in the default constructor --- src/effects/Outline.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/effects/Outline.h b/src/effects/Outline.h index 2cdb3392..a4df35cb 100644 --- a/src/effects/Outline.h +++ b/src/effects/Outline.h @@ -55,7 +55,7 @@ namespace openshot /// Blank constructor, useful when using Json to load the effect properties Outline(); - /// Default constructor, which require width + /// Default constructor, which require width, red, green, blue, alpha /// /// @param width the width of the outline (between 0 and 1000, rounded to int) /// @param red the red channel of the outline (between 0 and 255, rounded to int) From 4109a9b953bd978a7df2a25d72480610cc6c7809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C5=A9=20Quang=20H=E1=BA=A3i?= Date: Mon, 16 Dec 2024 14:17:08 +0700 Subject: [PATCH 08/16] Update Outline.cpp --- src/effects/Outline.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/effects/Outline.cpp b/src/effects/Outline.cpp index ddbc813a..26d79edd 100644 --- a/src/effects/Outline.cpp +++ b/src/effects/Outline.cpp @@ -97,9 +97,10 @@ std::shared_ptr Outline::GetFrame(std::shared_ptr new_frame_image = BGRACvMatToQImage(final_image); + + frame_image.swap(new_frame_image); // FIXME: The shared_ptr::swap does not work somehow - // frame_image.swap(new_frame_image); - *frame_image = *new_frame_image; + // *frame_image = *new_frame_image; // return the modified frame return frame; From e63fc6448e27c9d5a22ff3a2ff5861f1d8bcaacd Mon Sep 17 00:00:00 2001 From: HaiVQ Date: Mon, 16 Dec 2024 09:22:15 +0000 Subject: [PATCH 09/16] switch back to trditional pointer assignment --- src/effects/Outline.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/effects/Outline.cpp b/src/effects/Outline.cpp index 26d79edd..d70f7ee0 100644 --- a/src/effects/Outline.cpp +++ b/src/effects/Outline.cpp @@ -97,10 +97,10 @@ std::shared_ptr Outline::GetFrame(std::shared_ptr new_frame_image = BGRACvMatToQImage(final_image); - - frame_image.swap(new_frame_image); // FIXME: The shared_ptr::swap does not work somehow - // *frame_image = *new_frame_image; + // frame_image.swap(new_frame_image); + *frame_image = *new_frame_image; + // return the modified frame return frame; From f475670f0aa7bd84cc1e7ecfb53025e39f0caa16 Mon Sep 17 00:00:00 2001 From: HaiVQ Date: Wed, 18 Dec 2024 02:32:07 +0000 Subject: [PATCH 10/16] Add Outline effect to EffectInfo and update JSON output --- src/EffectInfo.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/EffectInfo.cpp b/src/EffectInfo.cpp index 658450b0..94221aed 100644 --- a/src/EffectInfo.cpp +++ b/src/EffectInfo.cpp @@ -98,6 +98,9 @@ EffectBase* EffectInfo::CreateEffect(std::string effect_type) { return new Whisperization(); #ifdef USE_OPENCV + else if (effect_type == "Outline") + return new Outline(); + else if(effect_type == "Stabilizer") return new Stabilizer(); @@ -145,7 +148,8 @@ Json::Value EffectInfo::JsonValue() { root.append(Whisperization().JsonInfo()); #ifdef USE_OPENCV - root.append(Stabilizer().JsonInfo()); + root.append(Outline().JsonInfo()); + root.append(Stabilizer().JsonInfo()); root.append(Tracker().JsonInfo()); root.append(ObjectDetection().JsonInfo()); #endif From 9593a36b4f1292716a6cdb0c68840fd86958cde5 Mon Sep 17 00:00:00 2001 From: HaiVQ Date: Wed, 18 Dec 2024 02:37:03 +0000 Subject: [PATCH 11/16] Add validation for width and alpha values in Outline effect --- src/effects/Outline.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/effects/Outline.cpp b/src/effects/Outline.cpp index d70f7ee0..4fe6fafb 100644 --- a/src/effects/Outline.cpp +++ b/src/effects/Outline.cpp @@ -50,12 +50,19 @@ std::shared_ptr Outline::GetFrame(std::shared_ptr frame_image = frame->GetImage(); - int sigmaValue = width.GetValue(frame_number) / 3; + int widthValue = width.GetValue(frame_number); int redValue = red.GetValue(frame_number); int greenValue = green.GetValue(frame_number); int blueValue = blue.GetValue(frame_number); int alphaValue = alpha.GetValue(frame_number); + if ((widthValue <= 0) || (alphaValue <= 0)) { + // If alpha or width is zero, return the original frame + return frame; + } + + int sigmaValue = widthValue / 3; + // Get BGRA image from QImage cv::Mat cv_image = QImageToBGRACvMat(frame_image); From 8c846262a38b9c45eb792f9044520e34518c2afe Mon Sep 17 00:00:00 2001 From: HaiVQ Date: Fri, 21 Feb 2025 12:33:50 +0000 Subject: [PATCH 12/16] Correct color channel while converting QImage to cv::Mat --- src/effects/Outline.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/effects/Outline.cpp b/src/effects/Outline.cpp index 4fe6fafb..2d2e52e7 100644 --- a/src/effects/Outline.cpp +++ b/src/effects/Outline.cpp @@ -114,7 +114,9 @@ std::shared_ptr Outline::GetFrame(std::shared_ptr& qimage) { - return cv::Mat(qimage->height(), qimage->width(), CV_8UC4, (uchar*)qimage->constBits(), qimage->bytesPerLine()); + cv::Mat cv_img(qimage->height(), qimage->width(), CV_8UC4, (uchar*)qimage->constBits(), qimage->bytesPerLine()); + cv::cvtColor(cv_img, cv_img, cv::COLOR_RGBA2BGRA); + return cv_img; } std::shared_ptr Outline::BGRACvMatToQImage(cv::Mat img) { From 0acb091effee8d014d1331463f0b6dff30628abf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C5=A9=20Quang=20H=E1=BA=A3i?= Date: Sat, 22 Feb 2025 18:03:31 +0700 Subject: [PATCH 13/16] Update Outline.cpp --- src/effects/Outline.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/effects/Outline.cpp b/src/effects/Outline.cpp index 2d2e52e7..59bd23bf 100644 --- a/src/effects/Outline.cpp +++ b/src/effects/Outline.cpp @@ -115,12 +115,13 @@ std::shared_ptr Outline::GetFrame(std::shared_ptr& qimage) { cv::Mat cv_img(qimage->height(), qimage->width(), CV_8UC4, (uchar*)qimage->constBits(), qimage->bytesPerLine()); - cv::cvtColor(cv_img, cv_img, cv::COLOR_RGBA2BGRA); return cv_img; } std::shared_ptr Outline::BGRACvMatToQImage(cv::Mat img) { - QImage qimage(img.data, img.cols, img.rows, img.step, QImage::Format_ARGB32); + cv::Mat final_img; + cv::cvtColor(final_img, img, cv::COLOR_RGBA2BGRA); + QImage qimage(final_img.data, final_img.cols, final_img.rows, final_img.step, QImage::Format_ARGB32); std::shared_ptr imgIn = std::make_shared(qimage.convertToFormat(QImage::Format_RGBA8888_Premultiplied)); return imgIn; } From 795fad74a8c842b2ae3ddf0d72bfffe403d24dde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C5=A9=20Quang=20H=E1=BA=A3i?= Date: Sat, 22 Feb 2025 21:51:04 +0700 Subject: [PATCH 14/16] fix cvtColor src dst --- src/effects/Outline.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/effects/Outline.cpp b/src/effects/Outline.cpp index 59bd23bf..81478f28 100644 --- a/src/effects/Outline.cpp +++ b/src/effects/Outline.cpp @@ -120,7 +120,7 @@ cv::Mat Outline::QImageToBGRACvMat(std::shared_ptr& qimage) { std::shared_ptr Outline::BGRACvMatToQImage(cv::Mat img) { cv::Mat final_img; - cv::cvtColor(final_img, img, cv::COLOR_RGBA2BGRA); + cv::cvtColor(img, final_img, cv::COLOR_RGBA2BGRA); QImage qimage(final_img.data, final_img.cols, final_img.rows, final_img.step, QImage::Format_ARGB32); std::shared_ptr imgIn = std::make_shared(qimage.convertToFormat(QImage::Format_RGBA8888_Premultiplied)); return imgIn; From 20692af7c043e4d22bd54815b0b6848930f30251 Mon Sep 17 00:00:00 2001 From: HaiVQ Date: Wed, 26 Feb 2025 03:44:54 +0000 Subject: [PATCH 15/16] Reorder color channel parameters in Outline constructors and update JSON handling --- src/effects/Outline.cpp | 26 +++++++++++++------------- src/effects/Outline.h | 11 +++++------ 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/effects/Outline.cpp b/src/effects/Outline.cpp index 81478f28..36d6e23a 100644 --- a/src/effects/Outline.cpp +++ b/src/effects/Outline.cpp @@ -16,14 +16,14 @@ using namespace openshot; /// Blank constructor, useful when using Json to load the effect properties -Outline::Outline() : width(3.0), red(0.0), green(0.0), blue(0.0), alpha(255.0) { +Outline::Outline() : width(3.0), blue(0.0), green(0.0), red(0.0), alpha(255.0) { // Init effect properties init_effect_details(); } // Default constructor -Outline::Outline(Keyframe width, Keyframe red, Keyframe green, Keyframe blue, Keyframe alpha) : - width(width), red(red), green(green), blue(blue), alpha(alpha) +Outline::Outline(Keyframe width, Keyframe blue, Keyframe green, Keyframe red, Keyframe alpha) : + width(width), blue(red), green(green), red(blue), alpha(alpha) { // Init effect properties init_effect_details(); @@ -51,9 +51,9 @@ std::shared_ptr Outline::GetFrame(std::shared_ptr frame_image = frame->GetImage(); int widthValue = width.GetValue(frame_number); + int blueValue = blue.GetValue(frame_number); int redValue = red.GetValue(frame_number); int greenValue = green.GetValue(frame_number); - int blueValue = blue.GetValue(frame_number); int alphaValue = alpha.GetValue(frame_number); if ((widthValue <= 0) || (alphaValue <= 0)) { @@ -140,9 +140,9 @@ Json::Value Outline::JsonValue() const { Json::Value root = EffectBase::JsonValue(); // get parent properties root["type"] = info.class_name; root["width"] = width.JsonValue(); - root["red"] = red.JsonValue(); - root["green"] = green.JsonValue(); root["blue"] = blue.JsonValue(); + root["green"] = green.JsonValue(); + root["red"] = red.JsonValue(); root["alpha"] = alpha.JsonValue(); // return JsonValue @@ -175,12 +175,12 @@ void Outline::SetJsonValue(const Json::Value root) { // Set data from Json (if key is found) if (!root["width"].isNull()) width.SetJsonValue(root["width"]); - if (!root["red"].isNull()) - red.SetJsonValue(root["red"]); - if (!root["green"].isNull()) - green.SetJsonValue(root["green"]); if (!root["blue"].isNull()) blue.SetJsonValue(root["blue"]); + if (!root["green"].isNull()) + green.SetJsonValue(root["green"]); + if (!root["red"].isNull()) + red.SetJsonValue(root["red"]); if (!root["alpha"].isNull()) alpha.SetJsonValue(root["alpha"]); } @@ -192,10 +192,10 @@ std::string Outline::PropertiesJSON(int64_t requested_frame) const { Json::Value root = BasePropertiesJSON(requested_frame); // Keyframes - root["width"] = add_property_json("Width", width.GetValue(requested_frame), "float", "", &width, 0, 1000, false, requested_frame); - root["red"] = add_property_json("Red", red.GetValue(requested_frame), "float", "", &red, 0, 255, false, requested_frame); - root["green"] = add_property_json("Green", green.GetValue(requested_frame), "float", "", &green, 0, 255, false, requested_frame); + root["width"] = add_property_json("Width", width.GetValue(requested_frame), "float", "", &width, 0, 10000, false, requested_frame); root["blue"] = add_property_json("Blue", blue.GetValue(requested_frame), "float", "", &blue, 0, 255, false, requested_frame); + root["green"] = add_property_json("Green", green.GetValue(requested_frame), "float", "", &green, 0, 255, false, requested_frame); + root["red"] = add_property_json("Red", red.GetValue(requested_frame), "float", "", &red, 0, 255, false, requested_frame); root["alpha"] = add_property_json("Alpha", alpha.GetValue(requested_frame), "float", "", &alpha, 0, 255, false, requested_frame); // Return formatted string diff --git a/src/effects/Outline.h b/src/effects/Outline.h index a4df35cb..215d957a 100644 --- a/src/effects/Outline.h +++ b/src/effects/Outline.h @@ -47,9 +47,9 @@ namespace openshot public: Keyframe width; ///< Width of the outline - Keyframe red; ///< Red channel of the outline - Keyframe green; ///< Green of the outline Keyframe blue; ///< Blue of the outline + Keyframe green; ///< Green of the outline + Keyframe red; ///< Red channel of the outline Keyframe alpha; ///< Alpha of the outline /// Blank constructor, useful when using Json to load the effect properties @@ -58,11 +58,11 @@ namespace openshot /// Default constructor, which require width, red, green, blue, alpha /// /// @param width the width of the outline (between 0 and 1000, rounded to int) - /// @param red the red channel of the outline (between 0 and 255, rounded to int) - /// @param green the green channel of the outline (between 0 and 255, rounded to int) /// @param blue the blue channel of the outline (between 0 and 255, rounded to int) + /// @param green the green channel of the outline (between 0 and 255, rounded to int) + /// @param red the red channel of the outline (between 0 and 255, rounded to int) /// @param alpha the alpha channel of the outline (between 0 and 255, rounded to int) - Outline(Keyframe width, Keyframe red, Keyframe green, Keyframe blue, Keyframe alpha); + Outline(Keyframe width, Keyframe blue, Keyframe green, Keyframe red, Keyframe alpha); /// @brief This method is required for all derived classes of ClipBase, and returns a /// new openshot::Frame object. All Clip keyframes and effects are resolved into @@ -93,7 +93,6 @@ namespace openshot /// of all properties at any time) std::string PropertiesJSON(int64_t requested_frame) const override; }; - } #endif From 96da88e1f35c65fe87e059ba8949432b300bad17 Mon Sep 17 00:00:00 2001 From: HaiVQ Date: Wed, 26 Feb 2025 03:47:23 +0000 Subject: [PATCH 16/16] Fix color channel assignment in Outline constructor --- src/effects/Outline.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/effects/Outline.cpp b/src/effects/Outline.cpp index 36d6e23a..80999f89 100644 --- a/src/effects/Outline.cpp +++ b/src/effects/Outline.cpp @@ -23,7 +23,7 @@ Outline::Outline() : width(3.0), blue(0.0), green(0.0), red(0.0), alpha(255.0) { // Default constructor Outline::Outline(Keyframe width, Keyframe blue, Keyframe green, Keyframe red, Keyframe alpha) : - width(width), blue(red), green(green), red(blue), alpha(alpha) + width(width), blue(blue), green(green), red(red), alpha(alpha) { // Init effect properties init_effect_details(); @@ -52,8 +52,8 @@ std::shared_ptr Outline::GetFrame(std::shared_ptr