diff --git a/Userland/Applications/PixelPaint/CMakeLists.txt b/Userland/Applications/PixelPaint/CMakeLists.txt index 92e4e6d9cb..f9f53a2d24 100644 --- a/Userland/Applications/PixelPaint/CMakeLists.txt +++ b/Userland/Applications/PixelPaint/CMakeLists.txt @@ -17,6 +17,7 @@ set(SOURCES FilterGallery.cpp FilterGalleryGML.h FilterModel.cpp + Filters/Bloom.cpp Filters/BoxBlur3.cpp Filters/BoxBlur5.cpp Filters/Filter.cpp diff --git a/Userland/Applications/PixelPaint/FilterModel.cpp b/Userland/Applications/PixelPaint/FilterModel.cpp index f26392c661..a41883e488 100644 --- a/Userland/Applications/PixelPaint/FilterModel.cpp +++ b/Userland/Applications/PixelPaint/FilterModel.cpp @@ -7,6 +7,7 @@ #include "FilterModel.h" #include "FilterParams.h" +#include "Filters/Bloom.h" #include "Filters/BoxBlur3.h" #include "Filters/BoxBlur5.h" #include "Filters/FastBoxBlur.h" @@ -23,6 +24,11 @@ namespace PixelPaint { FilterModel::FilterModel(ImageEditor* editor) { + auto artistic_category = FilterInfo::create_category("Artistic"); + auto bloom_filter = FilterInfo::create_filter(editor, artistic_category); + + m_filters.append(artistic_category); + auto spatial_category = FilterInfo::create_category("Spatial"); auto edge_detect_category = FilterInfo::create_category("Edge Detection", spatial_category); diff --git a/Userland/Applications/PixelPaint/Filters/Bloom.cpp b/Userland/Applications/PixelPaint/Filters/Bloom.cpp new file mode 100644 index 0000000000..f20cbd8695 --- /dev/null +++ b/Userland/Applications/PixelPaint/Filters/Bloom.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022, Tobias Christiansen + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "Bloom.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace PixelPaint::Filters { + +void Bloom::apply() const +{ + if (!m_editor) + return; + if (auto* layer = m_editor->active_layer()) { + auto intermediate_bitmap_or_error = layer->bitmap().clone(); + if (intermediate_bitmap_or_error.is_error()) + return; + + auto intermediate_bitmap = intermediate_bitmap_or_error.release_value(); + + Gfx::LumaFilter luma_filter(intermediate_bitmap); + luma_filter.apply(m_luma_lower, 255); + + Gfx::FastBoxBlurFilter blur_filter(intermediate_bitmap); + blur_filter.apply_three_passes(m_blur_radius); + + Gfx::BitmapMixer mixer(layer->bitmap()); + mixer.mix_with(intermediate_bitmap, Gfx::BitmapMixer::MixingMethod::Lightest); + } +} +RefPtr Bloom::get_settings_widget() +{ + if (!m_settings_widget) { + m_settings_widget = GUI::Widget::construct(); + m_settings_widget->set_layout(); + + auto& name_label = m_settings_widget->add("Bloom Filter"); + name_label.set_font_weight(Gfx::FontWeight::Bold); + name_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); + name_label.set_fixed_height(20); + + auto& luma_lower_container = m_settings_widget->add(); + luma_lower_container.set_fixed_height(50); + luma_lower_container.set_layout(); + luma_lower_container.layout()->set_margins({ 4, 0, 4, 0 }); + + auto& luma_lower_label = luma_lower_container.add("Luma lower bound:"); + luma_lower_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); + luma_lower_label.set_fixed_height(20); + + auto& luma_lower_slider = luma_lower_container.add(Orientation::Horizontal); + luma_lower_slider.set_range(0, 255); + luma_lower_slider.set_value(m_luma_lower); + luma_lower_slider.on_change = [&](int value) { + m_luma_lower = value; + }; + + auto& radius_container = m_settings_widget->add(); + radius_container.set_fixed_height(50); + radius_container.set_layout(); + radius_container.layout()->set_margins({ 4, 0, 4, 0 }); + + auto& radius_label = radius_container.add("Blur Radius:"); + radius_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); + radius_label.set_fixed_height(20); + + auto& radius_slider = radius_container.add(Orientation::Horizontal, "px"); + radius_slider.set_range(0, 50); + radius_slider.set_value(m_blur_radius); + radius_slider.on_change = [&](int value) { + m_blur_radius = value; + }; + } + + return m_settings_widget; +} + +} diff --git a/Userland/Applications/PixelPaint/Filters/Bloom.h b/Userland/Applications/PixelPaint/Filters/Bloom.h new file mode 100644 index 0000000000..a9ce73e25a --- /dev/null +++ b/Userland/Applications/PixelPaint/Filters/Bloom.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022, Tobias Christiansen + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include "Filter.h" + +namespace PixelPaint::Filters { + +class Bloom final : public Filter { +public: + virtual void apply() const override; + virtual RefPtr get_settings_widget() override; + + virtual StringView filter_name() override { return "Bloom Filter"sv; } + + Bloom(ImageEditor* editor) + : Filter(editor) {}; + +private: + int m_luma_lower { 128 }; + int m_blur_radius { 15 }; +}; + +}