소스 검색

PixelPaint: Add Hue/Saturation filter

This filter mimics the functionality from Photoshop and other image
editors, allowing you to adjust the hue, saturation, and lightness of
an image. I always found this a very handy feature :^)
MacDue 2 년 전
부모
커밋
fef19aa589

+ 1 - 0
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

+ 2 - 0
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<NonnullRefPtr<GUI::TreeViewModel>> create_filter_tree_model(ImageEditor*
     add_filter_node.template operator()<Filters::Median>(blur_category);
 
     auto color_category = filter_tree_model->add_node("Color", directory_icon);
+    add_filter_node.template operator()<Filters::HueAndSaturation>(color_category);
     add_filter_node.template operator()<Filters::Grayscale>(color_category);
     add_filter_node.template operator()<Filters::Invert>(color_category);
     add_filter_node.template operator()<Filters::Sepia>(color_category);

+ 59 - 0
Userland/Applications/PixelPaint/Filters/HueAndSaturation.cpp

@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2022, MacDue <macdue@dueutil.tech>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "HueAndSaturation.h"
+#include "../FilterParams.h"
+#include <LibGUI/Label.h>
+#include <LibGUI/ValueSlider.h>
+#include <LibGfx/Filters/HueRotateFilter.h>
+#include <LibGfx/Filters/SaturateFilter.h>
+#include <LibGfx/Filters/TintFilter.h>
+
+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<GUI::Widget> HueAndSaturation::get_settings_widget()
+{
+    if (!m_settings_widget) {
+        m_settings_widget = GUI::Widget::construct();
+        m_settings_widget->set_layout<GUI::VerticalBoxLayout>();
+
+        auto add_slider = [&](auto name, int min, int max, auto member) {
+            auto& name_label = m_settings_widget->add<GUI::Label>(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<GUI::ValueSlider>(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;
+}
+
+}

+ 29 - 0
Userland/Applications/PixelPaint/Filters/HueAndSaturation.h

@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2022, MacDue <macdue@dueutil.tech>
+ *
+ * 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<GUI::Widget> 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 };
+};
+
+}