Skip to content

Commit d81c511

Browse files
Merge pull request #1773 from SixLabors/af/jpeg-pack-sandbox
Decode Jpeg into Rgb24 when pixel type not specified
2 parents 2410a37 + 4323c8d commit d81c511

File tree

62 files changed

+590
-746
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+590
-746
lines changed

src/ImageSharp/Common/Helpers/InliningOptions.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ namespace SixLabors.ImageSharp
1212
/// </summary>
1313
internal static class InliningOptions
1414
{
15+
/// <summary>
16+
/// <see cref="MethodImplOptions.AggressiveInlining"/> regardless of the build conditions.
17+
/// </summary>
18+
public const MethodImplOptions AlwaysInline = MethodImplOptions.AggressiveInlining;
1519
#if PROFILING
1620
public const MethodImplOptions HotPath = MethodImplOptions.NoInlining;
1721
public const MethodImplOptions ShortMethod = MethodImplOptions.NoInlining;

src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ private static void Shuffle4Slice3(
537537
/// <param name="vm0">The first vector to multiply.</param>
538538
/// <param name="vm1">The second vector to multiply.</param>
539539
/// <returns>The <see cref="Vector256{T}"/>.</returns>
540-
[MethodImpl(InliningOptions.ShortMethod)]
540+
[MethodImpl(InliningOptions.AlwaysInline)]
541541
public static Vector256<float> MultiplyAdd(
542542
in Vector256<float> va,
543543
in Vector256<float> vm0,

src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -22,60 +22,39 @@ public FromCmykAvx2(int precision)
2222
{
2323
}
2424

25-
protected override void ConvertCoreVectorized(in ComponentValues values, Span<Vector4> result)
25+
protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
2626
{
2727
#if SUPPORTS_RUNTIME_INTRINSICS
28-
ref Vector256<float> cBase =
28+
ref Vector256<float> c0Base =
2929
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0));
30-
ref Vector256<float> mBase =
30+
ref Vector256<float> c1Base =
3131
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component1));
32-
ref Vector256<float> yBase =
32+
ref Vector256<float> c2Base =
3333
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component2));
34-
ref Vector256<float> kBase =
34+
ref Vector256<float> c3Base =
3535
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component3));
3636

37-
ref Vector256<float> resultBase =
38-
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(result));
39-
4037
// Used for the color conversion
4138
var scale = Vector256.Create(1 / this.MaximumValue);
42-
var one = Vector256.Create(1F);
43-
44-
// Used for packing
45-
ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32);
46-
Vector256<int> vcontrol = Unsafe.As<byte, Vector256<int>>(ref control);
4739

48-
int n = result.Length / 8;
49-
for (int i = 0; i < n; i++)
40+
nint n = values.Component0.Length / 8;
41+
for (nint i = 0; i < n; i++)
5042
{
51-
Vector256<float> k = Avx2.PermuteVar8x32(Unsafe.Add(ref kBase, i), vcontrol);
52-
Vector256<float> c = Avx2.PermuteVar8x32(Unsafe.Add(ref cBase, i), vcontrol);
53-
Vector256<float> m = Avx2.PermuteVar8x32(Unsafe.Add(ref mBase, i), vcontrol);
54-
Vector256<float> y = Avx2.PermuteVar8x32(Unsafe.Add(ref yBase, i), vcontrol);
43+
ref Vector256<float> c = ref Unsafe.Add(ref c0Base, i);
44+
ref Vector256<float> m = ref Unsafe.Add(ref c1Base, i);
45+
ref Vector256<float> y = ref Unsafe.Add(ref c2Base, i);
46+
Vector256<float> k = Unsafe.Add(ref c3Base, i);
5547

5648
k = Avx.Multiply(k, scale);
57-
5849
c = Avx.Multiply(Avx.Multiply(c, k), scale);
5950
m = Avx.Multiply(Avx.Multiply(m, k), scale);
6051
y = Avx.Multiply(Avx.Multiply(y, k), scale);
61-
62-
Vector256<float> cmLo = Avx.UnpackLow(c, m);
63-
Vector256<float> yoLo = Avx.UnpackLow(y, one);
64-
Vector256<float> cmHi = Avx.UnpackHigh(c, m);
65-
Vector256<float> yoHi = Avx.UnpackHigh(y, one);
66-
67-
ref Vector256<float> destination = ref Unsafe.Add(ref resultBase, i * 4);
68-
69-
destination = Avx.Shuffle(cmLo, yoLo, 0b01_00_01_00);
70-
Unsafe.Add(ref destination, 1) = Avx.Shuffle(cmLo, yoLo, 0b11_10_11_10);
71-
Unsafe.Add(ref destination, 2) = Avx.Shuffle(cmHi, yoHi, 0b01_00_01_00);
72-
Unsafe.Add(ref destination, 3) = Avx.Shuffle(cmHi, yoHi, 0b11_10_11_10);
7352
}
7453
#endif
7554
}
7655

