From eb06f8d6b4d2a5e24f117b3162b5b08430bdc7dd Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 15 Mar 2016 02:15:07 +1100 Subject: [PATCH] Add color blindness filters Former-commit-id: 584e0dbc90cb5fbdc8d7d103dfc4c1d6716a726d Former-commit-id: 15bb157c19f09ee87889512a686b2b92deca44e7 Former-commit-id: ac3d596ab00ba5f1184edda33db8ec616f6797f9 --- .../ColorBlindness/Achromatomaly.cs | 32 ++++++++ .../ColorBlindness/Achromatopsia.cs | 32 ++++++++ .../ColorBlindness/ColorBlindness.cs | 53 ++++++++++++++ .../ColorBlindness/Deuteranomaly.cs | 29 ++++++++ .../ColorBlindness/Deuteranopia.cs | 29 ++++++++ .../ColorMatrix/ColorBlindness/Protanomaly.cs | 29 ++++++++ .../ColorMatrix/ColorBlindness/Protanopia.cs | 29 ++++++++ .../ColorMatrix/ColorBlindness/README.md | 4 + .../ColorMatrix/ColorBlindness/Tritanomaly.cs | 29 ++++++++ .../ColorMatrix/ColorBlindness/Tritanopia.cs | 29 ++++++++ .../Filters/ImageFilterExtensions.cs | 73 +++++++++++++++++++ .../Processors/Filters/FilterTests.cs | 11 ++- 12 files changed, 378 insertions(+), 1 deletion(-) create mode 100644 src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Achromatomaly.cs create mode 100644 src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Achromatopsia.cs create mode 100644 src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/ColorBlindness.cs create mode 100644 src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Deuteranomaly.cs create mode 100644 src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Deuteranopia.cs create mode 100644 src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Protanomaly.cs create mode 100644 src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Protanopia.cs create mode 100644 src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/README.md create mode 100644 src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Tritanomaly.cs create mode 100644 src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Tritanopia.cs diff --git a/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Achromatomaly.cs b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Achromatomaly.cs new file mode 100644 index 0000000000..b649fcba5d --- /dev/null +++ b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Achromatomaly.cs @@ -0,0 +1,32 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageProcessorCore.Filters +{ + using System.Numerics; + + /// + /// Converts the colors of the image recreating Achromatomaly (Color desensitivity) color blindness. + /// + public class Achromatomaly : ColorMatrixFilter + { + /// + public override Matrix4x4 Matrix => new Matrix4x4() + { + M11 = .618f, + M12 = .163f, + M13 = .163f, + M21 = .320f, + M22 = .775f, + M23 = .320f, + M31 = .062f, + M32 = .062f, + M33 = .516f + }; + + /// + public override bool Compand => false; + } +} diff --git a/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Achromatopsia.cs b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Achromatopsia.cs new file mode 100644 index 0000000000..794e71ca3c --- /dev/null +++ b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Achromatopsia.cs @@ -0,0 +1,32 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageProcessorCore.Filters +{ + using System.Numerics; + + /// + /// Converts the colors of the image recreating Achromatopsia (Monochrome) color blindness. + /// + public class Achromatopsia : ColorMatrixFilter + { + /// + public override Matrix4x4 Matrix => new Matrix4x4() + { + M11 = .299f, + M12 = .299f, + M13 = .299f, + M21 = .587f, + M22 = .587f, + M23 = .587f, + M31 = .114f, + M32 = .114f, + M33 = .114f + }; + + /// + public override bool Compand => false; + } +} diff --git a/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/ColorBlindness.cs b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/ColorBlindness.cs new file mode 100644 index 0000000000..7416a42d2b --- /dev/null +++ b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/ColorBlindness.cs @@ -0,0 +1,53 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageProcessorCore.Filters +{ + /// + /// Enumerates the various types of color blindness. + /// + public enum ColorBlindness + { + /// + /// Partial color desensitivity. + /// + Achromatomaly, + + /// + /// Complete color desensitivity (Monochrome) + /// + Achromatopsia, + + /// + /// Green weak + /// + Deuteranomaly, + + /// + /// Green blind + /// + Deuteranopia, + + /// + /// Red weak + /// + Protanomaly, + + /// + /// Red blind + /// + Protanopia, + + /// + /// Blue weak + /// + Tritanomaly, + + /// + /// Blue blind + /// + Tritanopia + } +} diff --git a/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Deuteranomaly.cs b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Deuteranomaly.cs new file mode 100644 index 0000000000..a8f7d5f2ca --- /dev/null +++ b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Deuteranomaly.cs @@ -0,0 +1,29 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageProcessorCore.Filters +{ + using System.Numerics; + + /// + /// Converts the colors of the image recreating Deuteranomaly (Green-Weak) color blindness. + /// + public class Deuteranomaly : ColorMatrixFilter + { + /// + public override Matrix4x4 Matrix => new Matrix4x4() + { + M11 = 0.8f, + M12 = 0.258f, + M21 = 0.2f, + M22 = 0.742f, + M23 = 0.142f, + M33 = 0.858f + }; + + /// + public override bool Compand => false; + } +} diff --git a/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Deuteranopia.cs b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Deuteranopia.cs new file mode 100644 index 0000000000..630c2fa3cb --- /dev/null +++ b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Deuteranopia.cs @@ -0,0 +1,29 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageProcessorCore.Filters +{ + using System.Numerics; + + /// + /// Converts the colors of the image recreating Deuteranopia (Green-Blind) color blindness. + /// + public class Deuteranopia : ColorMatrixFilter + { + /// + public override Matrix4x4 Matrix => new Matrix4x4() + { + M11 = 0.625f, + M12 = 0.7f, + M21 = 0.375f, + M22 = 0.3f, + M23 = 0.3f, + M33 = 0.7f + }; + + /// + public override bool Compand => false; + } +} diff --git a/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Protanomaly.cs b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Protanomaly.cs new file mode 100644 index 0000000000..73d3bdcaa5 --- /dev/null +++ b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Protanomaly.cs @@ -0,0 +1,29 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageProcessorCore.Filters +{ + using System.Numerics; + + /// + /// Converts the colors of the image recreating Protanopia (Red-Weak) color blindness. + /// + public class Protanomaly : ColorMatrixFilter + { + /// + public override Matrix4x4 Matrix => new Matrix4x4() + { + M11 = 0.817f, + M12 = 0.333f, + M21 = 0.183f, + M22 = 0.667f, + M23 = 0.125f, + M33 = 0.875f + }; + + /// + public override bool Compand => false; + } +} diff --git a/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Protanopia.cs b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Protanopia.cs new file mode 100644 index 0000000000..a6cfef24e4 --- /dev/null +++ b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Protanopia.cs @@ -0,0 +1,29 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageProcessorCore.Filters +{ + using System.Numerics; + + /// + /// Converts the colors of the image recreating Protanopia (Red-Blind) color blindness. + /// + public class Protanopia : ColorMatrixFilter + { + /// + public override Matrix4x4 Matrix => new Matrix4x4() + { + M11 = 0.567f, + M12 = 0.558f, + M21 = 0.433f, + M22 = 0.442f, + M23 = 0.242f, + M33 = 0.758f + }; + + /// + public override bool Compand => false; + } +} diff --git a/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/README.md b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/README.md new file mode 100644 index 0000000000..209f3b67bd --- /dev/null +++ b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/README.md @@ -0,0 +1,4 @@ +Color blindness matrices adapted from and tested against: + +http://web.archive.org/web/20090413045433/http://nofunc.org/Color_Matrix_Library +http://www.color-blindness.com/coblis-color-blindness-simulator/ \ No newline at end of file diff --git a/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Tritanomaly.cs b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Tritanomaly.cs new file mode 100644 index 0000000000..851b179154 --- /dev/null +++ b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Tritanomaly.cs @@ -0,0 +1,29 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageProcessorCore.Filters +{ + using System.Numerics; + + /// + /// Converts the colors of the image recreating Tritanomaly (Blue-Weak) color blindness. + /// + public class Tritanomaly : ColorMatrixFilter + { + /// + public override Matrix4x4 Matrix => new Matrix4x4() + { + M11 = 0.967f, + M21 = 0.33f, + M22 = 0.733f, + M23 = 0.183f, + M32 = 0.267f, + M33 = 0.817f + }; + + /// + public override bool Compand => false; + } +} diff --git a/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Tritanopia.cs b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Tritanopia.cs new file mode 100644 index 0000000000..338f0877c0 --- /dev/null +++ b/src/ImageProcessorCore/Filters/ColorMatrix/ColorBlindness/Tritanopia.cs @@ -0,0 +1,29 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageProcessorCore.Filters +{ + using System.Numerics; + + /// + /// Converts the colors of the image recreating Tritanopia (Blue-Blind) color blindness. + /// + public class Tritanopia : ColorMatrixFilter + { + /// + public override Matrix4x4 Matrix => new Matrix4x4() + { + M11 = 0.95f, + M21 = 0.05f, + M22 = 0.433f, + M23 = 0.475f, + M32 = 0.567f, + M33 = 0.525f + }; + + /// + public override bool Compand => false; + } +} diff --git a/src/ImageProcessorCore/Filters/ImageFilterExtensions.cs b/src/ImageProcessorCore/Filters/ImageFilterExtensions.cs index 0da5f6b588..5bdb72e529 100644 --- a/src/ImageProcessorCore/Filters/ImageFilterExtensions.cs +++ b/src/ImageProcessorCore/Filters/ImageFilterExtensions.cs @@ -217,6 +217,79 @@ namespace ImageProcessorCore.Filters } } + /// + /// Applies the given colorblindness simulator to the image. + /// + /// The image this method extends. + /// The type of color blindness simulator to apply. + /// A delegate which is called as progress is made processing the image. + /// The . + public static Image ColorBlindness(this Image source, ColorBlindness colorBlindness, ProgressEventHandler progressHandler = null) + { + return ColorBlindness(source, colorBlindness, source.Bounds, progressHandler); + } + + /// + /// Applies the given colorblindness simulator to the image. + /// + /// The image this method extends. + /// The type of color blindness simulator to apply. + /// + /// The structure that specifies the portion of the image object to alter. + /// + /// A delegate which is called as progress is made processing the image. + /// The . + public static Image ColorBlindness(this Image source, ColorBlindness colorBlindness, Rectangle rectangle, ProgressEventHandler progressHandler = null) + { + IImageProcessor processor; + + switch (colorBlindness) + { + case Filters.ColorBlindness.Achromatomaly: + processor = new Achromatomaly(); + break; + + case Filters.ColorBlindness.Achromatopsia: + processor = new Achromatopsia(); + break; + + case Filters.ColorBlindness.Deuteranomaly: + processor = new Deuteranomaly(); + break; + + case Filters.ColorBlindness.Deuteranopia: + processor = new Deuteranopia(); + break; + + case Filters.ColorBlindness.Protanomaly: + processor = new Protanomaly(); + break; + + case Filters.ColorBlindness.Protanopia: + processor = new Protanopia(); + break; + + case Filters.ColorBlindness.Tritanomaly: + processor = new Tritanomaly(); + break; + + default: + processor = new Tritanopia(); + break; + } + + processor.OnProgress += progressHandler; + + try + { + return source.Process(rectangle, processor); + } + finally + { + processor.OnProgress -= progressHandler; + } + } + /// /// Alters the contrast component of the image. /// diff --git a/tests/ImageProcessorCore.Tests/Processors/Filters/FilterTests.cs b/tests/ImageProcessorCore.Tests/Processors/Filters/FilterTests.cs index bd1b17cb6d..577f07a2c0 100644 --- a/tests/ImageProcessorCore.Tests/Processors/Filters/FilterTests.cs +++ b/tests/ImageProcessorCore.Tests/Processors/Filters/FilterTests.cs @@ -44,7 +44,16 @@ namespace ImageProcessorCore.Tests { "Hue-180", new Hue(180) }, { "Hue--180", new Hue(-180) }, { "BoxBlur", new BoxBlur(10) }, - { "Vignette", new Vignette()} + { "Vignette", new Vignette() }, + { "Protanopia", new Protanopia() }, + { "Protanomaly", new Protanomaly() }, + { "Deuteranopia", new Deuteranopia() }, + { "Deuteranomaly", new Deuteranomaly() }, + { "Tritanopia", new Tritanopia() }, + { "Tritanomaly", new Tritanomaly() }, + { "Achromatopsia", new Achromatopsia() }, + { "Achromatomaly", new Achromatomaly() } + }; [Theory]