Skip to content

Commit

Permalink
Merge pull request #1773 from SixLabors/af/jpeg-pack-sandbox
Browse files Browse the repository at this point in the history
Decode Jpeg into Rgb24 when pixel type not specified
  • Loading branch information
JimBobSquarePants committed Oct 5, 2021
2 parents 2410a37 + 4323c8d commit d81c511
Show file tree
Hide file tree
Showing 62 changed files with 590 additions and 746 deletions.
4 changes: 4 additions & 0 deletions src/ImageSharp/Common/Helpers/InliningOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ namespace SixLabors.ImageSharp
/// </summary>
internal static class InliningOptions
{
/// <summary>
/// <see cref="MethodImplOptions.AggressiveInlining"/> regardless of the build conditions.
/// </summary>
public const MethodImplOptions AlwaysInline = MethodImplOptions.AggressiveInlining;
#if PROFILING
public const MethodImplOptions HotPath = MethodImplOptions.NoInlining;
public const MethodImplOptions ShortMethod = MethodImplOptions.NoInlining;
Expand Down
2 changes: 1 addition & 1 deletion src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ private static void Shuffle4Slice3(
/// <param name="vm0">The first vector to multiply.</param>
/// <param name="vm1">The second vector to multiply.</param>
/// <returns>The <see cref="Vector256{T}"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
[MethodImpl(InliningOptions.AlwaysInline)]
public static Vector256<float> MultiplyAdd(
in Vector256<float> va,
in Vector256<float> vm0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,60 +22,39 @@ public FromCmykAvx2(int precision)
{
}

protected override void ConvertCoreVectorized(in ComponentValues values, Span<Vector4> result)
protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
{
#if SUPPORTS_RUNTIME_INTRINSICS
ref Vector256<float> cBase =
ref Vector256<float> c0Base =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0));
ref Vector256<float> mBase =
ref Vector256<float> c1Base =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component1));
ref Vector256<float> yBase =
ref Vector256<float> c2Base =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component2));
ref Vector256<float> kBase =
ref Vector256<float> c3Base =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component3));

ref Vector256<float> resultBase =
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(result));

// Used for the color conversion
var scale = Vector256.Create(1 / this.MaximumValue);
var one = Vector256.Create(1F);

// Used for packing
ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32);
Vector256<int> vcontrol = Unsafe.As<byte, Vector256<int>>(ref control);

int n = result.Length / 8;
for (int i = 0; i < n; i++)
nint n = values.Component0.Length / 8;
for (nint i = 0; i < n; i++)
{
Vector256<float> k = Avx2.PermuteVar8x32(Unsafe.Add(ref kBase, i), vcontrol);
Vector256<float> c = Avx2.PermuteVar8x32(Unsafe.Add(ref cBase, i), vcontrol);
Vector256<float> m = Avx2.PermuteVar8x32(Unsafe.Add(ref mBase, i), vcontrol);
Vector256<float> y = Avx2.PermuteVar8x32(Unsafe.Add(ref yBase, i), vcontrol);
ref Vector256<float> c = ref Unsafe.Add(ref c0Base, i);
ref Vector256<float> m = ref Unsafe.Add(ref c1Base, i);
ref Vector256<float> y = ref Unsafe.Add(ref c2Base, i);
Vector256<float> k = Unsafe.Add(ref c3Base, i);

k = Avx.Multiply(k, scale);

c = Avx.Multiply(Avx.Multiply(c, k), scale);
m = Avx.Multiply(Avx.Multiply(m, k), scale);
y = Avx.Multiply(Avx.Multiply(y, k), scale);

Vector256<float> cmLo = Avx.UnpackLow(c, m);
Vector256<float> yoLo = Avx.UnpackLow(y, one);
Vector256<float> cmHi = Avx.UnpackHigh(c, m);
Vector256<float> yoHi = Avx.UnpackHigh(y, one);

ref Vector256<float> destination = ref Unsafe.Add(ref resultBase, i * 4);

destination = Avx.Shuffle(cmLo, yoLo, 0b01_00_01_00);
Unsafe.Add(ref destination, 1) = Avx.Shuffle(cmLo, yoLo, 0b11_10_11_10);
Unsafe.Add(ref destination, 2) = Avx.Shuffle(cmHi, yoHi, 0b01_00_01_00);
Unsafe.Add(ref destination, 3) = Avx.Shuffle(cmHi, yoHi, 0b11_10_11_10);
}
#endif
}

protected override void ConvertCore(in ComponentValues values, Span<Vector4> result) =>
FromCmykBasic.ConvertCore(values, result, this.MaximumValue);
protected override void ConvertCoreInplace(in ComponentValues values) =>
FromCmykBasic.ConvertCoreInplace(values, this.MaximumValue);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,27 @@ public FromCmykBasic(int precision)
{
}

