diff options
author | TheGrizzlyDev <tonio9681@gmail.com> | 2021-12-17 22:59:01 +0000 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-12-28 17:10:44 +0100 |
commit | ebaf2112604553c2713dc5f84dd2b1fae54c07e2 (patch) | |
tree | 14afaed2cac619132152de20d83ba71066cfd911 /Userland/Libraries/LibGfx | |
parent | 1c05d39abc003bca16a7a56fdb131fc01dccc059 (diff) | |
download | serenity-ebaf2112604553c2713dc5f84dd2b1fae54c07e2.zip |
ThemeEditor: Implement a way to simulate color blindness in preview
Implement a mechanism that allows us to alter colors so that they
mimic those a colorblind person would see. From the color we can then
alter the colors for the whole preview so we can simulate everything
in the theme including icons/decorations.
This filter is also available as a Filter in LibGfx so it can be
reused in multiple other places.
The color simulation algorithm is based on this one
https://github.com/MaPePeR/jsColorblindSimulator publicly available.
Diffstat (limited to 'Userland/Libraries/LibGfx')
4 files changed, 192 insertions, 0 deletions
diff --git a/Userland/Libraries/LibGfx/CMakeLists.txt b/Userland/Libraries/LibGfx/CMakeLists.txt index d048a52df8..3086cd75d2 100644 --- a/Userland/Libraries/LibGfx/CMakeLists.txt +++ b/Userland/Libraries/LibGfx/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCES DDSLoader.cpp DisjointRectSet.cpp Emoji.cpp + Filters/ColorBlindnessFilter.cpp Filters/FastBoxBlurFilter.cpp FontDatabase.cpp GIFLoader.cpp diff --git a/Userland/Libraries/LibGfx/Filters/ColorBlindnessFilter.cpp b/Userland/Libraries/LibGfx/Filters/ColorBlindnessFilter.cpp new file mode 100644 index 0000000000..7924ccd69c --- /dev/null +++ b/Userland/Libraries/LibGfx/Filters/ColorBlindnessFilter.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021, Antonio Di Stefano <tonio9681@gmail.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "ColorBlindnessFilter.h" + +namespace Gfx { + +NonnullOwnPtr<ColorBlindnessFilter> ColorBlindnessFilter::create_protanopia() +{ + return make<ColorBlindnessFilter>( + .56, .44, .0, + .55, .45, .0, + .0, .24, .76); +} + +NonnullOwnPtr<ColorBlindnessFilter> ColorBlindnessFilter::create_protanomaly() +{ + return make<ColorBlindnessFilter>( + .82, .18, .0, + .33, .67, .0, + .0, .13, .87); +} + +NonnullOwnPtr<ColorBlindnessFilter> ColorBlindnessFilter::create_deuteranopia() +{ + return make<ColorBlindnessFilter>( + .63, .37, .0, + .7, .3, .0, + .0, .3, .7); +} + +NonnullOwnPtr<ColorBlindnessFilter> ColorBlindnessFilter::create_deuteranomaly() +{ + return make<ColorBlindnessFilter>( + .8, .2, .0, + .26, .74, .0, + .0, .15, .85); +} + +NonnullOwnPtr<ColorBlindnessFilter> ColorBlindnessFilter::create_tritanopia() +{ + return make<ColorBlindnessFilter>( + .95, .05, .0, + .0, .44, .56, + .0, .48, .52); +} + +NonnullOwnPtr<ColorBlindnessFilter> ColorBlindnessFilter::create_tritanomaly() +{ + return make<ColorBlindnessFilter>( + .97, .03, .0, + .0, .73, .27, + .0, .18, .82); +} + +NonnullOwnPtr<ColorBlindnessFilter> ColorBlindnessFilter::create_achromatopsia() +{ + return make<ColorBlindnessFilter>( + .3, .59, .11, + .3, .59, .11, + .3, .59, .11); +} + +NonnullOwnPtr<ColorBlindnessFilter> ColorBlindnessFilter::create_achromatomaly() +{ + return make<ColorBlindnessFilter>( + .62, .32, .06, + .16, .78, .06, + .16, .32, .52); +} + +Color ColorBlindnessFilter::convert_color(Color original) +{ + return Color( + (u8)(original.red() * m_red_in_red_band + original.green() * m_green_in_red_band + original.blue() * m_blue_in_red_band), + (u8)(original.red() * m_red_in_green_band + original.green() * m_green_in_green_band + original.blue() * m_blue_in_green_band), + (u8)(original.red() * m_red_in_blue_band + original.green() * m_green_in_blue_band + original.blue() * m_blue_in_blue_band), + original.alpha()); +}; + +} diff --git a/Userland/Libraries/LibGfx/Filters/ColorBlindnessFilter.h b/Userland/Libraries/LibGfx/Filters/ColorBlindnessFilter.h new file mode 100644 index 0000000000..71a36639b9 --- /dev/null +++ b/Userland/Libraries/LibGfx/Filters/ColorBlindnessFilter.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021, Antonio Di Stefano <tonio9681@gmail.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include "ColorFilter.h" +#include <AK/NonnullOwnPtr.h> + +namespace Gfx { +class ColorBlindnessFilter : public ColorFilter { +public: + ColorBlindnessFilter( + double red_in_red_band, + double green_in_red_band, + double blue_in_red_band, + double red_in_green_band, + double green_in_green_band, + double blue_in_green_band, + double red_in_blue_band, + double green_in_blue_band, + double blue_in_blue_band) + : m_red_in_red_band(red_in_red_band) + , m_green_in_red_band(green_in_red_band) + , m_blue_in_red_band(blue_in_red_band) + , m_red_in_green_band(red_in_green_band) + , m_green_in_green_band(green_in_green_band) + , m_blue_in_green_band(blue_in_green_band) + , m_red_in_blue_band(red_in_blue_band) + , m_green_in_blue_band(green_in_blue_band) + , m_blue_in_blue_band(blue_in_blue_band) + { + } + + virtual ~ColorBlindnessFilter() = default; + virtual char const* class_name() const override { return "ColorBlindnessFilter"; } + + static NonnullOwnPtr<ColorBlindnessFilter> create_protanopia(); + static NonnullOwnPtr<ColorBlindnessFilter> create_protanomaly(); + static NonnullOwnPtr<ColorBlindnessFilter> create_deuteranopia(); + static NonnullOwnPtr<ColorBlindnessFilter> create_deuteranomaly(); + static NonnullOwnPtr<ColorBlindnessFilter> create_tritanopia(); + static NonnullOwnPtr<ColorBlindnessFilter> create_tritanomaly(); + static NonnullOwnPtr<ColorBlindnessFilter> create_achromatopsia(); + static NonnullOwnPtr<ColorBlindnessFilter> create_achromatomaly(); + +protected: + Color convert_color(Color original) override; + +private: + double m_red_in_red_band; + double m_green_in_red_band; + double m_blue_in_red_band; + double m_red_in_green_band; + double m_green_in_green_band; + double m_blue_in_green_band; + double m_red_in_blue_band; + double m_green_in_blue_band; + double m_blue_in_blue_band; +}; +} diff --git a/Userland/Libraries/LibGfx/Filters/ColorFilter.h b/Userland/Libraries/LibGfx/Filters/ColorFilter.h new file mode 100644 index 0000000000..248eb8113c --- /dev/null +++ b/Userland/Libraries/LibGfx/Filters/ColorFilter.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021, Antonio Di Stefano <tonio9681@gmail.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include "Filter.h" + +namespace Gfx { + +class ColorFilter : public Filter { +public: + virtual ~ColorFilter() = default; + + virtual void apply(Bitmap& target_bitmap, IntRect const& target_rect, Bitmap const& source_bitmap, IntRect const& source_rect) override + { + 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 = convert_color(source_pixel); + + target_bitmap.set_pixel(target_x, target_y, target_color); + } + } + } + +protected: + ColorFilter() = default; + + virtual Color convert_color(Color) = 0; +}; + +} |