Browse Source

Use Convert.To after rounding to avoid different behavior on ARM vs x86/x64

pull/1790/head
Brian Popow 4 years ago
parent
commit
151bacc020
  1. 12
      src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte2.cs
  2. 20
      src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs
  3. 11
      src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort2.cs
  4. 23
      src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs
  5. 4
      src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs
  6. 8
      src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs

12
src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte2.cs

@ -15,7 +15,9 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public partial struct NormalizedByte2 : IPixel<NormalizedByte2>, IPackedVector<ushort>
{
private static readonly Vector2 Half = new Vector2(127);
private const float MaxPos = 127F;
private static readonly Vector2 Half = new Vector2(MaxPos);
private static readonly Vector2 MinusOne = new Vector2(-1F);
/// <summary>
@ -154,8 +156,8 @@ namespace SixLabors.ImageSharp.PixelFormats
public readonly Vector2 ToVector2()
{
return new Vector2(
(sbyte)((this.PackedValue >> 0) & 0xFF) / 127F,
(sbyte)((this.PackedValue >> 8) & 0xFF) / 127F);
(sbyte)((this.PackedValue >> 0) & 0xFF) / MaxPos,
(sbyte)((this.PackedValue >> 8) & 0xFF) / MaxPos);
}
/// <inheritdoc />
@ -181,8 +183,8 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector = Vector2.Clamp(vector, MinusOne, Vector2.One) * Half;
int byte2 = ((ushort)Math.Round(vector.X) & 0xFF) << 0;
int byte1 = ((ushort)Math.Round(vector.Y) & 0xFF) << 8;
int byte2 = ((ushort)Convert.ToInt16(Math.Round(vector.X)) & 0xFF) << 0;
int byte1 = ((ushort)Convert.ToInt16(Math.Round(vector.Y)) & 0xFF) << 8;
return (ushort)(byte2 | byte1);
}

20
src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs

@ -15,7 +15,9 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public partial struct NormalizedByte4 : IPixel<NormalizedByte4>, IPackedVector<uint>
{
private static readonly Vector4 Half = new Vector4(127);
private const float MaxPos = 127F;
private static readonly Vector4 Half = new Vector4(MaxPos);
private static readonly Vector4 MinusOne = new Vector4(-1F);
/// <summary>
@ -92,10 +94,10 @@ namespace SixLabors.ImageSharp.PixelFormats
public readonly Vector4 ToVector4()
{
return new Vector4(
(sbyte)((this.PackedValue >> 0) & 0xFF) / 127F,
(sbyte)((this.PackedValue >> 8) & 0xFF) / 127F,
(sbyte)((this.PackedValue >> 16) & 0xFF) / 127F,
(sbyte)((this.PackedValue >> 24) & 0xFF) / 127F);
(sbyte)((this.PackedValue >> 0) & 0xFF) / MaxPos,
(sbyte)((this.PackedValue >> 8) & 0xFF) / MaxPos,
(sbyte)((this.PackedValue >> 16) & 0xFF) / MaxPos,
(sbyte)((this.PackedValue >> 24) & 0xFF) / MaxPos);
}
/// <inheritdoc />
@ -176,10 +178,10 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector = Numerics.Clamp(vector, MinusOne, Vector4.One) * Half;
uint byte4 = ((uint)MathF.Round(vector.X) & 0xFF) << 0;
uint byte3 = ((uint)MathF.Round(vector.Y) & 0xFF) << 8;
uint byte2 = ((uint)MathF.Round(vector.Z) & 0xFF) << 16;
uint byte1 = ((uint)MathF.Round(vector.W) & 0xFF) << 24;
uint byte4 = ((uint)Convert.ToInt16(MathF.Round(vector.X)) & 0xFF) << 0;
uint byte3 = ((uint)Convert.ToInt16(MathF.Round(vector.Y)) & 0xFF) << 8;
uint byte2 = ((uint)Convert.ToInt16(MathF.Round(vector.Z)) & 0xFF) << 16;
uint byte1 = ((uint)Convert.ToInt16(MathF.Round(vector.W)) & 0xFF) << 24;
return byte4 | byte3 | byte2 | byte1;
}

11
src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort2.cs

@ -15,7 +15,10 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public partial struct NormalizedShort2 : IPixel<NormalizedShort2>, IPackedVector<uint>
{
private static readonly Vector2 Max = new Vector2(0x7FFF);
// Largest two byte positive number 0xFFFF >> 1;
private const float MaxPos = 0x7FFF;
private static readonly Vector2 Max = new Vector2(MaxPos);
private static readonly Vector2 Min = Vector2.Negate(Max);
/// <summary>
@ -156,11 +159,9 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public readonly Vector2 ToVector2()
{
const float MaxVal = 0x7FFF;
return new Vector2(
(short)(this.PackedValue & 0xFFFF) / MaxVal,
(short)(this.PackedValue >> 0x10) / MaxVal);
(short)(this.PackedValue & 0xFFFF) / MaxPos,
(short)(this.PackedValue >> 0x10) / MaxPos);
}
/// <inheritdoc />

