diff options
-rw-r--r-- | Userland/Applications/PixelPaint/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Applications/PixelPaint/FilterModel.cpp | 2 | ||||
-rw-r--r-- | Userland/Applications/PixelPaint/FilterParams.h | 1 | ||||
-rw-r--r-- | Userland/Applications/PixelPaint/Filters/Sepia.cpp | 57 | ||||
-rw-r--r-- | Userland/Applications/PixelPaint/Filters/Sepia.h | 27 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/Color.h | 27 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/Filters/SepiaFilter.h | 32 |
7 files changed, 147 insertions, 0 deletions
diff --git a/Userland/Applications/PixelPaint/CMakeLists.txt b/Userland/Applications/PixelPaint/CMakeLists.txt index f9f53a2d24..8919cc3695 100644 --- a/Userland/Applications/PixelPaint/CMakeLists.txt +++ b/Userland/Applications/PixelPaint/CMakeLists.txt @@ -28,6 +28,7 @@ set(SOURCES Filters/Invert.cpp Filters/LaplaceCardinal.cpp Filters/LaplaceDiagonal.cpp + Filters/Sepia.cpp Filters/Sharpen.cpp Image.cpp ImageEditor.cpp diff --git a/Userland/Applications/PixelPaint/FilterModel.cpp b/Userland/Applications/PixelPaint/FilterModel.cpp index a41883e488..025be5b23b 100644 --- a/Userland/Applications/PixelPaint/FilterModel.cpp +++ b/Userland/Applications/PixelPaint/FilterModel.cpp @@ -17,6 +17,7 @@ #include "Filters/Invert.h" #include "Filters/LaplaceCardinal.h" #include "Filters/LaplaceDiagonal.h" +#include "Filters/Sepia.h" #include "Filters/Sharpen.h" #include "Layer.h" #include <LibGUI/FileIconProvider.h> @@ -48,6 +49,7 @@ FilterModel::FilterModel(ImageEditor* editor) auto color_category = FilterInfo::create_category("Color"); auto grayscale_filter = FilterInfo::create_filter<Filters::Grayscale>(editor, color_category); auto invert_filter = FilterInfo::create_filter<Filters::Invert>(editor, color_category); + auto sepia_filter = FilterInfo::create_filter<Filters::Sepia>(editor, color_category); m_filters.append(color_category); diff --git a/Userland/Applications/PixelPaint/FilterParams.h b/Userland/Applications/PixelPaint/FilterParams.h index 6f97466828..189e11a19b 100644 --- a/Userland/Applications/PixelPaint/FilterParams.h +++ b/Userland/Applications/PixelPaint/FilterParams.h @@ -19,6 +19,7 @@ #include <LibGfx/Filters/GrayscaleFilter.h> #include <LibGfx/Filters/InvertFilter.h> #include <LibGfx/Filters/LaplacianFilter.h> +#include <LibGfx/Filters/SepiaFilter.h> #include <LibGfx/Filters/SharpenFilter.h> #include <LibGfx/Filters/SpatialGaussianBlurFilter.h> diff --git a/Userland/Applications/PixelPaint/Filters/Sepia.cpp b/Userland/Applications/PixelPaint/Filters/Sepia.cpp new file mode 100644 index 0000000000..ba86e6a75e --- /dev/null +++ b/Userland/Applications/PixelPaint/Filters/Sepia.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022, Xavier Defrang <xavier.defrang@gmail.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "Sepia.h" +#include "../FilterParams.h" +#include <LibGUI/Label.h> +#include <LibGUI/ValueSlider.h> + +namespace PixelPaint::Filters { + +void Sepia::apply() 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(); + } +} + +RefPtr<GUI::Widget> Sepia::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>("Sepia Filter"); + name_label.set_font_weight(Gfx::FontWeight::Bold); + name_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); + name_label.set_fixed_height(20); + + auto& amount_container = m_settings_widget->add<GUI::Widget>(); + amount_container.set_fixed_height(20); + amount_container.set_layout<GUI::HorizontalBoxLayout>(); + amount_container.layout()->set_margins({ 4, 0, 4, 0 }); + + auto& amount_label = amount_container.add<GUI::Label>("Amount:"); + amount_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); + amount_label.set_fixed_size(50, 20); + + auto& amount_slider = amount_container.add<GUI::ValueSlider>(Orientation::Horizontal, "%"); + amount_slider.set_range(0, 100); + amount_slider.set_value(m_amount * 100); + amount_slider.on_change = [&](int value) { + m_amount = value * 0.01f; + }; + } + + return m_settings_widget; +} + +} diff --git a/Userland/Applications/PixelPaint/Filters/Sepia.h b/Userland/Applications/PixelPaint/Filters/Sepia.h new file mode 100644 index 0000000000..a8d1a8a788 --- /dev/null +++ b/Userland/Applications/PixelPaint/Filters/Sepia.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022, Xavier Defrang <xavier.defrang@gmail.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include "Filter.h" + +namespace PixelPaint::Filters { + +class Sepia final : public Filter { +public: + virtual void apply() const override; + virtual RefPtr<GUI::Widget> get_settings_widget() override; + + virtual StringView filter_name() override { return "Sepia"sv; } + + Sepia(ImageEditor* editor) + : Filter(editor) {}; + +private: + float m_amount { 1.0f }; +}; + +} diff --git a/Userland/Libraries/LibGfx/Color.h b/Userland/Libraries/LibGfx/Color.h index 89ed8a3a4e..38975db38e 100644 --- a/Userland/Libraries/LibGfx/Color.h +++ b/Userland/Libraries/LibGfx/Color.h @@ -232,6 +232,33 @@ public: return Color(gray, gray, gray, alpha()); } + constexpr Color sepia(float amount = 1.0f) const + { + auto blend_factor = 1.0f - amount; + + auto r1 = 0.393f + 0.607f * blend_factor; + auto r2 = 0.769f - 0.769f * blend_factor; + auto r3 = 0.189f - 0.189f * blend_factor; + + auto g1 = 0.349f - 0.349f * blend_factor; + auto g2 = 0.686f + 0.314f * blend_factor; + auto g3 = 0.168f - 0.168f * blend_factor; + + auto b1 = 0.272f - 0.272f * blend_factor; + auto b2 = 0.534f - 0.534f * blend_factor; + auto b3 = 0.131f + 0.869f * blend_factor; + + auto r = red(); + auto g = green(); + auto b = blue(); + + return Color( + clamp(lroundf(r * r1 + g * r2 + b * r3), 0, 255), + clamp(lroundf(r * g1 + g * g2 + b * g3), 0, 255), + clamp(lroundf(r * b1 + g * b2 + b * b3), 0, 255), + alpha()); + } + constexpr Color darkened(float amount = 0.5f) const { return Color(red() * amount, green() * amount, blue() * amount, alpha()); diff --git a/Userland/Libraries/LibGfx/Filters/SepiaFilter.h b/Userland/Libraries/LibGfx/Filters/SepiaFilter.h new file mode 100644 index 0000000000..da7b1e7319 --- /dev/null +++ b/Userland/Libraries/LibGfx/Filters/SepiaFilter.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022, Xavier Defrang <xavier.defrang@gmail.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/StdLibExtras.h> +#include <LibGfx/Filters/ColorFilter.h> +#include <math.h> + +namespace Gfx { + +class SepiaFilter : public ColorFilter { +public: + SepiaFilter(float amount = 1.0f) + : m_amount(amount) + { + } + virtual ~SepiaFilter() { } + + virtual char const* class_name() const override { return "SepiaFilter"; } + +protected: + Color convert_color(Color original) override { return original.sepia(m_amount); }; + +private: + float m_amount; +}; + +} |