Skip to content

Commit 4735e26

Browse files
committed
添加颜色转换代码
1 parent 856f76e commit 4735e26

3 files changed

Lines changed: 302 additions & 0 deletions

File tree

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Numerics;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using SixLabors.ImageSharp;
8+
using SixLabors.ImageSharp.PixelFormats;
9+
using ColorMatrix = DotNetCampus.MediaConverters.Imaging.Effect.Color.ColorMatrix5x5;
10+
11+
namespace DotNetCampus.MediaConverters.Imaging.Effect.Color;
12+
13+
/// <summary>
14+
/// 颜色转换矩阵
15+
/// </summary>
16+
public static class ColorMatrices
17+
{
18+
/// <summary>
19+
/// 在图像上执行颜色矩阵的应用。
20+
/// </summary>
21+
/// <param name="color">颜色</param>
22+
/// <param name="m">颜色处理矩阵.</param>
23+
/// <returns>处理后的颜色</returns>
24+
public static ColorMetadata ApplyMatrix(ColorMetadata color, in ColorMatrix5x5 m)
25+
{
26+
// 应用颜色转换矩阵将RGB颜色转换为新颜色
27+
var r = color.ARGB.Item1;
28+
var g = color.ARGB.Item2;
29+
var b = color.ARGB.Item3;
30+
var a = color.ARGB.Item4;
31+
var w = 1.0f;
32+
Span<float> newColor =
33+
[
34+
(m.Matrix00 * r) + (m.Matrix10 * g) + (m.Matrix20 * b) + (m.Matrix30 * a) + (m.Matrix40 * w),
35+
(m.Matrix01 * r) + (m.Matrix11 * g) + (m.Matrix21 * b) + (m.Matrix31 * a) + (m.Matrix41 * w),
36+
(m.Matrix02 * r) + (m.Matrix12 * g) + (m.Matrix22 * b) + (m.Matrix32 * a) + (m.Matrix42 * w),
37+
(m.Matrix03 * r) + (m.Matrix13 * g) + (m.Matrix23 * b) + (m.Matrix33 * a) + (m.Matrix43 * w),
38+
(m.Matrix04 * r) + (m.Matrix14 * g) + (m.Matrix24 * b) + (m.Matrix34 * a) + (m.Matrix44 * w)
39+
];
40+
41+
if (newColor[0] < 0) newColor[0] = 0;
42+
if (newColor[0] > 1) newColor[0] = 1;
43+
if (newColor[1] < 0) newColor[1] = 0;
44+
if (newColor[1] > 1) newColor[1] = 1;
45+
if (newColor[2] < 0) newColor[2] = 0;
46+
if (newColor[2] > 1) newColor[2] = 1;
47+
if (newColor[3] < 0) newColor[3] = 0;
48+
if (newColor[3] > 1) newColor[3] = 1;
49+
if (newColor[4] < 0) newColor[4] = 0;
50+
if (newColor[4] > 1) newColor[4] = 1;
51+
52+
return new ColorMetadata(newColor[0], newColor[1], newColor[2], newColor[3]);
53+
}
54+
55+
/// <summary>
56+
/// 使用给定的数量创建亮度过滤器矩阵。
57+
/// <para>
58+
/// 使用算法<see href="https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc"/>
59+
/// </para>
60+
/// </summary>
61+
/// <remarks>
62+
/// 值为 0 将创建一个完全黑色的图像。值为 1 时输入保持不变。
63+
/// 其他值是效果的线性乘数。允许超过 1 的值,从而提供更明亮的结果。
64+
/// </remarks>
65+
/// <param name="amount">转化比例,必须大于或等于 0。</param>
66+
/// <returns>The <see cref="ColorMatrix"/>.</returns>
67+
public static ColorMatrix CreateBrightnessFilter(float amount)
68+
{
69+
if (amount < 0)
70+
{
71+
throw new ArgumentOutOfRangeException(nameof(amount), "Threshold must be >= 0");
72+
}
73+
74+
return new ColorMatrix
75+
{
76+
Matrix00 = amount,
77+
Matrix11 = amount,
78+
Matrix22 = amount,
79+
Matrix33 = 1F
80+
};
81+
}
82+
83+
/// <summary>
84+
/// 使用给定的数量创建灰度滤波器矩阵。
85+
/// <para>
86+
/// 使用算法<see href="https://en.wikipedia.org/wiki/Luma_%28video%29#Rec._601_luma_versus_Rec._709_luma_coefficients"/>
87+
/// </para>
88+
/// </summary>
89+
/// <param name="amount">转化比例,必须大于或等于 0 小于等于 1。</param>amount
90+
/// <returns>The <see cref="ColorMatrix"/>.</returns>
91+
public static ColorMatrix CreateGrayScaleFilter(float amount)
92+
{
93+
if (amount < 0 || amount > 1)
94+
{
95+
throw new ArgumentOutOfRangeException(
96+
nameof(amount),
97+
"Threshold must be in range 0..1");
98+
}
99+
100+
amount = 1F - amount;
101+
102+
var matrix = new ColorMatrix
103+
{
104+
Matrix00 = .299F + (.701F * amount),
105+
Matrix10 = .587F - (.587F * amount),
106+
Matrix01 = .299F - (.299F * amount),
107+
Matrix11 = .587F + (.2848F * amount),
108+
Matrix02 = .299F - (.299F * amount),
109+
Matrix12 = .587F - (.587F * amount),
110+
Matrix33 = 1F
111+
};
112+
113+
matrix = matrix with
114+
{
115+
Matrix20 = 1F - (matrix.Matrix00 + matrix.Matrix10),
116+
Matrix21 = 1F - (matrix.Matrix01 + matrix.Matrix11),
117+
Matrix22 = 1F - (matrix.Matrix02 + matrix.Matrix12),
118+
};
119+
120+
return matrix;
121+
}
122+
123+
/// <summary>
124+
/// 使用给定的数量创建对比度过滤器矩阵。
125+
/// <para>
126+
/// 使用算法<see href="https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc"/>
127+
/// </para>
128+
/// </summary>
129+
/// <remarks>
130+
/// 值为 0 将创建一个完全灰色的图像。值为 1 时输入保持不变。
131+
/// 其他值是效果的线性乘数。允许超过 1 的值,从而提供具有更高对比度的结果。
132+
/// </remarks>
133+
/// <param name="amount">转化比例,必须大于或等于 0。</param>
134+
/// <returns>The <see cref="ColorMatrix"/>.</returns>
135+
public static ColorMatrix CreateContrastFilter(float amount)
136+
{
137+
if (amount < 0)
138+
{
139+
throw new ArgumentOutOfRangeException(nameof(amount), "Threshold must be >= 0");
140+
}
141+
142+
var contrast = (-.5F * amount) + .5F;
143+
144+
return new ColorMatrix
145+
{
146+
Matrix00 = amount,
147+
Matrix11 = amount,
148+
Matrix22 = amount,
149+
Matrix33 = 1F,
150+
Matrix40 = contrast,
151+
Matrix41 = contrast,
152+
Matrix42 = contrast
153+
};
154+
}
155+
156+
/// <summary>
157+
/// 使用给定的数量创建饱和度过滤器矩阵。
158+
/// <para>
159+
/// 使用算法<see href="https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc"/>
160+
/// </para>
161+
/// </summary>
162+
/// <remarks>
163+
/// 0 值是完全不饱和的。值为 1 时输入保持不变。
164+
/// 其他值是效果的线性乘数。允许超过 1 的值,提供超饱和结果。
165+
/// </remarks>
166+
/// <param name="amount">转化比例,必须大于或等于 0。</param>
167+
/// <returns>The <see cref="ColorMatrix"/>.</returns>
168+
public static ColorMatrix CreateSaturationFilter(float amount)
169+
{
170+
if (amount < 0)
171+
{
172+
throw new ArgumentOutOfRangeException(nameof(amount), "Threshold must be >= 0");
173+
}
174+
175+
var matrix = new ColorMatrix
176+
{
177+
Matrix00 = .213F + (.787F * amount),
178+
Matrix10 = .715F - (.715F * amount),
179+
Matrix01 = .213F - (.213F * amount),
180+
Matrix11 = .715F + (.285F * amount),
181+
Matrix02 = .213F - (.213F * amount),
182+
Matrix12 = .715F - (.715F * amount),
183+
Matrix33 = 1F
184+
};
185+
186+
matrix = matrix with
187+
{
188+
Matrix20 = 1F - (matrix.Matrix00 + matrix.Matrix10),
189+
Matrix21 = 1F - (matrix.Matrix01 + matrix.Matrix11),
190+
Matrix22 = 1F - (matrix.Matrix02 + matrix.Matrix12),
191+
};
192+
193+
return matrix;
194+
}
195+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace DotNetCampus.MediaConverters.Imaging.Effect.Color;
2+
3+
// ReSharper disable once InconsistentNaming
4+
public readonly record struct ColorMatrix5x5()
5+
{
6+
public float Matrix00 { get; init; } = 1.0f;
7+
public float Matrix01 { get; init; } = 0.0f;
8+
public float Matrix02 { get; init; } = 0.0f;
9+
public float Matrix03 { get; init; } = 0.0f;
10+
public float Matrix04 { get; init; } = 0.0f;
11+
public float Matrix10 { get; init; } = 0.0f;
12+
public float Matrix11 { get; init; } = 1.0f;
13+
public float Matrix12 { get; init; } = 0.0f;
14+
public float Matrix13 { get; init; } = 0.0f;
15+
public float Matrix14 { get; init; } = 0.0f;
16+
public float Matrix20 { get; init; } = 0.0f;
17+
public float Matrix21 { get; init; } = 0.0f;
18+
public float Matrix22 { get; init; } = 1.0f;
19+
public float Matrix23 { get; init; } = 0.0f;
20+
public float Matrix24 { get; init; } = 0.0f;
21+
public float Matrix30 { get; init; } = 0.0f;
22+
public float Matrix31 { get; init; } = 0.0f;
23+
public float Matrix32 { get; init; } = 0.0f;
24+
public float Matrix33 { get; init; } = 1.0f;
25+
public float Matrix34 { get; init; } = 0.0f;
26+
public float Matrix40 { get; init; } = 0.0f;
27+
public float Matrix41 { get; init; } = 0.0f;
28+
public float Matrix42 { get; init; } = 0.0f;
29+
public float Matrix43 { get; init; } = 0.0f;
30+
public float Matrix44 { get; init; } = 1.0f;
31+
32+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using SixLabors.ImageSharp.PixelFormats;
7+
8+
namespace DotNetCampus.MediaConverters.Imaging.Effect.Color;
9+
10+
public readonly struct ColorMetadata
11+
{
12+
public ColorMetadata(Rgba32 color)
13+
{
14+
Color = color;
15+
ARGB = (color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f);
16+
}
17+
18+
/// <summary>
19+
/// 使用RGB数据进行构造
20+
/// </summary>
21+
/// <param name="r"></param>
22+
/// <param name="g"></param>
23+
/// <param name="b"></param>
24+
/// <param name="a"></param>
25+
public ColorMetadata(float r, float g, float b, float a = 1)
26+
{
27+
ARGB = (r, g, b, a);
28+
Color = new Rgba32(To8BitValue(r), To8BitValue(g), To8BitValue(b), To8BitValue(a));
29+
30+
static byte To8BitValue(float value)
31+
{
32+
if (value < 0)
33+
{
34+
return 0;
35+
}
36+
else if (value >= 1)
37+
{
38+
return byte.MaxValue;
39+
}
40+
41+
return (byte) Math.Min(Math.Round(value * byte.MaxValue), byte.MaxValue);
42+
}
43+
}
44+
45+
public Rgba32 Color { get; init; }
46+
47+
/// <summary>
48+
/// RGB模式的红色、绿色、蓝色、透明度通道值[范围0-1]
49+
/// 注意Alpha通道是最后一个值
50+
/// </summary>
51+
public (float R, float G, float B, float A) ARGB { get; }
52+
53+
/// <summary>
54+
/// RGB模式的红色、绿色、蓝色通道值[范围0-1]
55+
/// </summary>
56+
public (float R, float G, float B) RGB => (ARGB.R, ARGB.G, ARGB.B);
57+
58+
/// <summary>
59+
/// RGB模式的红色、绿色、蓝色、透明度通道值[范围0-255]
60+
/// 注意Alpha通道是最后一个值
61+
/// </summary>
62+
public (byte R, byte G, byte B, byte A) ARGB8bit => (Color.R, Color.G, Color.B, Color.A);
63+
64+
/// <summary>
65+
/// 获取颜色的灰度值
66+
/// </summary>
67+
/// <returns></returns>
68+
public float GetGrayScale()
69+
{
70+
var r = ARGB.R;
71+
var g = ARGB.G;
72+
var b = ARGB.B;
73+
return 0.30f * r + 0.59f * g + 0.11f * b;
74+
}
75+
}

0 commit comments

Comments
 (0)