public override void ConvertToRgba(in ComponentValues values, Span<Vector4> result)
{
ConvertCore(values, result, this.MaximumValue);
}
public override void ConvertToRgbInplace(in ComponentValues values) =>
ConvertCoreInplace(values, this.MaximumValue);

internal static void ConvertCore(in ComponentValues values, Span<Vector4> result, float maxValue)
internal static void ConvertCoreInplace(in ComponentValues values, float maxValue)
{
ReadOnlySpan<float> cVals = values.Component0;
ReadOnlySpan<float> mVals = values.Component1;
ReadOnlySpan<float> yVals = values.Component2;
ReadOnlySpan<float> kVals = values.Component3;

var v = new Vector4(0, 0, 0, 1F);

var maximum = 1 / maxValue;
var scale = new Vector4(maximum, maximum, maximum, 1F);
Span<float> c0 = values.Component0;
Span<float> c1 = values.Component1;
Span<float> c2 = values.Component2;
Span<float> c3 = values.Component3;

for (int i = 0; i < result.Length; i++)
float scale = 1 / maxValue;
for (int i = 0; i < c0.Length; i++)
{
float c = cVals[i];
float m = mVals[i];
float y = yVals[i];
float k = kVals[i] / maxValue;

v.X = c * k;
v.Y = m * k;
v.Z = y * k;
v.W = 1F;

v *= scale;

result[i] = v;
float c = c0[i];
float m = c1[i];
float y = c2[i];
float k = c3[i] / maxValue;

c0[i] = c * k * scale;
c1[i] = m * k * scale;
c2[i] = y * k * scale;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public FromCmykVector8(int precision)
{
}

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

ref Vector4Octet resultBase =
ref Unsafe.As<Vector4, Vector4Octet>(ref MemoryMarshal.GetReference(result));

Vector4Pair cc = default;
Vector4Pair mm = default;
Vector4Pair yy = default;
ref Vector<float> ccRefAsVector = ref Unsafe.As<Vector4Pair, Vector<float>>(ref cc);
ref Vector<float> mmRefAsVector = ref Unsafe.As<Vector4Pair, Vector<float>>(ref mm);
ref Vector<float> yyRefAsVector = ref Unsafe.As<Vector4Pair, Vector<float>>(ref yy);

var scale = new Vector<float>(1 / this.MaximumValue);

// Walking 8 elements at one step:
int n = result.Length / 8;
for (int i = 0; i < n; i++)
nint n = values.Component0.Length / 8;
for (nint i = 0; i < n; i++)
{
Vector<float> c = Unsafe.Add(ref cBase, i);
Vector<float> m = Unsafe.Add(ref mBase, i);
Vector<float> y = Unsafe.Add(ref yBase, i);
ref Vector<float> c = ref Unsafe.Add(ref cBase, i);
ref Vector<float> m = ref Unsafe.Add(ref mBase, i);
ref Vector<float> y = ref Unsafe.Add(ref yBase, i);
Vector<float> k = Unsafe.Add(ref kBase, i) * scale;

c = (c * k) * scale;
m = (m * k) * scale;
y = (y * k) * scale;

ccRefAsVector = c;
mmRefAsVector = m;
yyRefAsVector = y;

// Collect (c0,c1...c8) (m0,m1...m8) (y0,y1...y8) vector values in the expected (r0,g0,g1,1), (r1,g1,g2,1) ... order:
ref Vector4Octet destination = ref Unsafe.Add(ref resultBase, i);
destination.Pack(ref cc, ref mm, ref yy);
}
}

protected override void ConvertCore(in ComponentValues values, Span<Vector4> result) =>
FromCmykBasic.ConvertCore(values, result, this.MaximumValue);
protected override void ConvertCoreInplace(in ComponentValues values) =>
FromCmykBasic.ConvertCoreInplace(values, this.MaximumValue);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,42 +22,26 @@ public FromGrayscaleAvx2(int precision)
{
}

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

ref Vector256<float> resultBase =
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(result));

// Used for the color conversion
var scale = Vector256.Create(1 / this.MaximumValue);
var one = Vector256.Create(1F);

// Used for packing
ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32);
Vector256<int> vcontrol = Unsafe.As<byte, Vector256<int>>(ref control);

