Skip to content

Commit 3b430e1

Browse files
Port CMYK converter
1 parent 597bc0c commit 3b430e1

File tree

9 files changed

+447
-211
lines changed

9 files changed

+447
-211
lines changed

src/ImageSharp/Common/Helpers/Vector128Utilities.cs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -244,16 +244,6 @@ public static Vector128<float> MultiplyAdd(
244244
return Fma.MultiplyAdd(vm1, vm0, va);
245245
}
246246

247-
if (AdvSimd.IsSupported)
248-
{
249-
return AdvSimd.Add(AdvSimd.Multiply(vm0, vm1), va);
250-
}
251-
252-
if (Sse.IsSupported)
253-
{
254-
return Sse.Add(Sse.Multiply(vm0, vm1), va);
255-
}
256-
257247
return va + (vm0 * vm1);
258248
}
259249

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Six Labors Split License.
3+
4+
using System.Runtime.CompilerServices;
5+
using System.Runtime.InteropServices;
6+
using System.Runtime.Intrinsics;
7+
8+
namespace SixLabors.ImageSharp.Formats.Jpeg.Components;
9+
10+
internal abstract partial class JpegColorConverterBase
11+
{
12+
internal sealed class CmykVector128 : JpegColorConverterVector128
13+
{
14+
public CmykVector128(int precision)
15+
: base(JpegColorSpace.Cmyk, precision)
16+
{
17+
}
18+
19+
/// <inheritdoc/>
20+
public override void ConvertToRgbInPlace(in ComponentValues values)
21+
{
22+
ref Vector128<float> c0Base =
23+
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component0));
24+
ref Vector128<float> c1Base =
25+
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component1));
26+
ref Vector128<float> c2Base =
27+
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component2));
28+
ref Vector128<float> c3Base =
29+
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component3));
30+
31+
// Used for the color conversion
32+
Vector128<float> scale = Vector128.Create(1 / (this.MaximumValue * this.MaximumValue));
33+
34+
nuint n = values.Component0.Vector128Count<float>();
35+
for (nuint i = 0; i < n; i++)
36+
{
37+
ref Vector128<float> c = ref Unsafe.Add(ref c0Base, i);
38+
ref Vector128<float> m = ref Unsafe.Add(ref c1Base, i);
39+
ref Vector128<float> y = ref Unsafe.Add(ref c2Base, i);
40+
Vector128<float> k = Unsafe.Add(ref c3Base, i);
41+
42+
k *= scale;
43+
c *= k;
44+
m *= k;
45+
y *= k;
46+
}
47+
}
48+
49+
/// <inheritdoc/>
50+
public override void ConvertFromRgb(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane)
51+
=> ConvertFromRgb(in values, this.MaximumValue, rLane, gLane, bLane);
52+
53+
public static void ConvertFromRgb(in ComponentValues values, float maxValue, Span<float> rLane, Span<float> gLane, Span<float> bLane)
54+
{
55+
ref Vector128<float> destC =
56+
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component0));
57+
ref Vector128<float> destM =
58+
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component1));
59+
ref Vector128<float> destY =
60+
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component2));
61+
ref Vector128<float> destK =
62+
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component3));
63+
64+
ref Vector128<float> srcR =
65+
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(rLane));
66+
ref Vector128<float> srcG =
67+
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(gLane));
68+
ref Vector128<float> srcB =
69+
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(bLane));
70+
71+
Vector128<float> scale = Vector128.Create(maxValue);
72+
73+
nuint n = values.Component0.Vector128Count<float>();
74+
for (nuint i = 0; i < n; i++)
75+
{
76+
Vector128<float> ctmp = scale - Unsafe.Add(ref srcR, i);
77+
Vector128<float> mtmp = scale - Unsafe.Add(ref srcG, i);
78+
Vector128<float> ytmp = scale - Unsafe.Add(ref srcB, i);
79+
Vector128<float> ktmp = Vector128.Min(ctmp, Vector128.Min(mtmp, ytmp));
80+
81+
Vector128<float> kMask = Vector128.Equals(ktmp, scale);
82+
ctmp = Vector128.AndNot((ctmp - ktmp) / (scale - ktmp), kMask);
83+
mtmp = Vector128.AndNot((mtmp - ktmp) / (scale - ktmp), kMask);
84+
ytmp = Vector128.AndNot((ytmp - ktmp) / (scale - ktmp), kMask);
85+
86+
Unsafe.Add(ref destC, i) = scale - (ctmp * scale);
87+
Unsafe.Add(ref destM, i) = scale - (mtmp * scale);
88+
Unsafe.Add(ref destY, i) = scale - (ytmp * scale);
89+
Unsafe.Add(ref destK, i) = scale - ktmp;
90+
}
91+
}
92+
}
93+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Six Labors Split License.
3+
4+
using System.Runtime.CompilerServices;
5+
using System.Runtime.InteropServices;
6+
using System.Runtime.Intrinsics;
7+
8+
namespace SixLabors.ImageSharp.Formats.Jpeg.Components;
9+
10+
internal abstract partial class JpegColorConverterBase
11+
{
12+
internal sealed class CmykVector256 : JpegColorConverterVector256
13+
{
14+
public CmykVector256(int precision)
15+
: base(JpegColorSpace.Cmyk, precision)
16+
{
17+
}
18+
19+
/// <inheritdoc/>
20+
public override void ConvertToRgbInPlace(in ComponentValues values)
21+
{
22+
ref Vector256<float> c0Base =
23+
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0));
24+
ref Vector256<float> c1Base =
25+
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component1));
26+
ref Vector256<float> c2Base =
27+
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component2));
28+
ref Vector256<float> c3Base =
29+
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component3));
30+
31+
// Used for the color conversion
32+
Vector256<float> scale = Vector256.Create(1 / (this.MaximumValue * this.MaximumValue));
33+
34+
nuint n = values.Component0.Vector256Count<float>();
35+
for (nuint i = 0; i < n; i++)
36+
{
37+
ref Vector256<float> c = ref Unsafe.Add(ref c0Base, i);
38+
ref Vector256<float> m = ref Unsafe.Add(ref c1Base, i);
39+
ref Vector256<float> y = ref Unsafe.Add(ref c2Base, i);
40+
Vector256<float> k = Unsafe.Add(ref c3Base, i);
41+
42+
k *= scale;
43+
c *= k;
44+
m *= k;
45+
y *= k;
46+
}
47+
}
48+
49+
/// <inheritdoc/>
50+
public override void ConvertFromRgb(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane)
51+
=> ConvertFromRgb(in values, this.MaximumValue, rLane, gLane, bLane);
52+
53+
public static void ConvertFromRgb(in ComponentValues values, float maxValue, Span<float> rLane, Span<float> gLane, Span<float> bLane)
54+
{
55+
ref Vector256<float> destC =
56+
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0));
57+
ref Vector256<float> destM =
58+
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component1));
59+
ref Vector256<float> destY =
60+
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component2));
61+
ref Vector256<float> destK =
62+
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component3));
63+
64+
ref Vector256<float> srcR =
65+
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(rLane));
66+
ref Vector256<float> srcG =
67+
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(gLane));
68+
ref Vector256<float> srcB =
69+
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(bLane));
70+
71+
Vector256<float> scale = Vector256.Create(maxValue);
72+
73+
nuint n = values.Component0.Vector256Count<float>();
74+
for (nuint i = 0; i < n; i++)
75+
{
76+
Vector256<float> ctmp = scale - Unsafe.Add(ref srcR, i);
77+
Vector256<float> mtmp = scale - Unsafe.Add(ref srcG, i);
78+
Vector256<float> ytmp = scale - Unsafe.Add(ref srcB, i);
79+
Vector256<float> ktmp = Vector256.Min(ctmp, Vector256.Min(mtmp, ytmp));
80+
81+
Vector256<float> kMask = Vector256.Equals(ktmp, scale);
82+
ctmp = Vector256.AndNot((ctmp - ktmp) / (scale - ktmp), kMask);
83+
mtmp = Vector256.AndNot((mtmp - ktmp) / (scale - ktmp), kMask);
84+
ytmp = Vector256.AndNot((ytmp - ktmp) / (scale - ktmp), kMask);
85+
86+
Unsafe.Add(ref destC, i) = scale - (ctmp * scale);
87+
Unsafe.Add(ref destM, i) = scale - (mtmp * scale);
88+
Unsafe.Add(ref destY, i) = scale - (ytmp * scale);
89+
Unsafe.Add(ref destK, i) = scale - ktmp;
90+
}
91+
}
92+
}
93+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Six Labors Split License.
3+
4+
using System.Runtime.CompilerServices;
5+
using System.Runtime.InteropServices;
6+
using System.Runtime.Intrinsics;
7+
8+
namespace SixLabors.ImageSharp.Formats.Jpeg.Components;
9+
10+
internal abstract partial class JpegColorConverterBase
11+
{
12+
internal sealed class CmykVector512 : JpegColorConverterVector512
13+
{
14+
public CmykVector512(int precision)
15+
: base(JpegColorSpace.Cmyk, precision)
16+
{
17+
}
18+
19+
/// <inheritdoc/>
20+
protected override void ConvertToRgbInPlaceVectorized(in ComponentValues values)
21+
{
22+
ref Vector512<float> c0Base =
23+
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component0));
24+
ref Vector512<float> c1Base =
25+
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component1));
26+
ref Vector512<float> c2Base =
27+
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component2));
28+
ref Vector512<float> c3Base =
29+
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component3));
30+
31+
// Used for the color conversion
32+
Vector512<float> scale = Vector512.Create(1 / (this.MaximumValue * this.MaximumValue));
33+
34+
nuint n = values.Component0.Vector512Count<float>();
35+
for (nuint i = 0; i < n; i++)
36+
{
37+
ref Vector512<float> c = ref Unsafe.Add(ref c0Base, i);
38+
ref Vector512<float> m = ref Unsafe.Add(ref c1Base, i);
39+
ref Vector512<float> y = ref Unsafe.Add(ref c2Base, i);
40+
Vector512<float> k = Unsafe.Add(ref c3Base, i);
41+
42+
k *= scale;
43+
c *= k;
44+
m *= k;
45+
y *= k;
46+
}
47+
}
48+
49+
/// <inheritdoc/>
50+
protected override void ConvertFromRgbVectorized(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane)
51+
{
52+
ref Vector512<float> destC =
53+
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component0));
54+
ref Vector512<float> destM =
55+
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component1));
56+
ref Vector512<float> destY =
57+
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component2));
58+
ref Vector512<float> destK =
59+
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component3));
60+
61+
ref Vector512<float> srcR =
62+
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(rLane));
63+
ref Vector512<float> srcG =
64+
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(gLane));
65+
ref Vector512<float> srcB =
66+
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(bLane));
67+
68+
Vector512<float> scale = Vector512.Create(this.MaximumValue);
69+
70+
nuint n = values.Component0.Vector512Count<float>();
71+
for (nuint i = 0; i < n; i++)
72+
{
73+
Vector512<float> ctmp = scale - Unsafe.Add(ref srcR, i);
74+
Vector512<float> mtmp = scale - Unsafe.Add(ref srcG, i);
75+
Vector512<float> ytmp = scale - Unsafe.Add(ref srcB, i);
76+
Vector512<float> ktmp = Vector512.Min(ctmp, Vector512.Min(mtmp, ytmp));
77+
78+
Vector512<float> kMask = Vector512.Equals(ktmp, scale);
79+
ctmp = Vector512.AndNot((ctmp - ktmp) / (scale - ktmp), kMask);
80+
mtmp = Vector512.AndNot((mtmp - ktmp) / (scale - ktmp), kMask);
81+
ytmp = Vector512.AndNot((ytmp - ktmp) / (scale - ktmp), kMask);
82+
83+
Unsafe.Add(ref destC, i) = scale - (ctmp * scale);
84+
Unsafe.Add(ref destM, i) = scale - (mtmp * scale);
85+
Unsafe.Add(ref destY, i) = scale - (ytmp * scale);
86+
Unsafe.Add(ref destK, i) = scale - ktmp;
87+
}
88+
}
89+
90+
/// <inheritdoc/>
91+
protected override void ConvertToRgbInPlaceScalarRemainder(in ComponentValues values)
92+
=> CmykScalar.ConvertToRgbInplace(values, this.MaximumValue);
93+
94+
/// <inheritdoc/>
95+
protected override void ConvertFromRgbScalarRemainder(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane)
96+
=> CmykScalar.ConvertFromRgb(values, this.MaximumValue, rLane, gLane, bLane);
97+
}
98+
}

0 commit comments

Comments
 (0)