From 05d891582992da4e6aed7a7dcb10457f69809def Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 29 Mar 2018 00:32:48 +1100 Subject: [PATCH 1/6] Add per-pixel scaled vector packing --- src/ImageSharp/PixelFormats/Alpha8.cs | 14 ++ src/ImageSharp/PixelFormats/Argb32.cs | 18 +- src/ImageSharp/PixelFormats/Bgr24.cs | 14 ++ src/ImageSharp/PixelFormats/Bgr565.cs | 14 ++ src/ImageSharp/PixelFormats/Bgra32.cs | 14 ++ src/ImageSharp/PixelFormats/Bgra4444.cs | 14 ++ src/ImageSharp/PixelFormats/Bgra5551.cs | 24 +- src/ImageSharp/PixelFormats/Byte4.cs | 28 ++- src/ImageSharp/PixelFormats/HalfSingle.cs | 31 ++- src/ImageSharp/PixelFormats/HalfVector2.cs | 35 ++- src/ImageSharp/PixelFormats/HalfVector4.cs | 35 ++- src/ImageSharp/PixelFormats/IPixel.cs | 14 ++ .../PixelFormats/NormalizedByte2.cs | 33 ++- .../PixelFormats/NormalizedByte4.cs | 33 ++- .../PixelFormats/NormalizedShort2.cs | 33 ++- .../PixelFormats/NormalizedShort4.cs | 33 ++- src/ImageSharp/PixelFormats/Rg32.cs | 24 +- src/ImageSharp/PixelFormats/Rgb24.cs | 14 ++ src/ImageSharp/PixelFormats/Rgba1010102.cs | 14 ++ src/ImageSharp/PixelFormats/Rgba32.cs | 16 +- src/ImageSharp/PixelFormats/Rgba64.cs | 14 ++ src/ImageSharp/PixelFormats/RgbaVector.cs | 24 +- src/ImageSharp/PixelFormats/Short2.cs | 31 ++- src/ImageSharp/PixelFormats/Short4.cs | 33 ++- .../PixelFormats/PackedPixelTests.cs | 235 +++++++++++++++++- 25 files changed, 701 insertions(+), 91 deletions(-) diff --git a/src/ImageSharp/PixelFormats/Alpha8.cs b/src/ImageSharp/PixelFormats/Alpha8.cs index c266035a6..71480650d 100644 --- a/src/ImageSharp/PixelFormats/Alpha8.cs +++ b/src/ImageSharp/PixelFormats/Alpha8.cs @@ -62,6 +62,20 @@ namespace SixLabors.ImageSharp.PixelFormats /// public PixelOperations CreatePixelOperations() => new PixelOperations(); + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + return this.ToVector4(); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) diff --git a/src/ImageSharp/PixelFormats/Argb32.cs b/src/ImageSharp/PixelFormats/Argb32.cs index 33294838e..3b25efb9f 100644 --- a/src/ImageSharp/PixelFormats/Argb32.cs +++ b/src/ImageSharp/PixelFormats/Argb32.cs @@ -237,6 +237,20 @@ namespace SixLabors.ImageSharp.PixelFormats /// public PixelOperations CreatePixelOperations() => new PixelOperations(); + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + return this.ToVector4(); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ToVector4() @@ -321,7 +335,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint Pack(float x, float y, float z, float w) { - Vector4 value = new Vector4(x, y, z, w); + var value = new Vector4(x, y, z, w); return Pack(ref value); } @@ -347,7 +361,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint Pack(ref Vector3 vector) { - Vector4 value = new Vector4(vector, 1); + var value = new Vector4(vector, 1); return Pack(ref value); } diff --git a/src/ImageSharp/PixelFormats/Bgr24.cs b/src/ImageSharp/PixelFormats/Bgr24.cs index e210856b3..423e28140 100644 --- a/src/ImageSharp/PixelFormats/Bgr24.cs +++ b/src/ImageSharp/PixelFormats/Bgr24.cs @@ -80,6 +80,20 @@ namespace SixLabors.ImageSharp.PixelFormats this = source.Bgr; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + return this.ToVector4(); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) diff --git a/src/ImageSharp/PixelFormats/Bgr565.cs b/src/ImageSharp/PixelFormats/Bgr565.cs index b4e7aad58..b8a17bb9e 100644 --- a/src/ImageSharp/PixelFormats/Bgr565.cs +++ b/src/ImageSharp/PixelFormats/Bgr565.cs @@ -85,6 +85,20 @@ namespace SixLabors.ImageSharp.PixelFormats (this.PackedValue & 0x1F) * (1F / 31F)); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + return this.ToVector4(); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) diff --git a/src/ImageSharp/PixelFormats/Bgra32.cs b/src/ImageSharp/PixelFormats/Bgra32.cs index e8469414d..8a8dcd84c 100644 --- a/src/ImageSharp/PixelFormats/Bgra32.cs +++ b/src/ImageSharp/PixelFormats/Bgra32.cs @@ -116,6 +116,20 @@ namespace SixLabors.ImageSharp.PixelFormats } } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + return this.ToVector4(); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) diff --git a/src/ImageSharp/PixelFormats/Bgra4444.cs b/src/ImageSharp/PixelFormats/Bgra4444.cs index c51a872d1..718f164c3 100644 --- a/src/ImageSharp/PixelFormats/Bgra4444.cs +++ b/src/ImageSharp/PixelFormats/Bgra4444.cs @@ -70,6 +70,20 @@ namespace SixLabors.ImageSharp.PixelFormats /// public PixelOperations CreatePixelOperations() => new PixelOperations(); + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + return this.ToVector4(); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ToVector4() diff --git a/src/ImageSharp/PixelFormats/Bgra5551.cs b/src/ImageSharp/PixelFormats/Bgra5551.cs index 8be4ce82c..295ac06bc 100644 --- a/src/ImageSharp/PixelFormats/Bgra5551.cs +++ b/src/ImageSharp/PixelFormats/Bgra5551.cs @@ -72,6 +72,20 @@ namespace SixLabors.ImageSharp.PixelFormats /// public PixelOperations CreatePixelOperations() => new PixelOperations(); + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + return this.ToVector4(); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ToVector4() @@ -101,7 +115,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -111,7 +125,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -122,7 +136,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -132,7 +146,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -190,6 +204,6 @@ namespace SixLabors.ImageSharp.PixelFormats } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Vector4 ToScaledVector4() => this.ToVector4() * 255f; + private Vector4 ToByteScaledVector4() => this.ToVector4() * 255f; } } diff --git a/src/ImageSharp/PixelFormats/Byte4.cs b/src/ImageSharp/PixelFormats/Byte4.cs index 829937c8a..bb7bfbd4e 100644 --- a/src/ImageSharp/PixelFormats/Byte4.cs +++ b/src/ImageSharp/PixelFormats/Byte4.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing four 8-bit unsigned integer values, ranging from 0 to 255. /// - /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// Ranges from <0, 0, 0, 0> to <255, 255, 255, 255> in vector form. /// /// public struct Byte4 : IPixel, IPackedVector @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The w-component public Byte4(float x, float y, float z, float w) { - Vector4 vector = new Vector4(x, y, z, w); + var vector = new Vector4(x, y, z, w); this.PackedValue = Pack(ref vector); } @@ -73,6 +73,20 @@ namespace SixLabors.ImageSharp.PixelFormats /// public PixelOperations CreatePixelOperations() => new PixelOperations(); + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + this.PackFromVector4(vector * 255F); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + return this.ToVector4() / 255F; + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) @@ -95,14 +109,14 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgba32(Rgba32 source) { - this.PackFromVector4(source.ToUnscaledVector4()); + this.PackFromVector4(source.ToByteScaledVector4()); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToVector4(); + var vector = this.ToVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -112,7 +126,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToVector4(); + var vector = this.ToVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -123,7 +137,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToVector4(); + var vector = this.ToVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -133,7 +147,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToVector4(); + var vector = this.ToVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; diff --git a/src/ImageSharp/PixelFormats/HalfSingle.cs b/src/ImageSharp/PixelFormats/HalfSingle.cs index b4bc491eb..d32e43324 100644 --- a/src/ImageSharp/PixelFormats/HalfSingle.cs +++ b/src/ImageSharp/PixelFormats/HalfSingle.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing a single 16 bit floating point value. /// - /// Ranges from <0, 0, 0, 1> to <1, 0, 0, 1> in vector form. + /// Ranges from <-1, 0, 0, 1> to <1, 0, 0, 1> in vector form. /// /// public struct HalfSingle : IPixel, IPackedVector @@ -86,6 +86,25 @@ namespace SixLabors.ImageSharp.PixelFormats return HalfTypeHelper.Unpack(this.PackedValue); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + float scaled = vector.X; + scaled *= 2F; + scaled -= 1F; + this.PackedValue = HalfTypeHelper.Pack(scaled); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + float single = this.ToSingle() + 1F; + single /= 2F; + return new Vector4(single, 0, 0, 1); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) @@ -111,7 +130,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -121,7 +140,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -132,7 +151,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -142,7 +161,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -176,7 +195,7 @@ namespace SixLabors.ImageSharp.PixelFormats } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Vector4 ToScaledVector4() + private Vector4 ToByteScaledVector4() { var vector = this.ToVector4(); vector *= MaxBytes; diff --git a/src/ImageSharp/PixelFormats/HalfVector2.cs b/src/ImageSharp/PixelFormats/HalfVector2.cs index aa5f32190..47255f0af 100644 --- a/src/ImageSharp/PixelFormats/HalfVector2.cs +++ b/src/ImageSharp/PixelFormats/HalfVector2.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing two 16-bit floating-point values. /// - /// Ranges from <0, 0, 0, 1> to <1, 0, 0, 1> in vector form. + /// Ranges from <-1, -1, 0, 1> to <1, 1, 0, 1> in vector form. /// /// public struct HalfVector2 : IPixel, IPackedVector @@ -99,6 +99,25 @@ namespace SixLabors.ImageSharp.PixelFormats return vector; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + Vector2 scaled = new Vector2(vector.X, vector.Y) * 2F; + scaled -= Vector2.One; + this.PackedValue = Pack(scaled.X, scaled.Y); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + var scaled = this.ToVector2(); + scaled += Vector2.One; + scaled /= 2F; + return new Vector4(scaled, 0F, 1F); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) @@ -110,7 +129,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ToVector4() { - Vector2 vector = this.ToVector2(); + var vector = this.ToVector2(); return new Vector4(vector.X, vector.Y, 0F, 1F); } @@ -125,7 +144,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = 0; @@ -135,7 +154,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = 0; @@ -146,7 +165,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = 0; @@ -156,7 +175,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = 0; @@ -204,9 +223,9 @@ namespace SixLabors.ImageSharp.PixelFormats } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Vector4 ToScaledVector4() + private Vector4 ToByteScaledVector4() { - Vector4 vector = this.ToVector4(); + var vector = this.ToVector4(); vector *= MaxBytes; vector += Half; vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); diff --git a/src/ImageSharp/PixelFormats/HalfVector4.cs b/src/ImageSharp/PixelFormats/HalfVector4.cs index 87a1c9a49..9e102be18 100644 --- a/src/ImageSharp/PixelFormats/HalfVector4.cs +++ b/src/ImageSharp/PixelFormats/HalfVector4.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing four 16-bit floating-point values. /// - /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// Ranges from <-1, -1, -1, -1> to <1, 1, 1, 1> in vector form. /// /// public struct HalfVector4 : IPixel, IPackedVector @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The w-component. public HalfVector4(float x, float y, float z, float w) { - Vector4 vector = new Vector4(x, y, z, w); + var vector = new Vector4(x, y, z, w); this.PackedValue = Pack(ref vector); } @@ -89,6 +89,25 @@ namespace SixLabors.ImageSharp.PixelFormats /// public PixelOperations CreatePixelOperations() => new PixelOperations(); + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + vector *= 2F; + vector -= Vector4.One; + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + var scaled = this.ToVector4(); + scaled += Vector4.One; + scaled /= 2F; + return scaled; + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) @@ -118,7 +137,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -128,7 +147,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -139,7 +158,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -149,7 +168,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -198,9 +217,9 @@ namespace SixLabors.ImageSharp.PixelFormats } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Vector4 ToScaledVector4() + private Vector4 ToByteScaledVector4() { - Vector4 vector = this.ToVector4(); + var vector = this.ToVector4(); vector *= MaxBytes; vector += Half; vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); diff --git a/src/ImageSharp/PixelFormats/IPixel.cs b/src/ImageSharp/PixelFormats/IPixel.cs index 37c505c84..954e14cc0 100644 --- a/src/ImageSharp/PixelFormats/IPixel.cs +++ b/src/ImageSharp/PixelFormats/IPixel.cs @@ -32,6 +32,20 @@ namespace SixLabors.ImageSharp.PixelFormats /// The vector to create the packed representation from. void PackFromVector4(Vector4 vector); + /// + /// Sets the packed representation from a scaled . + /// + /// The vector to create the packed representation from. + void PackFromScaledVector4(Vector4 vector); + + /// + /// Expands the packed representation into a scaled + /// with values clamped between 0 and 1. + /// The vector components are typically expanded in least to greatest significance order. + /// + /// The . + Vector4 ToScaledVector4(); + /// /// Expands the packed representation into a . /// The vector components are typically expanded in least to greatest significance order. diff --git a/src/ImageSharp/PixelFormats/NormalizedByte2.cs b/src/ImageSharp/PixelFormats/NormalizedByte2.cs index 9a69f6ab3..692635a7f 100644 --- a/src/ImageSharp/PixelFormats/NormalizedByte2.cs +++ b/src/ImageSharp/PixelFormats/NormalizedByte2.cs @@ -104,6 +104,25 @@ namespace SixLabors.ImageSharp.PixelFormats (sbyte)((this.PackedValue >> 8) & 0xFF) / 127F); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + Vector2 scaled = new Vector2(vector.X, vector.Y) * 2F; + scaled -= Vector2.One; + this.PackedValue = Pack(scaled.X, scaled.Y); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + var scaled = this.ToVector2(); + scaled += Vector2.One; + scaled /= 2F; + return new Vector4(scaled, 0F, 1F); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) @@ -122,7 +141,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgba32(Rgba32 source) { - Vector4 vector = source.ToUnscaledVector4(); + Vector4 vector = source.ToByteScaledVector4(); vector -= Round; vector -= Half; vector -= Round; @@ -134,7 +153,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = 0; @@ -144,7 +163,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = 0; @@ -155,7 +174,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = 0; @@ -165,7 +184,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = 0; @@ -214,9 +233,9 @@ namespace SixLabors.ImageSharp.PixelFormats } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Vector4 ToScaledVector4() + private Vector4 ToByteScaledVector4() { - Vector4 vector = this.ToVector4(); + var vector = this.ToVector4(); vector *= Half; vector += Round; vector += Half; diff --git a/src/ImageSharp/PixelFormats/NormalizedByte4.cs b/src/ImageSharp/PixelFormats/NormalizedByte4.cs index 920f92cae..2df67196e 100644 --- a/src/ImageSharp/PixelFormats/NormalizedByte4.cs +++ b/src/ImageSharp/PixelFormats/NormalizedByte4.cs @@ -93,6 +93,25 @@ namespace SixLabors.ImageSharp.PixelFormats /// public PixelOperations CreatePixelOperations() => new PixelOperations(); + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + vector *= 2F; + vector -= Vector4.One; + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + var scaled = this.ToVector4(); + scaled += Vector4.One; + scaled /= 2F; + return scaled; + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) @@ -115,7 +134,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgba32(Rgba32 source) { - Vector4 vector = source.ToUnscaledVector4(); + Vector4 vector = source.ToByteScaledVector4(); vector -= Round; vector -= Half; vector -= Round; @@ -127,7 +146,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -137,7 +156,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -148,7 +167,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -158,7 +177,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -211,9 +230,9 @@ namespace SixLabors.ImageSharp.PixelFormats } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Vector4 ToScaledVector4() + private Vector4 ToByteScaledVector4() { - Vector4 vector = this.ToVector4(); + var vector = this.ToVector4(); vector *= Half; vector += Round; vector += Half; diff --git a/src/ImageSharp/PixelFormats/NormalizedShort2.cs b/src/ImageSharp/PixelFormats/NormalizedShort2.cs index 6d28f61c2..263e6d0f3 100644 --- a/src/ImageSharp/PixelFormats/NormalizedShort2.cs +++ b/src/ImageSharp/PixelFormats/NormalizedShort2.cs @@ -91,6 +91,25 @@ namespace SixLabors.ImageSharp.PixelFormats /// public PixelOperations CreatePixelOperations() => new PixelOperations(); + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + Vector2 scaled = new Vector2(vector.X, vector.Y) * 2F; + scaled -= Vector2.One; + this.PackedValue = Pack(scaled.X, scaled.Y); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + var scaled = this.ToVector2(); + scaled += Vector2.One; + scaled /= 2F; + return new Vector4(scaled, 0F, 1F); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) @@ -109,7 +128,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgba32(Rgba32 source) { - Vector4 vector = source.ToUnscaledVector4(); + Vector4 vector = source.ToByteScaledVector4(); vector -= Round; vector -= Half; vector -= Round; @@ -121,7 +140,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = 0; @@ -131,7 +150,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = 0; @@ -142,7 +161,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = 0; @@ -152,7 +171,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = 0; @@ -221,9 +240,9 @@ namespace SixLabors.ImageSharp.PixelFormats } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Vector4 ToScaledVector4() + private Vector4 ToByteScaledVector4() { - Vector4 vector = this.ToVector4(); + var vector = this.ToVector4(); vector *= Half; vector += Round; vector += Half; diff --git a/src/ImageSharp/PixelFormats/NormalizedShort4.cs b/src/ImageSharp/PixelFormats/NormalizedShort4.cs index 45f984da0..9a54377cf 100644 --- a/src/ImageSharp/PixelFormats/NormalizedShort4.cs +++ b/src/ImageSharp/PixelFormats/NormalizedShort4.cs @@ -93,6 +93,25 @@ namespace SixLabors.ImageSharp.PixelFormats /// public PixelOperations CreatePixelOperations() => new PixelOperations(); + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + vector *= 2F; + vector -= Vector4.One; + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + var scaled = this.ToVector4(); + scaled += Vector4.One; + scaled /= 2F; + return scaled; + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) @@ -117,7 +136,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgba32(Rgba32 source) { - Vector4 vector = source.ToUnscaledVector4(); + Vector4 vector = source.ToByteScaledVector4(); vector -= Round; vector -= Half; vector -= Round; @@ -129,7 +148,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = (byte)MathF.Round(vector.Z); @@ -139,7 +158,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = (byte)MathF.Round(vector.Z); @@ -150,7 +169,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = (byte)MathF.Round(vector.Z); @@ -160,7 +179,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = (byte)MathF.Round(vector.Z); @@ -217,9 +236,9 @@ namespace SixLabors.ImageSharp.PixelFormats } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Vector4 ToScaledVector4() + private Vector4 ToByteScaledVector4() { - Vector4 vector = this.ToVector4(); + var vector = this.ToVector4(); vector *= Half; vector += Round; vector += Half; diff --git a/src/ImageSharp/PixelFormats/Rg32.cs b/src/ImageSharp/PixelFormats/Rg32.cs index d2c296515..e17d1dd0b 100644 --- a/src/ImageSharp/PixelFormats/Rg32.cs +++ b/src/ImageSharp/PixelFormats/Rg32.cs @@ -89,6 +89,20 @@ namespace SixLabors.ImageSharp.PixelFormats ((this.PackedValue >> 16) & 0xFFFF) / 65535F); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + return this.ToVector4(); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) @@ -114,7 +128,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -124,7 +138,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -135,7 +149,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -145,7 +159,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)vector.X; dest.G = (byte)vector.Y; dest.B = (byte)vector.Z; @@ -193,6 +207,6 @@ namespace SixLabors.ImageSharp.PixelFormats } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Vector4 ToScaledVector4() => this.ToVector4() * 255f; + private Vector4 ToByteScaledVector4() => this.ToVector4() * 255F; } } diff --git a/src/ImageSharp/PixelFormats/Rgb24.cs b/src/ImageSharp/PixelFormats/Rgb24.cs index d867d9065..6a93028cb 100644 --- a/src/ImageSharp/PixelFormats/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/Rgb24.cs @@ -80,6 +80,20 @@ namespace SixLabors.ImageSharp.PixelFormats this = Unsafe.As(ref source); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + return this.ToVector4(); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) diff --git a/src/ImageSharp/PixelFormats/Rgba1010102.cs b/src/ImageSharp/PixelFormats/Rgba1010102.cs index e6967d23e..627eb247f 100644 --- a/src/ImageSharp/PixelFormats/Rgba1010102.cs +++ b/src/ImageSharp/PixelFormats/Rgba1010102.cs @@ -79,6 +79,20 @@ namespace SixLabors.ImageSharp.PixelFormats /// public PixelOperations CreatePixelOperations() => new PixelOperations(); + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + return this.ToVector4(); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ToVector4() diff --git a/src/ImageSharp/PixelFormats/Rgba32.cs b/src/ImageSharp/PixelFormats/Rgba32.cs index 701de7770..1630cac35 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.cs @@ -318,6 +318,20 @@ namespace SixLabors.ImageSharp.PixelFormats dest.A = this.A; } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + return this.ToVector4(); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) @@ -383,7 +397,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// A of values in [0, 255] [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal Vector4 ToUnscaledVector4() + internal Vector4 ToByteScaledVector4() { return new Vector4(this.R, this.G, this.B, this.A); } diff --git a/src/ImageSharp/PixelFormats/Rgba64.cs b/src/ImageSharp/PixelFormats/Rgba64.cs index 040ae15b1..5d513458f 100644 --- a/src/ImageSharp/PixelFormats/Rgba64.cs +++ b/src/ImageSharp/PixelFormats/Rgba64.cs @@ -78,6 +78,20 @@ namespace SixLabors.ImageSharp.PixelFormats /// public PixelOperations CreatePixelOperations() => new PixelOperations(); + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + return this.ToVector4(); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ToVector4() diff --git a/src/ImageSharp/PixelFormats/RgbaVector.cs b/src/ImageSharp/PixelFormats/RgbaVector.cs index ba641d590..d4137a2d0 100644 --- a/src/ImageSharp/PixelFormats/RgbaVector.cs +++ b/src/ImageSharp/PixelFormats/RgbaVector.cs @@ -235,7 +235,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = (byte)MathF.Round(vector.Z); @@ -245,7 +245,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = (byte)MathF.Round(vector.Z); @@ -256,7 +256,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = (byte)MathF.Round(vector.Z); @@ -266,13 +266,27 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = (byte)MathF.Round(vector.Z); dest.A = (byte)MathF.Round(vector.W); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + return this.ToVector4(); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) @@ -316,6 +330,6 @@ namespace SixLabors.ImageSharp.PixelFormats } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Vector4 ToScaledVector4() => Vector4.Clamp(this.backingVector, Vector4.Zero, Vector4.One) * MaxBytes; + private Vector4 ToByteScaledVector4() => Vector4.Clamp(this.backingVector, Vector4.Zero, Vector4.One) * MaxBytes; } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/Short2.cs b/src/ImageSharp/PixelFormats/Short2.cs index 1355a9413..77eee03a2 100644 --- a/src/ImageSharp/PixelFormats/Short2.cs +++ b/src/ImageSharp/PixelFormats/Short2.cs @@ -91,6 +91,25 @@ namespace SixLabors.ImageSharp.PixelFormats /// public PixelOperations CreatePixelOperations() => new PixelOperations(); + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + Vector2 scaled = new Vector2(vector.X, vector.Y) * 65534F; + scaled -= new Vector2(32767F); + this.PackedValue = Pack(scaled.X, scaled.Y); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + var scaled = this.ToVector2(); + scaled += new Vector2(32767F); + scaled /= 65534F; + return new Vector4(scaled, 0F, 1F); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) @@ -119,7 +138,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgb24(ref Rgb24 dest) { - Vector2 vector = this.ToScaledVector2(); + Vector2 vector = this.ToByteScaledVector2(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = 0; @@ -129,7 +148,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgba32(ref Rgba32 dest) { - Vector2 vector = this.ToScaledVector2(); + Vector2 vector = this.ToByteScaledVector2(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = 0; @@ -140,7 +159,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgr24(ref Bgr24 dest) { - Vector2 vector = this.ToScaledVector2(); + Vector2 vector = this.ToByteScaledVector2(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = 0; @@ -150,7 +169,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgra32(ref Bgra32 dest) { - Vector2 vector = this.ToScaledVector2(); + Vector2 vector = this.ToByteScaledVector2(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = 0; @@ -215,9 +234,9 @@ namespace SixLabors.ImageSharp.PixelFormats } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Vector2 ToScaledVector2() + private Vector2 ToByteScaledVector2() { - Vector2 vector = this.ToVector2(); + var vector = this.ToVector2(); vector /= 65534; vector *= 255; vector += Half; diff --git a/src/ImageSharp/PixelFormats/Short4.cs b/src/ImageSharp/PixelFormats/Short4.cs index aecb4d2de..4a1676f09 100644 --- a/src/ImageSharp/PixelFormats/Short4.cs +++ b/src/ImageSharp/PixelFormats/Short4.cs @@ -93,6 +93,25 @@ namespace SixLabors.ImageSharp.PixelFormats /// public PixelOperations CreatePixelOperations() => new PixelOperations(); + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PackFromScaledVector4(Vector4 vector) + { + vector *= 65534F; + vector -= new Vector4(32767F); + this.PackFromVector4(vector); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 ToScaledVector4() + { + var scaled = this.ToVector4(); + scaled += new Vector4(32767F); + scaled /= 65534F; + return scaled; + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) @@ -115,7 +134,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgba32(Rgba32 source) { - Vector4 vector = source.ToVector4(); + var vector = source.ToVector4(); vector *= 65534; vector -= new Vector4(32767); this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); @@ -125,7 +144,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = (byte)MathF.Round(vector.Z); @@ -135,7 +154,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = (byte)MathF.Round(vector.Z); @@ -146,7 +165,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = (byte)MathF.Round(vector.Z); @@ -156,7 +175,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToScaledVector4(); + Vector4 vector = this.ToByteScaledVector4(); dest.R = (byte)MathF.Round(vector.X); dest.G = (byte)MathF.Round(vector.Y); dest.B = (byte)MathF.Round(vector.Z); @@ -222,9 +241,9 @@ namespace SixLabors.ImageSharp.PixelFormats } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Vector4 ToScaledVector4() + private Vector4 ToByteScaledVector4() { - Vector4 vector = this.ToVector4(); + var vector = this.ToVector4(); vector /= 65534; vector *= 255; vector += Half; diff --git a/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs b/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs index 9b6d53fd9..96e899316 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs @@ -32,14 +32,26 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.Equal(124, new Alpha8(124F / 0xFF).PackedValue); Assert.Equal(26, new Alpha8(0.1F).PackedValue); - // Test ordering + // Test ToVector4. var vector = new Alpha8(.5F).ToVector4(); - Assert.Equal(0, vector.X); Assert.Equal(0, vector.Y); Assert.Equal(0, vector.Z); Assert.Equal(.5F, vector.W, 2); + // Test ToScaledVector4. + Vector4 scaled = new Alpha8(.5F).ToScaledVector4(); + Assert.Equal(0, scaled.X); + Assert.Equal(0, scaled.Y); + Assert.Equal(0, scaled.Z); + Assert.Equal(.5F, scaled.W, 2); + + // Test PackFromScaledVector4. + var pixel = default(Alpha8); + pixel.PackFromScaledVector4(scaled); + Assert.Equal(128, pixel.PackedValue); + + // Test Rgb conversion var rgb = default(Rgb24); var rgba = default(Rgba32); var bgr = default(Bgr24); @@ -73,6 +85,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.True(Equal(Vector4.UnitZ, new Argb32(Vector4.UnitZ).ToVector4())); Assert.True(Equal(Vector4.UnitW, new Argb32(Vector4.UnitW).ToVector4())); + // Test ToScaledVector4. + Vector4 scaled = new Argb32(Vector4.One).ToScaledVector4(); + Assert.Equal(1, scaled.X); + Assert.Equal(1, scaled.Y); + Assert.Equal(1, scaled.Z); + Assert.Equal(1, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(Argb32); + pixel.PackFromScaledVector4(scaled); + Assert.Equal(0xFFFFFFFF, pixel.PackedValue); + // Test clamping. Assert.True(Equal(Vector4.Zero, new Argb32(Vector4.One * -1234.0f).ToVector4())); Assert.True(Equal(Vector4.One, new Argb32(Vector4.One * +1234.0f).ToVector4())); @@ -90,6 +114,7 @@ namespace SixLabors.ImageSharp.Tests.Colors var bgr = default(Bgr24); var bgra = default(Bgra32); + argb.ToRgb24(ref rgb); Assert.Equal(rgb, new Rgb24(0x1a, 0, 0x80)); @@ -117,6 +142,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.True(Equal(Vector3.UnitY, new Bgr565(Vector3.UnitY).ToVector3())); Assert.True(Equal(Vector3.UnitZ, new Bgr565(Vector3.UnitZ).ToVector3())); + // Test ToScaledVector4. + Vector4 scaled = new Bgr565(Vector3.One).ToScaledVector4(); + Assert.Equal(1, scaled.X); + Assert.Equal(1, scaled.Y); + Assert.Equal(1, scaled.Z); + Assert.Equal(1, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(Bgr565); + pixel.PackFromScaledVector4(scaled); + Assert.Equal(0xFFFF, pixel.PackedValue); + // Test clamping. Assert.True(Equal(Vector3.Zero, new Bgr565(Vector3.One * -1234F).ToVector3())); Assert.True(Equal(Vector3.One, new Bgr565(Vector3.One * 1234F).ToVector3())); @@ -165,6 +202,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.True(Equal(Vector4.UnitZ, new Bgra4444(Vector4.UnitZ).ToVector4())); Assert.True(Equal(Vector4.UnitW, new Bgra4444(Vector4.UnitW).ToVector4())); + // Test ToScaledVector4. + Vector4 scaled = new Bgra4444(Vector4.One).ToScaledVector4(); + Assert.Equal(1, scaled.X); + Assert.Equal(1, scaled.Y); + Assert.Equal(1, scaled.Z); + Assert.Equal(1, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(Bgra4444); + pixel.PackFromScaledVector4(scaled); + Assert.Equal(0xFFFF, pixel.PackedValue); + // Test clamping. Assert.True(Equal(Vector4.Zero, new Bgra4444(Vector4.One * -1234.0f).ToVector4())); Assert.True(Equal(Vector4.One, new Bgra4444(Vector4.One * 1234.0f).ToVector4())); @@ -211,6 +260,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.True(Equal(Vector4.Zero, new Bgra5551(Vector4.Zero).ToVector4())); Assert.True(Equal(Vector4.One, new Bgra5551(Vector4.One).ToVector4())); + // Test ToScaledVector4. + Vector4 scaled = new Bgra5551(Vector4.One).ToScaledVector4(); + Assert.Equal(1, scaled.X); + Assert.Equal(1, scaled.Y); + Assert.Equal(1, scaled.Z); + Assert.Equal(1, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(Bgra5551); + pixel.PackFromScaledVector4(scaled); + Assert.Equal(0xFFFF, pixel.PackedValue); + // Test clamping. Assert.Equal(Vector4.Zero, new Bgra5551(Vector4.One * -1234.0f).ToVector4()); Assert.Equal(Vector4.One, new Bgra5551(Vector4.One * 1234.0f).ToVector4()); @@ -261,6 +322,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.True(Equal(Vector4.UnitZ * 255, new Byte4(Vector4.UnitZ * 255).ToVector4())); Assert.True(Equal(Vector4.UnitW * 255, new Byte4(Vector4.UnitW * 255).ToVector4())); + // Test ToScaledVector4. + Vector4 scaled = new Byte4(Vector4.One * 255).ToScaledVector4(); + Assert.Equal(1, scaled.X); + Assert.Equal(1, scaled.Y); + Assert.Equal(1, scaled.Z); + Assert.Equal(1, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(Byte4); + pixel.PackFromScaledVector4(scaled); + Assert.Equal(0xFFFFFFFF, pixel.PackedValue); + // Test clamping. Assert.True(Equal(Vector4.Zero, new Byte4(Vector4.One * -1234.0f).ToVector4())); Assert.True(Equal(Vector4.One * 255, new Byte4(Vector4.One * 1234.0f).ToVector4())); @@ -318,6 +391,18 @@ namespace SixLabors.ImageSharp.Tests.Colors float x = .5F; Assert.True(Equal(new Vector4(x, 0, 0, 1), new HalfSingle(x).ToVector4())); + // Test ToScaledVector4. + Vector4 scaled = new HalfSingle(-1F).ToScaledVector4(); + Assert.Equal(0, scaled.X); + Assert.Equal(0, scaled.Y); + Assert.Equal(0, scaled.Z); + Assert.Equal(1, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(HalfSingle); + pixel.PackFromScaledVector4(scaled); + Assert.Equal(48128, pixel.PackedValue); + var rgb = default(Rgb24); var rgba = default(Rgba32); var bgr = default(Bgr24); @@ -350,6 +435,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.True(Equal(Vector2.UnitX, new HalfVector2(Vector2.UnitX).ToVector2())); Assert.True(Equal(Vector2.UnitY, new HalfVector2(Vector2.UnitY).ToVector2())); + // Test ToScaledVector4. + Vector4 scaled = new HalfVector2(Vector2.One).ToScaledVector4(); + Assert.Equal(1F, scaled.X); + Assert.Equal(1F, scaled.Y); + Assert.Equal(0, scaled.Z); + Assert.Equal(1, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(HalfVector2); + pixel.PackFromScaledVector4(scaled); + Assert.Equal(1006648320u, pixel.PackedValue); + // Test ordering float x = .5F; float y = .25F; @@ -395,6 +492,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.True(Equal(Vector4.UnitZ, new HalfVector4(Vector4.UnitZ).ToVector4())); Assert.True(Equal(Vector4.UnitW, new HalfVector4(Vector4.UnitW).ToVector4())); + // Test ToScaledVector4. + Vector4 scaled = new HalfVector4(-Vector4.One).ToScaledVector4(); + Assert.Equal(0, scaled.X); + Assert.Equal(0, scaled.Y); + Assert.Equal(0, scaled.Z); + Assert.Equal(0, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(HalfVector4); + pixel.PackFromScaledVector4(scaled); + Assert.Equal(13547034390470638592uL, pixel.PackedValue); + // Test ordering float x = .25F; float y = .5F; @@ -438,6 +547,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.True(Equal(new Vector4(1, 1, 0, 1), new NormalizedByte2(Vector2.One).ToVector4())); Assert.True(Equal(new Vector4(0, 0, 0, 1), new NormalizedByte2(Vector2.Zero).ToVector4())); + // Test ToScaledVector4. + Vector4 scaled = new NormalizedByte2(-Vector2.One).ToScaledVector4(); + Assert.Equal(0, scaled.X); + Assert.Equal(0, scaled.Y); + Assert.Equal(0, scaled.Z); + Assert.Equal(1F, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(NormalizedByte2); + pixel.PackFromScaledVector4(scaled); + Assert.Equal(0x8181, pixel.PackedValue); + // Test Ordering float x = 0.1f; float y = -0.3f; @@ -479,6 +600,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.True(Equal(Vector4.One, new NormalizedByte4(Vector4.One * 1234.0f).ToVector4())); Assert.True(Equal(-Vector4.One, new NormalizedByte4(Vector4.One * -1234.0f).ToVector4())); + // Test ToScaledVector4. + Vector4 scaled = new NormalizedByte4(-Vector4.One).ToScaledVector4(); + Assert.Equal(0, scaled.X); + Assert.Equal(0, scaled.Y); + Assert.Equal(0, scaled.Z); + Assert.Equal(0, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(NormalizedByte4); + pixel.PackFromScaledVector4(scaled); + Assert.Equal(0x81818181, pixel.PackedValue); + // Test Ordering float x = 0.1f; float y = -0.3f; @@ -535,6 +668,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.True(Equal(new Vector4(1, 1, 0, 1), (new NormalizedShort2(Vector2.One)).ToVector4())); Assert.True(Equal(new Vector4(0, 0, 0, 1), (new NormalizedShort2(Vector2.Zero)).ToVector4())); + // Test ToScaledVector4. + Vector4 scaled = new NormalizedShort2(-Vector2.One).ToScaledVector4(); + Assert.Equal(0, scaled.X); + Assert.Equal(0, scaled.Y); + Assert.Equal(0, scaled.Z); + Assert.Equal(1, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(NormalizedShort2); + pixel.PackFromScaledVector4(scaled); + Assert.Equal(0x80018001, pixel.PackedValue); + // Test Ordering float x = 0.35f; float y = -0.2f; @@ -584,6 +729,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.True(Equal(Vector4.One, new NormalizedShort4(Vector4.One * 1234.0f).ToVector4())); Assert.True(Equal(-Vector4.One, new NormalizedShort4(Vector4.One * -1234.0f).ToVector4())); + // Test ToScaledVector4. + Vector4 scaled = new NormalizedShort4(Vector4.One).ToScaledVector4(); + Assert.Equal(1, scaled.X); + Assert.Equal(1, scaled.Y); + Assert.Equal(1, scaled.Z); + Assert.Equal(1, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(NormalizedShort4); + pixel.PackFromScaledVector4(scaled); + Assert.Equal((ulong)0x7FFF7FFF7FFF7FFF, pixel.PackedValue); + // Test Ordering float x = 0.1f; float y = -0.3f; @@ -626,6 +783,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.True(Equal(Vector2.Zero, new Rg32(Vector2.Zero).ToVector2())); Assert.True(Equal(Vector2.One, new Rg32(Vector2.One).ToVector2())); + // Test ToScaledVector4. + Vector4 scaled = new Rg32(Vector2.One).ToScaledVector4(); + Assert.Equal(1, scaled.X); + Assert.Equal(1, scaled.Y); + Assert.Equal(0, scaled.Z); + Assert.Equal(1, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(Rg32); + pixel.PackFromScaledVector4(scaled); + Assert.Equal(0xFFFFFFFF, pixel.PackedValue); + // Test clamping. Assert.True(Equal(Vector2.Zero, new Rg32(Vector2.One * -1234.0f).ToVector2())); Assert.True(Equal(Vector2.One, new Rg32(Vector2.One * 1234.0f).ToVector2())); @@ -668,6 +837,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.True(Equal(Vector4.Zero, new Rgba1010102(Vector4.Zero).ToVector4())); Assert.True(Equal(Vector4.One, new Rgba1010102(Vector4.One).ToVector4())); + // Test ToScaledVector4. + Vector4 scaled = new Rgba1010102(Vector4.One).ToScaledVector4(); + Assert.Equal(1, scaled.X); + Assert.Equal(1, scaled.Y); + Assert.Equal(1, scaled.Z); + Assert.Equal(1, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(Rgba1010102); + pixel.PackFromScaledVector4(scaled); + Assert.Equal(0xFFFFFFFF, pixel.PackedValue); + // Test clamping. Assert.True(Equal(Vector4.Zero, new Rgba1010102(Vector4.One * -1234.0f).ToVector4())); Assert.True(Equal(Vector4.One, new Rgba1010102(Vector4.One * 1234.0f).ToVector4())); @@ -709,7 +890,7 @@ namespace SixLabors.ImageSharp.Tests.Colors } [Fact] - public void Color() + public void Rgba32() { // Test the limits. Assert.Equal((uint)0x0, new Rgba32(Vector4.Zero).PackedValue); @@ -723,6 +904,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.True(Equal(Vector4.UnitZ, new Rgba32(Vector4.UnitZ).ToVector4())); Assert.True(Equal(Vector4.UnitW, new Rgba32(Vector4.UnitW).ToVector4())); + // Test ToScaledVector4. + Vector4 scaled = new Rgba32(Vector4.One).ToScaledVector4(); + Assert.Equal(1, scaled.X); + Assert.Equal(1, scaled.Y); + Assert.Equal(1, scaled.Z); + Assert.Equal(1, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(Rgba32); + pixel.PackFromScaledVector4(scaled); + Assert.Equal(0xFFFFFFFF, pixel.PackedValue); + // Test clamping. Assert.True(Equal(Vector4.Zero, new Rgba32(Vector4.One * -1234.0f).ToVector4())); Assert.True(Equal(Vector4.One, new Rgba32(Vector4.One * +1234.0f).ToVector4())); @@ -764,6 +957,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.True(Equal(Vector4.Zero, new Rgba64(Vector4.Zero).ToVector4())); Assert.True(Equal(Vector4.One, new Rgba64(Vector4.One).ToVector4())); + // Test ToScaledVector4. + Vector4 scaled = new Rgba64(Vector4.One).ToScaledVector4(); + Assert.Equal(1, scaled.X); + Assert.Equal(1, scaled.Y); + Assert.Equal(1, scaled.Z); + Assert.Equal(1, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(Rgba64); + pixel.PackFromScaledVector4(scaled); + Assert.Equal(0xFFFFFFFFFFFFFFFF, pixel.PackedValue); + // Test clamping. Assert.True(Equal(Vector4.Zero, new Rgba64(Vector4.One * -1234.0f).ToVector4())); Assert.True(Equal(Vector4.One, new Rgba64(Vector4.One * 1234.0f).ToVector4())); @@ -825,6 +1030,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.True(Equal(new Vector4(0, 0, 0, 1), (new Short2(Vector2.Zero)).ToVector4())); Assert.True(Equal(new Vector4(-0x8000, -0x8000, 0, 1), (new Short2(Vector2.One * -0x8000)).ToVector4())); + // Test ToScaledVector4. + Vector4 scaled = new Short2(Vector2.One * 0x7FFF).ToScaledVector4(); + Assert.Equal(1, scaled.X); + Assert.Equal(1, scaled.Y); + Assert.Equal(0, scaled.Z); + Assert.Equal(1, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(Short2); + pixel.PackFromScaledVector4(scaled); + Assert.Equal((uint)0x7FFF7FFF, pixel.PackedValue); + // Test ordering float x = 0x2db1; float y = 0x361d; @@ -873,6 +1090,18 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.Equal(Vector4.UnitZ * 0x7FFF, new Short4(Vector4.UnitZ * 0x7FFF).ToVector4()); Assert.Equal(Vector4.UnitW * 0x7FFF, new Short4(Vector4.UnitW * 0x7FFF).ToVector4()); + // Test ToScaledVector4. + Vector4 scaled = new Short4(Vector4.One * 0x7FFF).ToScaledVector4(); + Assert.Equal(1, scaled.X); + Assert.Equal(1, scaled.Y); + Assert.Equal(1, scaled.Z); + Assert.Equal(1, scaled.W); + + // Test PackFromScaledVector4. + var pixel = default(Short4); + pixel.PackFromScaledVector4(scaled); + Assert.Equal((ulong)0x7FFF7FFF7FFF7FFF, pixel.PackedValue); + // Test clamping. Assert.Equal(Vector4.One * 0x7FFF, new Short4(Vector4.One * 1234567.0f).ToVector4()); Assert.Equal(Vector4.One * -0x8000, new Short4(Vector4.One * -1234567.0f).ToVector4()); From 55fbcb0fb86c3086c5e3af73e4b761b868c6699b Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 29 Mar 2018 01:04:00 +1100 Subject: [PATCH 2/6] Simplify CloneAs() --- src/ImageSharp/ImageFrame{TPixel}.cs | 32 +- .../PackedPixelConverterHelper.cs | 365 ------------------ .../ImageSharp.Tests/Image/ImageCloneTests.cs | 88 ++++- 3 files changed, 96 insertions(+), 389 deletions(-) delete mode 100644 src/ImageSharp/PixelFormats/PackedPixelConverterHelper.cs diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs index 338a18a40..1d9622aa4 100644 --- a/src/ImageSharp/ImageFrame{TPixel}.cs +++ b/src/ImageSharp/ImageFrame{TPixel}.cs @@ -246,27 +246,23 @@ namespace SixLabors.ImageSharp return this.Clone() as ImageFrame; } - Func scaleFunc = PackedPixelConverterHelper.ComputeScaleFunction(); - var target = new ImageFrame(this.MemoryManager, this.Width, this.Height, this.MetaData.Clone()); - using (PixelAccessor pixels = this.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - 0, - target.Height, - Configuration.Default.ParallelOptions, - y => + Parallel.For( + 0, + target.Height, + Configuration.Default.ParallelOptions, + y => + { + Span sourceRow = this.GetPixelRowSpan(y); + Span targetRow = target.GetPixelRowSpan(y); + + for (int x = 0; x < target.Width; x++) { - for (int x = 0; x < target.Width; x++) - { - var color = default(TPixel2); - color.PackFromVector4(scaleFunc(pixels[x, y].ToVector4())); - targetPixels[x, y] = color; - } - }); - } + ref var pixel = ref targetRow[x]; + pixel.PackFromScaledVector4(sourceRow[x].ToScaledVector4()); + } + }); return target; } diff --git a/src/ImageSharp/PixelFormats/PackedPixelConverterHelper.cs b/src/ImageSharp/PixelFormats/PackedPixelConverterHelper.cs deleted file mode 100644 index ae5f785a9..000000000 --- a/src/ImageSharp/PixelFormats/PackedPixelConverterHelper.cs +++ /dev/null @@ -1,365 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Numerics; - -namespace SixLabors.ImageSharp.PixelFormats -{ - /// - /// Assists with the conversion of known packed pixel formats from one to another. - /// - internal static class PackedPixelConverterHelper - { - /// - /// A non operative function. Simply returns the original vector. - /// - private static readonly Func Noop = vector4 => vector4; - - /// - /// Returns the correct scaling function for the given types The compute scale function. - /// - /// The source pixel format. - /// The target pixel format. - /// The - public static Func ComputeScaleFunction() - { - Type source = typeof(TPixel); - Type target = typeof(TPixel2); - - // Normalized standard - if (IsStandardNormalizedType(source)) - { - return FromStandardNormalizedType(target); - } - - // Standard - if (IsStandardType(source)) - { - return FromStandardType(target); - } - - // Normalized offsets. All four components. - if (IsOffsetNormalizedType(source)) - { - return FromOffsetNormalizedType(target); - } - - // Offset. All four components. - if (IsOffsetType(source)) - { - return FromOffsetType(target); - } - - // Normalized offsets. First component pair only. - if (IsOffsetTwoComponentNormalizedType(source)) - { - return FromOffsetTwoComponentNormalizedType(target); - } - - // Offsets. First component pair only. - if (IsOffsetTwoComponentType(source)) - { - return FromOffsetTwoComponentType(target); - } - - return Noop; - } - - /// - /// Returns the correct conversion function to convert from types having vector values representing all four components - /// ranging from 0 to 1. - /// - /// The target type - /// The - private static Func FromStandardNormalizedType(Type target) - { - if (IsStandardType(target)) - { - return vector4 => 255F * vector4; - } - - if (IsOffsetNormalizedType(target) || IsOffsetTwoComponentNormalizedType(target)) - { - // Expand the range then offset the center down. - return vector4 => (2F * vector4) - Vector4.One; - } - - if (IsOffsetType(target) || IsOffsetTwoComponentType(target)) - { - return vector4 => (65534F * vector4) - new Vector4(32767F); - } - - return Noop; - } - - /// - /// Returns the correct conversion function to convert from types having vector values representing all four components - /// ranging from 0 to 255. - /// - /// The target type - /// The - private static Func FromStandardType(Type target) - { - // Scale down - if (IsStandardNormalizedType(target)) - { - return vector4 => vector4 / 255F; - } - - if (IsOffsetNormalizedType(target) || IsOffsetTwoComponentNormalizedType(target)) - { - // Expand the range, divide, then offset the center down. - return vector4 => ((2F * (vector4 / 255F)) - Vector4.One); - } - - if (IsOffsetType(target) || IsOffsetTwoComponentType(target)) - { - return vector4 => (65534F * (vector4 / 255F)) - new Vector4(32767F); - } - - return Noop; - } - - /// - /// Returns the correct conversion function to convert from types having vector values representing all four components - /// ranging from -1 to 1. - /// - /// The target type - /// The - private static Func FromOffsetNormalizedType(Type target) - { - if (IsStandardNormalizedType(target)) - { - // Compress the range then offset the center up. - return vector4 => (vector4 / 2F) + new Vector4(.5F); - } - - if (IsStandardType(target)) - { - // Compress the range, multiply, then offset the center up. - return vector4 => ((vector4 / 2F) * 255F) + new Vector4(127.5F); - } - - if (IsOffsetType(target) || IsOffsetTwoComponentType(target)) - { - // Multiply out the range, two component won't read the last two values. - return vector4 => (vector4 * 32767F); - } - - return Noop; - } - - /// - /// Returns the correct conversion function to convert from types having vector values representing all four components - /// ranging from -32767 to 32767. - /// - /// The target type - /// The - private static Func FromOffsetType(Type target) - { - if (IsStandardNormalizedType(target)) - { - // Compress the range then offset the center up. - return vector4 => (vector4 / 65534F) + new Vector4(.5F); - } - - if (IsStandardType(target)) - { - // Compress the range, multiply, then offset the center up. - return vector4 => ((vector4 / 65534F) * 255F) + new Vector4(127.5F); - } - - if (IsOffsetNormalizedType(target) || IsOffsetTwoComponentNormalizedType(target)) - { - // Compress the range. Two component won't read the last two values. - return vector4 => (vector4 / 32767F); - } - - return Noop; - } - - /// - /// Returns the correct conversion function to convert from types having vector with the first component pair ranging from -1 to 1. - /// and the second component pair ranging from 0 to 1. - /// - /// The target type - /// The - private static Func FromOffsetTwoComponentNormalizedType(Type target) - { - if (IsStandardNormalizedType(target)) - { - return vector4 => - { - // Compress the range then offset the center up for first pair. - Vector4 v = (vector4 / 2F) + new Vector4(.5F); - return new Vector4(v.X, v.Y, 0F, 1F); - }; - } - - if (IsStandardType(target)) - { - return vector4 => - { - // Compress the range, multiply, then offset the center up for first pair. - Vector4 v = ((vector4 / 2F) * 255F) + new Vector4(127.5F); - return new Vector4(v.X, v.Y, 0F, 255F); - }; - } - - if (IsOffsetNormalizedType(target)) - { - // Copy the first two components and set second pair to 0 and 1 equivalent. - return vector4 => new Vector4(vector4.X, vector4.Y, -1F, 1F); - } - - if (IsOffsetTwoComponentType(target)) - { - // Multiply. Two component won't read the last two values. - return vector4 => (vector4 * 32767F); - } - - if (IsOffsetType(target)) - { - return vector4 => - { - // Multiply the first two components and set second pair to 0 and 1 equivalent. - Vector4 v = vector4 * 32767F; - return new Vector4(v.X, v.Y, -32767F, 32767F); - }; - } - - return Noop; - } - - /// - /// Returns the correct conversion function to convert from types having vector with the first component pair ranging from -32767 to 32767. - /// and the second component pair ranging from 0 to 1. - /// - /// The target type - /// The - private static Func FromOffsetTwoComponentType(Type target) - { - if (IsStandardNormalizedType(target)) - { - return vector4 => - { - Vector4 v = (vector4 / 65534F) + new Vector4(.5F); - return new Vector4(v.X, v.Y, 0, 1); - }; - } - - if (IsStandardType(target)) - { - return vector4 => - { - Vector4 v = ((vector4 / 65534F) * 255F) + new Vector4(127.5F); - return new Vector4(v.X, v.Y, 0, 255F); - }; - } - - if (IsOffsetType(target)) - { - // Copy the first two components and set second pair to 0 and 1 equivalent. - return vector4 => new Vector4(vector4.X, vector4.Y, -32767F, 32767F); - } - - if (IsOffsetNormalizedType(target)) - { - return vector4 => - { - // Divide the first two components and set second pair to 0 and 1 equivalent. - Vector4 v = vector4 / 32767F; - return new Vector4(v.X, v.Y, -1F, 1F); - }; - } - - if (IsOffsetTwoComponentNormalizedType(target)) - { - // Divide. Two component won't read the last two values. - return vector4 => (vector4 / 32767F); - } - - return Noop; - } - - /// - /// Identifies the type as having vector component values ranging from 0 to 1. - /// - /// The type to test. - /// The - private static bool IsStandardNormalizedType(Type type) - { - return - type == typeof(Alpha8) - || type == typeof(Argb32) - || type == typeof(Bgr24) - || type == typeof(Bgra32) - || type == typeof(Bgr565) - || type == typeof(Bgra4444) - || type == typeof(Bgra5551) - || type == typeof(HalfSingle) - || type == typeof(HalfVector2) - || type == typeof(HalfVector4) - || type == typeof(Rg32) - || type == typeof(Rgb24) - || type == typeof(Rgba32) - || type == typeof(Rgba64) - || type == typeof(Rgba1010102); - } - - /// - /// Identifies the type as having vector component values ranging from 0 to 255. - /// - /// The type to test. - /// The - private static bool IsStandardType(Type type) - { - return type == typeof(Byte4); - } - - /// - /// Identifies the type as having vector values representing the first component pair ranging from -1 to 1. - /// and the second component pair ranging from 0 to 1. - /// - /// The type to test. - /// The - private static bool IsOffsetTwoComponentNormalizedType(Type type) - { - return type == typeof(NormalizedByte2) - || type == typeof(NormalizedShort2); - } - - /// - /// Identifies the type as having vector values representing all four components ranging from -1 to 1. - /// - /// The type to test. - /// The - private static bool IsOffsetNormalizedType(Type type) - { - return type == typeof(NormalizedByte4) - || type == typeof(NormalizedShort4); - } - - /// - /// Identifies the type as having vector values representing the first component pair ranging from -32767 to 32767. - /// and the second component pair ranging from 0 to 1. - /// - /// The type to test. - /// The - private static bool IsOffsetTwoComponentType(Type type) - { - return type == typeof(Short2); - } - - /// - /// Identifies the type as having vector values representing all four components ranging from -32767 to 32767. - /// - /// The type to test. - /// The - private static bool IsOffsetType(Type type) - { - return type == typeof(Short4); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Image/ImageCloneTests.cs b/tests/ImageSharp.Tests/Image/ImageCloneTests.cs index 12e0fc883..82864f156 100644 --- a/tests/ImageSharp.Tests/Image/ImageCloneTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageCloneTests.cs @@ -21,13 +21,89 @@ namespace SixLabors.ImageSharp.Tests for (int x = 0; x < image.Width; x++) { - Rgba32 rgba = row[x]; - Bgra32 bgra = rowClone[x]; + Rgba32 expected = row[x]; + Bgra32 actual = rowClone[x]; - Assert.Equal(rgba.R, bgra.R); - Assert.Equal(rgba.G, bgra.G); - Assert.Equal(rgba.B, bgra.B); - Assert.Equal(rgba.A, bgra.A); + Assert.Equal(expected.R, actual.R); + Assert.Equal(expected.G, actual.G); + Assert.Equal(expected.B, actual.B); + Assert.Equal(expected.A, actual.A); + } + } + } + } + + [Theory] + [WithTestPatternImages(9, 9, PixelTypes.Rgba32)] + public void CloneAs_ToBgr24(TestImageProvider provider) + { + using (Image image = provider.GetImage()) + using (Image clone = image.CloneAs()) + { + for (int y = 0; y < image.Height; y++) + { + Span row = image.GetPixelRowSpan(y); + Span rowClone = clone.GetPixelRowSpan(y); + + for (int x = 0; x < image.Width; x++) + { + Rgba32 expected = row[x]; + Bgr24 actual = rowClone[x]; + + Assert.Equal(expected.R, actual.R); + Assert.Equal(expected.G, actual.G); + Assert.Equal(expected.B, actual.B); + } + } + } + } + + [Theory] + [WithTestPatternImages(9, 9, PixelTypes.Rgba32)] + public void CloneAs_ToArgb32(TestImageProvider provider) + { + using (Image image = provider.GetImage()) + using (Image clone = image.CloneAs()) + { + for (int y = 0; y < image.Height; y++) + { + Span row = image.GetPixelRowSpan(y); + Span rowClone = clone.GetPixelRowSpan(y); + + for (int x = 0; x < image.Width; x++) + { + Rgba32 expected = row[x]; + Argb32 actual = rowClone[x]; + + Assert.Equal(expected.R, actual.R); + Assert.Equal(expected.G, actual.G); + Assert.Equal(expected.B, actual.B); + Assert.Equal(expected.A, actual.A); + } + } + } + } + + [Theory] + [WithTestPatternImages(9, 9, PixelTypes.Rgba32)] + public void CloneAs_ToRgb24(TestImageProvider provider) + { + using (Image image = provider.GetImage()) + using (Image clone = image.CloneAs()) + { + for (int y = 0; y < image.Height; y++) + { + Span row = image.GetPixelRowSpan(y); + Span rowClone = clone.GetPixelRowSpan(y); + + for (int x = 0; x < image.Width; x++) + { + Rgba32 expected = row[x]; + Rgb24 actual = rowClone[x]; + + Assert.Equal(expected.R, actual.R); + Assert.Equal(expected.G, actual.G); + Assert.Equal(expected.B, actual.B); } } } From 0cde2c102694aab6ab17d830342c00765606f0e9 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 29 Mar 2018 13:53:23 +1100 Subject: [PATCH 3/6] Cleanup --- src/ImageSharp/PixelFormats/Alpha8.cs | 2 +- src/ImageSharp/PixelFormats/Argb32.cs | 2 +- src/ImageSharp/PixelFormats/Bgr24.cs | 4 +++- src/ImageSharp/PixelFormats/Bgr565.cs | 2 +- src/ImageSharp/PixelFormats/Bgra32.cs | 3 +++ src/ImageSharp/PixelFormats/Bgra4444.cs | 2 +- src/ImageSharp/PixelFormats/Bgra5551.cs | 2 +- src/ImageSharp/PixelFormats/Byte4.cs | 2 +- src/ImageSharp/PixelFormats/HalfSingle.cs | 3 +-- src/ImageSharp/PixelFormats/HalfTypeHelper.cs | 4 ++-- src/ImageSharp/PixelFormats/HalfVector2.cs | 2 +- src/ImageSharp/PixelFormats/HalfVector4.cs | 2 +- src/ImageSharp/PixelFormats/NormalizedByte2.cs | 2 +- src/ImageSharp/PixelFormats/NormalizedByte4.cs | 2 +- src/ImageSharp/PixelFormats/NormalizedShort2.cs | 2 +- src/ImageSharp/PixelFormats/NormalizedShort4.cs | 2 +- src/ImageSharp/PixelFormats/Rg32.cs | 2 +- src/ImageSharp/PixelFormats/Rgb24.cs | 3 +++ src/ImageSharp/PixelFormats/Rgba1010102.cs | 2 +- src/ImageSharp/PixelFormats/Rgba32.cs | 2 +- src/ImageSharp/PixelFormats/Rgba64.cs | 2 +- src/ImageSharp/PixelFormats/RgbaVector.cs | 2 +- src/ImageSharp/PixelFormats/Short2.cs | 2 +- src/ImageSharp/PixelFormats/Short4.cs | 2 +- 24 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/ImageSharp/PixelFormats/Alpha8.cs b/src/ImageSharp/PixelFormats/Alpha8.cs index 71480650d..922926e38 100644 --- a/src/ImageSharp/PixelFormats/Alpha8.cs +++ b/src/ImageSharp/PixelFormats/Alpha8.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing a single 8 bit normalized W values. /// - /// Ranges from <0, 0, 0, 0> to <0, 0, 0, 1> in vector form. + /// Ranges from [0, 0, 0, 0] to [0, 0, 0, 1] in vector form. /// /// public struct Alpha8 : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/Argb32.cs b/src/ImageSharp/PixelFormats/Argb32.cs index 3b25efb9f..b70023192 100644 --- a/src/ImageSharp/PixelFormats/Argb32.cs +++ b/src/ImageSharp/PixelFormats/Argb32.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255. /// The color components are stored in alpha, red, green, and blue order. /// - /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form. /// /// /// diff --git a/src/ImageSharp/PixelFormats/Bgr24.cs b/src/ImageSharp/PixelFormats/Bgr24.cs index 423e28140..e8fc24b31 100644 --- a/src/ImageSharp/PixelFormats/Bgr24.cs +++ b/src/ImageSharp/PixelFormats/Bgr24.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -11,6 +10,9 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Pixel type containing three 8-bit unsigned normalized values ranging from 0 to 255. /// The color components are stored in blue, green, red order. + /// + /// Ranges from [0, 0, 0, 1] to [1, 1, 1, 1] in vector form. + /// /// [StructLayout(LayoutKind.Sequential)] public struct Bgr24 : IPixel diff --git a/src/ImageSharp/PixelFormats/Bgr565.cs b/src/ImageSharp/PixelFormats/Bgr565.cs index b8a17bb9e..54e29e21e 100644 --- a/src/ImageSharp/PixelFormats/Bgr565.cs +++ b/src/ImageSharp/PixelFormats/Bgr565.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing unsigned normalized values ranging from 0 to 1. The x and z components use 5 bits, and the y component uses 6 bits. /// - /// Ranges from <0, 0, 0, 1> to <1, 1, 1, 1> in vector form. + /// Ranges from [0, 0, 0, 1] to [1, 1, 1, 1] in vector form. /// /// public struct Bgr565 : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/Bgra32.cs b/src/ImageSharp/PixelFormats/Bgra32.cs index 8a8dcd84c..2b9a447bd 100644 --- a/src/ImageSharp/PixelFormats/Bgra32.cs +++ b/src/ImageSharp/PixelFormats/Bgra32.cs @@ -11,6 +11,9 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255. /// The color components are stored in blue, green, red, and alpha order. + /// + /// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form. + /// /// [StructLayout(LayoutKind.Sequential)] public struct Bgra32 : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/Bgra4444.cs b/src/ImageSharp/PixelFormats/Bgra4444.cs index 718f164c3..f339881d0 100644 --- a/src/ImageSharp/PixelFormats/Bgra4444.cs +++ b/src/ImageSharp/PixelFormats/Bgra4444.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing unsigned normalized values, ranging from 0 to 1, using 4 bits each for x, y, z, and w. /// - /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form. /// /// public struct Bgra4444 : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/Bgra5551.cs b/src/ImageSharp/PixelFormats/Bgra5551.cs index 295ac06bc..ea1d7446d 100644 --- a/src/ImageSharp/PixelFormats/Bgra5551.cs +++ b/src/ImageSharp/PixelFormats/Bgra5551.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing unsigned normalized values ranging from 0 to 1. The x , y and z components use 5 bits, and the w component uses 1 bit. /// - /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form. /// /// public struct Bgra5551 : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/Byte4.cs b/src/ImageSharp/PixelFormats/Byte4.cs index bb7bfbd4e..d7aae5df9 100644 --- a/src/ImageSharp/PixelFormats/Byte4.cs +++ b/src/ImageSharp/PixelFormats/Byte4.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing four 8-bit unsigned integer values, ranging from 0 to 255. /// - /// Ranges from <0, 0, 0, 0> to <255, 255, 255, 255> in vector form. + /// Ranges from [0, 0, 0, 0] to [255, 255, 255, 255] in vector form. /// /// public struct Byte4 : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/HalfSingle.cs b/src/ImageSharp/PixelFormats/HalfSingle.cs index d32e43324..0569b796d 100644 --- a/src/ImageSharp/PixelFormats/HalfSingle.cs +++ b/src/ImageSharp/PixelFormats/HalfSingle.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using System.Numerics; using System.Runtime.CompilerServices; @@ -10,7 +9,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing a single 16 bit floating point value. /// - /// Ranges from <-1, 0, 0, 1> to <1, 0, 0, 1> in vector form. + /// Ranges from [-1, 0, 0, 1] to [1, 0, 0, 1] in vector form. /// /// public struct HalfSingle : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/HalfTypeHelper.cs b/src/ImageSharp/PixelFormats/HalfTypeHelper.cs index 4d6ef0fb4..cf8b9f4a2 100644 --- a/src/ImageSharp/PixelFormats/HalfTypeHelper.cs +++ b/src/ImageSharp/PixelFormats/HalfTypeHelper.cs @@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ushort Pack(float value) { - Uif uif = new Uif { F = value }; + var uif = new Uif { F = value }; return Pack(uif.I); } @@ -113,7 +113,7 @@ namespace SixLabors.ImageSharp.PixelFormats result = ((((uint)value & 0x8000) << 16) | ((((((uint)value >> 10) & 0x1f) - 15) + 127) << 23)) | (mantissa << 13); } - Uif uif = new Uif { U = result }; + var uif = new Uif { U = result }; return uif.F; } diff --git a/src/ImageSharp/PixelFormats/HalfVector2.cs b/src/ImageSharp/PixelFormats/HalfVector2.cs index 47255f0af..b26ae9598 100644 --- a/src/ImageSharp/PixelFormats/HalfVector2.cs +++ b/src/ImageSharp/PixelFormats/HalfVector2.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing two 16-bit floating-point values. /// - /// Ranges from <-1, -1, 0, 1> to <1, 1, 0, 1> in vector form. + /// Ranges from [-1, -1, 0, 1] to [1, 1, 0, 1] in vector form. /// /// public struct HalfVector2 : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/HalfVector4.cs b/src/ImageSharp/PixelFormats/HalfVector4.cs index 9e102be18..f19d1ec95 100644 --- a/src/ImageSharp/PixelFormats/HalfVector4.cs +++ b/src/ImageSharp/PixelFormats/HalfVector4.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing four 16-bit floating-point values. /// - /// Ranges from <-1, -1, -1, -1> to <1, 1, 1, 1> in vector form. + /// Ranges from [-1, -1, -1, -1] to [1, 1, 1, 1] in vector form. /// /// public struct HalfVector4 : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/NormalizedByte2.cs b/src/ImageSharp/PixelFormats/NormalizedByte2.cs index 692635a7f..69ed25e43 100644 --- a/src/ImageSharp/PixelFormats/NormalizedByte2.cs +++ b/src/ImageSharp/PixelFormats/NormalizedByte2.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed packed pixel type containing two 8-bit signed normalized values, ranging from −1 to 1. /// - /// Ranges from <-1, -1, 0, 1> to <1, 1, 0, 1> in vector form. + /// Ranges from [-1, -1, 0, 1] to [1, 1, 0, 1] in vector form. /// /// public struct NormalizedByte2 : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/NormalizedByte4.cs b/src/ImageSharp/PixelFormats/NormalizedByte4.cs index 2df67196e..18af886df 100644 --- a/src/ImageSharp/PixelFormats/NormalizedByte4.cs +++ b/src/ImageSharp/PixelFormats/NormalizedByte4.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing four 8-bit signed normalized values, ranging from −1 to 1. /// - /// Ranges from <-1, -1, -1, -1> to <1, 1, 1, 1> in vector form. + /// Ranges from [-1, -1, -1, -1] to [1, 1, 1, 1] in vector form. /// /// public struct NormalizedByte4 : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/NormalizedShort2.cs b/src/ImageSharp/PixelFormats/NormalizedShort2.cs index 263e6d0f3..afea6aaad 100644 --- a/src/ImageSharp/PixelFormats/NormalizedShort2.cs +++ b/src/ImageSharp/PixelFormats/NormalizedShort2.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing two 16-bit signed normalized values, ranging from −1 to 1. /// - /// Ranges from <-1, -1, 0, 1> to <1, 1, 0, 1> in vector form. + /// Ranges from [-1, -1, 0, 1] to [1, 1, 0, 1] in vector form. /// /// public struct NormalizedShort2 : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/NormalizedShort4.cs b/src/ImageSharp/PixelFormats/NormalizedShort4.cs index 9a54377cf..157f7419b 100644 --- a/src/ImageSharp/PixelFormats/NormalizedShort4.cs +++ b/src/ImageSharp/PixelFormats/NormalizedShort4.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing four 16-bit signed normalized values, ranging from −1 to 1. /// - /// Ranges from <-1, -1, -1, -1> to <1, 1, 1, 1> in vector form. + /// Ranges from [-1, -1, -1, -1] to [1, 1, 1, 1] in vector form. /// /// public struct NormalizedShort4 : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/Rg32.cs b/src/ImageSharp/PixelFormats/Rg32.cs index e17d1dd0b..5ce029af3 100644 --- a/src/ImageSharp/PixelFormats/Rg32.cs +++ b/src/ImageSharp/PixelFormats/Rg32.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing two 16-bit unsigned normalized values ranging from 0 to 1. /// - /// Ranges from <0, 0, 0, 1> to <1, 1, 0, 1> in vector form. + /// Ranges from [0, 0, 0, 1] to [1, 1, 0, 1] in vector form. /// /// public struct Rg32 : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/Rgb24.cs b/src/ImageSharp/PixelFormats/Rgb24.cs index 6a93028cb..bb31d9ae9 100644 --- a/src/ImageSharp/PixelFormats/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/Rgb24.cs @@ -11,6 +11,9 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Pixel type containing three 8-bit unsigned normalized values ranging from 0 to 255. /// The color components are stored in red, green, blue order. + /// + /// Ranges from [0, 0, 0, 1] to [1, 1, 1, 1] in vector form. + /// /// [StructLayout(LayoutKind.Sequential)] public struct Rgb24 : IPixel diff --git a/src/ImageSharp/PixelFormats/Rgba1010102.cs b/src/ImageSharp/PixelFormats/Rgba1010102.cs index 627eb247f..39eed08f3 100644 --- a/src/ImageSharp/PixelFormats/Rgba1010102.cs +++ b/src/ImageSharp/PixelFormats/Rgba1010102.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Packed vector type containing unsigned normalized values ranging from 0 to 1. /// The x, y and z components use 10 bits, and the w component uses 2 bits. /// - /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form. /// /// public struct Rgba1010102 : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/Rgba32.cs b/src/ImageSharp/PixelFormats/Rgba32.cs index 1630cac35..182fd7cce 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255. /// The color components are stored in red, green, blue, and alpha order. /// - /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form. /// /// /// diff --git a/src/ImageSharp/PixelFormats/Rgba64.cs b/src/ImageSharp/PixelFormats/Rgba64.cs index 5d513458f..4a2f9ef6a 100644 --- a/src/ImageSharp/PixelFormats/Rgba64.cs +++ b/src/ImageSharp/PixelFormats/Rgba64.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing four 16-bit unsigned normalized values ranging from 0 to 1. /// - /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form. /// /// public struct Rgba64 : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/RgbaVector.cs b/src/ImageSharp/PixelFormats/RgbaVector.cs index d4137a2d0..0234a4826 100644 --- a/src/ImageSharp/PixelFormats/RgbaVector.cs +++ b/src/ImageSharp/PixelFormats/RgbaVector.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Unpacked pixel type containing four 16-bit floating-point values typically ranging from 0 to 1. /// The color components are stored in red, green, blue, and alpha order. /// - /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form. /// /// /// diff --git a/src/ImageSharp/PixelFormats/Short2.cs b/src/ImageSharp/PixelFormats/Short2.cs index 77eee03a2..16151256d 100644 --- a/src/ImageSharp/PixelFormats/Short2.cs +++ b/src/ImageSharp/PixelFormats/Short2.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing two 16-bit signed integer values. /// - /// Ranges from <-32767, -32767, 0, 1> to <32767, 32767, 0, 1> in vector form. + /// Ranges from [-32767, -32767, 0, 1] to [32767, 32767, 0, 1] in vector form. /// /// public struct Short2 : IPixel, IPackedVector diff --git a/src/ImageSharp/PixelFormats/Short4.cs b/src/ImageSharp/PixelFormats/Short4.cs index 4a1676f09..6eab37617 100644 --- a/src/ImageSharp/PixelFormats/Short4.cs +++ b/src/ImageSharp/PixelFormats/Short4.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Packed pixel type containing four 16-bit signed integer values. /// - /// Ranges from <-37267, -37267, -37267, -37267> to <37267, 37267, 37267, 37267> in vector form. + /// Ranges from [-37267, -37267, -37267, -37267] to [37267, 37267, 37267, 37267] in vector form. /// /// public struct Short4 : IPixel, IPackedVector From 6fea9050fdf6eecfc4b33d84ddfaa04bb4864d54 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 29 Mar 2018 13:56:37 +1100 Subject: [PATCH 4/6] Formatting --- src/ImageSharp/PixelFormats/Argb32.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/PixelFormats/Argb32.cs b/src/ImageSharp/PixelFormats/Argb32.cs index b70023192..7030006f6 100644 --- a/src/ImageSharp/PixelFormats/Argb32.cs +++ b/src/ImageSharp/PixelFormats/Argb32.cs @@ -237,7 +237,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// public PixelOperations CreatePixelOperations() => new PixelOperations(); - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromScaledVector4(Vector4 vector) { From 1b9676aac4a2ddd14cf2b78a862db0bc2383a2bf Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 1 Apr 2018 12:17:39 +1000 Subject: [PATCH 5/6] Add bulk scaled pixel operations methods --- .../PixelFormats/PixelOperations{TPixel}.cs | 42 ++++++++++ .../PixelFormats/PixelOperationsTests.cs | 84 ++++++++++++++++--- 2 files changed, 116 insertions(+), 10 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 6d25fe9f4..b12a2bfa5 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -63,6 +63,48 @@ namespace SixLabors.ImageSharp.PixelFormats } } + /// + /// Bulk version of + /// + /// The to the source vectors. + /// The to the destination colors. + /// The number of pixels to convert. + internal virtual void PackFromScaledVector4(ReadOnlySpan sourceVectors, Span destinationColors, int count) + { + GuardSpans(sourceVectors, nameof(sourceVectors), destinationColors, nameof(destinationColors), count); + + ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors); + ref TPixel destRef = ref MemoryMarshal.GetReference(destinationColors); + + for (int i = 0; i < count; i++) + { + ref Vector4 sp = ref Unsafe.Add(ref sourceRef, i); + ref TPixel dp = ref Unsafe.Add(ref destRef, i); + dp.PackFromScaledVector4(sp); + } + } + + /// + /// Bulk version of . + /// + /// The to the source colors. + /// The to the destination vectors. + /// The number of pixels to convert. + internal virtual void ToScaledVector4(ReadOnlySpan sourceColors, Span destinationVectors, int count) + { + GuardSpans(sourceColors, nameof(sourceColors), destinationVectors, nameof(destinationVectors), count); + + ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourceColors); + ref Vector4 destRef = ref MemoryMarshal.GetReference(destinationVectors); + + for (int i = 0; i < count; i++) + { + ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); + ref Vector4 dp = ref Unsafe.Add(ref destRef, i); + dp = sp.ToScaledVector4(); + } + } + /// /// Verifies that the given 'source' and 'destination' spans are at least of 'minLength' size. /// Throwing an if the condition is not met. diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs index 7a942246e..56f495b77 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs @@ -97,7 +97,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats internal static TPixel[] CreateExpectedPixelData(Vector4[] source) { - TPixel[] expected = new TPixel[source.Length]; + var expected = new TPixel[source.Length]; for (int i = 0; i < expected.Length; i++) { @@ -106,6 +106,17 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats return expected; } + internal static TPixel[] CreateScaledExpectedPixelData(Vector4[] source) + { + var expected = new TPixel[source.Length]; + + for (int i = 0; i < expected.Length; i++) + { + expected[i].PackFromScaledVector4(source[i]); + } + return expected; + } + [Theory] [MemberData(nameof(ArraySizesData))] public void PackFromVector4(int count) @@ -120,9 +131,23 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats ); } + [Theory] + [MemberData(nameof(ArraySizesData))] + public void PackFromScaledVector4(int count) + { + Vector4[] source = CreateVector4TestData(count); + TPixel[] expected = CreateScaledExpectedPixelData(source); + + TestOperation( + source, + expected, + (s, d) => Operations.PackFromScaledVector4(s, d.Span, count) + ); + } + internal static Vector4[] CreateExpectedVector4Data(TPixel[] source) { - Vector4[] expected = new Vector4[source.Length]; + var expected = new Vector4[source.Length]; for (int i = 0; i < expected.Length; i++) { @@ -131,6 +156,17 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats return expected; } + internal static Vector4[] CreateExpectedScaledVector4Data(TPixel[] source) + { + var expected = new Vector4[source.Length]; + + for (int i = 0; i < expected.Length; i++) + { + expected[i] = source[i].ToScaledVector4(); + } + return expected; + } + [Theory] [MemberData(nameof(ArraySizesData))] public void ToVector4(int count) @@ -145,13 +181,26 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats ); } + [Theory] + [MemberData(nameof(ArraySizesData))] + public void ToScaledVector4(int count) + { + TPixel[] source = CreateScaledPixelTestData(count); + Vector4[] expected = CreateExpectedScaledVector4Data(source); + + TestOperation( + source, + expected, + (s, d) => Operations.ToScaledVector4(s, d.Span, count) + ); + } [Theory] [MemberData(nameof(ArraySizesData))] public void PackFromXyzBytes(int count) { byte[] source = CreateByteTestData(count * 3); - TPixel[] expected = new TPixel[count]; + var expected = new TPixel[count]; for (int i = 0; i < count; i++) { @@ -196,7 +245,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats public void PackFromXyzwBytes(int count) { byte[] source = CreateByteTestData(count * 4); - TPixel[] expected = new TPixel[count]; + var expected = new TPixel[count]; for (int i = 0; i < count; i++) { @@ -242,7 +291,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats public void PackFromZyxBytes(int count) { byte[] source = CreateByteTestData(count * 3); - TPixel[] expected = new TPixel[count]; + var expected = new TPixel[count]; for (int i = 0; i < count; i++) { @@ -287,7 +336,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats public void PackFromZyxwBytes(int count) { byte[] source = CreateByteTestData(count * 4); - TPixel[] expected = new TPixel[count]; + var expected = new TPixel[count]; for (int i = 0; i < count; i++) { @@ -336,7 +385,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats public TSource[] SourceBuffer { get; } public IBuffer ActualDestBuffer { get; } public TDest[] ExpectedDestBuffer { get; } - + public TestBuffers(TSource[] source, TDest[] expectedDest) { this.SourceBuffer = source; @@ -357,7 +406,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats if (typeof(TDest) == typeof(Vector4)) { - + Span expected = this.ExpectedDestBuffer.AsSpan().NonPortableCast(); Span actual = this.ActualDestBuffer.Span.NonPortableCast(); @@ -396,7 +445,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats internal static Vector4[] CreateVector4TestData(int length) { - Vector4[] result = new Vector4[length]; + var result = new Vector4[length]; var rnd = new Random(42); // Deterministic random values for (int i = 0; i < result.Length; i++) @@ -408,7 +457,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats internal static TPixel[] CreatePixelTestData(int length) { - TPixel[] result = new TPixel[length]; + var result = new TPixel[length]; var rnd = new Random(42); // Deterministic random values @@ -421,6 +470,21 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats return result; } + internal static TPixel[] CreateScaledPixelTestData(int length) + { + var result = new TPixel[length]; + + var rnd = new Random(42); // Deterministic random values + + for (int i = 0; i < result.Length; i++) + { + Vector4 v = GetVector(rnd); + result[i].PackFromScaledVector4(v); + } + + return result; + } + internal static byte[] CreateByteTestData(int length) { byte[] result = new byte[length]; From 525153834a3f8b6b2d2582bb18330c72ed20d5fa Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 4 Apr 2018 18:11:17 +1000 Subject: [PATCH 6/6] Use PixelOperations --- src/ImageSharp/ImageFrame{TPixel}.cs | 18 +++++++++--------- .../PixelFormats/Rgba32.PixelOperations.cs | 13 +++++++++++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs index 1d9622aa4..cf7a1ae4f 100644 --- a/src/ImageSharp/ImageFrame{TPixel}.cs +++ b/src/ImageSharp/ImageFrame{TPixel}.cs @@ -248,20 +248,20 @@ namespace SixLabors.ImageSharp var target = new ImageFrame(this.MemoryManager, this.Width, this.Height, this.MetaData.Clone()); - Parallel.For( + // TODO: ImageFrame has no visibility of the current configuration. It should have. + ParallelFor.WithTemporaryBuffer( 0, - target.Height, - Configuration.Default.ParallelOptions, - y => + this.Height, + Configuration.Default, + this.Width, + (int y, IBuffer tempRowBuffer) => { Span sourceRow = this.GetPixelRowSpan(y); Span targetRow = target.GetPixelRowSpan(y); + Span tempRowSpan = tempRowBuffer.Span; - for (int x = 0; x < target.Width; x++) - { - ref var pixel = ref targetRow[x]; - pixel.PackFromScaledVector4(sourceRow[x].ToScaledVector4()); - } + PixelOperations.Instance.ToScaledVector4(sourceRow, tempRowSpan, sourceRow.Length); + PixelOperations.Instance.PackFromScaledVector4(tempRowSpan, targetRow, targetRow.Length); }); return target; diff --git a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs index 7d5d63241..beb0bd3ab 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs @@ -115,6 +115,7 @@ namespace SixLabors.ImageSharp.PixelFormats } } + /// internal override void PackFromVector4(ReadOnlySpan sourceVectors, Span destColors, int count) { GuardSpans(sourceVectors, nameof(sourceVectors), destColors, nameof(destColors), count); @@ -144,6 +145,18 @@ namespace SixLabors.ImageSharp.PixelFormats } } + /// + internal override void ToScaledVector4(ReadOnlySpan sourceColors, Span destinationVectors, int count) + { + this.ToVector4(sourceColors, destinationVectors, count); + } + + /// + internal override void PackFromScaledVector4(ReadOnlySpan sourceVectors, Span destinationColors, int count) + { + this.PackFromVector4(sourceVectors, destinationColors, count); + } + /// internal override void PackFromRgba32(ReadOnlySpan source, Span destPixels, int count) {