diff --git a/Userland/Applications/PixelPaint/FilterParams.h b/Userland/Applications/PixelPaint/FilterParams.h index 906e7d6a42..f923f90853 100644 --- a/Userland/Applications/PixelPaint/FilterParams.h +++ b/Userland/Applications/PixelPaint/FilterParams.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/Userland/Applications/PixelPaint/main.cpp b/Userland/Applications/PixelPaint/main.cpp index 7b7661b3c4..7ed498e4a5 100644 --- a/Userland/Applications/PixelPaint/main.cpp +++ b/Userland/Applications/PixelPaint/main.cpp @@ -660,6 +660,18 @@ int main(int argc, char** argv) } })); + auto& color_filters_menu = filter_menu.add_submenu("&Color"); + color_filters_menu.add_action(GUI::Action::create("Grayscale", [&](auto&) { + auto* editor = current_image_editor(); + if (!editor) + return; + if (auto* layer = editor->active_layer()) { + Gfx::GrayscaleFilter filter; + filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect()); + editor->did_complete_action(); + } + })); + auto& help_menu = window->add_menu("&Help"); help_menu.add_action(GUI::CommonActions::make_about_action("Pixel Paint", app_icon, window)); diff --git a/Userland/Libraries/LibGfx/Filters/Filter.h b/Userland/Libraries/LibGfx/Filters/Filter.h index bf0eb54a2d..d196361abe 100644 --- a/Userland/Libraries/LibGfx/Filters/Filter.h +++ b/Userland/Libraries/LibGfx/Filters/Filter.h @@ -23,7 +23,8 @@ public: virtual const char* class_name() const = 0; - virtual void apply(Bitmap&, const IntRect&, const Bitmap&, const IntRect&, const Parameters&) = 0; + virtual void apply(Bitmap&, IntRect const&, Bitmap const&, IntRect const&, Parameters const&) {}; + virtual void apply(Bitmap&, IntRect const&, Bitmap const&, IntRect const&) {}; protected: Filter() { } diff --git a/Userland/Libraries/LibGfx/Filters/GrayscaleFilter.h b/Userland/Libraries/LibGfx/Filters/GrayscaleFilter.h new file mode 100644 index 0000000000..c5c626fb78 --- /dev/null +++ b/Userland/Libraries/LibGfx/Filters/GrayscaleFilter.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021, David Savary + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Gfx { + +class GrayscaleFilter : public Filter { +public: + GrayscaleFilter() { } + virtual ~GrayscaleFilter() { } + + virtual char const* class_name() const override { return "GrayscaleFilter"; } + + virtual void apply(Bitmap& target_bitmap, IntRect const& target_rect, Bitmap const& source_bitmap, IntRect const& source_rect) override + { + // source_rect should be describing the pixels that can be accessed + // to apply this filter, while target_rect should describe the area + // where to apply the filter on. + VERIFY(source_rect.size() == target_rect.size()); + VERIFY(target_bitmap.rect().contains(target_rect)); + VERIFY(source_bitmap.rect().contains(source_rect)); + + for (auto y = 0; y < source_rect.height(); ++y) { + ssize_t source_y = y + source_rect.y(); + ssize_t target_y = y + target_rect.y(); + for (auto x = 0; x < source_rect.width(); ++x) { + ssize_t source_x = x + source_rect.x(); + ssize_t target_x = x + target_rect.x(); + + auto source_pixel = source_bitmap.get_pixel(source_x, source_y); + auto target_color = source_pixel.to_grayscale(); + + target_bitmap.set_pixel(target_x, target_y, target_color); + } + } + } +}; + +}