mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 07:07:45 +00:00
PixelPaint: Move out common logic from Filters into base class
Now, each new filter only has to describe how to actually change the bitmaps, and the common logic of pulling out the bitmap from the layer, and marking the action as done, etc is all handled in the `Filter` base class. This also makes it possible to apply filters to external bitmaps, which are not embedded in a `Layer` (which we can use to preview filters in the future!)
This commit is contained in:
parent
5c0c126122
commit
0e6576b376
26 changed files with 90 additions and 144 deletions
|
@ -16,27 +16,24 @@
|
|||
|
||||
namespace PixelPaint::Filters {
|
||||
|
||||
void Bloom::apply() const
|
||||
void Bloom::apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const
|
||||
{
|
||||
if (!m_editor)
|
||||
auto intermediate_bitmap_or_error = source_bitmap.clone();
|
||||
if (intermediate_bitmap_or_error.is_error())
|
||||
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();
|
||||
auto intermediate_bitmap = intermediate_bitmap_or_error.release_value();
|
||||
|
||||
Gfx::LumaFilter luma_filter(intermediate_bitmap);
|
||||
luma_filter.apply(m_luma_lower, 255);
|
||||
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::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);
|
||||
}
|
||||
Gfx::BitmapMixer mixer(target_bitmap);
|
||||
mixer.mix_with(intermediate_bitmap, Gfx::BitmapMixer::MixingMethod::Lightest);
|
||||
}
|
||||
|
||||
RefPtr<GUI::Widget> Bloom::get_settings_widget()
|
||||
{
|
||||
if (!m_settings_widget) {
|
||||
|
|
|
@ -12,7 +12,8 @@ namespace PixelPaint::Filters {
|
|||
|
||||
class Bloom final : public Filter {
|
||||
public:
|
||||
virtual void apply() const override;
|
||||
virtual void apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const override;
|
||||
|
||||
virtual RefPtr<GUI::Widget> get_settings_widget() override;
|
||||
|
||||
virtual StringView filter_name() override { return "Bloom Filter"sv; }
|
||||
|
|
|
@ -9,18 +9,11 @@
|
|||
|
||||
namespace PixelPaint::Filters {
|
||||
|
||||
void BoxBlur3::apply() const
|
||||
void BoxBlur3::apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const
|
||||
{
|
||||
if (!m_editor)
|
||||
return;
|
||||
if (auto* layer = m_editor->active_layer()) {
|
||||
Gfx::BoxBlurFilter<3> filter;
|
||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::BoxBlurFilter<3>>::get()) {
|
||||
filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect(), *parameters);
|
||||
layer->did_modify_bitmap(layer->rect());
|
||||
m_editor->did_complete_action();
|
||||
}
|
||||
}
|
||||
Gfx::BoxBlurFilter<3> filter;
|
||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::BoxBlurFilter<3>>::get())
|
||||
filter.apply(target_bitmap, target_bitmap.rect(), source_bitmap, source_bitmap.rect(), *parameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace PixelPaint::Filters {
|
|||
|
||||
class BoxBlur3 final : public Filter {
|
||||
public:
|
||||
virtual void apply() const override;
|
||||
virtual void apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const override;
|
||||
virtual StringView filter_name() override { return "Box Blur (3x3)"sv; }
|
||||
|
||||
BoxBlur3(ImageEditor* editor)
|
||||
|
|
|
@ -9,18 +9,11 @@
|
|||
|
||||
namespace PixelPaint::Filters {
|
||||
|
||||
void BoxBlur5::apply() const
|
||||
void BoxBlur5::apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const
|
||||
{
|
||||
if (!m_editor)
|
||||
return;
|
||||
if (auto* layer = m_editor->active_layer()) {
|
||||
Gfx::BoxBlurFilter<5> filter;
|
||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::BoxBlurFilter<5>>::get()) {
|
||||
filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect(), *parameters);
|
||||
layer->did_modify_bitmap(layer->rect());
|
||||
m_editor->did_complete_action();
|
||||
}
|
||||
}
|
||||
Gfx::BoxBlurFilter<5> filter;
|
||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::BoxBlurFilter<5>>::get())
|
||||
filter.apply(target_bitmap, target_bitmap.rect(), source_bitmap, source_bitmap.rect(), *parameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace PixelPaint::Filters {
|
|||
|
||||
class BoxBlur5 final : public Filter {
|
||||
public:
|
||||
virtual void apply() const override;
|
||||
virtual void apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const override;
|
||||
virtual StringView filter_name() override { return "Box Blur (5x5)"sv; }
|
||||
|
||||
BoxBlur5(ImageEditor* editor)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org>
|
||||
* Copyright (c) 2022, Mustafa Quraish <mustafa@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -12,21 +13,20 @@
|
|||
|
||||
namespace PixelPaint::Filters {
|
||||
|
||||
void FastBoxBlur::apply() const
|
||||
void FastBoxBlur::apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const
|
||||
{
|
||||
if (!m_editor)
|
||||
return;
|
||||
if (auto* layer = m_editor->active_layer()) {
|
||||
Gfx::FastBoxBlurFilter filter(layer->bitmap());
|
||||
|
||||
if (m_approximate_gauss)
|
||||
filter.apply_three_passes(m_radius);
|
||||
else
|
||||
filter.apply_single_pass(m_radius);
|
||||
|
||||
layer->did_modify_bitmap(layer->rect());
|
||||
m_editor->did_complete_action();
|
||||
// This filter only works in-place, so if we have different target and source, we first copy over
|
||||
// the source bitmap to the target one.
|
||||
if (&target_bitmap != &source_bitmap) {
|
||||
VERIFY(source_bitmap.size_in_bytes() == target_bitmap.size_in_bytes());
|
||||
memcpy(target_bitmap.scanline(0), source_bitmap.scanline(0), source_bitmap.size_in_bytes());
|
||||
}
|
||||
|
||||
Gfx::FastBoxBlurFilter filter(target_bitmap);
|
||||
if (m_approximate_gauss)
|
||||
filter.apply_three_passes(m_radius);
|
||||
else
|
||||
filter.apply_single_pass(m_radius);
|
||||
}
|
||||
|
||||
RefPtr<GUI::Widget> FastBoxBlur::get_settings_widget()
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace PixelPaint::Filters {
|
|||
|
||||
class FastBoxBlur final : public Filter {
|
||||
public:
|
||||
virtual void apply() const override;
|
||||
virtual void apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const override;
|
||||
virtual RefPtr<GUI::Widget> get_settings_widget() override;
|
||||
|
||||
virtual StringView filter_name() override { return "Fast Box Blur (& Gauss)"sv; }
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org>
|
||||
* Copyright (c) 2022, Mustafa Quraish <mustafa@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -25,4 +26,15 @@ RefPtr<GUI::Widget> Filter::get_settings_widget()
|
|||
return m_settings_widget.ptr();
|
||||
}
|
||||
|
||||
void Filter::apply() const
|
||||
{
|
||||
if (!m_editor)
|
||||
return;
|
||||
if (auto* layer = m_editor->active_layer()) {
|
||||
apply(layer->bitmap(), layer->bitmap());
|
||||
layer->did_modify_bitmap(layer->rect());
|
||||
m_editor->did_complete_action();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org>
|
||||
* Copyright (c) 2022, Mustafa Quraish <mustafa@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -14,7 +15,9 @@ namespace PixelPaint {
|
|||
|
||||
class Filter {
|
||||
public:
|
||||
virtual void apply() const = 0;
|
||||
virtual void apply() const;
|
||||
virtual void apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const = 0;
|
||||
|
||||
virtual RefPtr<GUI::Widget> get_settings_widget();
|
||||
|
||||
virtual StringView filter_name() = 0;
|
||||
|
|
|
@ -9,18 +9,11 @@
|
|||
|
||||
namespace PixelPaint::Filters {
|
||||
|
||||
void GaussBlur3::apply() const
|
||||
void GaussBlur3::apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const
|
||||
{
|
||||
if (!m_editor)
|
||||
return;
|
||||
if (auto* layer = m_editor->active_layer()) {
|
||||
Gfx::SpatialGaussianBlurFilter<3> filter;
|
||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::SpatialGaussianBlurFilter<3>>::get()) {
|
||||
filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect(), *parameters);
|
||||
layer->did_modify_bitmap(layer->rect());
|
||||
m_editor->did_complete_action();
|
||||
}
|
||||
}
|
||||
Gfx::SpatialGaussianBlurFilter<3> filter;
|
||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::SpatialGaussianBlurFilter<3>>::get())
|
||||
filter.apply(target_bitmap, target_bitmap.rect(), source_bitmap, source_bitmap.rect(), *parameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace PixelPaint::Filters {
|
|||
// FIXME: Make a generic gaussian blur that does not need the templated radius
|
||||
class GaussBlur3 final : public Filter {
|
||||
public:
|
||||
virtual void apply() const override;
|
||||
virtual void apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const override;
|
||||
virtual StringView filter_name() override { return "Gaussian Blur (3x3)"sv; }
|
||||
|
||||
GaussBlur3(ImageEditor* editor)
|
||||
|
|
|
@ -9,18 +9,11 @@
|
|||
|
||||
namespace PixelPaint::Filters {
|
||||
|
||||
void GaussBlur5::apply() const
|
||||
void GaussBlur5::apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const
|
||||
{
|
||||
if (!m_editor)
|
||||
return;
|
||||
if (auto* layer = m_editor->active_layer()) {
|
||||
Gfx::SpatialGaussianBlurFilter<5> filter;
|
||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::SpatialGaussianBlurFilter<5>>::get()) {
|
||||
filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect(), *parameters);
|
||||
layer->did_modify_bitmap(layer->rect());
|
||||
m_editor->did_complete_action();
|
||||
}
|
||||
}
|
||||
Gfx::SpatialGaussianBlurFilter<5> filter;
|
||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::SpatialGaussianBlurFilter<5>>::get())
|
||||
filter.apply(target_bitmap, target_bitmap.rect(), source_bitmap, source_bitmap.rect(), *parameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace PixelPaint::Filters {
|
|||
|
||||
class GaussBlur5 final : public Filter {
|
||||
public:
|
||||
virtual void apply() const override;
|
||||
virtual void apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const override;
|
||||
virtual StringView filter_name() override { return "Gaussian Blur (5x5)"sv; }
|
||||
|
||||
GaussBlur5(ImageEditor* editor)
|
||||
|
|
|
@ -9,16 +9,10 @@
|
|||
|
||||
namespace PixelPaint::Filters {
|
||||
|
||||
void Grayscale::apply() const
|
||||
void Grayscale::apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const
|
||||
{
|
||||
if (!m_editor)
|
||||
return;
|
||||
if (auto* layer = m_editor->active_layer()) {
|
||||
Gfx::GrayscaleFilter filter;
|
||||
filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect());
|
||||
layer->did_modify_bitmap(layer->rect());
|
||||
m_editor->did_complete_action();
|
||||
}
|
||||
Gfx::GrayscaleFilter filter;
|
||||
filter.apply(target_bitmap, target_bitmap.rect(), source_bitmap, source_bitmap.rect());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace PixelPaint::Filters {
|
|||
|
||||
class Grayscale final : public Filter {
|
||||
public:
|
||||
virtual void apply() const override;
|
||||
virtual void apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const override;
|
||||
virtual StringView filter_name() override { return "Grayscale"sv; }
|
||||
|
||||
Grayscale(ImageEditor* editor)
|
||||
|
|
|
@ -9,16 +9,10 @@
|
|||
|
||||
namespace PixelPaint::Filters {
|
||||
|
||||
void Invert::apply() const
|
||||
void Invert::apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const
|
||||
{
|
||||
if (!m_editor)
|
||||
return;
|
||||
if (auto* layer = m_editor->active_layer()) {
|
||||
Gfx::InvertFilter filter;
|
||||
filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect());
|
||||
layer->did_modify_bitmap(layer->rect());
|
||||
m_editor->did_complete_action();
|
||||
}
|
||||
Gfx::InvertFilter filter;
|
||||
filter.apply(target_bitmap, target_bitmap.rect(), source_bitmap, source_bitmap.rect());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace PixelPaint::Filters {
|
|||
|
||||
class Invert final : public Filter {
|
||||
public:
|
||||
virtual void apply() const override;
|
||||
virtual void apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const override;
|
||||
virtual StringView filter_name() override { return "Invert"sv; }
|
||||
|
||||
Invert(ImageEditor* editor)
|
||||
|
|
|
@ -9,18 +9,11 @@
|
|||
|
||||
namespace PixelPaint::Filters {
|
||||
|
||||
void LaplaceCardinal::apply() const
|
||||
void LaplaceCardinal::apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const
|
||||
{
|
||||
if (!m_editor)
|
||||
return;
|
||||
if (auto* layer = m_editor->active_layer()) {
|
||||
Gfx::LaplacianFilter filter;
|
||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::LaplacianFilter>::get(false)) {
|
||||
filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect(), *parameters);
|
||||
layer->did_modify_bitmap(layer->rect());
|
||||
m_editor->did_complete_action();
|
||||
}
|
||||
}
|
||||
Gfx::LaplacianFilter filter;
|
||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::LaplacianFilter>::get(false))
|
||||
filter.apply(target_bitmap, target_bitmap.rect(), source_bitmap, source_bitmap.rect(), *parameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace PixelPaint::Filters {
|
|||
|
||||
class LaplaceCardinal final : public Filter {
|
||||
public:
|
||||
virtual void apply() const override;
|
||||
virtual void apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const override;
|
||||
virtual StringView filter_name() override { return "Laplacian Cardinal"sv; }
|
||||
|
||||
LaplaceCardinal(ImageEditor* editor)
|
||||
|
|
|
@ -9,18 +9,11 @@
|
|||
|
||||
namespace PixelPaint::Filters {
|
||||
|
||||
void LaplaceDiagonal::apply() const
|
||||
void LaplaceDiagonal::apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const
|
||||
{
|
||||
if (!m_editor)
|
||||
return;
|
||||
if (auto* layer = m_editor->active_layer()) {
|
||||
Gfx::LaplacianFilter filter;
|
||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::LaplacianFilter>::get(true)) {
|
||||
filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect(), *parameters);
|
||||
layer->did_modify_bitmap(layer->rect());
|
||||
m_editor->did_complete_action();
|
||||
}
|
||||
}
|
||||
Gfx::LaplacianFilter filter;
|
||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::LaplacianFilter>::get(true))
|
||||
filter.apply(target_bitmap, target_bitmap.rect(), source_bitmap, source_bitmap.rect(), *parameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace PixelPaint::Filters {
|
|||
|
||||
class LaplaceDiagonal final : public Filter {
|
||||
public:
|
||||
virtual void apply() const override;
|
||||
virtual void apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const override;
|
||||
virtual StringView filter_name() override { return "Laplacian Diagonal"sv; }
|
||||
|
||||
LaplaceDiagonal(ImageEditor* editor)
|
||||
|
|
|
@ -11,16 +11,10 @@
|
|||
|
||||
namespace PixelPaint::Filters {
|
||||
|
||||
void Sepia::apply() const
|
||||
void Sepia::apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const
|
||||
{
|
||||
if (!m_editor)
|
||||
return;
|
||||
if (auto* layer = m_editor->active_layer()) {
|
||||
Gfx::SepiaFilter filter(m_amount);
|
||||
filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect());
|
||||
layer->did_modify_bitmap(layer->rect());
|
||||
m_editor->did_complete_action();
|
||||
}
|
||||
Gfx::SepiaFilter filter(m_amount);
|
||||
filter.apply(target_bitmap, target_bitmap.rect(), source_bitmap, source_bitmap.rect());
|
||||
}
|
||||
|
||||
RefPtr<GUI::Widget> Sepia::get_settings_widget()
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace PixelPaint::Filters {
|
|||
|
||||
class Sepia final : public Filter {
|
||||
public:
|
||||
virtual void apply() const override;
|
||||
virtual void apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const override;
|
||||
virtual RefPtr<GUI::Widget> get_settings_widget() override;
|
||||
|
||||
virtual StringView filter_name() override { return "Sepia"sv; }
|
||||
|
|
|
@ -9,18 +9,11 @@
|
|||
|
||||
namespace PixelPaint::Filters {
|
||||
|
||||
void Sharpen::apply() const
|
||||
void Sharpen::apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const
|
||||
{
|
||||
if (!m_editor)
|
||||
return;
|
||||
if (auto* layer = m_editor->active_layer()) {
|
||||
Gfx::SharpenFilter filter;
|
||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::SharpenFilter>::get()) {
|
||||
filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect(), *parameters);
|
||||
layer->did_modify_bitmap(layer->rect());
|
||||
m_editor->did_complete_action();
|
||||
}
|
||||
}
|
||||
Gfx::SharpenFilter filter;
|
||||
if (auto parameters = PixelPaint::FilterParameters<Gfx::SharpenFilter>::get())
|
||||
filter.apply(target_bitmap, target_bitmap.rect(), source_bitmap, source_bitmap.rect(), *parameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace PixelPaint::Filters {
|
|||
|
||||
class Sharpen final : public Filter {
|
||||
public:
|
||||
virtual void apply() const override;
|
||||
virtual void apply(Gfx::Bitmap& target_bitmap, Gfx::Bitmap const& source_bitmap) const override;
|
||||
virtual StringView filter_name() override { return "Sharpen"sv; }
|
||||
|
||||
Sharpen(ImageEditor* editor)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue