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 :^)
This commit is contained in:
MacDue 2022-10-09 16:31:37 +01:00 committed by Sam Atkins
parent 71fb1ed226
commit fef19aa589
Notes: sideshowbarker 2024-07-17 06:06:45 +09:00
4 changed files with 91 additions and 0 deletions

View file

@ -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

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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 };
};
}