From 22c5c53119eec1bd14948aab1a16993c5547558b Mon Sep 17 00:00:00 2001 From: bianzheng Date: Tue, 10 Jun 2025 14:10:57 +0800 Subject: [PATCH] Add variable radius blur Signed-off-by: bianzheng --- BUILD.gn | 1 + include/ge_render.h | 3 + include/ge_shader_filter_params.h | 8 + .../ge_variable_radius_blur_shader_filter.h | 65 +++++ include/ge_visual_effect_impl.h | 13 + src/ge_render.cpp | 20 ++ src/ge_variable_radius_blur_shader_filter.cpp | 230 ++++++++++++++++++ src/ge_visual_effect_impl.cpp | 37 ++- test/unittest/BUILD.gn | 2 + ...ariable_radius_blur_shader_filter_test.cpp | 158 ++++++++++++ 10 files changed, 536 insertions(+), 1 deletion(-) create mode 100644 include/ge_variable_radius_blur_shader_filter.h create mode 100644 src/ge_variable_radius_blur_shader_filter.cpp create mode 100644 test/unittest/ge_variable_radius_blur_shader_filter_test.cpp diff --git a/BUILD.gn b/BUILD.gn index e12ecf7..59d246d 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -74,6 +74,7 @@ ohos_source_set("graphics_effect_src") { "src/ge_ripple_shader_mask.cpp", "src/ge_sound_wave_filter.cpp", "src/ge_system_properties.cpp", + "src/ge_variable_radius_blur_shader_filter.cpp", "src/ge_visual_effect.cpp", "src/ge_visual_effect_container.cpp", "src/ge_visual_effect_impl.cpp", diff --git a/include/ge_render.h b/include/ge_render.h index e926d2b..d14afc0 100644 --- a/include/ge_render.h +++ b/include/ge_render.h @@ -53,6 +53,9 @@ private: std::vector> GenerateShaderFilter(Drawing::GEVisualEffectContainer& veContainer); std::shared_ptr GenerateExtShaderFilter(const std::shared_ptr&); + + std::shared_ptr GenerateExtShaderVariableRadiusBlur( + const std::shared_ptr&); }; } // namespace GraphicsEffectEngine diff --git a/include/ge_shader_filter_params.h b/include/ge_shader_filter_params.h index c42f27d..ec499da 100644 --- a/include/ge_shader_filter_params.h +++ b/include/ge_shader_filter_params.h @@ -266,6 +266,14 @@ struct GEDispersionShaderFilterParams { float blueOffsetY; }; +constexpr char GE_FILTER_VARIABLE_RADIUS_BLUR[] = "VARIABLE_RADIUS_BLUR"; +constexpr char GE_FILTER_VARIABLE_RADIUS_BLUR_RADIUS[] = "VARIABLE_RADIUS_BLUR_RADIUS"; +constexpr char GE_FILTER_VARIABLE_RADIUS_BLUR_MASK[] = "VARIABLE_RADIUS_BLUR_MASK"; +struct GEVariableRadiusBlurShaderFilterParams { + std::shared_ptr mask; + float blurRadius; +}; + } // namespace Drawing } // namespace Rosen } // namespace OHOS diff --git a/include/ge_variable_radius_blur_shader_filter.h b/include/ge_variable_radius_blur_shader_filter.h new file mode 100644 index 0000000..95e6e06 --- /dev/null +++ b/include/ge_variable_radius_blur_shader_filter.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef GRAPHICS_EFFECT_GE_VARIABLERADIUS_BLUR_SHADER_FILTER_H +#define GRAPHICS_EFFECT_GE_VARIABLERADIUS_BLUR_SHADER_FILTER_H + +#include "ge_shader_filter.h" +#include "ge_visual_effect.h" + +#include "draw/canvas.h" +#include "effect/runtime_effect.h" +#include "effect/runtime_shader_builder.h" +#include "image/image.h" + +namespace OHOS { +namespace Rosen { + +class GE_EXPORT GEVariableRadiusBlurShaderFilter : public GEShaderFilter { +public: + GEVariableRadiusBlurShaderFilter(const Drawing::GEVariableRadiusBlurShaderFilterParams& params); + GEVariableRadiusBlurShaderFilter(const GEVariableRadiusBlurShaderFilter&) = delete; + GEVariableRadiusBlurShaderFilter operator=(const GEVariableRadiusBlurShaderFilter&) = delete; + ~GEVariableRadiusBlurShaderFilter() override = default; + + virtual std::shared_ptr ProcessImage(Drawing::Canvas& canvas, + const std::shared_ptr image, const Drawing::Rect& src, const Drawing::Rect& dst) override; + + std::string GetDescription(); + std::string GetDetailedDescription(); + +protected: + Drawing::GEVariableRadiusBlurShaderFilterParams params_; + +private: + static void MakeHorizontalMeanBlurEffect(); + static void MakeVerticalMeanBlurEffect(); + static void MakeTextureShaderEffect(); + + static std::shared_ptr DrawMeanLinearGradientBlur(const std::shared_ptr& image, + Drawing::Canvas& canvas, float radius, std::shared_ptr alphaGradientShader, + const Drawing::Rect& dst); + static std::shared_ptr BuildMeanLinearGradientBlur(const std::shared_ptr& image, + Drawing::Canvas& canvas, float radius, std::shared_ptr alphaGradientShader, + Drawing::Matrix blurMatrix); + + static std::shared_ptr horizontalMeanBlurShaderEffect_; + static std::shared_ptr verticalMeanBlurShaderEffect_; + static std::shared_ptr textureShaderEffect_; +}; + +} // namespace Rosen +} // namespace OHOS + +#endif // GRAPHICS_EFFECT_GE_VARIABLERADIUS_BLUR_SHADER_FILTER_H \ No newline at end of file diff --git a/include/ge_visual_effect_impl.h b/include/ge_visual_effect_impl.h index 0e656f0..f18e7e2 100644 --- a/include/ge_visual_effect_impl.h +++ b/include/ge_visual_effect_impl.h @@ -55,6 +55,7 @@ public: EDGE_LIGHT, BEZIER_WARP, DISPERSION, + VARIABLE_RADIUS_BLUR, MAX }; @@ -220,6 +221,16 @@ public: return dispersionParams_; } + void MakeVariableRadiusBlurParams() + { + variableRadiusBlurParams_ = std::make_shared(); + } + + const std::shared_ptr& GetVariableRadiusBlurParams() const + { + return variableRadiusBlurParams_; + } + private: static std::map> g_initialMap; @@ -236,6 +247,7 @@ private: void SetSoundWaveParamsFloat(const std::string& tag, float param); void SetEdgeLightParams(const std::string& tag, float param); void SetDispersionParams(const std::string& tag, float param); + void SetVariableRadiusBlurParams(const std::string& tag, float param); FilterType filterType_ = GEVisualEffectImpl::FilterType::NONE; @@ -256,6 +268,7 @@ private: std::shared_ptr edgeLightParams_ = nullptr; std::shared_ptr bezierWarpParams_ = nullptr; std::shared_ptr dispersionParams_ = nullptr; + std::shared_ptr variableRadiusBlurParams_ = nullptr; }; } // namespace Drawing diff --git a/src/ge_render.cpp b/src/ge_render.cpp index 95d05ee..629b395 100644 --- a/src/ge_render.cpp +++ b/src/ge_render.cpp @@ -29,6 +29,7 @@ #include "ge_sound_wave_filter.h" #include "ge_external_dynamic_loader.h" #include "ge_edge_light_shader_filter.h" +#include "ge_variable_radius_blur_shader_filter.h" namespace OHOS { @@ -133,6 +134,21 @@ std::shared_ptr GERender::GenerateExtShaderFilter( return nullptr; } +std::shared_ptr GERender::GenerateExtShaderVariableRadiusBlur( + const std::shared_ptr &ve) +{ + const auto& variableRadiusBlurParams = ve->GetVariableRadiusBlurParams(); + auto object = GEExternalDynamicLoader::GetInstance().CreateGEXObjectByType( + static_cast(Drawing::GEVisualEffectImpl::FilterType::VARIABLE_RADIUS_BLUR), + sizeof(Drawing::GEVariableRadiusBlurShaderFilterParams), + static_cast(variableRadiusBlurParams.get())); + if (!object) { + return std::make_shared(*variableRadiusBlurParams); + } + std::shared_ptr dmShader(static_cast(object)); + return dmShader; +} + std::vector> GERender::GenerateShaderFilter( Drawing::GEVisualEffectContainer& veContainer) { @@ -204,6 +220,10 @@ std::vector> GERender::GenerateShaderFilter( shaderFilter = GenerateExtShaderFilter(ve); break; } + case Drawing::GEVisualEffectImpl::FilterType::VARIABLE_RADIUS_BLUR: { + shaderFilter = GenerateExtShaderVariableRadiusBlur(ve); + break; + } default: break; } diff --git a/src/ge_variable_radius_blur_shader_filter.cpp b/src/ge_variable_radius_blur_shader_filter.cpp new file mode 100644 index 0000000..638ce79 --- /dev/null +++ b/src/ge_variable_radius_blur_shader_filter.cpp @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ge_variable_radius_blur_shader_filter.h" + +#include "ge_log.h" +#include "ge_system_properties.h" + +namespace OHOS { +namespace Rosen { + +std::shared_ptr GEVariableRadiusBlurShaderFilter::horizontalMeanBlurShaderEffect_ = nullptr; +std::shared_ptr GEVariableRadiusBlurShaderFilter::verticalMeanBlurShaderEffect_ = nullptr; +std::shared_ptr GEVariableRadiusBlurShaderFilter::textureShaderEffect_ = nullptr; + +GEVariableRadiusBlurShaderFilter::GEVariableRadiusBlurShaderFilter( + const Drawing::GEVariableRadiusBlurShaderFilterParams ¶ms) + : params_(params) +{ +} + +std::shared_ptr GEVariableRadiusBlurShaderFilter::ProcessImage(Drawing::Canvas& canvas, + const std::shared_ptr image, const Drawing::Rect& src, const Drawing::Rect& dst) +{ + if (!image || params_.blurRadius <= 0 || !params_.mask) { + return image; + } + LOGD("GEVariableRadiusBlurShaderFilter::ProcessImage radius: %{public}f", params_.blurRadius); + + auto imageInfo = image->GetImageInfo(); + auto maskShader = params_.mask->GenerateDrawingShader(imageInfo.GetWidth(), imageInfo.GetHeight()); + if (maskShader == nullptr) { + LOGE("GEVariableRadiusBlurShaderFilter::ProcessImage mask generate failed"); + return image; + } + + float radius = std::clamp(params_.blurRadius, 0.0f, 60.0f); // 60.0 represents largest blur radius + radius = radius / 2; // 2 half blur radius + MakeHorizontalMeanBlurEffect(); + MakeVerticalMeanBlurEffect(); + MakeTextureShaderEffect(); + return DrawMeanLinearGradientBlur(image, canvas, radius, maskShader, dst); +} + +void GEVariableRadiusBlurShaderFilter::MakeTextureShaderEffect() +{ + static const std::string generateTextureShader(R"( + uniform shader imageInput; + half4 main(float2 xy) { + return imageInput.eval(xy); + } + )"); + + if (textureShaderEffect_ == nullptr) { + textureShaderEffect_ = Drawing::RuntimeEffect::CreateForShader(generateTextureShader); + } +} + +void GEVariableRadiusBlurShaderFilter::MakeHorizontalMeanBlurEffect() +{ + static const std::string HorizontalBlurString( + R"( + uniform half r; + uniform shader imageShader; + uniform shader gradientShader; + half4 meanFilter(float2 coord, half radius) + { + half4 sum = vec4(0.0); + half div = 0; + for (half x = -30.0; x < 30.0; x += 1.0) { + if (x > radius) { + break; + } + if (abs(x) < radius) { + div += 1; + sum += imageShader.eval(coord + float2(x, 0)); + } + } + return half4(sum.xyz / div, 1.0); + } + half4 main(float2 coord) + { + if (abs(gradientShader.eval(coord).a - 0) < 0.001) { + return imageShader.eval(coord); + } + float val = clamp(r * gradientShader.eval(coord).a, 1.0, r); + return meanFilter(coord, val); + } + )"); + + if (horizontalMeanBlurShaderEffect_ == nullptr) { + horizontalMeanBlurShaderEffect_ = Drawing::RuntimeEffect::CreateForShader(HorizontalBlurString); + } +} + +void GEVariableRadiusBlurShaderFilter::MakeVerticalMeanBlurEffect() +{ + static const std::string VerticalBlurString( + R"( + uniform half r; + uniform shader imageShader; + uniform shader gradientShader; + half4 meanFilter(float2 coord, half radius) + { + half4 sum = vec4(0.0); + half div = 0; + for (half y = -30.0; y < 30.0; y += 1.0) { + if (y > radius) { + break; + } + if (abs(y) < radius) { + div += 1; + sum += imageShader.eval(coord + float2(0, y)); + } + } + return half4(sum.xyz / div, 1.0); + } + half4 main(float2 coord) + { + if (abs(gradientShader.eval(coord).a - 0) < 0.001) { + return imageShader.eval(coord); + } + float val = clamp(r * gradientShader.eval(coord).a, 1.0, r); + return meanFilter(coord, val); + } + )"); + + if (verticalMeanBlurShaderEffect_ == nullptr) { + verticalMeanBlurShaderEffect_ = Drawing::RuntimeEffect::CreateForShader(VerticalBlurString); + } +} + +std::shared_ptr GEVariableRadiusBlurShaderFilter::DrawMeanLinearGradientBlur( + const std::shared_ptr& image, Drawing::Canvas& canvas, float radius, + std::shared_ptr alphaGradientShader, const Drawing::Rect& dst) +{ + if (!horizontalMeanBlurShaderEffect_ || !verticalMeanBlurShaderEffect_ || !image) { + return image; + } + + Drawing::Matrix m; + Drawing::Matrix blurMatrix; + blurMatrix.PostTranslate(dst.GetLeft(), dst.GetTop()); + + Drawing::SamplingOptions linear(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::NONE); + + auto tmpBlur4 = BuildMeanLinearGradientBlur(image, canvas, radius, alphaGradientShader, blurMatrix); + + Drawing::Matrix invBlurMatrix; + auto blurShader = Drawing::ShaderEffect::CreateImageShader( + *tmpBlur4, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, linear, invBlurMatrix); + + Drawing::RuntimeShaderBuilder builder(textureShaderEffect_); + builder.SetChild("imageInput", blurShader); + auto imageInfo = Drawing::ImageInfo(dst.GetWidth(), dst.GetHeight(), image->GetImageInfo().GetColorType(), + image->GetImageInfo().GetAlphaType(), image->GetImageInfo().GetColorSpace()); + auto blurImage = builder.MakeImage(canvas.GetGPUContext().get(), nullptr, imageInfo, false); + if (!blurImage) { + LOGE("GEVariableRadiusBlurShaderFilter::DrawMeanLinearGradientBlur fail to make final image"); + return image; + } + return blurImage; +} + +std::shared_ptr GEVariableRadiusBlurShaderFilter::BuildMeanLinearGradientBlur( + const std::shared_ptr& image, Drawing::Canvas& canvas, float radius, + std::shared_ptr alphaGradientShader, Drawing::Matrix blurMatrix) +{ + auto width = image->GetWidth(); + auto height = image->GetHeight(); + auto originImageInfo = image->GetImageInfo(); + auto scaledInfo = Drawing::ImageInfo(std::ceil(width), std::ceil(height), + originImageInfo.GetColorType(), originImageInfo.GetAlphaType(), originImageInfo.GetColorSpace()); + Drawing::Matrix m; + Drawing::SamplingOptions linear(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::NONE); + Drawing::RuntimeShaderBuilder hBlurBuilder(horizontalMeanBlurShaderEffect_); + hBlurBuilder.SetUniform("r", radius); + hBlurBuilder.SetChild("gradientShader", alphaGradientShader); + + Drawing::RuntimeShaderBuilder vBlurBuilder(verticalMeanBlurShaderEffect_); + vBlurBuilder.SetUniform("r", radius); + vBlurBuilder.SetChild("gradientShader", alphaGradientShader); + int blurTimes = 4; + auto localImage = image; + auto blurImageShader = Drawing::ShaderEffect::CreateImageShader( + *image, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, linear, blurMatrix); + + bool isHorizontal = true; + for (int i = 0; i < blurTimes; i++) { + Drawing::RuntimeShaderBuilder blurBuilder = isHorizontal ? hBlurBuilder : vBlurBuilder; + isHorizontal = !isHorizontal; + blurBuilder.SetChild("imageShader", blurImageShader); + localImage = +#ifdef RS_ENABLE_GPU + blurBuilder.MakeImage(canvas.GetGPUContext().get(), nullptr, scaledInfo, false); +#else + blurBuilder.MakeImage(nullptr, nullptr, scaledInfo, false); +#endif + if (!localImage) { + LOGE("GEVariableRadiusBlurShaderFilter::BuildMeanLinearGradientBlur fail to make blur image"); + return image; + } + blurImageShader = Drawing::ShaderEffect::CreateImageShader( + *localImage, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, linear, m); + } + return localImage; +} + +std::string GEVariableRadiusBlurShaderFilter::GetDescription() +{ + return "GEVariableRadiusBlurShaderFilter"; +} + +std::string GEVariableRadiusBlurShaderFilter::GetDetailedDescription() +{ + return "GEVariableRadiusBlurShaderFilterBlur, radius: " + std::to_string(params_.blurRadius); +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/src/ge_visual_effect_impl.cpp b/src/ge_visual_effect_impl.cpp index f494c49..c44c9f0 100644 --- a/src/ge_visual_effect_impl.cpp +++ b/src/ge_visual_effect_impl.cpp @@ -102,6 +102,12 @@ std::map> GEVisualEf impl->SetFilterType(GEVisualEffectImpl::FilterType::DISPERSION); impl->MakeDispersionParams(); } + }, + { GE_FILTER_VARIABLE_RADIUS_BLUR, + [](GEVisualEffectImpl* impl) { + impl->SetFilterType(GEVisualEffectImpl::FilterType::VARIABLE_RADIUS_BLUR); + impl->MakeVariableRadiusBlurParams(); + } } }; @@ -243,6 +249,10 @@ void GEVisualEffectImpl::SetParam(const std::string& tag, float param) SetDispersionParams(tag, param); break; } + case FilterType::VARIABLE_RADIUS_BLUR: { + SetVariableRadiusBlurParams(tag, param); + break; + } default: break; } @@ -414,12 +424,20 @@ void GEVisualEffectImpl::SetParam(const std::string& tag, const std::shared_ptr< if (dispersionParams_ == nullptr) { return; } - if (tag == GE_FILTER_DISPERSION_MASK) { dispersionParams_->mask = param; } break; } + case FilterType::VARIABLE_RADIUS_BLUR: { + if (variableRadiusBlurParams_ == nullptr) { + return; + } + if (tag == GE_FILTER_VARIABLE_RADIUS_BLUR_MASK) { + variableRadiusBlurParams_->mask = param; + } + break; + } default: break; } @@ -728,6 +746,23 @@ void GEVisualEffectImpl::SetDispersionParams(const std::string& tag, float param } } +void GEVisualEffectImpl::SetVariableRadiusBlurParams(const std::string& tag, float param) +{ + if (variableRadiusBlurParams_ == nullptr) { + return; + } + + static std::unordered_map> actions = { + { GE_FILTER_VARIABLE_RADIUS_BLUR_RADIUS, + [](GEVisualEffectImpl* obj, float p) { obj->variableRadiusBlurParams_->blurRadius = p; } }, + }; + + auto it = actions.find(tag); + if (it != actions.end()) { + it->second(this, param); + } +} + } // namespace Drawing } // namespace Rosen } // namespace OHOS diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 2edfb44..33fd4f1 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -70,6 +70,7 @@ ohos_source_set("graphics_effect_test_src") { "${graphics_effect_root}/src/ge_visual_effect_container.cpp", "${graphics_effect_root}/src/ge_visual_effect_impl.cpp", "${graphics_effect_root}/src/ge_water_ripple_filter.cpp", + "${graphics_effect_root}/src/ge_variable_radius_blur_shader_filter.cpp", ] external_deps = [] @@ -123,6 +124,7 @@ ohos_unittest("GraphicsEffectTest") { "ge_ripple_shader_mask_test.cpp", "ge_sound_wave_filter_test.cpp", "ge_system_properties_test.cpp", + "ge_variable_radius_blur_shader_filter_test.cpp", "ge_visual_effect_container_test.cpp", "ge_visual_effect_impl_test.cpp", "ge_visual_effect_test.cpp", diff --git a/test/unittest/ge_variable_radius_blur_shader_filter_test.cpp b/test/unittest/ge_variable_radius_blur_shader_filter_test.cpp new file mode 100644 index 0000000..f899c87 --- /dev/null +++ b/test/unittest/ge_variable_radius_blur_shader_filter_test.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "ge_variable_radius_blur_shader_filter.h" +#include "ge_ripple_shader_mask.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { + +class GEVariableRadiusBlurShaderFilterTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + std::shared_ptr MakeImage(Rosen::Drawing::Canvas &canvas); + + static inline Rosen::Drawing::Canvas canvas_; + std::shared_ptr image_{ nullptr }; + std::shared_ptr imageEmpty_ { nullptr }; + + // 1.0f, 1.0f, 2.0f, 2.0f is left top right bottom + Rosen::Drawing::Rect src_ { 1.0f, 1.0f, 2.0f, 2.0f }; + Rosen::Drawing::Rect dst_ { 1.0f, 1.0f, 2.0f, 2.0f }; +}; + +void GEVariableRadiusBlurShaderFilterTest::SetUpTestCase(void) {} +void GEVariableRadiusBlurShaderFilterTest::TearDownTestCase(void) {} + +void GEVariableRadiusBlurShaderFilterTest::SetUp() +{ + canvas_.Restore(); + + Rosen::Drawing::Bitmap bmp; + Rosen::Drawing::BitmapFormat format { Rosen::Drawing::COLORTYPE_RGBA_8888, Rosen::Drawing::ALPHATYPE_PREMUL }; + bmp.Build(50, 50, format); // 50, 50 bitmap size + bmp.ClearWithColor(Rosen::Drawing::Color::COLOR_BLUE); + image_ = bmp.MakeImage(); + + bmp.Build(0, 0, format); // 0, 0 bitmap size + imageEmpty_ = bmp.MakeImage(); +} + +void GEVariableRadiusBlurShaderFilterTest::TearDown() {} + +std::shared_ptr CreateVariableRadiusBlurShaderFilter(Drawing::GEVariableRadiusBlurShaderFilterParams params) +{ + return std::make_shared(params); +} + +std::shared_ptr CreateRippleShaderMask() +{ + Drawing::GERippleShaderMaskParams maskParams; + maskParams.center_ = {0.f, 0.f}; + maskParams.radius_ = 0.5f; + maskParams.width_ = 0.5f; + maskParams.widthCenterOffset_ = 0.0f; + return std::make_shared(maskParams); +} + + +std::shared_ptr CreateVariableRadiusBlurShaderFilter() +{ + + Drawing::GEVariableRadiusBlurShaderFilterParams params = { + CreateRippleShaderMask(), 100.0f}; + return CreateVariableRadiusBlurShaderFilter(params); +} + +/** + * @tc.name: CreateVariableRadiusBlurShaderFilterTest + * @tc.desc: GEVariableRadiusBlurShaderFilterTest.CreateVariableRadiusBlurShaderFilterTest + * @tc.type:FUNC + * @tc.require: + */ +HWTEST_F(GEVariableRadiusBlurShaderFilterTest, CreateVariableRadiusBlurShaderFilterTest, TestSize.Level1) +{ + auto variableRadiusBlurShaderFilter = CreateVariableRadiusBlurShaderFilter(); + ASSERT_NE(variableRadiusBlurShaderFilter, nullptr); +} + +/** + * @tc.name: GetDescriptionTest + * @tc.desc: GEVariableRadiusBlurShaderFilterTest.GetDescriptionTest + * @tc.type:FUNC + * @tc.require: + */ +HWTEST_F(GEVariableRadiusBlurShaderFilterTest, GetDescriptionTest, TestSize.Level1) +{ + auto variableRadiusBlurShaderFilter = CreateVariableRadiusBlurShaderFilter(); + ASSERT_NE(variableRadiusBlurShaderFilter, nullptr); + + std::string emptyString = ""; + EXPECT_NE(variableRadiusBlurShaderFilter->GetDescription(), emptyString); + EXPECT_NE(variableRadiusBlurShaderFilter->GetDetailedDescription(), emptyString); +} + +/** + * @tc.name: ProcessImageTest001 + * @tc.desc: GEVariableRadiusBlurShaderFilterTest.ProcessImageTest001 + * @tc.type:FUNC + * @tc.require: + */ +HWTEST_F(GEVariableRadiusBlurShaderFilterTest, ProcessImageTest001, TestSize.Level1) +{ + auto variableRadiusBlurShaderFilter = CreateVariableRadiusBlurShaderFilter(); + ASSERT_NE(variableRadiusBlurShaderFilter, nullptr); + + EXPECT_EQ(variableRadiusBlurShaderFilter->ProcessImage(canvas_, nullptr, src_, dst_), nullptr); + + variableRadiusBlurShaderFilter->params_.mask = nullptr; + EXPECT_EQ(variableRadiusBlurShaderFilter->ProcessImage(canvas_, image_, src_, dst_), image_); + + variableRadiusBlurShaderFilter->params_.mask = CreateRippleShaderMask(); + EXPECT_EQ(variableRadiusBlurShaderFilter->ProcessImage(canvas_, imageEmpty_, src_, dst_), imageEmpty_); + + EXPECT_NE(variableRadiusBlurShaderFilter->ProcessImage(canvas_, image_, src_, dst_), nullptr); +} + +/** + * @tc.name: MakeShaderTest001 + * @tc.desc: GEVariableRadiusBlurShaderFilterTest.MakeShaderTest001 + * @tc.type:FUNC + * @tc.require: + */ +HWTEST_F(GEVariableRadiusBlurShaderFilterTest, MakeShaderTest001, TestSize.Level1) +{ + auto variableRadiusBlurShaderFilter = CreateVariableRadiusBlurShaderFilter(); + ASSERT_NE(variableRadiusBlurShaderFilter, nullptr); + + variableRadiusBlurShaderFilter->MakeHorizontalMeanBlurEffect(); + EXPECT_NE(variableRadiusBlurShaderFilter->horizontalMeanBlurShaderEffect_, nullptr); + + variableRadiusBlurShaderFilter->MakeVerticalMeanBlurEffect(); + EXPECT_NE(variableRadiusBlurShaderFilter->verticalMeanBlurShaderEffect_, nullptr); + + variableRadiusBlurShaderFilter->MakeTextureShaderEffect(); + EXPECT_NE(variableRadiusBlurShaderFilter->textureShaderEffect_, nullptr); +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file -- Gitee