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