23
src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs

@ -15,7 +15,10 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public partial struct NormalizedShort4 : IPixel<NormalizedShort4>, IPackedVector<ulong>
{
private static readonly Vector4 Max = new Vector4(0x7FFF);
// Largest two byte positive number 0xFFFF >> 1;
private const float MaxPos = 0x7FFF;
private static readonly Vector4 Max = new Vector4(MaxPos);
private static readonly Vector4 Min = Vector4.Negate(Max);
/// <summary>
@ -91,13 +94,11 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public readonly Vector4 ToVector4()
{
const float MaxVal = 0x7FFF;
return new Vector4(
(short)((this.PackedValue >> 0x00) & 0xFFFF) / MaxVal,
(short)((this.PackedValue >> 0x10) & 0xFFFF) / MaxVal,
(short)((this.PackedValue >> 0x20) & 0xFFFF) / MaxVal,
(short)((this.PackedValue >> 0x30) & 0xFFFF) / MaxVal);
(short)((this.PackedValue >> 0x00) & 0xFFFF) / MaxPos,
(short)((this.PackedValue >> 0x10) & 0xFFFF) / MaxPos,
(short)((this.PackedValue >> 0x20) & 0xFFFF) / MaxPos,
(short)((this.PackedValue >> 0x30) & 0xFFFF) / MaxPos);
}
/// <inheritdoc />
@ -180,10 +181,10 @@ namespace SixLabors.ImageSharp.PixelFormats
vector = Numerics.Clamp(vector, Min, Max);
// Round rather than truncate.
ulong word4 = ((ulong)MathF.Round(vector.X) & 0xFFFF) << 0x00;
ulong word3 = ((ulong)MathF.Round(vector.Y) & 0xFFFF) << 0x10;
ulong word2 = ((ulong)MathF.Round(vector.Z) & 0xFFFF) << 0x20;
ulong word1 = ((ulong)MathF.Round(vector.W) & 0xFFFF) << 0x30;
ulong word4 = ((ulong)Convert.ToInt32(MathF.Round(vector.X)) & 0xFFFF) << 0x00;
ulong word3 = ((ulong)Convert.ToInt32(MathF.Round(vector.Y)) & 0xFFFF) << 0x10;
ulong word2 = ((ulong)Convert.ToInt32(MathF.Round(vector.Z)) & 0xFFFF) << 0x20;
ulong word1 = ((ulong)Convert.ToInt32(MathF.Round(vector.W)) & 0xFFFF) << 0x30;
return word4 | word3 | word2 | word1;
}

4
src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs

@ -181,8 +181,8 @@ namespace SixLabors.ImageSharp.PixelFormats
private static uint Pack(Vector2 vector)
{
vector = Vector2.Clamp(vector, Min, Max);
uint word2 = (uint)Math.Round(vector.X) & 0xFFFF;
uint word1 = ((uint)Math.Round(vector.Y) & 0xFFFF) << 0x10;
uint word2 = (uint)Convert.ToInt32(Math.Round(vector.X)) & 0xFFFF;
uint word1 = ((uint)Convert.ToInt32(Math.Round(vector.Y)) & 0xFFFF) << 0x10;
return word2 | word1;
}

8
src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs

@ -186,10 +186,10 @@ namespace SixLabors.ImageSharp.PixelFormats
vector = Numerics.Clamp(vector, Min, Max);
// Clamp the value between min and max values
ulong word4 = ((ulong)Math.Round(vector.X) & 0xFFFF) << 0x00;
ulong word3 = ((ulong)Math.Round(vector.Y) & 0xFFFF) << 0x10;
ulong word2 = ((ulong)Math.Round(vector.Z) & 0xFFFF) << 0x20;
ulong word1 = ((ulong)Math.Round(vector.W) & 0xFFFF) << 0x30;
ulong word4 = ((ulong)Convert.ToInt32(Math.Round(vector.X)) & 0xFFFF) << 0x00;
ulong word3 = ((ulong)Convert.ToInt32(Math.Round(vector.Y)) & 0xFFFF) << 0x10;
ulong word2 = ((ulong)Convert.ToInt32(Math.Round(vector.Z)) & 0xFFFF) << 0x20;
ulong word1 = ((ulong)Convert.ToInt32(Math.Round(vector.W)) & 0xFFFF) << 0x30;
return word4 | word3 | word2 | word1;
}

Loading…
Cancel
Save