From d2db3163c4f4eb3ca9305d5236ce7ad2e313170c Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 25 May 2017 23:13:23 +1000 Subject: [PATCH] Better Block8x8F clamp --- .../Jpeg/Components/Block8x8F.Generated.cs | 125 ++++++++++++++---- .../Jpeg/Components/Block8x8F.Generated.tt | 38 +++--- .../Formats/Jpeg/Components/Block8x8F.cs | 10 +- 3 files changed, 120 insertions(+), 53 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs index 211b66dac..f84dc977f 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs @@ -5,53 +5,120 @@ // ReSharper disable InconsistentNaming // #pragma warning disable -using System; -using System.Numerics; -using System.Runtime.CompilerServices; - - namespace ImageSharp.Formats.Jpg { + using System.Numerics; + using System.Runtime.CompilerServices; + internal partial struct Block8x8F { - private static readonly Vector4 CMin4 = new Vector4(-128f); - private static readonly Vector4 CMax4 = new Vector4(127f); - private static readonly Vector4 COff4 = new Vector4(128f); + private static readonly Vector4 CMin4 = new Vector4(0F); + private static readonly Vector4 CMax4 = new Vector4(255F); + private static readonly Vector4 COff4 = new Vector4(128F); /// - /// Transpose the block into d + /// Transpose the block into the destination block. /// - /// Destination + /// The destination block [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TransposeInto(ref Block8x8F d) { - d.V0L.X = V0L.X; d.V1L.X = V0L.Y; d.V2L.X = V0L.Z; d.V3L.X = V0L.W; d.V4L.X = V0R.X; d.V5L.X = V0R.Y; d.V6L.X = V0R.Z; d.V7L.X = V0R.W; - d.V0L.Y = V1L.X; d.V1L.Y = V1L.Y; d.V2L.Y = V1L.Z; d.V3L.Y = V1L.W; d.V4L.Y = V1R.X; d.V5L.Y = V1R.Y; d.V6L.Y = V1R.Z; d.V7L.Y = V1R.W; - d.V0L.Z = V2L.X; d.V1L.Z = V2L.Y; d.V2L.Z = V2L.Z; d.V3L.Z = V2L.W; d.V4L.Z = V2R.X; d.V5L.Z = V2R.Y; d.V6L.Z = V2R.Z; d.V7L.Z = V2R.W; - d.V0L.W = V3L.X; d.V1L.W = V3L.Y; d.V2L.W = V3L.Z; d.V3L.W = V3L.W; d.V4L.W = V3R.X; d.V5L.W = V3R.Y; d.V6L.W = V3R.Z; d.V7L.W = V3R.W; - d.V0R.X = V4L.X; d.V1R.X = V4L.Y; d.V2R.X = V4L.Z; d.V3R.X = V4L.W; d.V4R.X = V4R.X; d.V5R.X = V4R.Y; d.V6R.X = V4R.Z; d.V7R.X = V4R.W; - d.V0R.Y = V5L.X; d.V1R.Y = V5L.Y; d.V2R.Y = V5L.Z; d.V3R.Y = V5L.W; d.V4R.Y = V5R.X; d.V5R.Y = V5R.Y; d.V6R.Y = V5R.Z; d.V7R.Y = V5R.W; - d.V0R.Z = V6L.X; d.V1R.Z = V6L.Y; d.V2R.Z = V6L.Z; d.V3R.Z = V6L.W; d.V4R.Z = V6R.X; d.V5R.Z = V6R.Y; d.V6R.Z = V6R.Z; d.V7R.Z = V6R.W; - d.V0R.W = V7L.X; d.V1R.W = V7L.Y; d.V2R.W = V7L.Z; d.V3R.W = V7L.W; d.V4R.W = V7R.X; d.V5R.W = V7R.Y; d.V6R.W = V7R.Z; d.V7R.W = V7R.W; + d.V0L.X = V0L.X; + d.V1L.X = V0L.Y; + d.V2L.X = V0L.Z; + d.V3L.X = V0L.W; + d.V4L.X = V0R.X; + d.V5L.X = V0R.Y; + d.V6L.X = V0R.Z; + d.V7L.X = V0R.W; + + d.V0L.Y = V1L.X; + d.V1L.Y = V1L.Y; + d.V2L.Y = V1L.Z; + d.V3L.Y = V1L.W; + d.V4L.Y = V1R.X; + d.V5L.Y = V1R.Y; + d.V6L.Y = V1R.Z; + d.V7L.Y = V1R.W; + + d.V0L.Z = V2L.X; + d.V1L.Z = V2L.Y; + d.V2L.Z = V2L.Z; + d.V3L.Z = V2L.W; + d.V4L.Z = V2R.X; + d.V5L.Z = V2R.Y; + d.V6L.Z = V2R.Z; + d.V7L.Z = V2R.W; + + d.V0L.W = V3L.X; + d.V1L.W = V3L.Y; + d.V2L.W = V3L.Z; + d.V3L.W = V3L.W; + d.V4L.W = V3R.X; + d.V5L.W = V3R.Y; + d.V6L.W = V3R.Z; + d.V7L.W = V3R.W; + + d.V0R.X = V4L.X; + d.V1R.X = V4L.Y; + d.V2R.X = V4L.Z; + d.V3R.X = V4L.W; + d.V4R.X = V4R.X; + d.V5R.X = V4R.Y; + d.V6R.X = V4R.Z; + d.V7R.X = V4R.W; + + d.V0R.Y = V5L.X; + d.V1R.Y = V5L.Y; + d.V2R.Y = V5L.Z; + d.V3R.Y = V5L.W; + d.V4R.Y = V5R.X; + d.V5R.Y = V5R.Y; + d.V6R.Y = V5R.Z; + d.V7R.Y = V5R.W; + + d.V0R.Z = V6L.X; + d.V1R.Z = V6L.Y; + d.V2R.Z = V6L.Z; + d.V3R.Z = V6L.W; + d.V4R.Z = V6R.X; + d.V5R.Z = V6R.Y; + d.V6R.Z = V6R.Z; + d.V7R.Z = V6R.W; + + d.V0R.W = V7L.X; + d.V1R.W = V7L.Y; + d.V2R.W = V7L.Z; + d.V3R.W = V7L.W; + d.V4R.W = V7R.X; + d.V5R.W = V7R.Y; + d.V6R.W = V7R.Z; + d.V7R.W = V7R.W; } /// /// Level shift by +128, clip to [0, 255] /// - /// Destination + /// The destination block [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void TransformByteConvetibleColorValuesInto(ref Block8x8F d) { - d.V0L = Vector4.Max(Vector4.Min(V0L, CMax4), CMin4) + COff4;d.V0R = Vector4.Max(Vector4.Min(V0R, CMax4), CMin4) + COff4; - d.V1L = Vector4.Max(Vector4.Min(V1L, CMax4), CMin4) + COff4;d.V1R = Vector4.Max(Vector4.Min(V1R, CMax4), CMin4) + COff4; - d.V2L = Vector4.Max(Vector4.Min(V2L, CMax4), CMin4) + COff4;d.V2R = Vector4.Max(Vector4.Min(V2R, CMax4), CMin4) + COff4; - d.V3L = Vector4.Max(Vector4.Min(V3L, CMax4), CMin4) + COff4;d.V3R = Vector4.Max(Vector4.Min(V3R, CMax4), CMin4) + COff4; - d.V4L = Vector4.Max(Vector4.Min(V4L, CMax4), CMin4) + COff4;d.V4R = Vector4.Max(Vector4.Min(V4R, CMax4), CMin4) + COff4; - d.V5L = Vector4.Max(Vector4.Min(V5L, CMax4), CMin4) + COff4;d.V5R = Vector4.Max(Vector4.Min(V5R, CMax4), CMin4) + COff4; - d.V6L = Vector4.Max(Vector4.Min(V6L, CMax4), CMin4) + COff4;d.V6R = Vector4.Max(Vector4.Min(V6R, CMax4), CMin4) + COff4; - d.V7L = Vector4.Max(Vector4.Min(V7L, CMax4), CMin4) + COff4;d.V7R = Vector4.Max(Vector4.Min(V7R, CMax4), CMin4) + COff4; + d.V0L = Vector4.Clamp(V0L + COff4, CMin4, CMax4); + d.V0R = Vector4.Clamp(V0R + COff4, CMin4, CMax4); + d.V1L = Vector4.Clamp(V1L + COff4, CMin4, CMax4); + d.V1R = Vector4.Clamp(V1R + COff4, CMin4, CMax4); + d.V2L = Vector4.Clamp(V2L + COff4, CMin4, CMax4); + d.V2R = Vector4.Clamp(V2R + COff4, CMin4, CMax4); + d.V3L = Vector4.Clamp(V3L + COff4, CMin4, CMax4); + d.V3R = Vector4.Clamp(V3R + COff4, CMin4, CMax4); + d.V4L = Vector4.Clamp(V4L + COff4, CMin4, CMax4); + d.V4R = Vector4.Clamp(V4R + COff4, CMin4, CMax4); + d.V5L = Vector4.Clamp(V5L + COff4, CMin4, CMax4); + d.V5R = Vector4.Clamp(V5R + COff4, CMin4, CMax4); + d.V6L = Vector4.Clamp(V6L + COff4, CMin4, CMax4); + d.V6R = Vector4.Clamp(V6R + COff4, CMin4, CMax4); + d.V7L = Vector4.Clamp(V7L + COff4, CMin4, CMax4); + d.V7R = Vector4.Clamp(V7R + COff4, CMin4, CMax4); } - - } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt index be198a6fa..03566acbb 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt @@ -11,31 +11,29 @@ <#@ output extension=".cs" #> // #pragma warning disable -using System; -using System.Numerics; -using System.Runtime.CompilerServices; - <# char[] coordz = {'X', 'Y', 'Z', 'W'}; #> - namespace ImageSharp.Formats.Jpg { + using System.Numerics; + using System.Runtime.CompilerServices; + internal partial struct Block8x8F { - private static readonly Vector4 CMin4 = new Vector4(-128f); - private static readonly Vector4 CMax4 = new Vector4(127f); - private static readonly Vector4 COff4 = new Vector4(128f); + private static readonly Vector4 CMin4 = new Vector4(0F); + private static readonly Vector4 CMax4 = new Vector4(255F); + private static readonly Vector4 COff4 = new Vector4(128F); /// - /// Transpose the block into d + /// Transpose the block into the destination block. /// - /// Destination + /// The destination block [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TransposeInto(ref Block8x8F d) { <# - PushIndent(" "); + PushIndent(" "); for (int i = 0; i < 8; i++) { @@ -44,13 +42,16 @@ namespace ImageSharp.Formats.Jpg for (int j = 0; j < 8; j++) { + if(i > 0 && j == 0){ + WriteLine(""); + } + char srcCoord = coordz[j % 4]; char srcSide = (j / 4) % 2 == 0 ? 'L' : 'R'; - - string expression = $"d.V{j}{destSide}.{destCoord} = V{i}{srcSide}.{srcCoord}; "; + + string expression = $"d.V{j}{destSide}.{destCoord} = V{i}{srcSide}.{srcCoord};\r\n"; Write(expression); } - WriteLine(""); } PopIndent(); #> @@ -59,27 +60,24 @@ namespace ImageSharp.Formats.Jpg /// /// Level shift by +128, clip to [0, 255] /// - /// Destination + /// The destination block [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void TransformByteConvetibleColorValuesInto(ref Block8x8F d) { <# - PushIndent(" "); + PushIndent(" "); for (int i = 0; i < 8; i++) { for (int j = 0; j < 2; j++) { char side = j == 0 ? 'L' : 'R'; - Write($"d.V{i}{side} = Vector4.Max(Vector4.Min(V{i}{side}, CMax4), CMin4) + COff4;"); + Write($"d.V{i}{side} = Vector4.Clamp(V{i}{side} + COff4, CMin4, CMax4);\r\n"); } - WriteLine(""); } PopIndent(); #> } - - } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs index 56466d7a0..130b5856c 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs @@ -57,6 +57,9 @@ namespace ImageSharp.Formats.Jpg public Vector4 V7R; #pragma warning restore SA1600 // ElementsMustBeDocumented + private static readonly Vector4 NegativeOne = new Vector4(-1); + private static readonly Vector4 Offset = new Vector4(.5F); + /// /// Get/Set scalar elements at a given index /// @@ -402,12 +405,11 @@ namespace ImageSharp.Formats.Jpg [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Vector4 DivideRound(Vector4 dividend, Vector4 divisor) { - // sign(v) = max(min(v, 1), -1) - Vector4 sign = Vector4.Min(dividend, Vector4.One); - sign = Vector4.Max(sign, new Vector4(-1)); + // sign(dividend) = max(min(dividend, 1), -1) + var sign = Vector4.Clamp(dividend, NegativeOne, Vector4.One); // AlmostRound(dividend/divisor) = dividend/divisior + 0.5*sign(dividend) - return (dividend / divisor) + (sign * new Vector4(0.5f)); + return (dividend / divisor) + (sign * Offset); } } } \ No newline at end of file