77-
protected override void ConvertCore(in ComponentValues values, Span<Vector4> result) =>
78-
FromCmykBasic.ConvertCore(values, result, this.MaximumValue);
56+
protected override void ConvertCoreInplace(in ComponentValues values) =>
57+
FromCmykBasic.ConvertCoreInplace(values, this.MaximumValue);
7958
}
8059
}
8160
}

src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,38 +15,27 @@ public FromCmykBasic(int precision)
1515
{
1616
}
1717

18-
public override void ConvertToRgba(in ComponentValues values, Span<Vector4> result)
19-
{
20-
ConvertCore(values, result, this.MaximumValue);
21-
}
18+
public override void ConvertToRgbInplace(in ComponentValues values) =>
19+
ConvertCoreInplace(values, this.MaximumValue);
2220

23-
internal static void ConvertCore(in ComponentValues values, Span<Vector4> result, float maxValue)
21+
internal static void ConvertCoreInplace(in ComponentValues values, float maxValue)
2422
{
25-
ReadOnlySpan<float> cVals = values.Component0;
26-
ReadOnlySpan<float> mVals = values.Component1;
27-
ReadOnlySpan<float> yVals = values.Component2;
28-
ReadOnlySpan<float> kVals = values.Component3;
29-
30-
var v = new Vector4(0, 0, 0, 1F);
31-
32-
var maximum = 1 / maxValue;
33-
var scale = new Vector4(maximum, maximum, maximum, 1F);
23+
Span<float> c0 = values.Component0;
24+
Span<float> c1 = values.Component1;
25+
Span<float> c2 = values.Component2;
26+
Span<float> c3 = values.Component3;
3427

35-
for (int i = 0; i < result.Length; i++)
28+
float scale = 1 / maxValue;
29+
for (int i = 0; i < c0.Length; i++)
3630
{
37-
float c = cVals[i];
38-
float m = mVals[i];
39-
float y = yVals[i];
40-
float k = kVals[i] / maxValue;
41-
42-
v.X = c * k;
43-
v.Y = m * k;
44-
v.Z = y * k;
45-
v.W = 1F;
46-
47-
v *= scale;
48-
49-
result[i] = v;
31+
float c = c0[i];
32+
float m = c1[i];
33+
float y = c2[i];
34+
float k = c3[i] / maxValue;
35+
36+
c0[i] = c * k * scale;
37+
c1[i] = m * k * scale;
38+
c2[i] = y * k * scale;
5039
}
5140
}
5241
}

src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public FromCmykVector8(int precision)
1818
{
1919
}
2020

21-
protected override void ConvertCoreVectorized(in ComponentValues values, Span<Vector4> result)
21+
protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
2222
{
2323
ref Vector<float> cBase =
2424
ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(values.Component0));
@@ -29,43 +29,25 @@ protected override void ConvertCoreVectorized(in ComponentValues values, Span<Ve
2929
ref Vector<float> kBase =
3030
ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(values.Component3));
3131

32-
ref Vector4Octet resultBase =
33-
ref Unsafe.As<Vector4, Vector4Octet>(ref MemoryMarshal.GetReference(result));
34-
35-
Vector4Pair cc = default;
36-
Vector4Pair mm = default;
37-
Vector4Pair yy = default;
38-
ref Vector<float> ccRefAsVector = ref Unsafe.As<Vector4Pair, Vector<float>>(ref cc);
39-
ref Vector<float> mmRefAsVector = ref Unsafe.As<Vector4Pair, Vector<float>>(ref mm);
40-
ref Vector<float> yyRefAsVector = ref Unsafe.As<Vector4Pair, Vector<float>>(ref yy);
41-
4232
var scale = new Vector<float>(1 / this.MaximumValue);
4333

