summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibGfx
diff options
context:
space:
mode:
authorTheGrizzlyDev <tonio9681@gmail.com>2021-12-17 22:59:01 +0000
committerLinus Groh <mail@linusgroh.de>2021-12-28 17:10:44 +0100
commitebaf2112604553c2713dc5f84dd2b1fae54c07e2 (patch)
tree14afaed2cac619132152de20d83ba71066cfd911 /Userland/Libraries/LibGfx
parent1c05d39abc003bca16a7a56fdb131fc01dccc059 (diff)
downloadserenity-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')
-rw-r--r--Userland/Libraries/LibGfx/CMakeLists.txt1
-rw-r--r--Userland/Libraries/LibGfx/Filters/ColorBlindnessFilter.cpp84
-rw-r--r--Userland/Libraries/LibGfx/Filters/ColorBlindnessFilter.h63
-rw-r--r--Userland/Libraries/LibGfx/Filters/ColorFilter.h44
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;
+};
+
+}