int n = result.Length / 8;
for (int i = 0; i < n; i++)
nint n = values.Component0.Length / 8;
for (nint i = 0; i < n; i++)
{
Vector256<float> g = Avx.Multiply(Unsafe.Add(ref gBase, i), scale);

g = Avx2.PermuteVar8x32(g, vcontrol);

ref Vector256<float> destination = ref Unsafe.Add(ref resultBase, i * 4);

destination = Avx.Blend(Avx.Permute(g, 0b00_00_00_00), one, 0b1000_1000);
Unsafe.Add(ref destination, 1) = Avx.Blend(Avx.Shuffle(g, g, 0b01_01_01_01), one, 0b1000_1000);
Unsafe.Add(ref destination, 2) = Avx.Blend(Avx.Shuffle(g, g, 0b10_10_10_10), one, 0b1000_1000);
Unsafe.Add(ref destination, 3) = Avx.Blend(Avx.Shuffle(g, g, 0b11_11_11_11), one, 0b1000_1000);
ref Vector256<float> c0 = ref Unsafe.Add(ref c0Base, i);
c0 = Avx.Multiply(c0, scale);
}
#endif
}

protected override void ConvertCore(in ComponentValues values, Span<Vector4> result) =>
FromGrayscaleBasic.ConvertCore(values, result, this.MaximumValue);
protected override void ConvertCoreInplace(in ComponentValues values) =>
FromGrayscaleBasic.ScaleValues(values.Component0, this.MaximumValue);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,35 @@ public FromGrayscaleBasic(int precision)
{
}

public override void ConvertToRgba(in ComponentValues values, Span<Vector4> result)
{
ConvertCore(values, result, this.MaximumValue);
}
public override void ConvertToRgbInplace(in ComponentValues values) =>
ScaleValues(values.Component0, this.MaximumValue);

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

ref float sBase = ref MemoryMarshal.GetReference(values.Component0);
ref Vector4 dBase = ref MemoryMarshal.GetReference(result);
var scaleVector = new Vector4(1 / maxValue);

for (int i = 0; i < result.Length; i++)
for (int i = 0; i < vecValues.Length; i++)
{
var v = new Vector4(Unsafe.Add(ref sBase, i));
v.W = 1f;
v *= scale;
Unsafe.Add(ref dBase, i) = v;
vecValues[i] *= scaleVector;
}

values = values.Slice(vecValues.Length * 4);
if (!values.IsEmpty)
{
float scaleValue = 1f / maxValue;
values[0] *= scaleValue;

if ((uint)values.Length > 1)
{
values[1] *= scaleValue;

if ((uint)values.Length > 2)
{
values[2] *= scaleValue;
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public FromRgbAvx2(int precision)
{
}

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

ref Vector256<float> resultBase =
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(result));

// Used for the color conversion
var scale = Vector256.Create(1 / this.MaximumValue);
var one = Vector256.Create(1F);

// Used for packing
ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32);
Vector256<int> vcontrol = Unsafe.As<byte, Vector256<int>>(ref control);

int n = result.Length / 8;
for (int i = 0; i < n; i++)
nint n = values.Component0.Length / 8;
for (nint i = 0; i < n; i++)
{
Vector256<float> r = Avx.Multiply(Avx2.PermuteVar8x32(Unsafe.Add(ref rBase, i), vcontrol), scale);
Vector256<float> g = Avx.Multiply(Avx2.PermuteVar8x32(Unsafe.Add(ref gBase, i), vcontrol), scale);
Vector256<float> b = Avx.Multiply(Avx2.PermuteVar8x32(Unsafe.Add(ref bBase, i), vcontrol), scale);

Vector256<float> rgLo = Avx.UnpackLow(r, g);
Vector256<float> boLo = Avx.UnpackLow(b, one);
Vector256<float> rgHi = Avx.UnpackHigh(r, g);
Vector256<float> boHi = Avx.UnpackHigh(b, one);

ref Vector256<float> destination = ref Unsafe.Add(ref resultBase, i * 4);

destination = Avx.Shuffle(rgLo, boLo, 0b01_00_01_00);
Unsafe.Add(ref destination, 1) = Avx.Shuffle(rgLo, boLo, 0b11_10_11_10);
Unsafe.Add(ref destination, 2) = Avx.Shuffle(rgHi, boHi, 0b01_00_01_00);
Unsafe.Add(ref destination, 3) = Avx.Shuffle(rgHi, boHi, 0b11_10_11_10);
ref Vector256<float> r = ref Unsafe.Add(ref rBase, i);
ref Vector256<float> g = ref Unsafe.Add(ref gBase, i);
ref Vector256<float> b = ref Unsafe.Add(ref bBase, i);
r = Avx.Multiply(r, scale);
g = Avx.Multiply(g, scale);
b = Avx.Multiply(b, scale);
}
#endif
}

protected override void ConvertCore(in ComponentValues values, Span<Vector4> result) =>
FromRgbBasic.ConvertCore(values, result, this.MaximumValue);
protected override void ConvertCoreInplace(in ComponentValues values) =>
FromRgbBasic.ConvertCoreInplace(values, this.MaximumValue);
}
}
}
Loading

0 comments on commit d81c511

Please sign in to comment.