4434
// Walking 8 elements at one step:
45-
int n = result.Length / 8;
46-
for (int i = 0; i < n; i++)
35+
nint n = values.Component0.Length / 8;
36+
for (nint i = 0; i < n; i++)
4737
{
48-
Vector<float> c = Unsafe.Add(ref cBase, i);
49-
Vector<float> m = Unsafe.Add(ref mBase, i);
50-
Vector<float> y = Unsafe.Add(ref yBase, i);
38+
ref Vector<float> c = ref Unsafe.Add(ref cBase, i);
39+
ref Vector<float> m = ref Unsafe.Add(ref mBase, i);
40+
ref Vector<float> y = ref Unsafe.Add(ref yBase, i);
5141
Vector<float> k = Unsafe.Add(ref kBase, i) * scale;
5242

5343
c = (c * k) * scale;
5444
m = (m * k) * scale;
5545
y = (y * k) * scale;
56-
57-
ccRefAsVector = c;
58-
mmRefAsVector = m;
59-
yyRefAsVector = y;
60-
61-
// Collect (c0,c1...c8) (m0,m1...m8) (y0,y1...y8) vector values in the expected (r0,g0,g1,1), (r1,g1,g2,1) ... order:
62-
ref Vector4Octet destination = ref Unsafe.Add(ref resultBase, i);
63-
destination.Pack(ref cc, ref mm, ref yy);
6446
}
6547
}
6648

67-
protected override void ConvertCore(in ComponentValues values, Span<Vector4> result) =>
68-
FromCmykBasic.ConvertCore(values, result, this.MaximumValue);
49+
protected override void ConvertCoreInplace(in ComponentValues values) =>
50+
FromCmykBasic.ConvertCoreInplace(values, this.MaximumValue);
6951
}
7052
}
7153
}

src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,42 +22,26 @@ public FromGrayscaleAvx2(int precision)
2222
{
2323
}
2424

25-
protected override void ConvertCoreVectorized(in ComponentValues values, Span<Vector4> result)
25+
protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
2626
{
2727
#if SUPPORTS_RUNTIME_INTRINSICS
28-
ref Vector256<float> gBase =
28+
ref Vector256<float> c0Base =
2929
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0));
3030

31-
ref Vector256<float> resultBase =
32-
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(result));
33-
3431
// Used for the color conversion
3532
var scale = Vector256.Create(1 / this.MaximumValue);
36-
var one = Vector256.Create(1F);
37-
38-
// Used for packing
39-
ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32);
40-
Vector256<int> vcontrol = Unsafe.As<byte, Vector256<int>>(ref control);
4133

42-
int n = result.Length / 8;
43-
for (int i = 0; i < n; i++)
34+
nint n = values.Component0.Length / 8;
35+
for (nint i = 0; i < n; i++)
4436
{
45-
Vector256<float> g = Avx.Multiply(Unsafe.Add(ref gBase, i), scale);
46-
47-
g = Avx2.PermuteVar8x32(g, vcontrol);
48-
49-
ref Vector256<float> destination = ref Unsafe.Add(ref resultBase, i * 4);
50-
51-
destination = Avx.Blend(Avx.Permute(g, 0b00_00_00_00), one, 0b1000_1000);
52-
Unsafe.Add(ref destination, 1) = Avx.Blend(Avx.Shuffle(g, g, 0b01_01_01_01), one, 0b1000_1000);
53-
Unsafe.Add(ref destination, 2) = Avx.Blend(Avx.Shuffle(g, g, 0b10_10_10_10), one, 0b1000_1000);
54-
Unsafe.Add(ref destination, 3) = Avx.Blend(Avx.Shuffle(g, g, 0b11_11_11_11), one, 0b1000_1000);
37+
ref Vector256<float> c0 = ref Unsafe.Add(ref c0Base, i);
38+
c0 = Avx.Multiply(c0, scale);
5539
}
5640
#endif
5741
}
5842

59-
protected override void ConvertCore(in ComponentValues values, Span<Vector4> result) =>
60-
FromGrayscaleBasic.ConvertCore(values, result, this.MaximumValue);
43+
protected override void ConvertCoreInplace(in ComponentValues values) =>
44+
FromGrayscaleBasic.ScaleValues(values.Component0, this.MaximumValue);
6145
}
6246
}
6347
}

src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,35 @@ public FromGrayscaleBasic(int precision)
1717
{
1818
}
1919

20-
public override void ConvertToRgba(in ComponentValues values, Span<Vector4> result)
21-
{
22-
ConvertCore(values, result, this.MaximumValue);
23-
}
20+
public override void ConvertToRgbInplace(in ComponentValues values) =>
21+
ScaleValues(values.Component0, this.MaximumValue);
2422

