diff --git a/Userland/Applications/PixelPaint/CMakeLists.txt b/Userland/Applications/PixelPaint/CMakeLists.txt index bb44e2cb667..c9d21e6347a 100644 --- a/Userland/Applications/PixelPaint/CMakeLists.txt +++ b/Userland/Applications/PixelPaint/CMakeLists.txt @@ -26,6 +26,7 @@ set(SOURCES Filters/BoxBlur5.cpp Filters/Filter.cpp Filters/FastBoxBlur.cpp + Filters/HueAndSaturation.cpp Filters/GaussBlur3.cpp Filters/GaussBlur5.cpp Filters/Grayscale.cpp diff --git a/Userland/Applications/PixelPaint/FilterTreeModel.cpp b/Userland/Applications/PixelPaint/FilterTreeModel.cpp index 11a2b7486d1..d22bc1a8807 100644 --- a/Userland/Applications/PixelPaint/FilterTreeModel.cpp +++ b/Userland/Applications/PixelPaint/FilterTreeModel.cpp @@ -14,6 +14,7 @@ #include "Filters/GaussBlur3.h" #include "Filters/GaussBlur5.h" #include "Filters/Grayscale.h" +#include "Filters/HueAndSaturation.h" #include "Filters/Invert.h" #include "Filters/LaplaceCardinal.h" #include "Filters/LaplaceDiagonal.h" @@ -55,6 +56,7 @@ ErrorOr> create_filter_tree_model(ImageEditor* add_filter_node.template operator()(blur_category); auto color_category = filter_tree_model->add_node("Color", directory_icon); + add_filter_node.template operator()(color_category); add_filter_node.template operator()(color_category); add_filter_node.template operator()(color_category); add_filter_node.template operator()(color_category); diff --git a/Userland/Applications/PixelPaint/Filters/HueAndSaturation.cpp b/Userland/Applications/PixelPaint/Filters/HueAndSaturation.cpp new file mode 100644 index 00000000000..7d5fe60f3a5 --- /dev/null +++ b/Userland/Applications/PixelPaint/Filters/HueAndSaturation.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022, MacDue + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "HueAndSaturation.h" +#include "../FilterParams.h" +#include +#include +#include +#include +#include + +namespace PixelPaint::Filters { + +void HueAndSaturation::apply(Gfx::Bitmap& target_bitmap) const +{ + auto apply_filter = [&](auto filter) { + filter.apply(target_bitmap, target_bitmap.rect(), target_bitmap, target_bitmap.rect()); + }; + apply_filter(Gfx::HueRotateFilter { m_hue + 360 }); + apply_filter(Gfx::SaturateFilter { m_saturation / 100 + 1 }); + auto lightness = m_lightness / 100; + apply_filter(lightness < 0 + ? Gfx::TintFilter(Gfx::Color::Black, -lightness) + : Gfx::TintFilter(Gfx::Color::White, lightness)); +} + +RefPtr HueAndSaturation::get_settings_widget() +{ + if (!m_settings_widget) { + m_settings_widget = GUI::Widget::construct(); + m_settings_widget->set_layout(); + + auto add_slider = [&](auto name, int min, int max, auto member) { + auto& name_label = m_settings_widget->add(name); + name_label.set_font_weight(Gfx::FontWeight::Bold); + name_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); + name_label.set_fixed_height(20); + + auto& slider = m_settings_widget->add(Orientation::Horizontal); + slider.set_range(min, max); + slider.set_value(m_hue); + slider.on_change = [this, member](int value) { + this->*member = value; + update_preview(); + }; + }; + + add_slider("Hue", -180, 180, &HueAndSaturation::m_hue); + add_slider("Saturation", -100, 100, &HueAndSaturation::m_saturation); + add_slider("Lightness", -100, 100, &HueAndSaturation::m_lightness); + } + + return m_settings_widget; +} + +} diff --git a/Userland/Applications/PixelPaint/Filters/HueAndSaturation.h b/Userland/Applications/PixelPaint/Filters/HueAndSaturation.h new file mode 100644 index 00000000000..92e2475d11e --- /dev/null +++ b/Userland/Applications/PixelPaint/Filters/HueAndSaturation.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022, MacDue + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include "InplaceFilter.h" + +namespace PixelPaint::Filters { + +class HueAndSaturation final : public InplaceFilter { +public: + virtual void apply(Gfx::Bitmap& target_bitmap) const override; + virtual RefPtr get_settings_widget() override; + + virtual StringView filter_name() const override { return "Hue/Saturation"sv; } + + HueAndSaturation(ImageEditor* editor) + : InplaceFilter(editor) {}; + +private: + float m_hue { 0 }; + float m_saturation { 0 }; + float m_lightness { 0 }; +}; + +}