Skip to content

Commit 79e617b

Browse files
committed
1. 优化ImageBorderRemover
2. 新增ColorDeltaE色差比较类
1 parent 00520ae commit 79e617b

18 files changed

+790
-94
lines changed

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<PropertyGroup>
3-
<Version>2025.3.1</Version>
3+
<Version>2025.4</Version>
44
<Deterministic>true</Deterministic>
55
</PropertyGroup>
66
</Project>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using SixLabors.ImageSharp.PixelFormats;
2+
3+
namespace Masuit.Tools.Media;
4+
5+
/// <summary>
6+
/// 边框检测结果(包含多层边框信息)
7+
/// </summary>
8+
public struct BorderDetectionResult
9+
{
10+
private int CroppedBorderCount { get; set; }
11+
12+
public BorderDetectionResult(int croppedBorderCount)
13+
{
14+
CroppedBorderCount = croppedBorderCount;
15+
}
16+
17+
/// <summary>原始图片宽度</summary>
18+
public int ImageWidth { get; set; }
19+
20+
/// <summary>原始图片高度</summary>
21+
public int ImageHeight { get; set; }
22+
23+
/// <summary>内容上边界位置</summary>
24+
public int ContentTop { get; set; }
25+
26+
/// <summary>内容下边界位置</summary>
27+
public int ContentBottom { get; set; }
28+
29+
/// <summary>内容左边界位置</summary>
30+
public int ContentLeft { get; set; }
31+
32+
/// <summary>内容右边界位置</summary>
33+
public int ContentRight { get; set; }
34+
35+
/// <summary>检测到的边框层数</summary>
36+
public int BorderLayers { get; set; }
37+
38+
/// <summary>边框颜色层次(从外到内)</summary>
39+
public List<Rgba32> BorderColors { get; set; }
40+
41+
/// <summary>顶部边框总宽度(像素)</summary>
42+
public int TopBorderWidth => ContentTop;
43+
44+
/// <summary>底部边框总宽度(像素)</summary>
45+
public int BottomBorderWidth => ImageHeight - 1 - ContentBottom;
46+
47+
/// <summary>左侧边框总宽度(像素)</summary>
48+
public int LeftBorderWidth => ContentLeft;
49+
50+
/// <summary>右侧边框总宽度(像素)</summary>
51+
public int RightBorderWidth => ImageWidth - 1 - ContentRight;
52+
53+
/// <summary>是否有顶部边框</summary>
54+
public bool HasTopBorder => TopBorderWidth > 0;
55+
56+
/// <summary>是否有底部边框</summary>
57+
public bool HasBottomBorder => BottomBorderWidth > 0;
58+
59+
/// <summary>是否有左侧边框</summary>
60+
public bool HasLeftBorder => LeftBorderWidth > 0;
61+
62+
/// <summary>是否有右侧边框</summary>
63+
public bool HasRightBorder => RightBorderWidth > 0;
64+
65+
/// <summary>是否有任意边框</summary>
66+
public bool HasAnyBorder => BorderCount > 0;
67+
68+
/// <summary>是否满足裁剪条件(至少两个边)</summary>
69+
public bool CanBeCropped => BorderCount >= CroppedBorderCount;
70+
71+
public int BorderCount => (HasTopBorder ? 1 : 0) + (HasBottomBorder ? 1 : 0) + (HasLeftBorder ? 1 : 0) + (HasRightBorder ? 1 : 0);
72+
73+
/// <summary>内容区域宽度</summary>
74+
public int ContentWidth => ContentRight - ContentLeft + 1;
75+
76+
/// <summary>内容区域高度</summary>
77+
public int ContentHeight => ContentBottom - ContentTop + 1;
78+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace Masuit.Tools.Media;
2+
3+
public struct CMYColor
4+
{
5+
public double C { get; }
6+
public double M { get; }
7+
public double Y { get; }
8+
9+
public CMYColor(double c, double m, double y)
10+
{
11+
C = c;
12+
M = m;
13+
Y = y;
14+
}
15+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace Masuit.Tools.Media;
2+
3+
public struct CMYKColor
4+
{
5+
public double C { get; }
6+
public double M { get; }
7+
public double Y { get; }
8+
public double K { get; }
9+
10+
public CMYKColor(double c, double m, double y, double k)
11+
{
12+
C = c;
13+
M = m;
14+
Y = y;
15+
K = k;
16+
}
17+
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
using System.Drawing;
2+
3+
namespace Masuit.Tools.Media;
4+
5+
internal static class ColorConverter
6+
{
7+
// RGB转换器
8+
public static LabColor ToLab(this Color color)
9+
{
10+
// 第一步:将RGB转换为0-1范围
11+
double rLinear = color.R / 255.0;
12+
double gLinear = color.G / 255.0;
13+
double bLinear = color.B / 255.0;
14+
15+
// 第二步:应用逆伽马校正
16+
rLinear = (rLinear <= 0.04045) ? rLinear / 12.92 : Math.Pow((rLinear + 0.055) / 1.055, 2.4);
17+
gLinear = (gLinear <= 0.04045) ? gLinear / 12.92 : Math.Pow((gLinear + 0.055) / 1.055, 2.4);
18+
bLinear = (bLinear <= 0.04045) ? bLinear / 12.92 : Math.Pow((bLinear + 0.055) / 1.055, 2.4);
19+
20+
// 第三步:转换为XYZ(D65白点)
21+
double x = rLinear * 0.4124564 + gLinear * 0.3575761 + bLinear * 0.1804375;
22+
double y = rLinear * 0.2126729 + gLinear * 0.7151522 + bLinear * 0.0721750;
23+
double z = rLinear * 0.0193339 + gLinear * 0.1191920 + bLinear * 0.9503041;
24+
25+
// 第四步:XYZ转Lab(使用D65参考白)
26+
const double xn = 0.95047;
27+
const double yn = 1.00000;
28+
const double zn = 1.08883;
29+
30+
double xRatio = x / xn;
31+
double yRatio = y / yn;
32+
double zRatio = z / zn;
33+
34+
double fx = (xRatio > 0.008856) ? Math.Pow(xRatio, 1.0 / 3.0) : (903.3 * xRatio + 16) / 116.0;
35+
double fy = (yRatio > 0.008856) ? Math.Pow(yRatio, 1.0 / 3.0) : (903.3 * yRatio + 16) / 116.0;
36+
double fz = (zRatio > 0.008856) ? Math.Pow(zRatio, 1.0 / 3.0) : (903.3 * zRatio + 16) / 116.0;
37+
38+
double l = (yRatio > 0.008856) ? (116 * fy - 16) : (903.3 * yRatio);
39+
double a = 500 * (fx - fy);
40+
double bVal = 200 * (fy - fz);
41+
42+
return new LabColor(l, a, bVal);
43+
}
44+
45+
// CMY转换器
46+
public static LabColor ToLab(this CMYColor cmy)
47+
{
48+
// CMY转RGB (0-1范围)
49+
double r = 1 - cmy.C;
50+
double g = 1 - cmy.M;
51+
double b = 1 - cmy.Y;
52+
53+
// RGB转Lab
54+
return ToLab(Color.FromArgb((int)(r * 255), (int)(g * 255), (int)(b * 255)));
55+
}
56+
57+
// CMYK转换器
58+
public static LabColor ToLab(this CMYKColor cmyk)
59+
{
60+
// CMYK转RGB
61+
double r = (1 - cmyk.C) * (1 - cmyk.K);
62+
double g = (1 - cmyk.M) * (1 - cmyk.K);
63+
double b = (1 - cmyk.Y) * (1 - cmyk.K);
64+
65+
// RGB转Lab
66+
return ToLab(Color.FromArgb((int)(r * 255), (int)(g * 255), (int)(b * 255)));
67+
}
68+
69+
// HSL转换器
70+
public static LabColor ToLab(this HSLColor hsl)
71+
{
72+
// HSL转RGB
73+
Color rgb = ToRgb(hsl);
74+
return ToLab(rgb);
75+
}
76+
77+
private static Color ToRgb(HSLColor hsl)
78+
{
79+
double h = hsl.H / 360.0;
80+
double s = hsl.S;
81+
double l = hsl.L;
82+
double r, g, b;
83+
if (s == 0)
84+
{
85+
r = g = b = l;
86+
}
87+
else
88+
{
89+
double q = l < 0.5 ? l * (1 + s) : l + s - l * s;
90+
double p = 2 * l - q;
91+
92+
r = HueToRgb(p, q, h + 1.0 / 3);
93+
g = HueToRgb(p, q, h);
94+
b = HueToRgb(p, q, h - 1.0 / 3);
95+
}
96+
97+
return Color.FromArgb((int)(r * 255), (int)(g * 255), (int)(b * 255));
98+
}
99+
100+
private static double HueToRgb(double p, double q, double t)
101+
{
102+
if (t < 0) t += 1;
103+
if (t > 1) t -= 1;
104+
105+
if (t < 1.0 / 6) return p + (q - p) * 6 * t;
106+
if (t < 1.0 / 2) return q;
107+
if (t < 2.0 / 3) return p + (q - p) * (2.0 / 3 - t) * 6;
108+
109+
return p;
110+
}
111+
112+
// LCH转换器
113+
public static LabColor ToLab(this LCHColor lch)
114+
{
115+
// LCH转Lab
116+
double rad = lch.H * Math.PI / 180.0;
117+
double a = lch.C * Math.Cos(rad);
118+
double b = lch.C * Math.Sin(rad);
119+
return new LabColor(lch.L, a, b);
120+
}
121+
122+
// XYZ转换器
123+
public static LabColor ToLab(this XYZColor xyz)
124+
{
125+
// 使用D65参考白点
126+
const double xn = 0.95047;
127+
const double yn = 1.00000;
128+
const double zn = 1.08883;
129+
130+
double xRatio = xyz.X / xn;
131+
double yRatio = xyz.Y / yn;
132+
double zRatio = xyz.Z / zn;
133+
134+
double fx = Fxyz(xRatio);
135+
double fy = Fxyz(yRatio);
136+
double fz = Fxyz(zRatio);
137+
138+
double L = 116 * fy - 16;
139+
double a = 500 * (fx - fy);
140+
double b = 200 * (fy - fz);
141+
142+
return new LabColor(L, a, b);
143+
}
144+
145+
private static double Fxyz(double t)
146+
{
147+
const double delta = 6.0 / 29.0;
148+
const double delta3 = delta * delta * delta;
149+
return (t > delta3) ? Math.Pow(t, 1.0 / 3.0) : t / (3 * delta * delta) + 4.0 / 29.0;
150+
}
151+
152+
// YXZ转换器 (假设YXZ是Y,X,Z顺序)
153+
public static LabColor YxzToLab(this YXZColor yxz)
154+
{
155+
// 转换为标准XYZ顺序
156+
return ToLab(new XYZColor(yxz.X, yxz.Y, yxz.Z));
157+
}
158+
}

0 commit comments

Comments
 (0)