mirror of https://github.com/SixLabors/ImageSharp
Browse Source
Former-commit-id: 5ce61ca1e508ed598370b5817fa54fa6aaf7ecff Former-commit-id: b04c8676420dad90a6cb9515bdc8b9db67752576 Former-commit-id: 98da045e3b41b5369a5d8ef393b2b22b8c011665pull/1/head
18 changed files with 492 additions and 9 deletions
@ -0,0 +1,96 @@ |
|||||
|
// <copyright file="ColorBlindness.cs" company="James Jackson-South">
|
||||
|
// Copyright (c) James Jackson-South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>-------------------------------------------------------------------------------------------------------------------
|
||||
|
|
||||
|
namespace ImageProcessorCore |
||||
|
{ |
||||
|
using Processors; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Extension methods for the <see cref="Image"/> type.
|
||||
|
/// </summary>
|
||||
|
public static partial class ImageExtensions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies the given colorblindness simulator to the image.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The pixel format.</typeparam>
|
||||
|
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
|
||||
|
/// <param name="source">The image this method extends.</param>
|
||||
|
/// <param name="colorBlindness">The type of color blindness simulator to apply.</param>
|
||||
|
/// <param name="progressHandler">A delegate which is called as progress is made processing the image.</param>
|
||||
|
/// <returns>The <see cref="Image{T,TP}"/>.</returns>
|
||||
|
public static Image<T, TP> ColorBlindness<T, TP>(this Image<T, TP> source, ColorBlindness colorBlindness, ProgressEventHandler progressHandler = null) |
||||
|
where T : IPackedVector<TP> |
||||
|
where TP : struct |
||||
|
{ |
||||
|
return ColorBlindness(source, colorBlindness, source.Bounds, progressHandler); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Applies the given colorblindness simulator to the image.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The pixel format.</typeparam>
|
||||
|
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
|
||||
|
/// <param name="source">The image this method extends.</param>
|
||||
|
/// <param name="colorBlindness">The type of color blindness simulator to apply.</param>
|
||||
|
/// <param name="rectangle">
|
||||
|
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
|
||||
|
/// </param>
|
||||
|
/// <param name="progressHandler">A delegate which is called as progress is made processing the image.</param>
|
||||
|
/// <returns>The <see cref="Image{T,TP}"/>.</returns>
|
||||
|
public static Image<T, TP> ColorBlindness<T, TP>(this Image<T, TP> source, ColorBlindness colorBlindness, Rectangle rectangle, ProgressEventHandler progressHandler = null) |
||||
|
where T : IPackedVector<TP> |
||||
|
where TP : struct |
||||
|
{ |
||||
|
IImageProcessor<T, TP> processor; |
||||
|
|
||||
|
switch (colorBlindness) |
||||
|
{ |
||||
|
case ImageProcessorCore.ColorBlindness.Achromatomaly: |
||||
|
processor = new AchromatomalyProcessor<T, TP>(); |
||||
|
break; |
||||
|
|
||||
|
case ImageProcessorCore.ColorBlindness.Achromatopsia: |
||||
|
processor = new AchromatopsiaProcessor<T, TP>(); |
||||
|
break; |
||||
|
|
||||
|
case ImageProcessorCore.ColorBlindness.Deuteranomaly: |
||||
|
processor = new DeuteranomalyProcessor<T, TP>(); |
||||
|
break; |
||||
|
|
||||
|
case ImageProcessorCore.ColorBlindness.Deuteranopia: |
||||
|
processor = new DeuteranopiaProcessor<T, TP>(); |
||||
|
break; |
||||
|
|
||||
|
case ImageProcessorCore.ColorBlindness.Protanomaly: |
||||
|
processor = new ProtanomalyProcessor<T, TP>(); |
||||
|
break; |
||||
|
|
||||
|
case ImageProcessorCore.ColorBlindness.Protanopia: |
||||
|
processor = new ProtanopiaProcessor<T, TP>(); |
||||
|
break; |
||||
|
|
||||
|
case ImageProcessorCore.ColorBlindness.Tritanomaly: |
||||
|
processor = new TritanomalyProcessor<T, TP>(); |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
processor = new TritanopiaProcessor<T, TP>(); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
processor.OnProgress += progressHandler; |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
return source.Process(rectangle, processor); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
processor.OnProgress -= progressHandler; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,53 @@ |
|||||
|
// <copyright file="ColorBlindness.cs" company="James Jackson-South">
|
||||
|
// Copyright (c) James Jackson-South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessorCore |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Enumerates the various types of color blindness.
|
||||
|
/// </summary>
|
||||
|
public enum ColorBlindness |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Partial color desensitivity.
|
||||
|
/// </summary>
|
||||
|
Achromatomaly, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Complete color desensitivity (Monochrome)
|
||||
|
/// </summary>
|
||||
|
Achromatopsia, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Green weak
|
||||
|
/// </summary>
|
||||
|
Deuteranomaly, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Green blind
|
||||
|
/// </summary>
|
||||
|
Deuteranopia, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Red weak
|
||||
|
/// </summary>
|
||||
|
Protanomaly, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Red blind
|
||||
|
/// </summary>
|
||||
|
Protanopia, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Blue weak
|
||||
|
/// </summary>
|
||||
|
Tritanomaly, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Blue blind
|
||||
|
/// </summary>
|
||||
|
Tritanopia |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
// <copyright file="AchromatomalyProcessor.cs" company="James Jackson-South">
|
||||
|
// Copyright (c) James Jackson-South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessorCore.Processors |
||||
|
{ |
||||
|
using System.Numerics; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts the colors of the image recreating Achromatomaly (Color desensitivity) color blindness.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The pixel format.</typeparam>
|
||||
|
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
|
||||
|
public class AchromatomalyProcessor<T, TP> : ColorMatrixFilter<T, TP> |
||||
|
where T : IPackedVector<TP> |
||||
|
where TP : struct |
||||
|
{ |
||||
|
/// <inheritdoc/>
|
||||
|
public override Matrix4x4 Matrix => new Matrix4x4() |
||||
|
{ |
||||
|
M11 = .618f, |
||||
|
M12 = .163f, |
||||
|
M13 = .163f, |
||||
|
M21 = .320f, |
||||
|
M22 = .775f, |
||||
|
M23 = .320f, |
||||
|
M31 = .062f, |
||||
|
M32 = .062f, |
||||
|
M33 = .516f |
||||
|
}; |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public override bool Compand => false; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
// <copyright file="AchromatopsiaProcessor.cs" company="James Jackson-South">
|
||||
|
// Copyright (c) James Jackson-South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessorCore.Processors |
||||
|
{ |
||||
|
using System.Numerics; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts the colors of the image recreating Achromatopsia (Monochrome) color blindness.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The pixel format.</typeparam>
|
||||
|
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
|
||||
|
public class AchromatopsiaProcessor<T, TP> : ColorMatrixFilter<T, TP> |
||||
|
where T : IPackedVector<TP> |
||||
|
where TP : struct |
||||
|
{ |
||||
|
/// <inheritdoc/>
|
||||
|
public override Matrix4x4 Matrix => new Matrix4x4() |
||||
|
{ |
||||
|
M11 = .299f, |
||||
|
M12 = .299f, |
||||
|
M13 = .299f, |
||||
|
M21 = .587f, |
||||
|
M22 = .587f, |
||||
|
M23 = .587f, |
||||
|
M31 = .114f, |
||||
|
M32 = .114f, |
||||
|
M33 = .114f |
||||
|
}; |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public override bool Compand => false; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
// <copyright file="DeuteranomalyProcessor.cs" company="James Jackson-South">
|
||||
|
// Copyright (c) James Jackson-South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessorCore.Processors |
||||
|
{ |
||||
|
using System.Numerics; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts the colors of the image recreating Deuteranomaly (Green-Weak) color blindness.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The pixel format.</typeparam>
|
||||
|
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
|
||||
|
public class DeuteranomalyProcessor<T, TP> : ColorMatrixFilter<T, TP> |
||||
|
where T : IPackedVector<TP> |
||||
|
where TP : struct |
||||
|
{ |
||||
|
/// <inheritdoc/>
|
||||
|
public override Matrix4x4 Matrix => new Matrix4x4() |
||||
|
{ |
||||
|
M11 = 0.8f, |
||||
|
M12 = 0.258f, |
||||
|
M21 = 0.2f, |
||||
|
M22 = 0.742f, |
||||
|
M23 = 0.142f, |
||||
|
M33 = 0.858f |
||||
|
}; |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public override bool Compand => false; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
// <copyright file="DeuteranopiaProcessor.cs" company="James Jackson-South">
|
||||
|
// Copyright (c) James Jackson-South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessorCore.Processors |
||||
|
{ |
||||
|
using System.Numerics; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts the colors of the image recreating Deuteranopia (Green-Blind) color blindness.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The pixel format.</typeparam>
|
||||
|
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
|
||||
|
public class DeuteranopiaProcessor<T, TP> : ColorMatrixFilter<T, TP> |
||||
|
where T : IPackedVector<TP> |
||||
|
where TP : struct |
||||
|
{ |
||||
|
/// <inheritdoc/>
|
||||
|
public override Matrix4x4 Matrix => new Matrix4x4() |
||||
|
{ |
||||
|
M11 = 0.625f, |
||||
|
M12 = 0.7f, |
||||
|
M21 = 0.375f, |
||||
|
M22 = 0.3f, |
||||
|
M23 = 0.3f, |
||||
|
M33 = 0.7f |
||||
|
}; |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public override bool Compand => false; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
// <copyright file="ProtanomalyProcessor.cs" company="James Jackson-South">
|
||||
|
// Copyright (c) James Jackson-South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessorCore.Processors |
||||
|
{ |
||||
|
using System.Numerics; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts the colors of the image recreating Protanopia (Red-Weak) color blindness.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The pixel format.</typeparam>
|
||||
|
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
|
||||
|
public class ProtanomalyProcessor<T, TP> : ColorMatrixFilter<T, TP> |
||||
|
where T : IPackedVector<TP> |
||||
|
where TP : struct |
||||
|
{ |
||||
|
/// <inheritdoc/>
|
||||
|
public override Matrix4x4 Matrix => new Matrix4x4() |
||||
|
{ |
||||
|
M11 = 0.817f, |
||||
|
M12 = 0.333f, |
||||
|
M21 = 0.183f, |
||||
|
M22 = 0.667f, |
||||
|
M23 = 0.125f, |
||||
|
M33 = 0.875f |
||||
|
}; |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public override bool Compand => false; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
// <copyright file="ProtanopiaProcessor.cs" company="James Jackson-South">
|
||||
|
// Copyright (c) James Jackson-South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessorCore.Processors |
||||
|
{ |
||||
|
using System.Numerics; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts the colors of the image recreating Protanopia (Red-Blind) color blindness.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The pixel format.</typeparam>
|
||||
|
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
|
||||
|
public class ProtanopiaProcessor<T, TP> : ColorMatrixFilter<T, TP> |
||||
|
where T : IPackedVector<TP> |
||||
|
where TP : struct |
||||
|
{ |
||||
|
/// <inheritdoc/>
|
||||
|
public override Matrix4x4 Matrix => new Matrix4x4() |
||||
|
{ |
||||
|
M11 = 0.567f, |
||||
|
M12 = 0.558f, |
||||
|
M21 = 0.433f, |
||||
|
M22 = 0.442f, |
||||
|
M23 = 0.242f, |
||||
|
M33 = 0.758f |
||||
|
}; |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public override bool Compand => false; |
||||
|
} |
||||
|
} |
||||
@ -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/ |
||||
@ -0,0 +1,33 @@ |
|||||
|
// <copyright file="TritanomalyProcessor.cs" company="James Jackson-South">
|
||||
|
// Copyright (c) James Jackson-South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessorCore.Processors |
||||
|
{ |
||||
|
using System.Numerics; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts the colors of the image recreating Tritanomaly (Blue-Weak) color blindness.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The pixel format.</typeparam>
|
||||
|
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
|
||||
|
public class TritanomalyProcessor<T, TP> : ColorMatrixFilter<T, TP> |
||||
|
where T : IPackedVector<TP> |
||||
|
where TP : struct |
||||
|
{ |
||||
|
/// <inheritdoc/>
|
||||
|
public override Matrix4x4 Matrix => new Matrix4x4() |
||||
|
{ |
||||
|
M11 = 0.967f, |
||||
|
M21 = 0.33f, |
||||
|
M22 = 0.733f, |
||||
|
M23 = 0.183f, |
||||
|
M32 = 0.267f, |
||||
|
M33 = 0.817f |
||||
|
}; |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public override bool Compand => false; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
// <copyright file="TritanopiaProcessor.cs" company="James Jackson-South">
|
||||
|
// Copyright (c) James Jackson-South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessorCore.Processors |
||||
|
{ |
||||
|
using System.Numerics; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts the colors of the image recreating Tritanopia (Blue-Blind) color blindness.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The pixel format.</typeparam>
|
||||
|
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
|
||||
|
public class TritanopiaProcessor<T, TP> : ColorMatrixFilter<T, TP> |
||||
|
where T : IPackedVector<TP> |
||||
|
where TP : struct |
||||
|
{ |
||||
|
/// <inheritdoc/>
|
||||
|
public override Matrix4x4 Matrix => new Matrix4x4() |
||||
|
{ |
||||
|
M11 = 0.95f, |
||||
|
M21 = 0.05f, |
||||
|
M22 = 0.433f, |
||||
|
M23 = 0.475f, |
||||
|
M32 = 0.567f, |
||||
|
M33 = 0.525f |
||||
|
}; |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public override bool Compand => false; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
// <copyright file="SamplerTests.cs" company="James Jackson-South">
|
||||
|
// Copyright (c) James Jackson-South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessorCore.Tests |
||||
|
{ |
||||
|
using System.IO; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
public class ColorBlindnessTest : FileTestBase |
||||
|
{ |
||||
|
public static readonly TheoryData<ColorBlindness> ColorBlindnessFilters |
||||
|
= new TheoryData<ColorBlindness> |
||||
|
{ |
||||
|
ColorBlindness.Achromatomaly, |
||||
|
ColorBlindness.Achromatopsia, |
||||
|
ColorBlindness.Deuteranomaly, |
||||
|
ColorBlindness.Deuteranopia, |
||||
|
ColorBlindness.Protanomaly, |
||||
|
ColorBlindness.Protanopia, |
||||
|
ColorBlindness.Tritanomaly, |
||||
|
ColorBlindness.Tritanopia |
||||
|
}; |
||||
|
|
||||
|
[Theory] |
||||
|
[MemberData("ColorBlindnessFilters")] |
||||
|
public void ImageShouldApplyColorBlindnessFilter(ColorBlindness colorBlindness) |
||||
|
{ |
||||
|
const string path = "TestOutput/ColorBlindness"; |
||||
|
if (!Directory.Exists(path)) |
||||
|
{ |
||||
|
Directory.CreateDirectory(path); |
||||
|
} |
||||
|
|
||||
|
foreach (string file in Files) |
||||
|
{ |
||||
|
using (FileStream stream = File.OpenRead(file)) |
||||
|
{ |
||||
|
string filename = Path.GetFileNameWithoutExtension(file) + "-" + colorBlindness + Path.GetExtension(file); |
||||
|
Image image = new Image(stream); |
||||
|
using (FileStream output = File.OpenWrite($"{path}/{filename}")) |
||||
|
{ |
||||
|
image.ColorBlindness(colorBlindness) |
||||
|
.Save(output); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue