mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 09:51:57 -05:00
PixelPaint: Add a Bloom filter
A bloom filter creates fringes around bright areas in the image mimicking the behavior of real-world cameras. It gets its own category "Artistic" in the Filter Gallery since its not one filter per se but a combination of multiple. The filter works as follows: - Get only the light areas (above a threshold) of the image - Blur that image - Compose onto the original image
This commit is contained in:
parent
e4b7d38e18
commit
f92172c7c3
4 changed files with 122 additions and 0 deletions
|
@ -17,6 +17,7 @@ set(SOURCES
|
|||
FilterGallery.cpp
|
||||
FilterGalleryGML.h
|
||||
FilterModel.cpp
|
||||
Filters/Bloom.cpp
|
||||
Filters/BoxBlur3.cpp
|
||||
Filters/BoxBlur5.cpp
|
||||
Filters/Filter.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<Filters::Bloom>(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);
|
||||
|
|
87
Userland/Applications/PixelPaint/Filters/Bloom.cpp
Normal file
87
Userland/Applications/PixelPaint/Filters/Bloom.cpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "Bloom.h"
|
||||
#include <LibGUI/BoxLayout.h>
|
||||
#include <LibGUI/Label.h>
|
||||
#include <LibGUI/ValueSlider.h>
|
||||
#include <LibGUI/Widget.h>
|
||||
#include <LibGfx/BitmapMixer.h>
|
||||
#include <LibGfx/Filters/FastBoxBlurFilter.h>
|
||||
#include <LibGfx/Filters/LumaFilter.h>
|
||||
#include <LibGfx/FontDatabase.h>
|
||||
|
||||
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<GUI::Widget> Bloom::get_settings_widget()
|
||||
{
|
||||
if (!m_settings_widget) {
|
||||
m_settings_widget = GUI::Widget::construct();
|
||||
m_settings_widget->set_layout<GUI::VerticalBoxLayout>();
|
||||
|
||||
auto& name_label = m_settings_widget->add<GUI::Label>("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<GUI::Widget>();
|
||||
luma_lower_container.set_fixed_height(50);
|
||||
luma_lower_container.set_layout<GUI::VerticalBoxLayout>();
|
||||
luma_lower_container.layout()->set_margins({ 4, 0, 4, 0 });
|
||||
|
||||
auto& luma_lower_label = luma_lower_container.add<GUI::Label>("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<GUI::ValueSlider>(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<GUI::Widget>();
|
||||
radius_container.set_fixed_height(50);
|
||||
radius_container.set_layout<GUI::VerticalBoxLayout>();
|
||||
radius_container.layout()->set_margins({ 4, 0, 4, 0 });
|
||||
|
||||
auto& radius_label = radius_container.add<GUI::Label>("Blur Radius:");
|
||||
radius_label.set_text_alignment(Gfx::TextAlignment::CenterLeft);
|
||||
radius_label.set_fixed_height(20);
|
||||
|
||||
auto& radius_slider = radius_container.add<GUI::ValueSlider>(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;
|
||||
}
|
||||
|
||||
}
|
28
Userland/Applications/PixelPaint/Filters/Bloom.h
Normal file
28
Userland/Applications/PixelPaint/Filters/Bloom.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org>
|
||||
*
|
||||
* 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<GUI::Widget> 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 };
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue