diff --git a/ImageSharp.ruleset b/ImageSharp.ruleset new file mode 100644 index 0000000000..554dc16dd8 --- /dev/null +++ b/ImageSharp.ruleset @@ -0,0 +1,6 @@ + + + + + + diff --git a/ImageSharp.sln b/ImageSharp.sln index b168c63403..cd9e39a338 100644 --- a/ImageSharp.sln +++ b/ImageSharp.sln @@ -20,8 +20,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionIt build\dotnet-latest.ps1 = build\dotnet-latest.ps1 features.md = features.md global.json = global.json + ImageSharp.ruleset = ImageSharp.ruleset + NuGet.config = NuGet.config build\package.json = build\package.json README.md = README.md + Rebracer.xml = Rebracer.xml Settings.StyleCop = Settings.StyleCop EndProjectSection EndProject diff --git a/README.md b/README.md index bd122839d7..24145f7f91 100644 --- a/README.md +++ b/README.md @@ -98,3 +98,6 @@ Grand High Eternal Dictator Core Team - [Dirk Lemstra](https://github.com/dlemstra) - [Jeavon Leopold](https://github.com/jeavon) +- [Anton Firsov](https://github.com/antonfirsov) +- [Olivia Ifrim](https://github.com/olivif) +- [Scott Williams](https://github.com/tocsoft) diff --git a/src/ImageSharp/Colors/Color.cs b/src/ImageSharp/Colors/Color.cs index 109544ada3..036ee14c15 100644 --- a/src/ImageSharp/Colors/Color.cs +++ b/src/ImageSharp/Colors/Color.cs @@ -273,35 +273,37 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = this.B; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.R; - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = this.B; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.R; - bytes[startIndex + 3] = this.A; - break; - case ComponentOrder.XYZ: - bytes[startIndex] = this.R; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.B; - break; - case ComponentOrder.XYZW: - bytes[startIndex] = this.R; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.B; - bytes[startIndex + 3] = this.A; - break; - default: - throw new NotSupportedException(); - } + bytes[startIndex] = this.R; + bytes[startIndex + 1] = this.G; + bytes[startIndex + 2] = this.B; + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + bytes[startIndex] = this.R; + bytes[startIndex + 1] = this.G; + bytes[startIndex + 2] = this.B; + bytes[startIndex + 3] = this.A; + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + bytes[startIndex] = this.B; + bytes[startIndex + 1] = this.G; + bytes[startIndex + 2] = this.R; + } + + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + bytes[startIndex] = this.B; + bytes[startIndex + 1] = this.G; + bytes[startIndex + 2] = this.R; + bytes[startIndex + 3] = this.A; } /// diff --git a/src/ImageSharp/Colors/ColorspaceTransforms.cs b/src/ImageSharp/Colors/ColorspaceTransforms.cs index 0c70dd98b1..cda7022705 100644 --- a/src/ImageSharp/Colors/ColorspaceTransforms.cs +++ b/src/ImageSharp/Colors/ColorspaceTransforms.cs @@ -7,6 +7,7 @@ namespace ImageSharp { using System; using System.Numerics; + using Colors.Spaces; /// /// Packed vector type containing four 8-bit unsigned normalized values ranging from 0 to 255. @@ -18,11 +19,6 @@ namespace ImageSharp /// public partial struct Color { - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 0.001F; - /// /// Allows the implicit conversion of an instance of to a /// . @@ -62,9 +58,9 @@ namespace ImageSharp /// public static implicit operator Color(YCbCr color) { - byte y = color.Y; - int cb = color.Cb - 128; - int cr = color.Cr - 128; + float y = color.Y; + float cb = color.Cb - 128; + float cr = color.Cr - 128; byte r = (byte)(y + (1.402F * cr)).Clamp(0, 255); byte g = (byte)(y - (0.34414F * cb) - (0.71414F * cr)).Clamp(0, 255); @@ -109,12 +105,12 @@ namespace ImageSharp float s = color.S; float v = color.V; - if (Math.Abs(s) < Epsilon) + if (Math.Abs(s) < Constants.Epsilon) { return new Color(v, v, v, 1); } - float h = (Math.Abs(color.H - 360) < Epsilon) ? 0 : color.H / 60; + float h = (Math.Abs(color.H - 360) < Constants.Epsilon) ? 0 : color.H / 60; int i = (int)Math.Truncate(h); float f = h - i; @@ -182,9 +178,9 @@ namespace ImageSharp float s = color.S; float l = color.L; - if (Math.Abs(l) > Epsilon) + if (Math.Abs(l) > Constants.Epsilon) { - if (Math.Abs(s) < Epsilon) + if (Math.Abs(s) < Constants.Epsilon) { r = g = b = l; } diff --git a/src/ImageSharp/Colors/ComponentOrder.cs b/src/ImageSharp/Colors/ComponentOrder.cs index 7372ab9bfa..03fa3bbf81 100644 --- a/src/ImageSharp/Colors/ComponentOrder.cs +++ b/src/ImageSharp/Colors/ComponentOrder.cs @@ -13,21 +13,21 @@ namespace ImageSharp /// /// Z-> Y-> X order. Equivalent to B-> G-> R in /// - ZYX, + Zyx, /// /// Z-> Y-> X-> W order. Equivalent to B-> G-> R-> A in /// - ZYXW, + Zyxw, /// /// X-> Y-> Z order. Equivalent to R-> G-> B in /// - XYZ, + Xyz, /// /// X-> Y-> Z-> W order. Equivalent to R-> G-> B-> A in /// - XYZW, + Xyzw, } } diff --git a/src/ImageSharp/Colors/PackedPixel/Alpha8.cs b/src/ImageSharp/Colors/PackedPixel/Alpha8.cs index 0100afee13..361fe5b9e2 100644 --- a/src/ImageSharp/Colors/PackedPixel/Alpha8.cs +++ b/src/ImageSharp/Colors/PackedPixel/Alpha8.cs @@ -74,35 +74,37 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = 0; - bytes[startIndex + 1] = 0; - bytes[startIndex + 2] = 0; - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = 0; - bytes[startIndex + 1] = 0; - bytes[startIndex + 2] = 0; - bytes[startIndex + 3] = this.PackedValue; - break; - case ComponentOrder.XYZ: - bytes[startIndex] = 0; - bytes[startIndex + 1] = 0; - bytes[startIndex + 2] = 0; - break; - case ComponentOrder.XYZW: - bytes[startIndex] = 0; - bytes[startIndex + 1] = 0; - bytes[startIndex + 2] = 0; - bytes[startIndex + 3] = this.PackedValue; - break; - default: - throw new NotSupportedException(); - } + bytes[startIndex] = 0; + bytes[startIndex + 1] = 0; + bytes[startIndex + 2] = 0; + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + bytes[startIndex] = 0; + bytes[startIndex + 1] = 0; + bytes[startIndex + 2] = 0; + bytes[startIndex + 3] = this.PackedValue; + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + bytes[startIndex] = 0; + bytes[startIndex + 1] = 0; + bytes[startIndex + 2] = 0; + } + + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + bytes[startIndex] = 0; + bytes[startIndex + 1] = 0; + bytes[startIndex + 2] = 0; + bytes[startIndex + 3] = this.PackedValue; } /// diff --git a/src/ImageSharp/Colors/PackedPixel/Argb.cs b/src/ImageSharp/Colors/PackedPixel/Argb.cs index 996b8f1012..8ab8e3f43f 100644 --- a/src/ImageSharp/Colors/PackedPixel/Argb.cs +++ b/src/ImageSharp/Colors/PackedPixel/Argb.cs @@ -220,36 +220,38 @@ namespace ImageSharp this.PackedValue = Pack(x, y, z, w); } - /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + /// + public void ToXyzBytes(byte[] bytes, int startIndex) { - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = this.B; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.R; - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = this.B; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.R; - bytes[startIndex + 3] = this.A; - break; - case ComponentOrder.XYZ: - bytes[startIndex] = this.R; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.B; - break; - case ComponentOrder.XYZW: - bytes[startIndex] = this.R; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.B; - bytes[startIndex + 3] = this.A; - break; - default: - throw new NotSupportedException(); - } + bytes[startIndex] = this.R; + bytes[startIndex + 1] = this.G; + bytes[startIndex + 2] = this.B; + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + bytes[startIndex] = this.R; + bytes[startIndex + 1] = this.G; + bytes[startIndex + 2] = this.B; + bytes[startIndex + 3] = this.A; + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + bytes[startIndex] = this.B; + bytes[startIndex + 1] = this.G; + bytes[startIndex + 2] = this.R; + } + + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + bytes[startIndex] = this.B; + bytes[startIndex + 1] = this.G; + bytes[startIndex + 2] = this.R; + bytes[startIndex + 3] = this.A; } /// diff --git a/src/ImageSharp/Colors/PackedPixel/Bgr565.cs b/src/ImageSharp/Colors/PackedPixel/Bgr565.cs index e28c7aed02..1f1ce0a17e 100644 --- a/src/ImageSharp/Colors/PackedPixel/Bgr565.cs +++ b/src/ImageSharp/Colors/PackedPixel/Bgr565.cs @@ -96,37 +96,41 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { Vector4 vector = this.ToVector4() * 255F; + bytes[startIndex] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + bytes[startIndex] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); + bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + bytes[startIndex] = (byte)(float)Math.Round(vector.Z); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); + } - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = (byte)(float)Math.Round(vector.Z); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = (byte)(float)Math.Round(vector.Z); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); - break; - case ComponentOrder.XYZ: - bytes[startIndex] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); - break; - case ComponentOrder.XYZW: - bytes[startIndex] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); - bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); - break; - default: - throw new NotSupportedException(); - } + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + bytes[startIndex] = (byte)(float)Math.Round(vector.Z); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); } /// diff --git a/src/ImageSharp/Colors/PackedPixel/Bgra4444.cs b/src/ImageSharp/Colors/PackedPixel/Bgra4444.cs index ed07a69c0d..1f33cb7912 100644 --- a/src/ImageSharp/Colors/PackedPixel/Bgra4444.cs +++ b/src/ImageSharp/Colors/PackedPixel/Bgra4444.cs @@ -88,37 +88,41 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { Vector4 vector = this.ToVector4() * 255F; + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.Z; + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.Z; + bytes[startIndex + 3] = (byte)vector.W; + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + bytes[startIndex] = (byte)vector.Z; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + } - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; - break; - case ComponentOrder.XYZ: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - break; - case ComponentOrder.XYZW: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; - break; - default: - throw new NotSupportedException(); - } + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + bytes[startIndex] = (byte)vector.Z; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + bytes[startIndex + 3] = (byte)vector.W; } /// diff --git a/src/ImageSharp/Colors/PackedPixel/Bgra5551.cs b/src/ImageSharp/Colors/PackedPixel/Bgra5551.cs index 97153af9d6..d0c52068dc 100644 --- a/src/ImageSharp/Colors/PackedPixel/Bgra5551.cs +++ b/src/ImageSharp/Colors/PackedPixel/Bgra5551.cs @@ -88,37 +88,41 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { Vector4 vector = this.ToVector4() * 255F; + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.Z; + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.Z; + bytes[startIndex + 3] = (byte)vector.W; + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + bytes[startIndex] = (byte)vector.Z; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + } - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; - break; - case ComponentOrder.XYZ: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - break; - case ComponentOrder.XYZW: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; - break; - default: - throw new NotSupportedException(); - } + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + bytes[startIndex] = (byte)vector.Z; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + bytes[startIndex + 3] = (byte)vector.W; } /// diff --git a/src/ImageSharp/Colors/PackedPixel/Byte4.cs b/src/ImageSharp/Colors/PackedPixel/Byte4.cs index 31efd6094f..69c69ecaf4 100644 --- a/src/ImageSharp/Colors/PackedPixel/Byte4.cs +++ b/src/ImageSharp/Colors/PackedPixel/Byte4.cs @@ -95,37 +95,41 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { Vector4 vector = this.ToVector4(); + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.Z; + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.Z; + bytes[startIndex + 3] = (byte)vector.W; + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + bytes[startIndex] = (byte)vector.Z; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + } - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; - break; - case ComponentOrder.XYZ: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - break; - case ComponentOrder.XYZW: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; - break; - default: - throw new NotSupportedException(); - } + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + bytes[startIndex] = (byte)vector.Z; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + bytes[startIndex + 3] = (byte)vector.W; } /// diff --git a/src/ImageSharp/Colors/PackedPixel/HalfSingle.cs b/src/ImageSharp/Colors/PackedPixel/HalfSingle.cs index b2919b46a0..22e32aa569 100644 --- a/src/ImageSharp/Colors/PackedPixel/HalfSingle.cs +++ b/src/ImageSharp/Colors/PackedPixel/HalfSingle.cs @@ -97,40 +97,57 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { Vector4 vector = this.ToVector4(); vector *= MaxBytes; vector += Half; vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; - break; - case ComponentOrder.XYZ: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - break; - case ComponentOrder.XYZW: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; - break; - default: - throw new NotSupportedException(); - } + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.Z; + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= MaxBytes; + vector += Half; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.Z; + bytes[startIndex + 3] = (byte)vector.W; + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= MaxBytes; + vector += Half; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)vector.Z; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + } + + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= MaxBytes; + vector += Half; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)vector.Z; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + bytes[startIndex + 3] = (byte)vector.W; } /// diff --git a/src/ImageSharp/Colors/PackedPixel/HalfVector2.cs b/src/ImageSharp/Colors/PackedPixel/HalfVector2.cs index c41e01b2ac..7c17dcea8f 100644 --- a/src/ImageSharp/Colors/PackedPixel/HalfVector2.cs +++ b/src/ImageSharp/Colors/PackedPixel/HalfVector2.cs @@ -111,40 +111,57 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { Vector4 vector = this.ToVector4(); vector *= MaxBytes; vector += Half; vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; - break; - case ComponentOrder.XYZ: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - break; - case ComponentOrder.XYZW: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; - break; - default: - throw new NotSupportedException(); - } + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.Z; + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= MaxBytes; + vector += Half; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.Z; + bytes[startIndex + 3] = (byte)vector.W; + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= MaxBytes; + vector += Half; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)vector.Z; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + } + + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= MaxBytes; + vector += Half; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)vector.Z; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + bytes[startIndex + 3] = (byte)vector.W; } /// diff --git a/src/ImageSharp/Colors/PackedPixel/HalfVector4.cs b/src/ImageSharp/Colors/PackedPixel/HalfVector4.cs index 635155f0c0..a7f10fc71d 100644 --- a/src/ImageSharp/Colors/PackedPixel/HalfVector4.cs +++ b/src/ImageSharp/Colors/PackedPixel/HalfVector4.cs @@ -105,40 +105,57 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { Vector4 vector = this.ToVector4(); vector *= MaxBytes; vector += Half; vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; - break; - case ComponentOrder.XYZ: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - break; - case ComponentOrder.XYZW: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; - break; - default: - throw new NotSupportedException(); - } + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.Z; + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= MaxBytes; + vector += Half; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.Z; + bytes[startIndex + 3] = (byte)vector.W; + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= MaxBytes; + vector += Half; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)vector.Z; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + } + + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= MaxBytes; + vector += Half; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)vector.Z; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + bytes[startIndex + 3] = (byte)vector.W; } /// diff --git a/src/ImageSharp/Colors/PackedPixel/IPackedBytes.cs b/src/ImageSharp/Colors/PackedPixel/IPackedBytes.cs index 5793ea1ba7..3343a92c73 100644 --- a/src/ImageSharp/Colors/PackedPixel/IPackedBytes.cs +++ b/src/ImageSharp/Colors/PackedPixel/IPackedBytes.cs @@ -12,7 +12,7 @@ namespace ImageSharp public interface IPackedBytes { /// - /// Gets the packed representation from the gives bytes. + /// Sets the packed representation from the given byte array. /// /// The x-component. /// The y-component. @@ -21,11 +21,35 @@ namespace ImageSharp void PackFromBytes(byte x, byte y, byte z, byte w); /// - /// Sets the packed representation into the gives bytes. + /// Expands the packed representation into a given byte array. + /// Output is expanded to X-> Y-> Z order. Equivalent to R-> G-> B in /// /// The bytes to set the color in. /// The starting index of the . - /// The order of the components. - void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder); + void ToXyzBytes(byte[] bytes, int startIndex); + + /// + /// Expands the packed representation into a given byte array. + /// Output is expanded to X-> Y-> Z-> W order. Equivalent to R-> G-> B-> A in + /// + /// The bytes to set the color in. + /// The starting index of the . + void ToXyzwBytes(byte[] bytes, int startIndex); + + /// + /// Expands the packed representation into a given byte array. + /// Output is expanded to Z-> Y-> X order. Equivalent to B-> G-> R in + /// + /// The bytes to set the color in. + /// The starting index of the . + void ToZyxBytes(byte[] bytes, int startIndex); + + /// + /// Expands the packed representation into a given byte array. + /// Output is expanded to Z-> Y-> X-> W order. Equivalent to B-> G-> R-> A in + /// + /// The bytes to set the color in. + /// The starting index of the . + void ToZyxwBytes(byte[] bytes, int startIndex); } } diff --git a/src/ImageSharp/Colors/PackedPixel/NormalizedByte2.cs b/src/ImageSharp/Colors/PackedPixel/NormalizedByte2.cs index 3ff419ab66..f1dae10667 100644 --- a/src/ImageSharp/Colors/PackedPixel/NormalizedByte2.cs +++ b/src/ImageSharp/Colors/PackedPixel/NormalizedByte2.cs @@ -120,7 +120,7 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { Vector4 vector = this.ToVector4(); vector *= Half; @@ -129,33 +129,56 @@ namespace ImageSharp vector += Round; vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = 0; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = 0; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = 255; - break; - case ComponentOrder.XYZ: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = 0; - break; - case ComponentOrder.XYZW: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = 0; - bytes[startIndex + 3] = 255; - break; - default: - throw new NotSupportedException(); - } + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = 0; + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= Half; + vector += Round; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = 0; + bytes[startIndex + 3] = 255; + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= Half; + vector += Round; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = 0; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + } + + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= Half; + vector += Round; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = 0; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + bytes[startIndex + 3] = 255; } /// diff --git a/src/ImageSharp/Colors/PackedPixel/NormalizedByte4.cs b/src/ImageSharp/Colors/PackedPixel/NormalizedByte4.cs index 2638ff7f50..22eba51827 100644 --- a/src/ImageSharp/Colors/PackedPixel/NormalizedByte4.cs +++ b/src/ImageSharp/Colors/PackedPixel/NormalizedByte4.cs @@ -114,7 +114,7 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { Vector4 vector = this.ToVector4(); vector *= Half; @@ -123,33 +123,56 @@ namespace ImageSharp vector += Round; vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; - break; - case ComponentOrder.XYZ: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - break; - case ComponentOrder.XYZW: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; - break; - default: - throw new NotSupportedException(); - } + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.Z; + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= Half; + vector += Round; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.Z; + bytes[startIndex + 3] = (byte)vector.W; + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= Half; + vector += Round; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)vector.Z; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + } + + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= Half; + vector += Round; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)vector.Z; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + bytes[startIndex + 3] = (byte)vector.W; } /// diff --git a/src/ImageSharp/Colors/PackedPixel/NormalizedShort2.cs b/src/ImageSharp/Colors/PackedPixel/NormalizedShort2.cs index 0d63f1b4dc..34b2fc320c 100644 --- a/src/ImageSharp/Colors/PackedPixel/NormalizedShort2.cs +++ b/src/ImageSharp/Colors/PackedPixel/NormalizedShort2.cs @@ -108,7 +108,7 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { Vector4 vector = this.ToVector4(); vector *= Half; @@ -117,33 +117,56 @@ namespace ImageSharp vector += Round; vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = 0; - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = 0; - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 3] = 255; - break; - case ComponentOrder.XYZ: - bytes[startIndex] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = 0; - break; - case ComponentOrder.XYZW: - bytes[startIndex] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = 0; - bytes[startIndex + 3] = 255; - break; - default: - throw new NotSupportedException(); - } + bytes[startIndex] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = 0; + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= Half; + vector += Round; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = 0; + bytes[startIndex + 3] = 255; + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= Half; + vector += Round; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = 0; + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); + } + + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= Half; + vector += Round; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = 0; + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 3] = 255; } /// diff --git a/src/ImageSharp/Colors/PackedPixel/NormalizedShort4.cs b/src/ImageSharp/Colors/PackedPixel/NormalizedShort4.cs index 0f43c54b10..9742a5f347 100644 --- a/src/ImageSharp/Colors/PackedPixel/NormalizedShort4.cs +++ b/src/ImageSharp/Colors/PackedPixel/NormalizedShort4.cs @@ -116,7 +116,7 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { Vector4 vector = this.ToVector4(); vector *= Half; @@ -125,33 +125,56 @@ namespace ImageSharp vector += Round; vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = (byte)(float)Math.Round(vector.Z); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = (byte)(float)Math.Round(vector.Z); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); - break; - case ComponentOrder.XYZ: - bytes[startIndex] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); - break; - case ComponentOrder.XYZW: - bytes[startIndex] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); - bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); - break; - default: - throw new NotSupportedException(); - } + bytes[startIndex] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= Half; + vector += Round; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); + bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= Half; + vector += Round; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)(float)Math.Round(vector.Z); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); + } + + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector *= Half; + vector += Round; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)(float)Math.Round(vector.Z); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); } /// diff --git a/src/ImageSharp/Colors/PackedPixel/Rg32.cs b/src/ImageSharp/Colors/PackedPixel/Rg32.cs index 8ca53a8293..d885a4470f 100644 --- a/src/ImageSharp/Colors/PackedPixel/Rg32.cs +++ b/src/ImageSharp/Colors/PackedPixel/Rg32.cs @@ -100,37 +100,45 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { Vector4 vector = this.ToVector4() * 255F; - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; - break; - case ComponentOrder.XYZ: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - break; - case ComponentOrder.XYZW: - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; - break; - default: - throw new NotSupportedException(); - } + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.Z; + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + + bytes[startIndex] = (byte)vector.X; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.Z; + bytes[startIndex + 3] = (byte)vector.W; + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + + bytes[startIndex] = (byte)vector.Z; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + } + + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + + bytes[startIndex] = (byte)vector.Z; + bytes[startIndex + 1] = (byte)vector.Y; + bytes[startIndex + 2] = (byte)vector.X; + bytes[startIndex + 3] = (byte)vector.W; } /// diff --git a/src/ImageSharp/Colors/PackedPixel/Rgba1010102.cs b/src/ImageSharp/Colors/PackedPixel/Rgba1010102.cs index 54ac6279f7..da7dbe1ee1 100644 --- a/src/ImageSharp/Colors/PackedPixel/Rgba1010102.cs +++ b/src/ImageSharp/Colors/PackedPixel/Rgba1010102.cs @@ -95,37 +95,45 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { Vector4 vector = this.ToVector4() * 255F; - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = (byte)(float)Math.Round(vector.Z); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = (byte)(float)Math.Round(vector.Z); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); - break; - case ComponentOrder.XYZ: - bytes[startIndex] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); - break; - case ComponentOrder.XYZW: - bytes[startIndex] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); - bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); - break; - default: - throw new NotSupportedException(); - } + bytes[startIndex] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + + bytes[startIndex] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); + bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + + bytes[startIndex] = (byte)(float)Math.Round(vector.Z); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); + } + + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + + bytes[startIndex] = (byte)(float)Math.Round(vector.Z); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); } /// diff --git a/src/ImageSharp/Colors/PackedPixel/Rgba64.cs b/src/ImageSharp/Colors/PackedPixel/Rgba64.cs index 2b99325199..64631f1e1a 100644 --- a/src/ImageSharp/Colors/PackedPixel/Rgba64.cs +++ b/src/ImageSharp/Colors/PackedPixel/Rgba64.cs @@ -94,37 +94,45 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { Vector4 vector = this.ToVector4() * 255F; - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = (byte)(float)Math.Round(vector.Z); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = (byte)(float)Math.Round(vector.Z); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); - break; - case ComponentOrder.XYZ: - bytes[startIndex] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); - break; - case ComponentOrder.XYZW: - bytes[startIndex] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); - bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); - break; - default: - throw new NotSupportedException(); - } + bytes[startIndex] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + + bytes[startIndex] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); + bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + + bytes[startIndex] = (byte)(float)Math.Round(vector.Z); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); + } + + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4() * 255F; + + bytes[startIndex] = (byte)(float)Math.Round(vector.Z); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); } /// diff --git a/src/ImageSharp/Colors/PackedPixel/Short2.cs b/src/ImageSharp/Colors/PackedPixel/Short2.cs index 310c44ec8a..d45a80fcb2 100644 --- a/src/ImageSharp/Colors/PackedPixel/Short2.cs +++ b/src/ImageSharp/Colors/PackedPixel/Short2.cs @@ -106,7 +106,7 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { Vector2 vector = this.ToVector2(); vector /= 65534; @@ -115,33 +115,56 @@ namespace ImageSharp vector += Round; vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes); - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = 0; - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = 0; - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 3] = 255; - break; - case ComponentOrder.XYZ: - bytes[startIndex] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = 0; - break; - case ComponentOrder.XYZW: - bytes[startIndex] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = 0; - bytes[startIndex + 3] = 255; - break; - default: - throw new NotSupportedException(); - } + bytes[startIndex] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = 0; + } + + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + Vector2 vector = this.ToVector2(); + vector /= 65534; + vector *= 255; + vector += Half; + vector += Round; + vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes); + + bytes[startIndex] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = 0; + bytes[startIndex + 3] = 255; + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + Vector2 vector = this.ToVector2(); + vector /= 65534; + vector *= 255; + vector += Half; + vector += Round; + vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes); + + bytes[startIndex] = 0; + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); + } + + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + Vector2 vector = this.ToVector2(); + vector /= 65534; + vector *= 255; + vector += Half; + vector += Round; + vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes); + + bytes[startIndex] = 0; + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 3] = 255; } /// diff --git a/src/ImageSharp/Colors/PackedPixel/Short4.cs b/src/ImageSharp/Colors/PackedPixel/Short4.cs index 13bce08c88..cd112a90f4 100644 --- a/src/ImageSharp/Colors/PackedPixel/Short4.cs +++ b/src/ImageSharp/Colors/PackedPixel/Short4.cs @@ -112,7 +112,7 @@ namespace ImageSharp } /// - public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + public void ToXyzBytes(byte[] bytes, int startIndex) { Vector4 vector = this.ToVector4(); vector /= 65534; @@ -121,50 +121,65 @@ namespace ImageSharp vector += Round; vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - switch (componentOrder) - { - case ComponentOrder.ZYX: - bytes[startIndex] = (byte)(float)Math.Round(vector.Z); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); - break; - case ComponentOrder.ZYXW: - bytes[startIndex] = (byte)(float)Math.Round(vector.Z); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); - break; - case ComponentOrder.XYZ: - bytes[startIndex] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); - break; - case ComponentOrder.XYZW: - bytes[startIndex] = (byte)(float)Math.Round(vector.X); - bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); - bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); - bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); - break; - default: - throw new NotSupportedException(); - } + bytes[startIndex] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); } - /// - /// Returns a value that indicates whether the current instance is equal to a specified object. - /// - /// The object with which to make the comparison. - /// true if the current instance is equal to the specified object; false otherwise. + /// + public void ToXyzwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector /= 65534; + vector *= 255; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); + bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); + } + + /// + public void ToZyxBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector /= 65534; + vector *= 255; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)(float)Math.Round(vector.Z); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); + } + + /// + public void ToZyxwBytes(byte[] bytes, int startIndex) + { + Vector4 vector = this.ToVector4(); + vector /= 65534; + vector *= 255; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + + bytes[startIndex] = (byte)(float)Math.Round(vector.Z); + bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); + bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); + bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); + } + + /// public override bool Equals(object obj) { return (obj is Short4) && this == (Short4)obj; } - /// - /// Returns a value that indicates whether the current instance is equal to a specified object. - /// - /// The object with which to make the comparison. - /// true if the current instance is equal to the specified object; false otherwise. + /// public bool Equals(Short4 other) { return this == other; diff --git a/src/ImageSharp/Colors/Colorspaces/Bgra32.cs b/src/ImageSharp/Colors/Spaces/Bgra32.cs similarity index 90% rename from src/ImageSharp/Colors/Colorspaces/Bgra32.cs rename to src/ImageSharp/Colors/Spaces/Bgra32.cs index ff9203b03a..09475f42c8 100644 --- a/src/ImageSharp/Colors/Colorspaces/Bgra32.cs +++ b/src/ImageSharp/Colors/Spaces/Bgra32.cs @@ -3,7 +3,7 @@ // Licensed under the Apache License, Version 2.0. // -namespace ImageSharp +namespace ImageSharp.Colors.Spaces { using System; using System.ComponentModel; @@ -22,7 +22,7 @@ namespace ImageSharp /// /// The backing vector for SIMD support. /// - private Vector4 backingVector; + private readonly Vector4 backingVector; /// /// Initializes a new instance of the struct. @@ -133,7 +133,7 @@ namespace ImageSharp /// public override int GetHashCode() { - return GetHashCode(this); + return this.backingVector.GetHashCode(); } /// @@ -152,16 +152,5 @@ namespace ImageSharp { return this.backingVector.Equals(other.backingVector); } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private static int GetHashCode(Bgra32 color) => color.backingVector.GetHashCode(); } } diff --git a/src/ImageSharp/Colors/Colorspaces/CieLab.cs b/src/ImageSharp/Colors/Spaces/CieLab.cs similarity index 88% rename from src/ImageSharp/Colors/Colorspaces/CieLab.cs rename to src/ImageSharp/Colors/Spaces/CieLab.cs index e3300f3b87..f4f349b52b 100644 --- a/src/ImageSharp/Colors/Colorspaces/CieLab.cs +++ b/src/ImageSharp/Colors/Spaces/CieLab.cs @@ -3,7 +3,7 @@ // Licensed under the Apache License, Version 2.0. // -namespace ImageSharp +namespace ImageSharp.Colors.Spaces { using System; using System.ComponentModel; @@ -20,15 +20,10 @@ namespace ImageSharp /// public static readonly CieLab Empty = default(CieLab); - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 0.001f; - /// /// The backing vector for SIMD support. /// - private Vector3 backingVector; + private readonly Vector3 backingVector; /// /// Initializes a new instance of the struct. @@ -138,7 +133,7 @@ namespace ImageSharp /// public override int GetHashCode() { - return GetHashCode(this); + return this.backingVector.GetHashCode(); } /// @@ -166,7 +161,7 @@ namespace ImageSharp /// public bool Equals(CieLab other) { - return this.AlmostEquals(other, Epsilon); + return this.AlmostEquals(other, Constants.Epsilon); } /// @@ -178,16 +173,5 @@ namespace ImageSharp && result.Y < precision && result.Z < precision; } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private static int GetHashCode(CieLab color) => color.backingVector.GetHashCode(); } } diff --git a/src/ImageSharp/Colors/Colorspaces/CieXyz.cs b/src/ImageSharp/Colors/Spaces/CieXyz.cs similarity index 87% rename from src/ImageSharp/Colors/Colorspaces/CieXyz.cs rename to src/ImageSharp/Colors/Spaces/CieXyz.cs index 16d5cb8275..49396d3f61 100644 --- a/src/ImageSharp/Colors/Colorspaces/CieXyz.cs +++ b/src/ImageSharp/Colors/Spaces/CieXyz.cs @@ -3,7 +3,7 @@ // Licensed under the Apache License, Version 2.0. // -namespace ImageSharp +namespace ImageSharp.Colors.Spaces { using System; using System.ComponentModel; @@ -20,15 +20,10 @@ namespace ImageSharp /// public static readonly CieXyz Empty = default(CieXyz); - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 0.001f; - /// /// The backing vector for SIMD support. /// - private Vector3 backingVector; + private readonly Vector3 backingVector; /// /// Initializes a new instance of the struct. @@ -129,7 +124,7 @@ namespace ImageSharp /// public override int GetHashCode() { - return GetHashCode(this); + return this.backingVector.GetHashCode(); } /// @@ -157,7 +152,7 @@ namespace ImageSharp /// public bool Equals(CieXyz other) { - return this.AlmostEquals(other, Epsilon); + return this.AlmostEquals(other, Constants.Epsilon); } /// @@ -169,16 +164,5 @@ namespace ImageSharp && result.Y < precision && result.Z < precision; } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private static int GetHashCode(CieXyz color) => color.backingVector.GetHashCode(); } } diff --git a/src/ImageSharp/Colors/Colorspaces/Cmyk.cs b/src/ImageSharp/Colors/Spaces/Cmyk.cs similarity index 87% rename from src/ImageSharp/Colors/Colorspaces/Cmyk.cs rename to src/ImageSharp/Colors/Spaces/Cmyk.cs index 15bea263cc..190d73598f 100644 --- a/src/ImageSharp/Colors/Colorspaces/Cmyk.cs +++ b/src/ImageSharp/Colors/Spaces/Cmyk.cs @@ -3,7 +3,7 @@ // Licensed under the Apache License, Version 2.0. // -namespace ImageSharp +namespace ImageSharp.Colors.Spaces { using System; using System.ComponentModel; @@ -19,15 +19,10 @@ namespace ImageSharp /// public static readonly Cmyk Empty = default(Cmyk); - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 0.001f; - /// /// The backing vector for SIMD support. /// - private Vector4 backingVector; + private readonly Vector4 backingVector; /// /// Initializes a new instance of the struct. @@ -90,7 +85,7 @@ namespace ImageSharp float k = Math.Min(c, Math.Min(m, y)); - if (Math.Abs(k - 1.0f) <= Epsilon) + if (Math.Abs(k - 1.0f) <= Constants.Epsilon) { return new Cmyk(0, 0, 0, 1); } @@ -139,7 +134,7 @@ namespace ImageSharp /// public override int GetHashCode() { - return GetHashCode(this); + return this.backingVector.GetHashCode(); } /// @@ -167,7 +162,7 @@ namespace ImageSharp /// public bool Equals(Cmyk other) { - return this.AlmostEquals(other, Epsilon); + return this.AlmostEquals(other, Constants.Epsilon); } /// @@ -180,16 +175,5 @@ namespace ImageSharp && result.Z < precision && result.W < precision; } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private static int GetHashCode(Cmyk color) => color.backingVector.GetHashCode(); } } diff --git a/src/ImageSharp/Colors/Colorspaces/Hsl.cs b/src/ImageSharp/Colors/Spaces/Hsl.cs similarity index 85% rename from src/ImageSharp/Colors/Colorspaces/Hsl.cs rename to src/ImageSharp/Colors/Spaces/Hsl.cs index 1cc54ec8c3..2cb02107b9 100644 --- a/src/ImageSharp/Colors/Colorspaces/Hsl.cs +++ b/src/ImageSharp/Colors/Spaces/Hsl.cs @@ -3,7 +3,7 @@ // Licensed under the Apache License, Version 2.0. // -namespace ImageSharp +namespace ImageSharp.Colors.Spaces { using System; using System.ComponentModel; @@ -19,15 +19,10 @@ namespace ImageSharp /// public static readonly Hsl Empty = default(Hsl); - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 0.001F; - /// /// The backing vector for SIMD support. /// - private Vector3 backingVector; + private readonly Vector3 backingVector; /// /// Initializes a new instance of the struct. @@ -85,20 +80,20 @@ namespace ImageSharp float s = 0; float l = (max + min) / 2; - if (Math.Abs(chroma) < Epsilon) + if (Math.Abs(chroma) < Constants.Epsilon) { return new Hsl(0, s, l); } - if (Math.Abs(r - max) < Epsilon) + if (Math.Abs(r - max) < Constants.Epsilon) { h = (g - b) / chroma; } - else if (Math.Abs(g - max) < Epsilon) + else if (Math.Abs(g - max) < Constants.Epsilon) { h = 2 + ((b - r) / chroma); } - else if (Math.Abs(b - max) < Epsilon) + else if (Math.Abs(b - max) < Constants.Epsilon) { h = 4 + ((r - g) / chroma); } @@ -158,7 +153,7 @@ namespace ImageSharp /// public override int GetHashCode() { - return GetHashCode(this); + return this.backingVector.GetHashCode(); } /// @@ -186,7 +181,7 @@ namespace ImageSharp /// public bool Equals(Hsl other) { - return this.AlmostEquals(other, Epsilon); + return this.AlmostEquals(other, Constants.Epsilon); } /// @@ -198,16 +193,5 @@ namespace ImageSharp && result.Y < precision && result.Z < precision; } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private static int GetHashCode(Hsl color) => color.backingVector.GetHashCode(); } } diff --git a/src/ImageSharp/Colors/Colorspaces/Hsv.cs b/src/ImageSharp/Colors/Spaces/Hsv.cs similarity index 85% rename from src/ImageSharp/Colors/Colorspaces/Hsv.cs rename to src/ImageSharp/Colors/Spaces/Hsv.cs index b55e07e6bd..8f7ebbdc76 100644 --- a/src/ImageSharp/Colors/Colorspaces/Hsv.cs +++ b/src/ImageSharp/Colors/Spaces/Hsv.cs @@ -3,7 +3,7 @@ // Licensed under the Apache License, Version 2.0. // -namespace ImageSharp +namespace ImageSharp.Colors.Spaces { using System; using System.ComponentModel; @@ -19,15 +19,10 @@ namespace ImageSharp /// public static readonly Hsv Empty = default(Hsv); - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 0.001F; - /// /// The backing vector for SIMD support. /// - private Vector3 backingVector; + private readonly Vector3 backingVector; /// /// Initializes a new instance of the struct. @@ -85,20 +80,20 @@ namespace ImageSharp float s = 0; float v = max; - if (Math.Abs(chroma) < Epsilon) + if (Math.Abs(chroma) < Constants.Epsilon) { return new Hsv(0, s, v); } - if (Math.Abs(r - max) < Epsilon) + if (Math.Abs(r - max) < Constants.Epsilon) { h = (g - b) / chroma; } - else if (Math.Abs(g - max) < Epsilon) + else if (Math.Abs(g - max) < Constants.Epsilon) { h = 2 + ((b - r) / chroma); } - else if (Math.Abs(b - max) < Epsilon) + else if (Math.Abs(b - max) < Constants.Epsilon) { h = 4 + ((r - g) / chroma); } @@ -151,7 +146,7 @@ namespace ImageSharp /// public override int GetHashCode() { - return GetHashCode(this); + return this.backingVector.GetHashCode(); } /// @@ -179,7 +174,7 @@ namespace ImageSharp /// public bool Equals(Hsv other) { - return this.AlmostEquals(other, Epsilon); + return this.AlmostEquals(other, Constants.Epsilon); } /// @@ -191,16 +186,5 @@ namespace ImageSharp && result.Y < precision && result.Z < precision; } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private static int GetHashCode(Hsv color) => color.backingVector.GetHashCode(); } } diff --git a/src/ImageSharp/Colors/Colorspaces/IAlmostEquatable.cs b/src/ImageSharp/Colors/Spaces/IAlmostEquatable.cs similarity index 97% rename from src/ImageSharp/Colors/Colorspaces/IAlmostEquatable.cs rename to src/ImageSharp/Colors/Spaces/IAlmostEquatable.cs index 1163657edb..a2183d396c 100644 --- a/src/ImageSharp/Colors/Colorspaces/IAlmostEquatable.cs +++ b/src/ImageSharp/Colors/Spaces/IAlmostEquatable.cs @@ -3,7 +3,7 @@ // Licensed under the Apache License, Version 2.0. // -namespace ImageSharp +namespace ImageSharp.Colors.Spaces { using System; diff --git a/src/ImageSharp/Colors/Colorspaces/YCbCr.cs b/src/ImageSharp/Colors/Spaces/YCbCr.cs similarity index 85% rename from src/ImageSharp/Colors/Colorspaces/YCbCr.cs rename to src/ImageSharp/Colors/Spaces/YCbCr.cs index c9a0872c51..83bddff7d0 100644 --- a/src/ImageSharp/Colors/Colorspaces/YCbCr.cs +++ b/src/ImageSharp/Colors/Spaces/YCbCr.cs @@ -3,10 +3,11 @@ // Licensed under the Apache License, Version 2.0. // -namespace ImageSharp +namespace ImageSharp.Colors.Spaces { using System; using System.ComponentModel; + using System.Numerics; /// /// Represents an YCbCr (luminance, blue chroma, red chroma) color conforming to the full range standard used in digital imaging systems. @@ -19,6 +20,16 @@ namespace ImageSharp /// public static readonly YCbCr Empty = default(YCbCr); + /// + /// Vector which is used in clamping to the max value + /// + private static readonly Vector3 VectorMax = new Vector3(255); + + /// + /// The backing vector for SIMD support. + /// + private readonly Vector3 backingVector; + /// /// Initializes a new instance of the struct. /// @@ -28,28 +39,26 @@ namespace ImageSharp public YCbCr(byte y, byte cb, byte cr) : this() { - this.Y = y; - this.Cb = cb; - this.Cr = cr; + this.backingVector = Vector3.Clamp(new Vector3(y, cb, cr), Vector3.Zero, VectorMax); } /// /// Gets the Y luminance component. /// A value ranging between 0 and 255. /// - public byte Y { get; } + public float Y => this.backingVector.X; /// /// Gets the Cb chroma component. /// A value ranging between 0 and 255. /// - public byte Cb { get; } + public float Cb => this.backingVector.Y; /// /// Gets the Cr chroma component. /// A value ranging between 0 and 255. /// - public byte Cr { get; } + public float Cr => this.backingVector.Z; /// /// Gets a value indicating whether this is empty. @@ -117,13 +126,7 @@ namespace ImageSharp /// public override int GetHashCode() { - unchecked - { - int hashCode = this.Y.GetHashCode(); - hashCode = (hashCode * 397) ^ this.Cb.GetHashCode(); - hashCode = (hashCode * 397) ^ this.Cr.GetHashCode(); - return hashCode; - } + return this.backingVector.GetHashCode(); } /// @@ -151,7 +154,7 @@ namespace ImageSharp /// public bool Equals(YCbCr other) { - return this.Y == other.Y && this.Cb == other.Cb && this.Cr == other.Cr; + return this.backingVector.Equals(other.backingVector); } } } \ No newline at end of file diff --git a/src/ImageSharp/Colors/Vector4BlendTransforms.cs b/src/ImageSharp/Colors/Vector4BlendTransforms.cs index 870d653888..2fa6aad4b4 100644 --- a/src/ImageSharp/Colors/Vector4BlendTransforms.cs +++ b/src/ImageSharp/Colors/Vector4BlendTransforms.cs @@ -14,11 +14,6 @@ namespace ImageSharp /// public class Vector4BlendTransforms { - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 0.0001F; - /// /// The blending formula simply selects the source vector. /// @@ -203,13 +198,13 @@ namespace ImageSharp amount = amount.Clamp(0, 1); // Santize on zero alpha - if (Math.Abs(backdrop.W) < Epsilon) + if (Math.Abs(backdrop.W) < Constants.Epsilon) { source.W *= amount; return source; } - if (Math.Abs(source.W) < Epsilon) + if (Math.Abs(source.W) < Constants.Epsilon) { return backdrop; } @@ -266,7 +261,7 @@ namespace ImageSharp /// private static float BlendDodge(float b, float s) { - return Math.Abs(s - 1F) < Epsilon ? s : Math.Min(b / (1F - s), 1F); + return Math.Abs(s - 1F) < Constants.Epsilon ? s : Math.Min(b / (1F - s), 1F); } /// @@ -279,7 +274,7 @@ namespace ImageSharp /// private static float BlendBurn(float b, float s) { - return Math.Abs(s) < Epsilon ? s : Math.Max(1F - ((1F - b) / s), 0F); + return Math.Abs(s) < Constants.Epsilon ? s : Math.Max(1F - ((1F - b) / s), 0F); } /// diff --git a/src/ImageSharp/Common/Constants.cs b/src/ImageSharp/Common/Constants.cs new file mode 100644 index 0000000000..cf43951bc5 --- /dev/null +++ b/src/ImageSharp/Common/Constants.cs @@ -0,0 +1,18 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + /// + /// Common constants used throughout the project + /// + internal static class Constants + { + /// + /// The epsilon for comparing floating point numbers. + /// + public static readonly float Epsilon = 0.001f; + } +} diff --git a/src/ImageSharp/Common/Helpers/ImageMaths.cs b/src/ImageSharp/Common/Helpers/ImageMaths.cs index 99212346aa..7455b542d1 100644 --- a/src/ImageSharp/Common/Helpers/ImageMaths.cs +++ b/src/ImageSharp/Common/Helpers/ImageMaths.cs @@ -91,9 +91,7 @@ namespace ImageSharp /// public static float SinC(float x) { - const float Epsilon = .00001F; - - if (Math.Abs(x) > Epsilon) + if (Math.Abs(x) > Constants.Epsilon) { x *= (float)Math.PI; return Clean((float)Math.Sin(x) / x); @@ -166,7 +164,6 @@ namespace ImageSharp public static Rectangle GetFilteredBoundingRectangle(ImageBase bitmap, float componentValue, RgbaComponent channel = RgbaComponent.B) where TColor : struct, IPackedPixel, IEquatable { - const float Epsilon = .00001f; int width = bitmap.Width; int height = bitmap.Height; Point topLeft = default(Point); @@ -178,19 +175,19 @@ namespace ImageSharp switch (channel) { case RgbaComponent.R: - delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().X - b) > Epsilon; + delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().X - b) > Constants.Epsilon; break; case RgbaComponent.G: - delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().Y - b) > Epsilon; + delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().Y - b) > Constants.Epsilon; break; case RgbaComponent.B: - delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().Z - b) > Epsilon; + delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().Z - b) > Constants.Epsilon; break; default: - delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().W - b) > Epsilon; + delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().W - b) > Constants.Epsilon; break; } @@ -278,9 +275,7 @@ namespace ImageSharp /// . private static float Clean(float x) { - const float Epsilon = .00001F; - - if (Math.Abs(x) < Epsilon) + if (Math.Abs(x) < Constants.Epsilon) { return 0F; } diff --git a/src/ImageSharp/Drawing/Processors/DrawPathProcessor.cs b/src/ImageSharp/Drawing/Processors/DrawPathProcessor.cs index 54ebc28efd..dab0baa5a2 100644 --- a/src/ImageSharp/Drawing/Processors/DrawPathProcessor.cs +++ b/src/ImageSharp/Drawing/Processors/DrawPathProcessor.cs @@ -9,7 +9,6 @@ namespace ImageSharp.Drawing.Processors using System.Linq; using System.Numerics; using System.Threading.Tasks; - using ImageSharp.Processors; using Paths; using Pens; @@ -27,7 +26,6 @@ namespace ImageSharp.Drawing.Processors { private const float AntialiasFactor = 1f; private const int PaddingFactor = 1; // needs to been the same or greater than AntialiasFactor - private const float Epsilon = 0.001f; private readonly IPen pen; private readonly IPath[] paths; @@ -138,7 +136,7 @@ namespace ImageSharp.Drawing.Processors var opacity = this.Opacity(color.DistanceFromElement); - if (opacity > Epsilon) + if (opacity > Constants.Epsilon) { int offsetColorX = x - minX; diff --git a/src/ImageSharp/Drawing/Processors/FillShapeProcessor.cs b/src/ImageSharp/Drawing/Processors/FillShapeProcessor.cs index df5cec71c8..7da2e041a2 100644 --- a/src/ImageSharp/Drawing/Processors/FillShapeProcessor.cs +++ b/src/ImageSharp/Drawing/Processors/FillShapeProcessor.cs @@ -21,8 +21,6 @@ namespace ImageSharp.Drawing.Processors public class FillShapeProcessor : ImageFilteringProcessor where TColor : struct, IPackedPixel, IEquatable { - private const float Epsilon = 0.001f; - private const float AntialiasFactor = 1f; private const int DrawPadding = 1; private readonly IBrush fillColor; @@ -95,7 +93,7 @@ namespace ImageSharp.Drawing.Processors float dist = this.poly.Distance(currentPoint); float opacity = this.Opacity(dist); - if (opacity > Epsilon) + if (opacity > Constants.Epsilon) { Vector4 backgroundVector = sourcePixels[offsetX, offsetY].ToVector4(); Vector4 sourceVector = applicator.GetColor(currentPoint).ToVector4(); diff --git a/src/ImageSharp/Filters/Processors/Effects/BackgroundColorProcessor.cs b/src/ImageSharp/Filters/Processors/Effects/BackgroundColorProcessor.cs index 122c5a0ffe..ab6fa2424f 100644 --- a/src/ImageSharp/Filters/Processors/Effects/BackgroundColorProcessor.cs +++ b/src/ImageSharp/Filters/Processors/Effects/BackgroundColorProcessor.cs @@ -16,11 +16,6 @@ namespace ImageSharp.Processors public class BackgroundColorProcessor : ImageFilteringProcessor where TColor : struct, IPackedPixel, IEquatable { - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 0.001f; - /// /// Initializes a new instance of the class. /// @@ -82,7 +77,7 @@ namespace ImageSharp.Processors color = Vector4BlendTransforms.PremultipliedLerp(backgroundColor, color, .5F); } - if (Math.Abs(a) < Epsilon) + if (Math.Abs(a) < Constants.Epsilon) { color = backgroundColor; } diff --git a/src/ImageSharp/Filters/Processors/Transforms/RotateProcessor.cs b/src/ImageSharp/Filters/Processors/Transforms/RotateProcessor.cs index 33e5b64707..e81cd7e57e 100644 --- a/src/ImageSharp/Filters/Processors/Transforms/RotateProcessor.cs +++ b/src/ImageSharp/Filters/Processors/Transforms/RotateProcessor.cs @@ -70,9 +70,7 @@ namespace ImageSharp.Processors /// protected override void BeforeApply(ImageBase source, Rectangle sourceRectangle) { - const float Epsilon = .0001F; - - if (Math.Abs(this.Angle) < Epsilon || Math.Abs(this.Angle - 90) < Epsilon || Math.Abs(this.Angle - 180) < Epsilon || Math.Abs(this.Angle - 270) < Epsilon) + if (Math.Abs(this.Angle) < Constants.Epsilon || Math.Abs(this.Angle - 90) < Constants.Epsilon || Math.Abs(this.Angle - 180) < Constants.Epsilon || Math.Abs(this.Angle - 270) < Constants.Epsilon) { return; } @@ -91,26 +89,25 @@ namespace ImageSharp.Processors /// The private bool OptimizedApply(ImageBase source) { - const float Epsilon = .0001F; - if (Math.Abs(this.Angle) < Epsilon) + if (Math.Abs(this.Angle) < Constants.Epsilon) { // No need to do anything so return. return true; } - if (Math.Abs(this.Angle - 90) < Epsilon) + if (Math.Abs(this.Angle - 90) < Constants.Epsilon) { this.Rotate90(source); return true; } - if (Math.Abs(this.Angle - 180) < Epsilon) + if (Math.Abs(this.Angle - 180) < Constants.Epsilon) { this.Rotate180(source); return true; } - if (Math.Abs(this.Angle - 270) < Epsilon) + if (Math.Abs(this.Angle - 270) < Constants.Epsilon) { this.Rotate270(source); return true; diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 981d6c0970..5624176010 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -275,7 +275,7 @@ namespace ImageSharp.Formats const int ComponentCount = 2; TColor color = default(TColor); - using (PixelArea row = new PixelArea(width, ComponentOrder.XYZ)) + using (PixelArea row = new PixelArea(width, ComponentOrder.Xyz)) { for (int y = 0; y < height; y++) { @@ -312,7 +312,7 @@ namespace ImageSharp.Formats where TColor : struct, IPackedPixel, IEquatable { int padding = CalculatePadding(width, 3); - using (PixelArea row = new PixelArea(width, ComponentOrder.ZYX, padding)) + using (PixelArea row = new PixelArea(width, ComponentOrder.Zyx, padding)) { for (int y = 0; y < height; y++) { @@ -336,7 +336,7 @@ namespace ImageSharp.Formats where TColor : struct, IPackedPixel, IEquatable { int padding = CalculatePadding(width, 4); - using (PixelArea row = new PixelArea(width, ComponentOrder.ZYXW, padding)) + using (PixelArea row = new PixelArea(width, ComponentOrder.Zyxw, padding)) { for (int y = 0; y < height; y++) { diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index 8b7d791568..20c899a18d 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -150,12 +150,12 @@ namespace ImageSharp.Formats private void Write32Bit(EndianBinaryWriter writer, PixelAccessor pixels) where TColor : struct, IPackedPixel, IEquatable { - using (PixelArea row = new PixelArea(pixels.Width, ComponentOrder.ZYXW, this.padding)) + using (PixelArea row = new PixelArea(pixels.Width, ComponentOrder.Zyxw, this.padding)) { for (int y = pixels.Height - 1; y >= 0; y--) { pixels.CopyTo(row, y); - writer.Write(row.Bytes); + writer.Write(row.Bytes, 0, row.Length); } } } @@ -169,12 +169,12 @@ namespace ImageSharp.Formats private void Write24Bit(EndianBinaryWriter writer, PixelAccessor pixels) where TColor : struct, IPackedPixel, IEquatable { - using (PixelArea row = new PixelArea(pixels.Width, ComponentOrder.ZYX, this.padding)) + using (PixelArea row = new PixelArea(pixels.Width, ComponentOrder.Zyx, this.padding)) { for (int y = pixels.Height - 1; y >= 0; y--) { pixels.CopyTo(row, y); - writer.Write(row.Bytes); + writer.Write(row.Bytes, 0, row.Length); } } } diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index c3eb075f30..2be8aed379 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -451,7 +451,7 @@ namespace ImageSharp.Formats } else { - using (PixelArea emptyRow = new PixelArea(this.restoreArea.Value.Width, ComponentOrder.XYZW)) + using (PixelArea emptyRow = new PixelArea(this.restoreArea.Value.Width, ComponentOrder.Xyzw)) { using (PixelAccessor pixelAccessor = frame.Lock()) { diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 6b99423aec..8a851fd682 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -129,10 +129,10 @@ namespace ImageSharp.Formats bool hasEmpty = false; // Some images may have more than one quantized pixel returned with an alpha value of zero - // (No idea why?!) so we should always ignore if we have empty pixels present. + // so we should always ignore if we have empty pixels present. for (int i = 0; i < quantized.Palette.Length; i++) { - quantized.Palette[i].ToBytes(this.buffer, 0, ComponentOrder.XYZW); + quantized.Palette[i].ToXyzwBytes(this.buffer, 0); if (!hasEmpty) { @@ -282,6 +282,7 @@ namespace ImageSharp.Formats where TColor : struct, IPackedPixel, IEquatable { writer.Write(GifConstants.ImageDescriptorLabel); // 2c + // TODO: Can we capture this? writer.Write((ushort)0); // Left position writer.Write((ushort)0); // Top position @@ -318,7 +319,7 @@ namespace ImageSharp.Formats for (int i = 0; i < pixelCount; i++) { int offset = i * 3; - image.Palette[i].ToBytes(this.buffer, 0, ComponentOrder.XYZ); + image.Palette[i].ToXyzBytes(this.buffer, 0); colorTable[offset] = this.buffer[0]; colorTable[offset + 1] = this.buffer[1]; colorTable[offset + 2] = this.buffer[2]; diff --git a/src/ImageSharp/Formats/Jpg/Components/BlockQuad.cs b/src/ImageSharp/Formats/Jpg/Components/BlockQuad.cs new file mode 100644 index 0000000000..63453da21a --- /dev/null +++ b/src/ImageSharp/Formats/Jpg/Components/BlockQuad.cs @@ -0,0 +1,18 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// +namespace ImageSharp.Formats.Jpg.Components +{ + /// + /// Poor man's stackalloc: Contains a value-type buffer sized for 4 instances. + /// Useful for decoder/encoder operations allocating a block for each Jpeg component. + /// + internal unsafe struct BlockQuad + { + /// + /// The value-type buffer sized for 4 instances. + /// + public fixed float Data[4 * Block8x8F.ScalarCount]; + } +} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpg/Components/Decoder/Bits.cs b/src/ImageSharp/Formats/Jpg/Components/Decoder/Bits.cs index dbe9035afc..88aa8a3fe8 100644 --- a/src/ImageSharp/Formats/Jpg/Components/Decoder/Bits.cs +++ b/src/ImageSharp/Formats/Jpg/Components/Decoder/Bits.cs @@ -47,7 +47,7 @@ namespace ImageSharp.Formats.Jpg // Grab the decode bytes, use them and then set them // back on the decoder. - var decoderBytes = decoder.Bytes; + Bytes decoderBytes = decoder.Bytes; byte c = decoderBytes.ReadByteStuffedByte(decoder.InputStream, out errorCode); decoder.Bytes = decoderBytes; @@ -84,7 +84,7 @@ namespace ImageSharp.Formats.Jpg { if (this.UnreadBits < t) { - var errorCode = this.EnsureNBits(t, decoder); + JpegDecoderCore.ErrorCodes errorCode = this.EnsureNBits(t, decoder); if (errorCode != JpegDecoderCore.ErrorCodes.NoError) { throw new JpegDecoderCore.MissingFF00Exception(); diff --git a/src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs index 4413163d3f..cd0ec0af48 100644 --- a/src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs +++ b/src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs @@ -2,6 +2,7 @@ // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // + namespace ImageSharp.Formats { using System; @@ -11,19 +12,20 @@ namespace ImageSharp.Formats using System.Runtime.CompilerServices; using ImageSharp.Formats.Jpg; + using ImageSharp.Formats.Jpg.Components; /// - /// Image encoder for writing an image to a stream as a jpeg. + /// Image encoder for writing an image to a stream as a jpeg. /// internal unsafe class JpegEncoderCore { /// - /// The number of quantization tables. + /// The number of quantization tables. /// private const int QuantizationTableCount = 2; /// - /// Counts the number of bits needed to hold an integer. + /// Counts the number of bits needed to hold an integer. /// private static readonly uint[] BitCountLut = { @@ -43,15 +45,15 @@ namespace ImageSharp.Formats }; /// - /// The SOS (Start Of Scan) marker "\xff\xda" followed by 12 bytes: - /// - the marker length "\x00\x0c", - /// - the number of components "\x03", - /// - component 1 uses DC table 0 and AC table 0 "\x01\x00", - /// - component 2 uses DC table 1 and AC table 1 "\x02\x11", - /// - component 3 uses DC table 1 and AC table 1 "\x03\x11", - /// - the bytes "\x00\x3f\x00". Section B.2.3 of the spec says that for - /// sequential DCTs, those bytes (8-bit Ss, 8-bit Se, 4-bit Ah, 4-bit Al) - /// should be 0x00, 0x3f, 0x00<<4 | 0x00. + /// The SOS (Start Of Scan) marker "\xff\xda" followed by 12 bytes: + /// - the marker length "\x00\x0c", + /// - the number of components "\x03", + /// - component 1 uses DC table 0 and AC table 0 "\x01\x00", + /// - component 2 uses DC table 1 and AC table 1 "\x02\x11", + /// - component 3 uses DC table 1 and AC table 1 "\x03\x11", + /// - the bytes "\x00\x3f\x00". Section B.2.3 of the spec says that for + /// sequential DCTs, those bytes (8-bit Ss, 8-bit Se, 4-bit Ah, 4-bit Al) + /// should be 0x00, 0x3f, 0x00<<4 | 0x00. /// private static readonly byte[] SosHeaderYCbCr = { @@ -76,10 +78,10 @@ namespace ImageSharp.Formats }; /// - /// The unscaled quantization tables in zig-zag order. Each - /// encoder copies and scales the tables according to its quality parameter. - /// The values are derived from section K.1 after converting from natural to - /// zig-zag order. + /// The unscaled quantization tables in zig-zag order. Each + /// encoder copies and scales the tables according to its quality parameter. + /// The values are derived from section K.1 after converting from natural to + /// zig-zag order. /// private static readonly byte[,] UnscaledQuant = { @@ -102,69 +104,59 @@ namespace ImageSharp.Formats }; /// - /// A scratch buffer to reduce allocations. + /// A scratch buffer to reduce allocations. /// private readonly byte[] buffer = new byte[16]; /// - /// A buffer for reducing the number of stream writes when emitting Huffman tables. 64 seems to be enough. + /// A buffer for reducing the number of stream writes when emitting Huffman tables. 64 seems to be enough. /// private readonly byte[] emitBuffer = new byte[64]; /// - /// A buffer for reducing the number of stream writes when emitting Huffman tables. Max combined table lengths + - /// identifier. + /// A buffer for reducing the number of stream writes when emitting Huffman tables. Max combined table lengths + + /// identifier. /// private readonly byte[] huffmanBuffer = new byte[179]; /// - /// The accumulated bits to write to the stream. + /// The accumulated bits to write to the stream. /// private uint accumulatedBits; /// - /// The accumulated bit count. + /// The accumulated bit count. /// private uint bitCount; /// - /// The scaled chrominance table, in zig-zag order. + /// The scaled chrominance table, in zig-zag order. /// private Block8x8F chrominanceQuantTable; /// - /// The scaled luminance table, in zig-zag order. + /// The scaled luminance table, in zig-zag order. /// private Block8x8F luminanceQuantTable; /// - /// The output stream. All attempted writes after the first error become no-ops. + /// The output stream. All attempted writes after the first error become no-ops. /// private Stream outputStream; /// - /// The subsampling method to use. + /// The subsampling method to use. /// private JpegSubsample subsample; /// /// Encode writes the image to the jpeg baseline format with the given options. /// - /// - /// The pixel format. - /// - /// - /// The image to write from. - /// - /// - /// The stream to write to. - /// - /// - /// The quality. - /// - /// - /// The subsampling mode. - /// + /// The pixel format. + /// The image to write from. + /// The stream to write to. + /// The quality. + /// The subsampling mode. public void Encode(Image image, Stream stream, int quality, JpegSubsample sample) where TColor : struct, IPackedPixel, IEquatable { @@ -235,6 +227,28 @@ namespace ImageSharp.Formats stream.Flush(); } + /// + /// Writes data to "Define Quantization Tables" block for QuantIndex + /// + /// The "Define Quantization Tables" block + /// Offset in "Define Quantization Tables" block + /// The quantization index + /// The quantization table to copy data from + private static void WriteDataToDqt(byte[] dqt, ref int offset, QuantIndex i, ref Block8x8F quant) + { + dqt[offset++] = (byte)i; + for (int j = 0; j < Block8x8F.ScalarCount; j++) + { + dqt[offset++] = (byte)quant[j]; + } + } + + /// + /// Initializes quantization table. + /// + /// The quantization index. + /// The scaling factor. + /// The quantization table. private static void InitQuantizationTable(int i, int scale, ref Block8x8F quant) { for (int j = 0; j < Block8x8F.ScalarCount; j++) @@ -258,30 +272,14 @@ namespace ImageSharp.Formats /// /// Converts the 8x8 region of the image whose top-left corner is x,y to its YCbCr values. /// - /// - /// The pixel format. - /// - /// - /// The pixel accessor. - /// - /// - /// The x-position within the image. - /// - /// - /// The y-position within the image. - /// - /// - /// The luminance block. - /// - /// - /// The red chroma block. - /// - /// - /// The blue chroma block. - /// - /// - /// Temporal provided by the caller - /// + /// The pixel format. + /// The pixel accessor. + /// The x-position within the image. + /// The y-position within the image. + /// The luminance block. + /// The red chroma block. + /// The blue chroma block. + /// Temporal provided by the caller private static void ToYCbCr( PixelAccessor pixels, int x, @@ -326,18 +324,14 @@ namespace ImageSharp.Formats /// /// Emits the least significant count of bits of bits to the bit-stream. - /// The precondition is bits - /// + /// The precondition is bits + /// /// < 1<<nBits && nBits <= 16 /// /// . /// - /// - /// The packed bits. - /// - /// - /// The number of bits - /// + /// The packed bits. + /// The number of bits private void Emit(uint bits, uint count) { count += this.bitCount; @@ -375,12 +369,8 @@ namespace ImageSharp.Formats /// /// Emits the given value with the given Huffman encoder. /// - /// - /// The index of the Huffman encoder - /// - /// - /// The value to encode. - /// + /// The index of the Huffman encoder + /// The value to encode. [MethodImpl(MethodImplOptions.AggressiveInlining)] private void EmitHuff(HuffIndex index, int value) { @@ -391,15 +381,9 @@ namespace ImageSharp.Formats /// /// Emits a run of runLength copies of value encoded with the given Huffman encoder. /// - /// - /// The index of the Huffman encoder - /// - /// - /// The number of copies to encode. - /// - /// - /// The value to encode. - /// + /// The index of the Huffman encoder + /// The number of copies to encode. + /// The value to encode. [MethodImpl(MethodImplOptions.AggressiveInlining)] private void EmitHuffRLE(HuffIndex index, int runLength, int value) { @@ -431,12 +415,8 @@ namespace ImageSharp.Formats /// /// Encodes the image with no subsampling. /// - /// - /// The pixel format. - /// - /// - /// The pixel accessor providing access to the image pixels. - /// + /// The pixel format. + /// The pixel accessor providing access to the image pixels. private void Encode444(PixelAccessor pixels) where TColor : struct, IPackedPixel, IEquatable { @@ -456,7 +436,7 @@ namespace ImageSharp.Formats // ReSharper disable once InconsistentNaming float prevDCY = 0, prevDCCb = 0, prevDCCr = 0; - using (PixelArea rgbBytes = new PixelArea(8, 8, ComponentOrder.XYZ, true)) + using (PixelArea rgbBytes = new PixelArea(8, 8, ComponentOrder.Xyz)) { for (int y = 0; y < pixels.Height; y += 8) { @@ -496,12 +476,8 @@ namespace ImageSharp.Formats /// /// Writes the application header containing the JFIF identifier plus extra data. /// - /// - /// The resolution of the image in the x- direction. - /// - /// - /// The resolution of the image in the y- direction. - /// + /// The resolution of the image in the x- direction. + /// The resolution of the image in the y- direction. private void WriteApplicationHeader(short horizontalResolution, short verticalResolution) { // Write the start of image marker. Markers are always prefixed with with 0xff. @@ -539,30 +515,16 @@ namespace ImageSharp.Formats /// /// Writes a block of pixel data using the given quantization table, - /// returning the post-quantized DC value of the DCT-transformed block. - /// The block is in natural (not zig-zag) order. + /// returning the post-quantized DC value of the DCT-transformed block. + /// The block is in natural (not zig-zag) order. /// - /// - /// The quantization table index. - /// - /// - /// The previous DC value. - /// - /// - /// Source block - /// - /// - /// Temporal block to be used as FDCT Destination - /// - /// - /// Temporal block 2 - /// - /// - /// Quantization table - /// - /// - /// The 8x8 Unzig block ptr - /// + /// The quantization table index. + /// The previous DC value. + /// Source block + /// Temporal block to be used as FDCT Destination + /// Temporal block 2 + /// Quantization table + /// The 8x8 Unzig block pointer /// /// The /// @@ -622,9 +584,7 @@ namespace ImageSharp.Formats /// /// Writes the Define Huffman Table marker and tables. /// - /// - /// The number of components to write. - /// + /// The number of components to write. private void WriteDefineHuffmanTables(int componentCount) { // Table identifiers. @@ -671,7 +631,7 @@ namespace ImageSharp.Formats } /// - /// Writes the Define Quantization Marker and tables. + /// Writes the Define Quantization Marker and tables. /// private void WriteDefineQuantizationTables() { @@ -685,8 +645,8 @@ namespace ImageSharp.Formats byte[] dqt = ArrayPool.Shared.Rent(dqtCount); int offset = 0; - JpegUtils.WriteDataToDqt(dqt, ref offset, QuantIndex.Luminance, ref this.luminanceQuantTable); - JpegUtils.WriteDataToDqt(dqt, ref offset, QuantIndex.Chrominance, ref this.chrominanceQuantTable); + WriteDataToDqt(dqt, ref offset, QuantIndex.Luminance, ref this.luminanceQuantTable); + WriteDataToDqt(dqt, ref offset, QuantIndex.Chrominance, ref this.chrominanceQuantTable); this.outputStream.Write(dqt, 0, dqtCount); ArrayPool.Shared.Return(dqt); @@ -695,9 +655,7 @@ namespace ImageSharp.Formats /// /// Writes the EXIF profile. /// - /// - /// The exif profile. - /// + /// The exif profile. /// /// Thrown if the EXIF profile size exceeds the limit /// @@ -729,12 +687,8 @@ namespace ImageSharp.Formats /// /// Writes the metadata profiles to the image. /// - /// - /// The image. - /// - /// - /// The pixel format. - /// + /// The image. + /// The pixel format. private void WriteProfiles(Image image) where TColor : struct, IPackedPixel, IEquatable { @@ -744,15 +698,9 @@ namespace ImageSharp.Formats /// /// Writes the Start Of Frame (Baseline) marker /// - /// - /// The width of the image - /// - /// - /// The height of the image - /// - /// - /// The number of components in a pixel - /// + /// The width of the image + /// The height of the image + /// The number of components in a pixel private void WriteStartOfFrame(int width, int height, int componentCount) { // "default" to 4:2:0 @@ -806,12 +754,8 @@ namespace ImageSharp.Formats /// /// Writes the StartOfScan marker. /// - /// - /// The pixel format. - /// - /// - /// The pixel accessor providing access to the image pixels. - /// + /// The pixel format. + /// The pixel accessor providing access to the image pixels. private void WriteStartOfScan(PixelAccessor pixels) where TColor : struct, IPackedPixel, IEquatable { @@ -833,28 +777,12 @@ namespace ImageSharp.Formats this.Emit(0x7f, 7); } -#pragma warning disable SA1201 // MethodShouldNotFollowAStruct - - /// - /// Poor man's stackalloc for Encode420. - /// This struct belongs to Encode420. Much easeier to understand code if they are close to each other. Why should I - /// move it Up? :P - /// - private struct BlockQuad - { - public fixed float Data[4 * Block8x8F.ScalarCount]; - } - /// /// Encodes the image with subsampling. The Cb and Cr components are each subsampled - /// at a factor of 2 both horizontally and vertically. + /// at a factor of 2 both horizontally and vertically. /// - /// - /// The pixel format. - /// - /// - /// The pixel accessor providing access to the image pixels. - /// + /// The pixel format. + /// The pixel accessor providing access to the image pixels. private void Encode420(PixelAccessor pixels) where TColor : struct, IPackedPixel, IEquatable { @@ -877,7 +805,7 @@ namespace ImageSharp.Formats // ReSharper disable once InconsistentNaming float prevDCY = 0, prevDCCb = 0, prevDCCr = 0; - using (var rgbBytes = new PixelArea(8, 8, ComponentOrder.XYZ, true)) + using (PixelArea rgbBytes = new PixelArea(8, 8, ComponentOrder.Xyz)) { for (int y = 0; y < pixels.Height; y += 16) { @@ -909,6 +837,7 @@ namespace ImageSharp.Formats &temp2, &onStackChrominanceQuantTable, unzig.Data); + Block8x8F.Scale16X16To8X8(&b, crPtr); prevDCCr = this.WriteBlock( QuantIndex.Chrominance, @@ -923,17 +852,11 @@ namespace ImageSharp.Formats } } -#pragma warning restore SA1201 - /// /// Writes the header for a marker with the given length. /// - /// - /// The marker to write. - /// - /// - /// The marker length. - /// + /// The marker to write. + /// The marker length. private void WriteMarkerHeader(byte marker, int length) { // Markers are always prefixed with with 0xff. diff --git a/src/ImageSharp/Formats/Jpg/Utils/JpegUtils.cs b/src/ImageSharp/Formats/Jpg/Utils/JpegUtils.cs index fa26477518..7f62058b7e 100644 --- a/src/ImageSharp/Formats/Jpg/Utils/JpegUtils.cs +++ b/src/ImageSharp/Formats/Jpg/Utils/JpegUtils.cs @@ -13,24 +13,13 @@ namespace ImageSharp.Formats.Jpg internal static unsafe class JpegUtils { /// - /// Copy a region of an image into dest. De "outlier" area will be stretched out with pixels on the right and bottom of - /// the image. + /// Copy a region of an image into dest. De "outlier" area will be stretched out with pixels on the right and bottom of the image. /// - /// - /// The pixel type - /// - /// - /// The input pixel acessor - /// - /// - /// The destination - /// - /// - /// Starting Y coord - /// - /// - /// Starting X coord - /// + /// The pixel type + /// The input pixel acessor + /// The destination + /// Starting Y coord + /// Starting X coord public static void CopyRGBBytesStretchedTo( this PixelAccessor pixels, PixelArea dest, @@ -38,7 +27,7 @@ namespace ImageSharp.Formats.Jpg int sourceX) where TColor : struct, IPackedPixel, IEquatable { - pixels.CopyTo(dest, sourceY, sourceX); + pixels.SafeCopyTo(dest, sourceY, sourceX); int stretchFromX = pixels.Width - sourceX; int stretchFromY = pixels.Height - sourceY; StretchPixels(dest, stretchFromX, stretchFromY); @@ -47,46 +36,19 @@ namespace ImageSharp.Formats.Jpg /// /// Copy an RGB value /// - /// - /// Source pointer - /// - /// - /// Destination pointer - /// + /// Source pointer + /// Destination pointer [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void CopyRgb(byte* source, byte* dest) + public static void CopyRgb(byte* source, byte* dest) { *dest++ = *source++; // R *dest++ = *source++; // G *dest = *source; // B } - /// - /// Writes data to "Define Quantization Tables" block for QuantIndex - /// - /// - /// The "Define Quantization Tables" block - /// - /// - /// Offset in dqt - /// - /// - /// The quantization index - /// - /// - /// The quantazation table to copy data from - /// - internal static void WriteDataToDqt(byte[] dqt, ref int offset, QuantIndex i, ref Block8x8F q) - { - dqt[offset++] = (byte)i; - for (int j = 0; j < Block8x8F.ScalarCount; j++) - { - dqt[offset++] = (byte)q[j]; - } - } - + // Nothing to stretch if (fromX, fromY) is outside the area, or is at (0,0) [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool IsInvalidStretchArea(PixelArea area, int fromX, int fromY) + private static bool IsInvalidStretchStartingPosition(PixelArea area, int fromX, int fromY) where TColor : struct, IPackedPixel, IEquatable { return fromX <= 0 || fromY <= 0 || fromX >= area.Width || fromY >= area.Height; @@ -95,14 +57,14 @@ namespace ImageSharp.Formats.Jpg private static void StretchPixels(PixelArea area, int fromX, int fromY) where TColor : struct, IPackedPixel, IEquatable { - if (IsInvalidStretchArea(area, fromX, fromY)) + if (IsInvalidStretchStartingPosition(area, fromX, fromY)) { return; } for (int y = 0; y < fromY; y++) { - byte* ptrBase = (byte*)area.DataPointer + (y * area.RowByteCount); + byte* ptrBase = (byte*)area.DataPointer + (y * area.RowStride); for (int x = fromX; x < area.Width; x++) { @@ -115,8 +77,8 @@ namespace ImageSharp.Formats.Jpg for (int y = fromY; y < area.Height; y++) { - byte* currBase = (byte*)area.DataPointer + (y * area.RowByteCount); - byte* prevBase = (byte*)area.DataPointer + ((y - 1) * area.RowByteCount); + byte* currBase = (byte*)area.DataPointer + (y * area.RowStride); + byte* prevBase = (byte*)area.DataPointer + ((y - 1) * area.RowStride); for (int x = 0; x < area.Width; x++) { diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 7d3d232651..78df6c72e5 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -286,7 +286,7 @@ namespace ImageSharp.Formats // Convert the color to YCbCr and store the luminance // Optionally store the original color alpha. int offset = x * this.bytesPerPixel; - pixels[x, row].ToBytes(this.chunkTypeBuffer, 0, ComponentOrder.XYZW); + pixels[x, row].ToXyzwBytes(this.chunkTypeBuffer, 0); byte luminance = (byte)((0.299F * this.chunkTypeBuffer[0]) + (0.587F * this.chunkTypeBuffer[1]) + (0.114F * this.chunkTypeBuffer[2])); for (int i = 0; i < this.bytesPerPixel; i++) @@ -314,7 +314,7 @@ namespace ImageSharp.Formats where TColor : struct, IPackedPixel, IEquatable { // We can use the optimized PixelAccessor here and copy the bytes in unmanaged memory. - using (PixelArea pixelRow = new PixelArea(this.width, rawScanline, this.bytesPerPixel == 4 ? ComponentOrder.XYZW : ComponentOrder.XYZ)) + using (PixelArea pixelRow = new PixelArea(this.width, rawScanline, this.bytesPerPixel == 4 ? ComponentOrder.Xyzw : ComponentOrder.Xyz)) { pixels.CopyTo(pixelRow, row); } @@ -507,7 +507,7 @@ namespace ImageSharp.Formats for (int i = 0; i < pixelCount; i++) { int offset = i * 3; - palette[i].ToBytes(bytes, 0, ComponentOrder.XYZW); + palette[i].ToXyzwBytes(bytes, 0); int alpha = bytes[3]; diff --git a/src/ImageSharp/Image/ImageBase{TColor}.cs b/src/ImageSharp/Image/ImageBase{TColor}.cs index 164b28160f..8fa40faccc 100644 --- a/src/ImageSharp/Image/ImageBase{TColor}.cs +++ b/src/ImageSharp/Image/ImageBase{TColor}.cs @@ -64,7 +64,7 @@ namespace ImageSharp using (PixelAccessor sourcePixels = other.Lock()) using (PixelAccessor target = this.Lock()) { - sourcePixels.CopyImage(target); + sourcePixels.CopyTo(target); } } diff --git a/src/ImageSharp/Image/PixelAccessor{TColor}.cs b/src/ImageSharp/Image/PixelAccessor{TColor}.cs index 1dd3edf940..991be5aec4 100644 --- a/src/ImageSharp/Image/PixelAccessor{TColor}.cs +++ b/src/ImageSharp/Image/PixelAccessor{TColor}.cs @@ -145,69 +145,40 @@ namespace ImageSharp } /// - /// Copies a block of pixels at the specified position. + /// Copy an area of pixels to the image. /// - /// The x-coordinate of the source image. - /// The y-coordinate of the source image. - /// The target pixel buffer accessor. - /// The x-coordinate of the target image. - /// The y-coordinate of the target image. - /// The number of pixels to copy - public void CopyBlock(int sourceX, int sourceY, PixelAccessor target, int targetX, int targetY, int pixelCount) + /// The area. + /// The target row index. + /// The target column index. + /// + /// Thrown when an unsupported component order value is passed. + /// + public void CopyFrom(PixelArea area, int targetY, int targetX = 0) { - int size = Unsafe.SizeOf(); - byte* sourcePtr = this.pixelsBase + (((sourceY * this.Width) + sourceX) * size); - byte* targetPtr = target.pixelsBase + (((targetY * target.Width) + targetX) * size); - uint byteCount = (uint)(pixelCount * size); - - Unsafe.CopyBlock(targetPtr, sourcePtr, byteCount); - } + this.CheckCoordinates(area, targetX, targetY); - /// - /// Copies an entire image. - /// - /// The target pixel buffer accessor. - public void CopyImage(PixelAccessor target) - { - this.CopyBlock(0, 0, target, 0, 0, target.Width * target.Height); + this.CopyFrom(area, targetX, targetY, area.Width, area.Height); } /// - /// Copied a row of pixels from the image. + /// Copy pixels from the image to an area of pixels. /// /// The area. - /// The target row index. - /// The target column index. + /// The source row index. + /// The source column index. /// /// Thrown when an unsupported component order value is passed. /// - public void CopyFrom(PixelArea area, int targetY, int targetX = 0) + public void CopyTo(PixelArea area, int sourceY, int sourceX = 0) { - int width = Math.Min(area.Width, this.Width - targetX); - int height = Math.Min(area.Height, this.Height - targetY); + this.CheckCoordinates(area, sourceX, sourceY); - // this.CheckDimensions(width, height); TODO: Why was width == 0 or height == 0 considered a problem? Copy implementations do not fail on this (just do nothing)! - switch (area.ComponentOrder) - { - case ComponentOrder.ZYX: - this.CopyFromZYX(area, targetY, targetX, width, height); - break; - case ComponentOrder.ZYXW: - this.CopyFromZYXW(area, targetY, targetX, width, height); - break; - case ComponentOrder.XYZ: - this.CopyFromXYZ(area, targetY, targetX, width, height); - break; - case ComponentOrder.XYZW: - this.CopyFromXYZW(area, targetY, targetX, width, height); - break; - default: - throw new NotSupportedException(); - } + this.CopyTo(area, sourceX, sourceY, area.Width, area.Height); } /// - /// Copied an area of pixels to the image. + /// Copy pixels from the image to an area of pixels. This method will make sure that the pixels + /// that are copied are within the bounds of the image. /// /// The area. /// The source row index. @@ -215,29 +186,21 @@ namespace ImageSharp /// /// Thrown when an unsupported component order value is passed. /// - public void CopyTo(PixelArea area, int sourceY, int sourceX = 0) + public void SafeCopyTo(PixelArea area, int sourceY, int sourceX = 0) { int width = Math.Min(area.Width, this.Width - sourceX); - int height = Math.Min(area.Height, this.Height - sourceY); + if (width < 1) + { + return; + } - // this.CheckDimensions(width, height); TODO: Why was width == 0 or height == 0 considered a problem? Copy implementations do not fail on this (just do nothing)! - switch (area.ComponentOrder) + int height = Math.Min(area.Height, this.Height - sourceY); + if (height < 1) { - case ComponentOrder.ZYX: - this.CopyToZYX(area, sourceY, sourceX, width, height); - break; - case ComponentOrder.ZYXW: - this.CopyToZYXW(area, sourceY, sourceX, width, height); - break; - case ComponentOrder.XYZ: - this.CopyToXYZ(area, sourceY, sourceX, width, height); - break; - case ComponentOrder.XYZW: - this.CopyToXYZW(area, sourceY, sourceX, width, height); - break; - default: - throw new NotSupportedException(); + return; } + + this.CopyTo(area, sourceX, sourceY, width, height); } /// @@ -269,6 +232,17 @@ namespace ImageSharp GC.SuppressFinalize(this); } + /// + /// Copies the pixels to another of the same size. + /// + /// The target pixel buffer accessor. + internal void CopyTo(PixelAccessor target) + { + uint byteCount = (uint)(this.Width * this.Height * Unsafe.SizeOf()); + + Unsafe.CopyBlock(target.pixelsBase, this.pixelsBase, byteCount); + } + /// /// Resets all the pixels to it's initial value. /// @@ -278,21 +252,21 @@ namespace ImageSharp } /// - /// Copies from an area in format. + /// Copies from an area in format. /// /// The area. - /// The target row index. /// The target column index. + /// The target row index. /// The width. /// The height. - protected virtual void CopyFromZYX(PixelArea area, int targetY, int targetX, int width, int height) + protected virtual void CopyFromZyx(PixelArea area, int targetX, int targetY, int width, int height) { TColor packed = default(TColor); int size = Unsafe.SizeOf(); for (int y = 0; y < height; y++) { - byte* source = area.PixelBase + (y * area.RowByteCount); + byte* source = area.PixelBase + (y * area.RowStride); byte* destination = this.GetRowPointer(targetX, targetY + y); for (int x = 0; x < width; x++) @@ -307,21 +281,21 @@ namespace ImageSharp } /// - /// Copies from an area in format. + /// Copies from an area in format. /// /// The area. - /// The target row index. /// The target column index. + /// The target row index. /// The width. /// The height. - protected virtual void CopyFromZYXW(PixelArea area, int targetY, int targetX, int width, int height) + protected virtual void CopyFromZyxw(PixelArea area, int targetX, int targetY, int width, int height) { TColor packed = default(TColor); int size = Unsafe.SizeOf(); for (int y = 0; y < height; y++) { - byte* source = area.PixelBase + (y * area.RowByteCount); + byte* source = area.PixelBase + (y * area.RowStride); byte* destination = this.GetRowPointer(targetX, targetY + y); for (int x = 0; x < width; x++) @@ -336,21 +310,21 @@ namespace ImageSharp } /// - /// Copies from an area in format. + /// Copies from an area in format. /// /// The area. - /// The target row index. /// The target column index. + /// The target row index. /// The width. /// The height. - protected virtual void CopyFromXYZ(PixelArea area, int targetY, int targetX, int width, int height) + protected virtual void CopyFromXyz(PixelArea area, int targetX, int targetY, int width, int height) { TColor packed = default(TColor); int size = Unsafe.SizeOf(); for (int y = 0; y < height; y++) { - byte* source = area.PixelBase + (y * area.RowByteCount); + byte* source = area.PixelBase + (y * area.RowStride); byte* destination = this.GetRowPointer(targetX, targetY + y); for (int x = 0; x < width; x++) @@ -365,21 +339,21 @@ namespace ImageSharp } /// - /// Copies from an area in format. + /// Copies from an area in format. /// /// The area. - /// The target row index. /// The target column index. + /// The target row index. /// The width. /// The height. - protected virtual void CopyFromXYZW(PixelArea area, int targetY, int targetX, int width, int height) + protected virtual void CopyFromXyzw(PixelArea area, int targetX, int targetY, int width, int height) { TColor packed = default(TColor); int size = Unsafe.SizeOf(); for (int y = 0; y < height; y++) { - byte* source = area.PixelBase + (y * area.RowByteCount); + byte* source = area.PixelBase + (y * area.RowStride); byte* destination = this.GetRowPointer(targetX, targetY + y); for (int x = 0; x < width; x++) @@ -394,84 +368,84 @@ namespace ImageSharp } /// - /// Copies to an area in format. + /// Copies to an area in format. /// /// The row. - /// The source row index. /// The source column index. + /// The source row index. /// The width. /// The height. - protected virtual void CopyToZYX(PixelArea area, int sourceY, int sourceX, int width, int height) + protected virtual void CopyToZyx(PixelArea area, int sourceX, int sourceY, int width, int height) { for (int y = 0; y < height; y++) { - int offset = y * area.RowByteCount; + int offset = y * area.RowStride; for (int x = 0; x < width; x++) { - this[sourceX + x, sourceY + y].ToBytes(area.Bytes, offset, ComponentOrder.ZYX); + this[sourceX + x, sourceY + y].ToZyxBytes(area.Bytes, offset); offset += 3; } } } /// - /// Copies to an area in format. + /// Copies to an area in format. /// /// The row. - /// The source row index. /// The source column index. + /// The source row index. /// The width. /// The height. - protected virtual void CopyToZYXW(PixelArea area, int sourceY, int sourceX, int width, int height) + protected virtual void CopyToZyxw(PixelArea area, int sourceX, int sourceY, int width, int height) { for (int y = 0; y < height; y++) { - int offset = y * area.RowByteCount; + int offset = y * area.RowStride; for (int x = 0; x < width; x++) { - this[sourceX + x, sourceY + y].ToBytes(area.Bytes, offset, ComponentOrder.ZYXW); + this[sourceX + x, sourceY + y].ToZyxwBytes(area.Bytes, offset); offset += 4; } } } /// - /// Copies to an area in format. + /// Copies to an area in format. /// /// The row. - /// The source row index. /// The source column index. + /// The source row index. /// The width. /// The height. - protected virtual void CopyToXYZ(PixelArea area, int sourceY, int sourceX, int width, int height) + protected virtual void CopyToXyz(PixelArea area, int sourceX, int sourceY, int width, int height) { for (int y = 0; y < height; y++) { - int offset = y * area.RowByteCount; + int offset = y * area.RowStride; for (int x = 0; x < width; x++) { - this[sourceX + x, sourceY + y].ToBytes(area.Bytes, offset, ComponentOrder.XYZ); + this[sourceX + x, sourceY + y].ToXyzBytes(area.Bytes, offset); offset += 3; } } } /// - /// Copies to an area in format. + /// Copies to an area in format. /// /// The row. - /// The source row index. /// The source column index. + /// The source row index. /// The width. /// The height. - protected virtual void CopyToXYZW(PixelArea area, int sourceY, int sourceX, int width, int height) + protected virtual void CopyToXyzw(PixelArea area, int sourceX, int sourceY, int width, int height) { for (int y = 0; y < height; y++) { - int offset = y * area.RowByteCount; + int offset = y * area.RowStride; for (int x = 0; x < width; x++) { - this[sourceX + x, sourceY + y].ToBytes(area.Bytes, offset, ComponentOrder.XYZW); + this[sourceX + x, sourceY + y].ToXyzwBytes(area.Bytes, offset); offset += 4; } } @@ -491,21 +465,88 @@ namespace ImageSharp } /// - /// Checks that the given dimensions are within the bounds of the image. + /// Copy an area of pixels to the image. /// - /// The width. - /// The height. + /// The area. + /// The target column index. + /// The target row index. + /// The width of the area to copy. + /// The height of the area to copy. + /// + /// Thrown when an unsupported component order value is passed. + /// + private void CopyFrom(PixelArea area, int targetX, int targetY, int width, int height) + { + switch (area.ComponentOrder) + { + case ComponentOrder.Zyx: + this.CopyFromZyx(area, targetX, targetY, width, height); + break; + case ComponentOrder.Zyxw: + this.CopyFromZyxw(area, targetX, targetY, width, height); + break; + case ComponentOrder.Xyz: + this.CopyFromXyz(area, targetX, targetY, width, height); + break; + case ComponentOrder.Xyzw: + this.CopyFromXyzw(area, targetX, targetY, width, height); + break; + default: + throw new NotSupportedException(); + } + } + + /// + /// Copy pixels from the image to an area of pixels. + /// + /// The area. + /// The source column index. + /// The source row index. + /// The width of the area to copy. + /// The height of the area to copy. + /// + /// Thrown when an unsupported component order value is passed. + /// + private void CopyTo(PixelArea area, int sourceX, int sourceY, int width, int height) + { + switch (area.ComponentOrder) + { + case ComponentOrder.Zyx: + this.CopyToZyx(area, sourceX, sourceY, width, height); + break; + case ComponentOrder.Zyxw: + this.CopyToZyxw(area, sourceX, sourceY, width, height); + break; + case ComponentOrder.Xyz: + this.CopyToXyz(area, sourceX, sourceY, width, height); + break; + case ComponentOrder.Xyzw: + this.CopyToXyzw(area, sourceX, sourceY, width, height); + break; + default: + throw new NotSupportedException(); + } + } + + /// + /// Checks that the given area and offset are within the bounds of the image. + /// + /// The area. + /// The x-coordinate of the pixel. Must be greater than zero and smaller than the width of the pixel. + /// The y-coordinate of the pixel. Must be greater than zero and smaller than the width of the pixel. /// /// Thrown if the dimensions are not within the bounds of the image. /// [Conditional("DEBUG")] - private void CheckDimensions(int width, int height) + private void CheckCoordinates(PixelArea area, int x, int y) { + int width = Math.Min(area.Width, this.Width - x); if (width < 1) { throw new ArgumentOutOfRangeException(nameof(width), width, $"Invalid area size specified."); } + int height = Math.Min(area.Height, this.Height - y); if (height < 1) { throw new ArgumentOutOfRangeException(nameof(height), height, $"Invalid area size specified."); diff --git a/src/ImageSharp/Image/PixelArea{TColor}.cs b/src/ImageSharp/Image/PixelArea{TColor}.cs index 12ccdd5bac..40da75c829 100644 --- a/src/ImageSharp/Image/PixelArea{TColor}.cs +++ b/src/ImageSharp/Image/PixelArea{TColor}.cs @@ -18,6 +18,11 @@ namespace ImageSharp public sealed unsafe class PixelArea : IDisposable where TColor : struct, IPackedPixel, IEquatable { + /// + /// True if was rented from by the constructor + /// + private readonly bool isBufferRented; + /// /// Provides a way to access the pixels from unmanaged memory. /// @@ -28,11 +33,6 @@ namespace ImageSharp /// private IntPtr dataPointer; - /// - /// True if was rented from by the constructor - /// - private bool isBufferRented; - /// /// A value indicating whether this instance of the given entity has been disposed. /// @@ -75,8 +75,10 @@ namespace ImageSharp this.Width = width; this.Height = height; this.ComponentOrder = componentOrder; - this.RowByteCount = width * GetComponentCount(componentOrder); + this.RowStride = width * GetComponentCount(componentOrder); this.Bytes = bytes; + this.Length = bytes.Length; + this.isBufferRented = false; this.pixelsHandle = GCHandle.Alloc(this.Bytes, GCHandleType.Pinned); // TODO: Why is Resharper warning us about an impure method call? @@ -88,34 +90,31 @@ namespace ImageSharp /// Initializes a new instance of the class. /// /// The width. - /// The height. /// The component order. - /// True if the buffer should be rented from ArrayPool - public PixelArea(int width, int height, ComponentOrder componentOrder, bool usePool = false) - : this(width, height, componentOrder, 0, usePool) + public PixelArea(int width, ComponentOrder componentOrder) + : this(width, 1, componentOrder, 0) { } /// /// Initializes a new instance of the class. /// - /// The width. + /// The width. /// The component order. - /// True if the buffer should be rented from ArrayPool - public PixelArea(int width, ComponentOrder componentOrder, bool usePool = false) - : this(width, 1, componentOrder, 0, usePool) + /// The number of bytes to pad each row. + public PixelArea(int width, ComponentOrder componentOrder, int padding) + : this(width, 1, componentOrder, padding) { } /// /// Initializes a new instance of the class. /// - /// The width. + /// The width. + /// The height. /// The component order. - /// The number of bytes to pad each row. - /// True if the buffer should be rented from ArrayPool - public PixelArea(int width, ComponentOrder componentOrder, int padding, bool usePool = false) - : this(width, 1, componentOrder, padding, usePool) + public PixelArea(int width, int height, ComponentOrder componentOrder) + : this(width, height, componentOrder, 0) { } @@ -126,27 +125,15 @@ namespace ImageSharp /// The height. /// The component order. /// The number of bytes to pad each row. - /// True if the buffer should be rented from ArrayPool - public PixelArea(int width, int height, ComponentOrder componentOrder, int padding, bool usePool = false) + public PixelArea(int width, int height, ComponentOrder componentOrder, int padding) { this.Width = width; this.Height = height; this.ComponentOrder = componentOrder; - this.RowByteCount = (width * GetComponentCount(componentOrder)) + padding; - - int bufferSize = this.RowByteCount * height; - - if (usePool) - { - this.Bytes = BytesPool.Rent(bufferSize); - this.isBufferRented = true; - Array.Clear(this.Bytes, 0, bufferSize); - } - else - { - this.Bytes = new byte[bufferSize]; - } - + this.RowStride = (width * GetComponentCount(componentOrder)) + padding; + this.Length = this.RowStride * height; + this.Bytes = BytesPool.Rent(this.Length); + this.isBufferRented = true; this.pixelsHandle = GCHandle.Alloc(this.Bytes, GCHandleType.Pinned); // TODO: Why is Resharper warning us about an impure method call? @@ -167,6 +154,11 @@ namespace ImageSharp /// public byte[] Bytes { get; } + /// + /// Gets the length of the buffer. + /// + public int Length { get; } + /// /// Gets the component order. /// @@ -188,9 +180,9 @@ namespace ImageSharp public byte* PixelBase { get; private set; } /// - /// Gets number of bytes in a row. + /// Gets the width of one row in the number of bytes. /// - public int RowByteCount { get; } + public int RowStride { get; } /// /// Gets the width. @@ -198,9 +190,9 @@ namespace ImageSharp public int Width { get; } /// - /// Gets the pool used to rent , when it's not coming from an external source + /// Gets the pool used to rent bytes, when it's not coming from an external source. /// - // ReSharper disable once StaticMemberInGenericType + // TODO: Use own pool? private static ArrayPool BytesPool => ArrayPool.Shared; /// @@ -209,6 +201,13 @@ namespace ImageSharp public void Dispose() { this.Dispose(true); + + // This object will be cleaned up by the Dispose method. + // Therefore, you should call GC.SuppressFinalize to + // take this object off the finalization queue + // and prevent finalization code for this object + // from executing a second time. + GC.SuppressFinalize(this); } /// @@ -217,7 +216,7 @@ namespace ImageSharp /// The stream. public void Read(Stream stream) { - stream.Read(this.Bytes, 0, this.Bytes.Length); + stream.Read(this.Bytes, 0, this.Length); } /// @@ -226,7 +225,7 @@ namespace ImageSharp /// The stream. public void Write(Stream stream) { - stream.Write(this.Bytes, 0, this.Bytes.Length); + stream.Write(this.Bytes, 0, this.Length); } /// @@ -234,7 +233,7 @@ namespace ImageSharp /// internal void Reset() { - Unsafe.InitBlock(this.PixelBase, 0, (uint)(this.RowByteCount * this.Height)); + Unsafe.InitBlock(this.PixelBase, 0, (uint)(this.RowStride * this.Height)); } /// @@ -251,17 +250,27 @@ namespace ImageSharp { switch (componentOrder) { - case ComponentOrder.ZYX: - case ComponentOrder.XYZ: + case ComponentOrder.Zyx: + case ComponentOrder.Xyz: return 3; - case ComponentOrder.ZYXW: - case ComponentOrder.XYZW: + case ComponentOrder.Zyxw: + case ComponentOrder.Xyzw: return 4; } throw new NotSupportedException(); } + /// + /// Checks that the length of the byte array to ensure that it matches the given width and height. + /// + /// The width. + /// The height. + /// The byte array. + /// The component order. + /// + /// Thrown if the byte array is th incorrect length. + /// [Conditional("DEBUG")] private void CheckBytesLength(int width, int height, byte[] bytes, ComponentOrder componentOrder) { @@ -274,6 +283,10 @@ namespace ImageSharp } } + /// + /// Disposes the object and frees resources for the Garbage Collector. + /// + /// If true, the object gets disposed. private void Dispose(bool disposing) { if (this.isDisposed) @@ -300,13 +313,6 @@ namespace ImageSharp this.PixelBase = null; this.isDisposed = true; - - // This object will be cleaned up by the Dispose method. - // Therefore, you should call GC.SuppressFinalize to - // take this object off the finalization queue - // and prevent finalization code for this object - // from executing a second time. - GC.SuppressFinalize(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelAccessor.cs b/src/ImageSharp/PixelAccessor.cs index c91f10cbdb..7827e7b47b 100644 --- a/src/ImageSharp/PixelAccessor.cs +++ b/src/ImageSharp/PixelAccessor.cs @@ -22,13 +22,13 @@ namespace ImageSharp } /// - protected override void CopyFromXYZW(PixelArea area, int targetY, int targetX, int width, int height) + protected override void CopyFromXyzw(PixelArea area, int targetX, int targetY, int width, int height) { uint byteCount = (uint)width * 4; for (int y = 0; y < height; y++) { - byte* source = area.PixelBase + (y * area.RowByteCount); + byte* source = area.PixelBase + (y * area.RowStride); byte* destination = this.GetRowPointer(targetX, targetY + y); Unsafe.CopyBlock(destination, source, byteCount); @@ -36,11 +36,11 @@ namespace ImageSharp } /// - protected override void CopyFromXYZ(PixelArea area, int targetY, int targetX, int width, int height) + protected override void CopyFromXyz(PixelArea area, int targetX, int targetY, int width, int height) { for (int y = 0; y < height; y++) { - byte* source = area.PixelBase + (y * area.RowByteCount); + byte* source = area.PixelBase + (y * area.RowStride); byte* destination = this.GetRowPointer(targetX, targetY + y); for (int x = 0; x < width; x++) @@ -54,11 +54,11 @@ namespace ImageSharp } /// - protected override void CopyFromZYX(PixelArea area, int targetY, int targetX, int width, int height) + protected override void CopyFromZyx(PixelArea area, int targetX, int targetY, int width, int height) { for (int y = 0; y < height; y++) { - byte* source = area.PixelBase + (y * area.RowByteCount); + byte* source = area.PixelBase + (y * area.RowStride); byte* destination = this.GetRowPointer(targetX, targetY + y); for (int x = 0; x < width; x++) @@ -72,11 +72,11 @@ namespace ImageSharp } /// - protected override void CopyFromZYXW(PixelArea area, int targetY, int targetX, int width, int height) + protected override void CopyFromZyxw(PixelArea area, int targetX, int targetY, int width, int height) { for (int y = 0; y < height; y++) { - byte* source = area.PixelBase + (y * area.RowByteCount); + byte* source = area.PixelBase + (y * area.RowStride); byte* destination = this.GetRowPointer(targetX, targetY + y); for (int x = 0; x < width; x++) @@ -90,12 +90,12 @@ namespace ImageSharp } /// - protected override void CopyToZYX(PixelArea area, int sourceY, int sourceX, int width, int height) + protected override void CopyToZyx(PixelArea area, int sourceX, int sourceY, int width, int height) { for (int y = 0; y < height; y++) { byte* source = this.GetRowPointer(sourceX, sourceY + y); - byte* destination = area.PixelBase + (y * area.RowByteCount); + byte* destination = area.PixelBase + (y * area.RowStride); for (int x = 0; x < width; x++) { @@ -110,12 +110,12 @@ namespace ImageSharp } /// - protected override unsafe void CopyToXYZ(PixelArea area, int sourceY, int sourceX, int width, int height) + protected override void CopyToXyz(PixelArea area, int sourceX, int sourceY, int width, int height) { for (int y = 0; y < height; y++) { byte* source = this.GetRowPointer(sourceX, sourceY + y); - byte* destination = area.PixelBase + (y * area.RowByteCount); + byte* destination = area.PixelBase + (y * area.RowStride); for (int x = 0; x < width; x++) { @@ -130,12 +130,12 @@ namespace ImageSharp } /// - protected override void CopyToZYXW(PixelArea area, int sourceY, int sourceX, int width, int height) + protected override void CopyToZyxw(PixelArea area, int sourceX, int sourceY, int width, int height) { for (int y = 0; y < height; y++) { byte* source = this.GetRowPointer(sourceX, sourceY + y); - byte* destination = area.PixelBase + (y * area.RowByteCount); + byte* destination = area.PixelBase + (y * area.RowStride); for (int x = 0; x < width; x++) { diff --git a/src/ImageSharp/Profiles/Exif/ExifTag.cs b/src/ImageSharp/Profiles/Exif/ExifTag.cs index 894f5a064c..6f4b494857 100644 --- a/src/ImageSharp/Profiles/Exif/ExifTag.cs +++ b/src/ImageSharp/Profiles/Exif/ExifTag.cs @@ -29,15 +29,15 @@ namespace ImageSharp /// /// SubfileType /// - [ExifTagDescription((uint)0, "Full-resolution Image")] - [ExifTagDescription((uint)1, "Reduced-resolution image")] - [ExifTagDescription((uint)2, "Single page of multi-page image")] - [ExifTagDescription((uint)3, "Single page of multi-page reduced-resolution image")] - [ExifTagDescription((uint)4, "Transparency mask")] - [ExifTagDescription((uint)5, "Transparency mask of reduced-resolution image")] - [ExifTagDescription((uint)6, "Transparency mask of multi-page image")] - [ExifTagDescription((uint)7, "Transparency mask of reduced-resolution multi-page image")] - [ExifTagDescription((uint)0x10001, "Alternate reduced-resolution image ")] + [ExifTagDescription(0U, "Full-resolution Image")] + [ExifTagDescription(1U, "Reduced-resolution image")] + [ExifTagDescription(2U, "Single page of multi-page image")] + [ExifTagDescription(3U, "Single page of multi-page reduced-resolution image")] + [ExifTagDescription(4U, "Transparency mask")] + [ExifTagDescription(5U, "Transparency mask of reduced-resolution image")] + [ExifTagDescription(6U, "Transparency mask of multi-page image")] + [ExifTagDescription(7U, "Transparency mask of reduced-resolution multi-page image")] + [ExifTagDescription(0x10001U, "Alternate reduced-resolution image ")] SubfileType = 0x00FE, /// @@ -276,15 +276,15 @@ namespace ImageSharp /// /// T4Options /// - [ExifTagDescription((uint)0, "2-Dimensional encoding")] - [ExifTagDescription((uint)1, "Uncompressed")] - [ExifTagDescription((uint)2, "Fill bits added")] + [ExifTagDescription(0U, "2-Dimensional encoding")] + [ExifTagDescription(1U, "Uncompressed")] + [ExifTagDescription(2U, "Fill bits added")] T4Options = 0x0124, /// /// T6Options /// - [ExifTagDescription((uint)1, "Uncompressed")] + [ExifTagDescription(1U, "Uncompressed")] T6Options = 0x0125, /// @@ -383,9 +383,9 @@ namespace ImageSharp /// /// CleanFaxData /// - [ExifTagDescription((uint)0, "Clean")] - [ExifTagDescription((uint)1, "Regenerated")] - [ExifTagDescription((uint)2, "Unclean")] + [ExifTagDescription(0U, "Clean")] + [ExifTagDescription(1U, "Regenerated")] + [ExifTagDescription(2U, "Unclean")] CleanFaxData = 0x0147, /// @@ -491,8 +491,8 @@ namespace ImageSharp /// /// ProfileType /// - [ExifTagDescription((uint)0, "Unspecified")] - [ExifTagDescription((uint)1, "Group 3 FAX")] + [ExifTagDescription(0U, "Unspecified")] + [ExifTagDescription(1U, "Group 3 FAX")] ProfileType = 0x0191, /// @@ -512,13 +512,13 @@ namespace ImageSharp /// /// CodingMethods /// - [ExifTagDescription((ulong)0, "Unspecified compression")] - [ExifTagDescription((ulong)1, "Modified Huffman")] - [ExifTagDescription((ulong)2, "Modified Read")] - [ExifTagDescription((ulong)4, "Modified MR")] - [ExifTagDescription((ulong)8, "JBIG")] - [ExifTagDescription((ulong)16, "Baseline JPEG")] - [ExifTagDescription((ulong)32, "JBIG color")] + [ExifTagDescription(0UL, "Unspecified compression")] + [ExifTagDescription(1UL, "Modified Huffman")] + [ExifTagDescription(2UL, "Modified Read")] + [ExifTagDescription(4UL, "Modified MR")] + [ExifTagDescription(8UL, "JBIG")] + [ExifTagDescription(16UL, "Baseline JPEG")] + [ExifTagDescription(32UL, "JBIG color")] CodingMethods = 0x0193, /// diff --git a/src/ImageSharp/Quantizers/Octree/OctreeQuantizer.cs b/src/ImageSharp/Quantizers/Octree/OctreeQuantizer.cs index 2898a5b713..2cd2de4f59 100644 --- a/src/ImageSharp/Quantizers/Octree/OctreeQuantizer.cs +++ b/src/ImageSharp/Quantizers/Octree/OctreeQuantizer.cs @@ -47,12 +47,7 @@ namespace ImageSharp.Quantizers public override QuantizedImage Quantize(ImageBase image, int maxColors) { this.colors = maxColors.Clamp(1, 255); - - if (this.octree == null) - { - // Construct the Octree - this.octree = new Octree(this.GetBitsNeededForColorDepth(maxColors)); - } + this.octree = new Octree(this.GetBitsNeededForColorDepth(maxColors)); return base.Quantize(image, maxColors); } @@ -117,6 +112,7 @@ namespace ImageSharp.Quantizers /// /// Mask used when getting the appropriate pixels for a given node /// + // ReSharper disable once StaticMemberInGenericType private static readonly int[] Mask = { 0x100, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; /// @@ -380,7 +376,7 @@ namespace ImageSharp.Quantizers { // Go to the next level down in the tree int shift = 7 - level; - pixel.ToBytes(buffer, 0, ComponentOrder.XYZW); + pixel.ToXyzwBytes(buffer, 0); int index = ((buffer[3] & Mask[0]) >> (shift - 3)) | ((buffer[2] & Mask[level + 1]) >> (shift - 2)) | @@ -484,7 +480,7 @@ namespace ImageSharp.Quantizers if (!this.leaf) { int shift = 7 - level; - pixel.ToBytes(buffer, 0, ComponentOrder.XYZW); + pixel.ToXyzwBytes(buffer, 0); int pixelIndex = ((buffer[3] & Mask[0]) >> (shift - 3)) | ((buffer[2] & Mask[level + 1]) >> (shift - 2)) | @@ -511,7 +507,7 @@ namespace ImageSharp.Quantizers /// The buffer array. public void Increment(TColor pixel, byte[] buffer) { - pixel.ToBytes(buffer, 0, ComponentOrder.XYZW); + pixel.ToXyzwBytes(buffer, 0); this.pixelCount++; this.red += buffer[0]; this.green += buffer[1]; diff --git a/src/ImageSharp/Quantizers/Palette/PaletteQuantizer.cs b/src/ImageSharp/Quantizers/Palette/PaletteQuantizer.cs index 92e0ae3c62..6edb7801bf 100644 --- a/src/ImageSharp/Quantizers/Palette/PaletteQuantizer.cs +++ b/src/ImageSharp/Quantizers/Palette/PaletteQuantizer.cs @@ -49,7 +49,7 @@ namespace ImageSharp.Quantizers for (int i = 0; i < constants.Length; i++) { - constants[i].ToBytes(this.pixelBuffer, 0, ComponentOrder.XYZW); + constants[i].ToXyzwBytes(this.pixelBuffer, 0); TColor packed = default(TColor); packed.PackFromBytes(this.pixelBuffer[0], this.pixelBuffer[1], this.pixelBuffer[2], this.pixelBuffer[3]); safe[i] = packed; diff --git a/src/ImageSharp/Quantizers/Wu/WuQuantizer.cs b/src/ImageSharp/Quantizers/Wu/WuQuantizer.cs index 2b491ff4c5..e235e68e88 100644 --- a/src/ImageSharp/Quantizers/Wu/WuQuantizer.cs +++ b/src/ImageSharp/Quantizers/Wu/WuQuantizer.cs @@ -33,11 +33,6 @@ namespace ImageSharp.Quantizers public sealed class WuQuantizer : IQuantizer where TColor : struct, IPackedPixel, IEquatable { - /// - /// The epsilon for comparing floating point numbers. - /// - private const float Epsilon = 1e-5F; - /// /// The index bits. /// @@ -340,7 +335,7 @@ namespace ImageSharp.Quantizers for (int x = 0; x < pixels.Width; x++) { // Colors are expected in r->g->b->a format - pixels[x, y].ToBytes(this.rgbaBuffer, 0, ComponentOrder.XYZW); + pixels[x, y].ToXyzwBytes(this.rgbaBuffer, 0); byte r = this.rgbaBuffer[0]; byte g = this.rgbaBuffer[1]; @@ -542,7 +537,7 @@ namespace ImageSharp.Quantizers double temp; - if (Math.Abs(halfW) < Epsilon) + if (Math.Abs(halfW) < Constants.Epsilon) { continue; } @@ -555,7 +550,7 @@ namespace ImageSharp.Quantizers halfA = wholeA - halfA; halfW = wholeW - halfW; - if (Math.Abs(halfW) < Epsilon) + if (Math.Abs(halfW) < Constants.Epsilon) { continue; } @@ -762,7 +757,7 @@ namespace ImageSharp.Quantizers double weight = Volume(cube[k], this.vwt); - if (Math.Abs(weight) > Epsilon) + if (Math.Abs(weight) > Constants.Epsilon) { float r = (float)(Volume(cube[k], this.vmr) / weight); float g = (float)(Volume(cube[k], this.vmg) / weight); @@ -785,7 +780,7 @@ namespace ImageSharp.Quantizers for (int x = 0; x < width; x++) { // Expected order r->g->b->a - imagePixels[x, y].ToBytes(rgba, 0, ComponentOrder.XYZW); + imagePixels[x, y].ToXyzwBytes(rgba, 0); int r = rgba[0] >> (8 - IndexBits); int g = rgba[1] >> (8 - IndexBits); diff --git a/src/ImageSharp/project.json b/src/ImageSharp/project.json index 33272594de..91cd277147 100644 --- a/src/ImageSharp/project.json +++ b/src/ImageSharp/project.json @@ -24,7 +24,7 @@ "buildOptions": { "allowUnsafe": true, "xmlDoc": true, - "additionalArguments": [ "/additionalfile:stylecop.json" ] + "additionalArguments": [ "/additionalfile:stylecop.json", "/ruleset:../../ImageSharp.ruleset" ] }, "configurations": { "Release": { @@ -36,7 +36,7 @@ }, "dependencies": { "StyleCop.Analyzers": { - "version": "1.0.0", + "version": "1.1.0-beta001", "type": "build" }, "System.Buffers": "4.0.0", diff --git a/tests/ImageSharp.Benchmarks/Image/CopyPixels.cs b/tests/ImageSharp.Benchmarks/Image/CopyPixels.cs index 1003aeaeb7..3c2b1b5d20 100644 --- a/tests/ImageSharp.Benchmarks/Image/CopyPixels.cs +++ b/tests/ImageSharp.Benchmarks/Image/CopyPixels.cs @@ -37,26 +37,5 @@ namespace ImageSharp.Benchmarks.Image return targetPixels[0, 0]; } } - - [Benchmark(Description = "Copy by Row")] - public CoreColor CopyByRow() - { - CoreImage source = new CoreImage(1024, 768); - CoreImage target = new CoreImage(1024, 768); - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - 0, - source.Height, - Bootstrapper.ParallelOptions, - y => - { - sourcePixels.CopyBlock(0, y, targetPixels, 0, y, source.Width); - }); - - return targetPixels[0, 0]; - } - } } } diff --git a/tests/ImageSharp.Tests/Colors/ColorConversionTests.cs b/tests/ImageSharp.Tests/Colors/ColorConversionTests.cs index f1b6d5f9b5..4884557522 100644 --- a/tests/ImageSharp.Tests/Colors/ColorConversionTests.cs +++ b/tests/ImageSharp.Tests/Colors/ColorConversionTests.cs @@ -7,7 +7,7 @@ namespace ImageSharp.Tests { using System; using System.Diagnostics.CodeAnalysis; - + using ImageSharp.Colors.Spaces; using Xunit; /// diff --git a/tests/ImageSharp.Tests/Colors/PackedPixelTests.cs b/tests/ImageSharp.Tests/Colors/PackedPixelTests.cs index 77fee1e79a..a79ef620ef 100644 --- a/tests/ImageSharp.Tests/Colors/PackedPixelTests.cs +++ b/tests/ImageSharp.Tests/Colors/PackedPixelTests.cs @@ -15,7 +15,7 @@ namespace ImageSharp.Tests.Colors /// /// /// The "ToVector4" tests should now be covered in - /// and at some point they can be safely removed from here. + /// and at some point they can be safely removed from here. /// public class PackedPixelTests { @@ -47,16 +47,16 @@ namespace ImageSharp.Tests.Colors byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - new Alpha8(.5F).ToBytes(rgb, 0, ComponentOrder.XYZ); + new Alpha8(.5F).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 0, 0, 0 }); - new Alpha8(.5F).ToBytes(rgba, 0, ComponentOrder.XYZW); + new Alpha8(.5F).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 0, 0, 0, 128 }); - new Alpha8(.5F).ToBytes(bgr, 0, ComponentOrder.ZYX); + new Alpha8(.5F).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 0, 0, 0 }); - new Alpha8(.5F).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new Alpha8(.5F).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 0, 0, 0, 128 }); } @@ -92,16 +92,16 @@ namespace ImageSharp.Tests.Colors byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - argb.ToBytes(rgb, 0, ComponentOrder.XYZ); + argb.ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 0x1a, 0, 0x80 }); - argb.ToBytes(rgba, 0, ComponentOrder.XYZW); + argb.ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 0x1a, 0, 0x80, 0 }); - argb.ToBytes(bgr, 0, ComponentOrder.ZYX); + argb.ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 0x80, 0, 0x1a }); - argb.ToBytes(bgra, 0, ComponentOrder.ZYXW); + argb.ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 0x80, 0, 0x1a, 0 }); } @@ -133,23 +133,22 @@ namespace ImageSharp.Tests.Colors float z = 0.5F; Assert.Equal(6160, new Bgr565(x, y, z).PackedValue); - // Test ordering byte[] rgb = new byte[3]; byte[] rgba = new byte[4]; byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - new Bgr565(x, y, z).ToBytes(rgb, 0, ComponentOrder.XYZ); + new Bgr565(x, y, z).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 25, 0, 132 }); - new Bgr565(x, y, z).ToBytes(rgba, 0, ComponentOrder.XYZW); + new Bgr565(x, y, z).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 25, 0, 132, 255 }); - new Bgr565(x, y, z).ToBytes(bgr, 0, ComponentOrder.ZYX); + new Bgr565(x, y, z).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 132, 0, 25 }); - new Bgr565(x, y, z).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new Bgr565(x, y, z).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 132, 0, 25, 255 }); } @@ -190,16 +189,16 @@ namespace ImageSharp.Tests.Colors byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - new Bgra4444(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ); + new Bgra4444(x, y, z, w).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 34, 0, 136 }); - new Bgra4444(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW); + new Bgra4444(x, y, z, w).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 34, 0, 136, 0 }); - new Bgra4444(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX); + new Bgra4444(x, y, z, w).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 136, 0, 34 }); - new Bgra4444(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new Bgra4444(x, y, z, w).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 136, 0, 34, 0 }); } @@ -236,16 +235,16 @@ namespace ImageSharp.Tests.Colors byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - new Bgra5551(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ); + new Bgra5551(x, y, z, w).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 24, 0, 131 }); - new Bgra5551(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW); + new Bgra5551(x, y, z, w).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 24, 0, 131, 0 }); - new Bgra5551(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX); + new Bgra5551(x, y, z, w).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 131, 0, 24 }); - new Bgra5551(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new Bgra5551(x, y, z, w).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 131, 0, 24, 0 }); } @@ -287,21 +286,21 @@ namespace ImageSharp.Tests.Colors byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - new Byte4(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ); + new Byte4(x, y, z, w).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 128, 0, 0 }); - new Byte4(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW); + new Byte4(x, y, z, w).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 128, 0, 0, 0 }); - new Byte4(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX); + new Byte4(x, y, z, w).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 0, 0, 128 }); - new Byte4(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new Byte4(x, y, z, w).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 0, 0, 128, 0 }); Byte4 r = new Byte4(); r.PackFromBytes(20, 38, 0, 255); - r.ToBytes(rgba, 0, ComponentOrder.XYZW); + r.ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 20, 38, 0, 255 }); } @@ -326,16 +325,16 @@ namespace ImageSharp.Tests.Colors byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - new HalfSingle(x).ToBytes(rgb, 0, ComponentOrder.XYZ); + new HalfSingle(x).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 128, 0, 0 }); - new HalfSingle(x).ToBytes(rgba, 0, ComponentOrder.XYZW); + new HalfSingle(x).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 128, 0, 0, 255 }); - new HalfSingle(x).ToBytes(bgr, 0, ComponentOrder.ZYX); + new HalfSingle(x).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 0, 0, 128 }); - new HalfSingle(x).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new HalfSingle(x).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 0, 0, 128, 255 }); } @@ -363,16 +362,16 @@ namespace ImageSharp.Tests.Colors byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - new HalfVector2(x, y).ToBytes(rgb, 0, ComponentOrder.XYZ); + new HalfVector2(x, y).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 128, 64, 0 }); - new HalfVector2(x, y).ToBytes(rgba, 0, ComponentOrder.XYZW); + new HalfVector2(x, y).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 128, 64, 0, 255 }); - new HalfVector2(x, y).ToBytes(bgr, 0, ComponentOrder.ZYX); + new HalfVector2(x, y).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 0, 64, 128 }); - new HalfVector2(x, y).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new HalfVector2(x, y).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 0, 64, 128, 255 }); } @@ -409,16 +408,16 @@ namespace ImageSharp.Tests.Colors byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - new HalfVector4(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ); + new HalfVector4(x, y, z, w).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 64, 128, 191 }); - new HalfVector4(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW); + new HalfVector4(x, y, z, w).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 64, 128, 191, 255 }); - new HalfVector4(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX); + new HalfVector4(x, y, z, w).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 191, 128, 64 }); - new HalfVector4(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new HalfVector4(x, y, z, w).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 191, 128, 64, 255 }); } @@ -454,16 +453,16 @@ namespace ImageSharp.Tests.Colors byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - new NormalizedByte2(x, y).ToBytes(rgb, 0, ComponentOrder.XYZ); + new NormalizedByte2(x, y).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 141, 90, 0 }); - new NormalizedByte2(x, y).ToBytes(rgba, 0, ComponentOrder.XYZW); + new NormalizedByte2(x, y).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 141, 90, 0, 255 }); - new NormalizedByte2(x, y).ToBytes(bgr, 0, ComponentOrder.ZYX); + new NormalizedByte2(x, y).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 0, 90, 141 }); - new NormalizedByte2(x, y).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new NormalizedByte2(x, y).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 0, 90, 141, 255 }); } @@ -499,26 +498,26 @@ namespace ImageSharp.Tests.Colors byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - new NormalizedByte4(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ); + new NormalizedByte4(x, y, z, w).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 141, 90, 192 }); - new NormalizedByte4(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW); + new NormalizedByte4(x, y, z, w).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 141, 90, 192, 39 }); - new NormalizedByte4(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX); + new NormalizedByte4(x, y, z, w).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 192, 90, 141 }); - new NormalizedByte4(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new NormalizedByte4(x, y, z, w).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 192, 90, 141, 39 }); // http://community.monogame.net/t/normalizedbyte4-texture2d-gives-different-results-from-xna/8012/8 NormalizedByte4 r = new NormalizedByte4(); r.PackFromBytes(9, 115, 202, 127); - r.ToBytes(rgba, 0, ComponentOrder.XYZW); + r.ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 9, 115, 202, 127 }); r.PackedValue = 0xff4af389; - r.ToBytes(rgba, 0, ComponentOrder.XYZW); + r.ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 9, 115, 202, 127 }); } @@ -553,22 +552,22 @@ namespace ImageSharp.Tests.Colors NormalizedShort2 n = new NormalizedShort2(); n.PackFromBytes(141, 90, 0, 0); - n.ToBytes(rgb, 0, ComponentOrder.XYZ); + n.ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 141, 90, 0 }); // TODO: I don't think this can ever pass since the bytes are already truncated. // Assert.Equal(3650751693, n.PackedValue); - new NormalizedShort2(x, y).ToBytes(rgb, 0, ComponentOrder.XYZ); + new NormalizedShort2(x, y).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 141, 90, 0 }); - new NormalizedShort2(x, y).ToBytes(rgba, 0, ComponentOrder.XYZW); + new NormalizedShort2(x, y).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 141, 90, 0, 255 }); - new NormalizedShort2(x, y).ToBytes(bgr, 0, ComponentOrder.ZYX); + new NormalizedShort2(x, y).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 0, 90, 141 }); - new NormalizedShort2(x, y).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new NormalizedShort2(x, y).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 0, 90, 141, 255 }); } @@ -600,21 +599,21 @@ namespace ImageSharp.Tests.Colors byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - new NormalizedShort4(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ); + new NormalizedShort4(x, y, z, w).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 141, 90, 192 }); - new NormalizedShort4(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW); + new NormalizedShort4(x, y, z, w).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 141, 90, 192, 39 }); - new NormalizedShort4(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX); + new NormalizedShort4(x, y, z, w).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 192, 90, 141 }); - new NormalizedShort4(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new NormalizedShort4(x, y, z, w).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 192, 90, 141, 39 }); NormalizedShort4 r = new NormalizedShort4(); r.PackFromBytes(9, 115, 202, 127); - r.ToBytes(rgba, 0, ComponentOrder.XYZW); + r.ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 9, 115, 202, 127 }); } @@ -647,16 +646,16 @@ namespace ImageSharp.Tests.Colors byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - new Rg32(x, y).ToBytes(rgb, 0, ComponentOrder.XYZ); + new Rg32(x, y).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 25, 0, 0 }); - new Rg32(x, y).ToBytes(rgba, 0, ComponentOrder.XYZW); + new Rg32(x, y).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 25, 0, 0, 255 }); - new Rg32(x, y).ToBytes(bgr, 0, ComponentOrder.ZYX); + new Rg32(x, y).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 0, 0, 25 }); - new Rg32(x, y).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new Rg32(x, y).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 0, 0, 25, 255 }); } @@ -692,22 +691,22 @@ namespace ImageSharp.Tests.Colors byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - new Rgba1010102(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ); + new Rgba1010102(x, y, z, w).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 25, 0, 128 }); - new Rgba1010102(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW); + new Rgba1010102(x, y, z, w).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 25, 0, 128, 0 }); - new Rgba1010102(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX); + new Rgba1010102(x, y, z, w).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 128, 0, 25 }); - new Rgba1010102(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new Rgba1010102(x, y, z, w).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 128, 0, 25, 0 }); // Alpha component accuracy will be awful. Rgba1010102 r = new Rgba1010102(); r.PackFromBytes(25, 0, 128, 0); - r.ToBytes(rgba, 0, ComponentOrder.XYZW); + r.ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 25, 0, 128, 0 }); } @@ -741,21 +740,21 @@ namespace ImageSharp.Tests.Colors byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - new Rgba64(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ); + new Rgba64(x, y, z, w).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 20, 38, 76 }); - new Rgba64(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW); + new Rgba64(x, y, z, w).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 20, 38, 76, 115 }); - new Rgba64(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX); + new Rgba64(x, y, z, w).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 76, 38, 20 }); - new Rgba64(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new Rgba64(x, y, z, w).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 76, 38, 20, 115 }); Rgba64 r = new Rgba64(); r.PackFromBytes(20, 38, 76, 115); - r.ToBytes(rgba, 0, ComponentOrder.XYZW); + r.ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 20, 38, 76, 115 }); } @@ -796,21 +795,21 @@ namespace ImageSharp.Tests.Colors byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - new Short2(x, y).ToBytes(rgb, 0, ComponentOrder.XYZ); + new Short2(x, y).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 128, 127, 0 }); - new Short2(x, y).ToBytes(rgba, 0, ComponentOrder.XYZW); + new Short2(x, y).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 128, 127, 0, 255 }); - new Short2(x, y).ToBytes(bgr, 0, ComponentOrder.ZYX); + new Short2(x, y).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 0, 127, 128 }); - new Short2(x, y).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new Short2(x, y).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 0, 127, 128, 255 }); Short2 r = new Short2(); r.PackFromBytes(20, 38, 0, 255); - r.ToBytes(rgba, 0, ComponentOrder.XYZW); + r.ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 20, 38, 0, 255 }); } @@ -853,21 +852,21 @@ namespace ImageSharp.Tests.Colors byte[] bgr = new byte[3]; byte[] bgra = new byte[4]; - new Short4(x, y, z, w).ToBytes(rgb, 0, ComponentOrder.XYZ); + new Short4(x, y, z, w).ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 172, 177, 243 }); - new Short4(x, y, z, w).ToBytes(rgba, 0, ComponentOrder.XYZW); + new Short4(x, y, z, w).ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 172, 177, 243, 128 }); - new Short4(x, y, z, w).ToBytes(bgr, 0, ComponentOrder.ZYX); + new Short4(x, y, z, w).ToZyxBytes(bgr, 0); Assert.Equal(bgr, new byte[] { 243, 177, 172 }); - new Short4(x, y, z, w).ToBytes(bgra, 0, ComponentOrder.ZYXW); + new Short4(x, y, z, w).ToZyxwBytes(bgra, 0); Assert.Equal(bgra, new byte[] { 243, 177, 172, 128 }); Short4 r = new Short4(); r.PackFromBytes(20, 38, 0, 255); - r.ToBytes(rgba, 0, ComponentOrder.XYZW); + r.ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 20, 38, 0, 255 }); } diff --git a/tests/ImageSharp.Tests/Common/ConstantsTests.cs b/tests/ImageSharp.Tests/Common/ConstantsTests.cs new file mode 100644 index 0000000000..0adda0c0f6 --- /dev/null +++ b/tests/ImageSharp.Tests/Common/ConstantsTests.cs @@ -0,0 +1,18 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Common +{ + using Xunit; + + public class ConstantsTests + { + [Fact] + public void Epsilon() + { + Assert.Equal(Constants.Epsilon, 0.001f); + } + } +} diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegTests.cs index 662ec97287..46847873ab 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegTests.cs @@ -146,7 +146,7 @@ namespace ImageSharp.Tests { var src = provider.GetImage(); - PixelArea area = new PixelArea(8, 8, ComponentOrder.XYZ); + PixelArea area = new PixelArea(8, 8, ComponentOrder.Xyz); var dest = provider.Factory.CreateImage(8, 8); using (var s = src.Lock()) @@ -171,7 +171,7 @@ namespace ImageSharp.Tests { var src = provider.GetImage(); - PixelArea area = new PixelArea(8, 8, ComponentOrder.XYZ); + PixelArea area = new PixelArea(8, 8, ComponentOrder.Xyz); var dest = provider.Factory.CreateImage(8, 8); using (var s = src.Lock()) diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementations.cs b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementations.cs index 56ca0d0a7d..a5bcd50e12 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementations.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementations.cs @@ -362,11 +362,11 @@ namespace ImageSharp.Tests float a0, a1, a2, a3, b0, b1, b2, b3; float z0, z1, z2, z3, z4; - float r0 = 1.414214f; + //float r0 = 1.414214f; float r1 = 1.387040f; float r2 = 1.306563f; float r3 = 1.175876f; - float r4 = 1.000000f; + //float r4 = 1.000000f; float r5 = 0.785695f; float r6 = 0.541196f; float r7 = 0.275899f; @@ -794,7 +794,7 @@ namespace ImageSharp.Tests r[7] = 0.275899f; const float invsqrt2 = 0.707107f; //(float)(1.0f / M_SQRT2); - const float invsqrt2h = 0.353554f; //invsqrt2*0.5f; + //const float invsqrt2h = 0.353554f; //invsqrt2*0.5f; c1 = x[0]; c2 = x[7]; diff --git a/tests/ImageSharp.Tests/Image/PixelAccessorTests.cs b/tests/ImageSharp.Tests/Image/PixelAccessorTests.cs index fbba55815a..ce28518d73 100644 --- a/tests/ImageSharp.Tests/Image/PixelAccessorTests.cs +++ b/tests/ImageSharp.Tests/Image/PixelAccessorTests.cs @@ -40,10 +40,10 @@ namespace ImageSharp.Tests } [Theory] - [WithMemberFactory(nameof(CreateTestImage), PixelTypes.All, ComponentOrder.XYZ)] - [WithMemberFactory(nameof(CreateTestImage), PixelTypes.All, ComponentOrder.ZYX)] - [WithMemberFactory(nameof(CreateTestImage), PixelTypes.All, ComponentOrder.XYZW)] - [WithMemberFactory(nameof(CreateTestImage), PixelTypes.All, ComponentOrder.ZYXW)] + [WithMemberFactory(nameof(CreateTestImage), PixelTypes.All, ComponentOrder.Xyz)] + [WithMemberFactory(nameof(CreateTestImage), PixelTypes.All, ComponentOrder.Zyx)] + [WithMemberFactory(nameof(CreateTestImage), PixelTypes.All, ComponentOrder.Xyzw)] + [WithMemberFactory(nameof(CreateTestImage), PixelTypes.All, ComponentOrder.Zyxw)] public void CopyTo_Then_CopyFrom_OnFullImageRect(TestImageProvider provider, ComponentOrder order) where TColor : struct, IPackedPixel, IEquatable { @@ -84,10 +84,10 @@ namespace ImageSharp.Tests } [Theory] - [WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.XYZ)] - [WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.ZYX)] - [WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.XYZW)] - [WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.ZYXW)] + [WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.Xyz)] + [WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.Zyx)] + [WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.Xyzw)] + [WithBlankImages(16, 16, PixelTypes.All, ComponentOrder.Zyxw)] public void CopyTo_Then_CopyFrom_WithOffset(TestImageProvider provider, ComponentOrder order) where TColor : struct, IPackedPixel, IEquatable @@ -181,7 +181,7 @@ namespace ImageSharp.Tests byte blue = 3; byte alpha = 255; - using (PixelArea row = new PixelArea(1, ComponentOrder.ZYX)) + using (PixelArea row = new PixelArea(1, ComponentOrder.Zyx)) { row.Bytes[0] = blue; row.Bytes[1] = green; @@ -208,7 +208,7 @@ namespace ImageSharp.Tests byte blue = 3; byte alpha = 4; - using (PixelArea row = new PixelArea(1, ComponentOrder.ZYXW)) + using (PixelArea row = new PixelArea(1, ComponentOrder.Zyxw)) { row.Bytes[0] = blue; row.Bytes[1] = green; @@ -235,7 +235,7 @@ namespace ImageSharp.Tests byte green = 2; byte blue = 3; - using (PixelArea row = new PixelArea(1, ComponentOrder.ZYX)) + using (PixelArea row = new PixelArea(1, ComponentOrder.Zyx)) { pixels[0, 0] = (TColor)(object)new Color(red, green, blue); @@ -258,7 +258,7 @@ namespace ImageSharp.Tests byte blue = 3; byte alpha = 4; - using (PixelArea row = new PixelArea(1, ComponentOrder.ZYXW)) + using (PixelArea row = new PixelArea(1, ComponentOrder.Zyxw)) { pixels[0, 0] = (TColor)(object)new Color(red, green, blue, alpha); diff --git a/tests/ImageSharp.Tests/TestUtilities/TestUtilityExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestUtilityExtensions.cs index bb517dda9f..8b0c65a3c4 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestUtilityExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestUtilityExtensions.cs @@ -21,7 +21,7 @@ namespace ImageSharp.Tests private static readonly Assembly ImageSharpAssembly = typeof(Color).GetTypeInfo().Assembly; private static readonly Dictionary PixelTypes2ClrTypes = new Dictionary(); - + private static readonly PixelTypes[] AllConcretePixelTypes = EnumHelper.GetSortedValues() .Except(new [] {PixelTypes.Undefined, PixelTypes.All }) .ToArray(); @@ -53,7 +53,7 @@ namespace ImageSharp.Tests return intrfcType.GetGenericArguments().Single(); } - + public static bool HasFlag(this PixelTypes pixelTypes, PixelTypes flag) => (pixelTypes & flag) == flag; public static bool IsEquivalentTo(this Image a, Image b, bool compareAlpha = true) @@ -87,11 +87,11 @@ namespace ImageSharp.Tests } else { - ca.ToBytes(bytesA, 0, ComponentOrder.XYZ); - cb.ToBytes(bytesB, 0, ComponentOrder.XYZ); + ca.ToXyzBytes(bytesA, 0); + cb.ToXyzBytes(bytesB, 0); - if (bytesA[0] != bytesB[0] || - bytesA[1] != bytesB[1] || + if (bytesA[0] != bytesB[0] || + bytesA[1] != bytesB[1] || bytesA[2] != bytesB[2]) { return false; diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs index 31014f89dc..2f5ec6c28d 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs @@ -35,7 +35,7 @@ namespace ImageSharp.Tests [WithBlankImages(42, 666, PixelTypes.All, "hello")] public void Use_WithBlankImagesAttribute_WithAllPixelTypes( TestImageProvider provider, - string message) + string message) where TColor : struct, IPackedPixel, IEquatable { var img = provider.GetImage(); @@ -59,7 +59,7 @@ namespace ImageSharp.Tests [WithBlankImages(1, 1, PixelTypes.StandardImageClass)] [WithFile(TestImages.Bmp.F, PixelTypes.StandardImageClass)] public void PixelTypes_ColorWithDefaultImageClass_TriggersCreatingTheNonGenericDerivedImageClass( - TestImageProvider provider) + TestImageProvider provider) where TColor : struct, IPackedPixel, IEquatable { var img = provider.GetImage(); @@ -112,7 +112,7 @@ namespace ImageSharp.Tests { for (int x = 0; x < pixels.Width; x++) { - pixels[x, y].ToBytes(colors, 0, ComponentOrder.XYZW); + pixels[x, y].ToXyzwBytes(colors, 0); Assert.Equal(colors[0], 255); Assert.Equal(colors[1], 100); @@ -129,7 +129,7 @@ namespace ImageSharp.Tests /// /// /// - public static Image CreateTestImage(GenericFactory factory) + public static Image CreateTestImage(GenericFactory factory) where TColor : struct, IPackedPixel, IEquatable { return factory.CreateImage(3, 3); diff --git a/tests/ImageSharp.Tests/project.json b/tests/ImageSharp.Tests/project.json index cdf1aa61ff..e0e269239e 100644 --- a/tests/ImageSharp.Tests/project.json +++ b/tests/ImageSharp.Tests/project.json @@ -12,6 +12,13 @@ "buildOptions": { "allowUnsafe": true }, + "configurations": { + "Release": { + "buildOptions": { + "warningsAsErrors": true + } + } + }, "dependencies": { "ImageSharp": "1.0.0-*", "xunit": "2.2.0-*",