25-
internal static void ConvertCore(in ComponentValues values, Span<Vector4> result, float maxValue)
23+
internal static void ScaleValues(Span<float> values, float maxValue)
2624
{
27-
var maximum = 1 / maxValue;
28-
var scale = new Vector4(maximum, maximum, maximum, 1F);
25+
Span<Vector4> vecValues = MemoryMarshal.Cast<float, Vector4>(values);
2926

30-
ref float sBase = ref MemoryMarshal.GetReference(values.Component0);
31-
ref Vector4 dBase = ref MemoryMarshal.GetReference(result);
27+
var scaleVector = new Vector4(1 / maxValue);
3228

33-
for (int i = 0; i < result.Length; i++)
29+
for (int i = 0; i < vecValues.Length; i++)
3430
{
35-
var v = new Vector4(Unsafe.Add(ref sBase, i));
36-
v.W = 1f;
37-
v *= scale;
38-
Unsafe.Add(ref dBase, i) = v;
31+
vecValues[i] *= scaleVector;
32+
}
33+
34+
values = values.Slice(vecValues.Length * 4);
35+
if (!values.IsEmpty)
36+
{
37+
float scaleValue = 1f / maxValue;
38+
values[0] *= scaleValue;
39+
40+
if ((uint)values.Length > 1)
41+
{
42+
values[1] *= scaleValue;
43+
44+
if ((uint)values.Length > 2)
45+
{
46+
values[2] *= scaleValue;
47+
}
48+
}
3949
}
4050
}
4151
}

src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public FromRgbAvx2(int precision)
2222
{
2323
}
2424

25-
protected override void ConvertCoreVectorized(in ComponentValues values, Span<Vector4> result)
25+
protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
2626
{
2727
#if SUPPORTS_RUNTIME_INTRINSICS
2828
ref Vector256<float> rBase =
@@ -32,41 +32,23 @@ protected override void ConvertCoreVectorized(in ComponentValues values, Span<Ve
3232
ref Vector256<float> bBase =
3333
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component2));
3434

35-
ref Vector256<float> resultBase =
36-
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(result));
37-
3835
// Used for the color conversion
3936
var scale = Vector256.Create(1 / this.MaximumValue);
40-
var one = Vector256.Create(1F);
41-
42-
// Used for packing
43-
ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32);
44-
Vector256<int> vcontrol = Unsafe.As<byte, Vector256<int>>(ref control);
45-
46-
int n = result.Length / 8;
47-
for (int i = 0; i < n; i++)
37+
nint n = values.Component0.Length / 8;
38+
for (nint i = 0; i < n; i++)
4839
{
49-
Vector256<float> r = Avx.Multiply(Avx2.PermuteVar8x32(Unsafe.Add(ref rBase, i), vcontrol), scale);
50-
Vector256<float> g = Avx.Multiply(Avx2.PermuteVar8x32(Unsafe.Add(ref gBase, i), vcontrol), scale);
51-
Vector256<float> b = Avx.Multiply(Avx2.PermuteVar8x32(Unsafe.Add(ref bBase, i), vcontrol), scale);
52-
53-
Vector256<float> rgLo = Avx.UnpackLow(r, g);
54-
Vector256<float> boLo = Avx.UnpackLow(b, one);
55-
Vector256<float> rgHi = Avx.UnpackHigh(r, g);
56-
Vector256<float> boHi = Avx.UnpackHigh(b, one);
57-
58-
ref Vector256<float> destination = ref Unsafe.Add(ref resultBase, i * 4);
59-
60-
destination = Avx.Shuffle(rgLo, boLo, 0b01_00_01_00);
61-
Unsafe.Add(ref destination, 1) = Avx.Shuffle(rgLo, boLo, 0b11_10_11_10);
62-
Unsafe.Add(ref destination, 2) = Avx.Shuffle(rgHi, boHi, 0b01_00_01_00);
63-
Unsafe.Add(ref destination, 3) = Avx.Shuffle(rgHi, boHi, 0b11_10_11_10);
40+
ref Vector256<float> r = ref Unsafe.Add(ref rBase, i);
41+
ref Vector256<float> g = ref Unsafe.Add(ref gBase, i);
42+
ref Vector256<float> b = ref Unsafe.Add(ref bBase, i);
43+
r = Avx.Multiply(r, scale);
44+
g = Avx.Multiply(g, scale);
45+
b = Avx.Multiply(b, scale);
6446
}
6547
#endif
6648
}
6749

68-
protected override void ConvertCore(in ComponentValues values, Span<Vector4> result) =>
69-
FromRgbBasic.ConvertCore(values, result, this.MaximumValue);
50+
protected override void ConvertCoreInplace(in ComponentValues values) =>
51+
FromRgbBasic.ConvertCoreInplace(values, this.MaximumValue);
7052
}
7153
}
7254
}

0 commit comments

Comments
 (0)